This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Compiler/DRA756: C66 CGT v8.1.3 Incremental Link Issue

Part Number: DRA756

Tool/software: TI C/C++ Compiler

We are seeing a potential issue with C66 CGTv8.1.3 and incremental linking

Attached are some files to reproduce the issue.  In the files, there is a diagram presented which shows the intended flow.

Each of the files contains an object with a global constructor:

Main.cpp object of type MainFile

libFile01.cpp object of type LibFile01

libFile02.cpp object of type LibFile02 (the object is instantiated with pragma RETAIN).

Only constructors for objects: MainFile and LibFile02 are executed.

 

1. To reproduce, please use attached source files and batch program compile2.bat to build the program. Please set path to includes in the compile2.bat file.

2. For gcc compiler (on x86 and A15) the constructor for object LibFile01 is called – batch file compile2_gcc.bat is used to build a program for PC.

3. It is likely that the pragma RETAIN could help, however issue is working with 3rd party code, which we cannot change even for one line.

4. If you compile all files and link them in one step, then all global constructors are called – batch file compile1.bat

5. A similar issue was reported here http://e2e.ti.com/support/development_tools/compiler/f/343/p/202214/721867 and was reported to be solved.2017.11.13_C66_Incremental_Link.zip

  • My analysis is not complete.  But I have one question I'm sure is central.  Why do an incremental link at all?  Why not put libFile01.obj and libFile02.obj in a library, and then link against that?  That is a much more typical way to organize a build with multiple layers.

    Thanks and regards,

    -George

  • Hi!

    Thanks for the answer. If you link to a library and then no global constructors from the library are invoked, despite pragma RETAIN. There is an interesting discussion about incremental linking below. I'll answer more completely tomorrow morning.

    compile3.zip

  • Hi!

    The last answer in the post explains what we want to achieve:

    Please find attached another scenario where we build according to the following diagram

    In that case, the constructor for libFile02 is called (due to pragma RETAIN).

    compile4.zip

    Best regards

    Przemek

  • Please consider this solution.  Build a static library with a command similar to ...

    ar6x -r name.lib libfile01.obj libfile02.obj

    Add name.lib to the link command, just like any other file.  The linker automatically determines that it is a library, and handles it accordingly.

    To force the global objects, and their constructors, to be part of the link, apply the linker option --undef_sym to each global object.  Please read more about that option in the C6000 assembly manual.  In this case, add these options to the link ...

    --undef_sym=libFile01 --undef_sym=libFile02

    Your full application probably has many more than two of these.  Feel free to write them in a text command file, one per line.  Supply that command file to the linker like any other file.  

    One other point ... Your batch file invokes lnk6x directly.  This is not the documented method, even though it does work in many cases.  The documented method is to invoke the linker through the compiler shell ...

    cl6x -z <options> <files>

    Thanks and regards,

    -George

  • Hi George!

    Thanks for your answer and suggestions. Now it works without the pragma RETAIN. What is interesting, incremental linking must be used. Attached is a command to build the program.

    /cfs-file/__key/communityserver-discussions-components-files/81/8561.compile5.zip

    Best regards

    Przemek

  • Przemyslaw_Baranski said:
    What is interesting, incremental linking must be used.

    I don't understand why.  When I build the library like this ...

    ar6x.exe -r libfile.lib libfile01.obj libfile02.obj

    ... and I don't do the incremental link at all, I get the same program.

    Thanks and regards,

    -George

  • Are you linking the program with undef_sym option, i.e.

    lnk6x.exe main.obj libfile.lib linker.cmd rts6600_elf.lib --ram_model -o prog5.out --undef_sym=libFile01 --undef_sym=libFile02

     


    Best regards

    Przemek

  • Przemyslaw_Baranski said:
    Are you linking the program with undef_sym option

    Yes.  I'll give you a bit more detail.

    After building the object files, I create a library with this command ...

    ar6x -r name.lib libfile01.obj libfile02.obj

    Then I link with this command ...

    cl6x -z --undef_sym=libFile01 --undef_sym=libFile02 main.obj linker.cmd name.lib rts6600_elf.lib --ram_model -o prog_lib.out

    I use the names utility a bit differently ...

    nm6x.exe -l -g prog_lib.out | dem6x -q --abi=eabi > prog_lib.txt

    With -g, you only get global symbols.  I run the output of the names utility through the demangler dem6x, to turn names like _ZZN9LibFile01C1EvEs into LibFile01::LibFile01()::string .  Then I inspect prog_lib.txt for any instance of libfile (case insensitive) ...

    C:\work\dir>find /i "libfile" prog_lib.txt
    
    ---------- PROG_LIB.TXT
    [1677]  |0x80007b60|   13|GLOB |OBJT |HIDN |8     |LibFile01::LibFile01()::string
    [1679]  |0x80007b70|   13|GLOB |OBJT |HIDN |8     |LibFile02::LibFile02()::string
    [1678]  |0x80006de0|    0|GLOB |FUNC |HIDN |4     |__sti___13_libfile01_cpp_73840bb6
    [1681]  |0x80006e20|    0|GLOB |FUNC |HIDN |4     |__sti___13_libfile02_cpp_ea8d5a0c
    [1676]  |0x80007cd8|    1|GLOB |OBJT |HIDN |12    |libFile01
    [1680]  |0x80007cd9|    1|GLOB |OBJT |HIDN |12    |libFile02

    When I do the same thing using your compile5 method, I see the same symbols.  I take this to mean the programs are, so far as these objects are concerned, the same.

    Thanks and regards,

    -George

  • Hi George!
    Indeed, your way of building the program works also for me. Thanks for suggesting this!

    Just for your information - I noticed that GCC compiler/linker behaves differently. When I build similarly using the following commands, the global constructors are not invoked.

    :: clean
    del *.obj
    del libfile.lib
    del prog5out_gcc.exe
    
    :: compile
    gcc.exe -c libfile01.cpp -o3 -o libfile01.obj
    gcc.exe -c libfile02.cpp -o3 -o libfile02.obj
    
    :: archive
    ar cr libfile.lib libfile01.obj libfile02.obj
    
    :: link final program
    gcc.exe main.cpp libfile.lib -Wl,--undefined=libFile01,--undefined=libFile02 -o prog5out_gcc.exe

    Best regards

    Przemek

  • George,

    is there a way to "undefine" all symbols in a file?

    Best regards
    Przemek

  • Unfortunately, no.  The effect of --undef_sym can be applied to only one symbol at a time.  Keep in mind you can list all the options in a text command file, then supply that file to the linker.  You could also consider writing a script which takes the output of the names utility and changes it into a list of --undef_sym options.

    Thanks and regards,

    -George