Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 4 of 4

Thread: __attribute__((constructor (200)) does not seem to work with Teensy 4.1

  1. #1
    Junior Member
    Join Date
    Feb 2021
    Posts
    2

    __attribute__((constructor (200)) does not seem to work with Teensy 4.1

    I recently purchased a Teensy 4.1 and am porting an application that heavily leverages constructor attributes. When running the following application under LInux, this snippet:

    Code:
    #include <stdio.h>
    
    int foo;
    
    int main(int argc, char *argv[])
    {
    	printf("foo is %d\n", foo);
    }
    
    void __attribute__((constructor (200))) init_foo(void)
    {
    	foo = 5;
    }
    Compiles and produces the following (expected output)

    Code:
    [markster@portamarko ~]$ gcc -o footest footest.c
    [markster@portamarko ~]$ ./footest 
    foo is 5
    [markster@portamarko ~]$
    That is, the funciton "init_foo" is called before main.

    However, running a similar snippet of code under teensyduino (or using Makefiles):

    Code:
    int foo;
    
    void setup() {
      while (!Serial);
      Serial.print("foo has the value ");
      Serial.println(foo);
    }
    
    // the loop routine runs over and over again forever:
    void loop() {
    }
    
    void __attribute__((constructor (200))) init_foo(void)
    {
      foo = 5;
    }
    Produces the incorrect output:

    Code:
    foo has the value 0
    Any thoughts on what I need to do to get the constructors to be called?

    Mark

  2. #2
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,450
    Don't ask me why but it works without the priority argument. I.e.,

    Code:
    void __attribute__((constructor )) init_foo(void)
    {
      foo = 5;
    }
    Are you sure that this is even supposed to work in c++ code? Seems to be relevant for C only?

  3. #3
    Junior Member
    Join Date
    Feb 2021
    Posts
    2
    Quote Originally Posted by luni View Post
    Don't ask me why but it works without the priority argument. I.e.,

    Code:
    void __attribute__((constructor )) init_foo(void)
    {
      foo = 5;
    }
    Are you sure that this is even supposed to work in c++ code? Seems to be relevant for C only?
    Luni,

    Thank you so much for the prompt reply. I can confirm your results. In my case, the code I am porting over is in C, but has the same result.

    Based on your idea, I copied two directory trees from arduino_build to compare the binaries being built with and without priority. Using "objdump -t" on each object file and comparing the results, I see the following:

    Code:
    [markster@portamarko xfs]$ diff -uNr ~/without.txt ~/with.txt 
    --- /home/markster/without.txt	2021-02-03 07:24:15.363077354 -0600
    +++ /home/markster/with.txt	2021-02-03 07:24:07.905046480 -0600
    @@ -1,5 +1,5 @@
     
    -arduino_without_priority/sketch/Blink.ino.cpp.o:     file format elf32-little
    +arduino_with_priority/sketch/Blink.ino.cpp.o:     file format elf32-little
     
     SYMBOL TABLE:
     00000000 l    df *ABS*	00000000 Blink.ino.cpp
    @@ -14,8 +14,8 @@
     00000000 l    d  .text.startup._Z8init_foov	00000000 .text.startup._Z8init_foov
     00000000 l       .text.startup._Z8init_foov	00000000 $t
     00000008 l       .text.startup._Z8init_foov	00000000 $d
    -00000000 l    d  .init_array	00000000 .init_array
    -00000000 l       .init_array	00000000 $d
    +00000000 l    d  .init_array.00200	00000000 .init_array.00200
    +00000000 l       .init_array.00200	00000000 $d
     00000000 l    d  .bss.foo	00000000 .bss.foo
     00000000 l       .bss.foo	00000000 $d
     00000000 l    d  .rodata.str1.4	00000000 .rodata.str1.4
    [markster@portamarko xfs]$
    So, importantly, we can see it's going from .init_array to .init_array.00200. With a quick scan of the linker script, it doesn't appear that there is a KEEP for things with stuff after init_array, so I added this line to the linker script:

    Code:
                   KEEP (*(.init_array.*))
    and voila, my constructors run. However, I am not sure if this should be differently in order to ensure they are placed in the order of priority. Any thoughts?

    Mark

  4. #4
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,450
    Interesting! However, linker scripts are definitely not my core competence. But I'm sure someone knowing more about this stuff will jump in to help.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •