Phuong Nguyen
Phuong Nguyen

Reputation: 909

Linux kernel module - accessing memory mapping

I'm running into some odd issue on kernel module load that I'm suspecting having to do with linking and loading. How to I programmatically figure out the address of each section after they are loaded in memory (from inside the module itself). Like where is .bss / .data / .text and so on.

From reading this article https://lwn.net/Articles/90913/

It is sorta in the directly that I'm looking for.

Upvotes: 1

Views: 2499

Answers (3)

peachykeen
peachykeen

Reputation: 4411

While this question is five years old, I thought I would contribute my two-cents. I was able to access the kernel's sections in a sort of hack-y way inspired by Alex Hoppus' answer. I don't advocate doing things this way, unless you are writing the kernel module to debug things or understand the kernel etc.

Anyway, I copy the following two structs into my module to help resolve incomplete types.

struct module_sect_attr {
    struct module_attribute mattr;
    char *name;
    unsigned long address;
};

struct module_sect_attrs {
    struct attribute_group grp;
    unsigned int nsections;
    struct module_sect_attr attrs[0];
};

Then, in my module initialization function, I do the following to get the section addresses.

unsigned long   text      = 0;
unsigned int    nsections = 0;
unsigned int    i;
struct module_sect_attr* sect_attr;

nsections = THIS_MODULE->sect_attrs->nsections;
sect_attr = THIS_MODULE->sect_attrs->attrs;

for (i = 0; i < nsections; i++) {
    if (strcmp((sect_attr + i)->name, ".text") == 0)
    text = (sect_attr + i)->address;
}

Finally, it should be noted that if you are looking for the address of .rodata, .bss, or .data you will need to define constant global variables, uninitialized global variables, or regular global variables, respectively, if you don't want those sections to be omitted.

Upvotes: 1

Alex Hoppus
Alex Hoppus

Reputation: 3935

You can see the sections begin addresses like this from userspace (need root permissions):

sudo cat /sys/module/<modulename>/sections/.text

I have browsed how syfs retrieves this addresses, and i found the following: There is a section attributes in struct module

309         /* Section attributes */
310         struct module_sect_attrs *sect_attrs;

This attrs is a bunch of attr structs

1296 struct module_sect_attrs {
1297         struct attribute_group grp;
1298         unsigned int nsections;
1299         struct module_sect_attr attrs[0];
1300 };

where sect attr is the thing you are looking for

1290 struct module_sect_attr {
1291         struct module_attribute mattr;
1292         char *name;
1293         unsigned long address;

Upvotes: 3

Tsyvarev
Tsyvarev

Reputation: 66153

From the module's code THIS_MODULE macro is actually a pointer to the struct module object. Its module_init and module_core fields point to memory regions, where all module sections are loaded.

As I understand, sections division is inaccessible from the module code(struct load_info is dropped after module is loaded into memory). But having module's file you can easily deduce section's addresses after load:

module_init:
    - init sections with code (.init.text)
    - init sections with readonly data
    - init sections with writable data

module_core:
    - sections with code (.text)
    - sections with readonly data
    - sections with writable data

If several sections suit to one category, they are placed in the same order, as in the module's file.

Within module's code you can also print address of any its symbol, and after calculate start of the section, contained this symbol.

Upvotes: 2

Related Questions