Ad

How To Run Each "function" In A Code Section?

- 1 answer

I want to be able to declare function so that they are added to a specific code section and then they are all executed before my start function. Something like this:

void __attribute__((__section__(".driverinit"))) disk_driver_init()  {
    dev_register(&diskDevice);
}

The purpose is that each of these would add their variable to an array so that the functions contained in it can be processed. I know I can add these functions all globally but I'm trying to avoid that if I can.

The problem is that as soon as the first one returns I don't know how to go to the next function in the set. Or possibly have the functions not generate a "ret" at the end and fall through. Not sure if that's possible.

Here's the disassembly, I would like it to run each function in the code section and then jump to _start at the end if that's possible somehow...

Disassembly of section .driverinit:

0000000000000000 <disk_driver_init>:
   0:   a9bf7bfd        stp     x29, x30, [sp, #-16]!
   4:   910003fd        mov     x29, sp
   8:   d0000040        adrp    x0, a000 <FLAG_APP_CMD+0x138>
   c:   9128e000        add     x0, x0, #0xa38
  10:   9400020f        bl      84c <dev_register>
  14:   d503201f        nop
  18:   a8c17bfd        ldp     x29, x30, [sp], #16
  1c:   d65f03c0        ret
  20:   14000002        b       28 <_start>
  24:   d65f03c0        ret

Disassembly of section .text.boot:

0000000000000028 <_start>:
  28:   d53800a0        mrs     x0, mpidr_el1
  2c:   92401c00        and     x0, x0, #0xff
  30:   b4000040        cbz     x0, 38 <startup_proc>

Can someone steer me in the right direction?

Ad

Answer

Instead of putting the functions themselves in a special section, put pointers to the functions in this special section:

void disk_driver_init()  {
    dev_register(&diskDevice);
}

void __attribute__((section(".driverinit")))(* const disk_driver_init_ptr)() = disk_driver_init;

You'd need something to mark the end of the section so have this in a file by itself and have it be the last object file you link with:

void __attribute__((section(".driverinit")))(* const driverinit_end)() = 0;

You can then call all the driver init functions with something like this:

void __attribute__((section(".driverinit")))(* const driverinit_start)() = 0;

void
call_driver_init_fns(void) {
    void (* const *fn)() = &driverinit_start + 1;
    while (fn != &driverinit_end) {
        (*fn)();
        fn++;
    }
}

Note that this object file needs to be first, or at least before any of the other object files that put function pointers in .driverinit when linking.

This is essentially how C++ constructors work. You can avoid the wasted space _start and _end variables take by using a custom linker script that provides symbols for the start and end of the .driverinit section. There's also the GCC constructor attribute, but if you're not using the standard runtime, as I'm guessing you're not, you'll have to figure how that works on your platform and implement the startup code yourself.

Ad
source: stackoverflow.com
Ad