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.

Dynamic linking library for C665x

Genius 5785 points

Hello,

I'd like to understand how to use dynamic linking library for C665x with CGTv7.4.7. It seems that the main application can call and run the dynamic library, but the library can not access its own global variable. When the library program accesses global variable declared by library, its address is not the main application but the library. The library address is dummy. I want to have the library program access the main application address.

That's the library program below. Please give me advices.

-------

__declspec(dllexport) int add_array(int d[], int size);
__declspec(dllexport) int arrayDataGbl[];

#pragma DATA_SECTION(arrayDataGbl,".startData")
int arrayDataGbl[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

int add_func( int d[],int size )
{
 int i, temp=0;
 for(i=0; i<size; i++){
  temp += d[i];
 }
 return temp;
}

#pragma CODE_SECTION(add_array,".startFunc")
int add_array(int arrayData[]/* not used */, int arraysize)
{
 int temp;
 temp = add_func(arrayDataGbl, arraysize);
 return temp;
}

-------

Regards,
Kazu

  • Hi Kazu,

    Moved this thread to TI Compiler forum for faster response.

    Thank you,

  • Unfortunately, I'm not sure how to handle this one, and the experts I normally consult are out until next week.  I apologize for the delay.

    Thanks and regards,

    -George

  • Hello George,

    Thank you for your reply. Could you give me an advice if you have already gotten it from your expert?

    Regards,

    Kazu

  • Hello Kazu,

    The "C6000 Embedded Application Binary Interface - Application Report" which you can find at http://www.ti.com/dsp/docs/litabsmultiplefilelist.tsp?sectionId=3&tabId=409&literatureNumber=sprab89a&docCategoryId=1&familyId=132&keyMatch=c6000 contains some useful information about the dynamic linking models that are supported in the C6000 Code Generation Tools. The section entitled "Addressing Model for Dynamic Linking" contains a description of different ways that data can be accessed via the Global Offset Table (GOT).

    In your example code, I would expect the compiler to generate a sequence of code like that detailed in the "GOT-Based Reference Using Near DP-Relative Addressing", i.e.:

       LDW *+DP($GOT(sym)),tmp              ;reloc R_C6000_SBR_GOT_U15

       LDW *tmp,dest

    In fact, when I compile your example code with "cl6x --linux --pic -mv6600 -k file.asm", I see the following instruction:

       LDW     .D2T1   *+DP($GOT(arrayDataGbl)),A4

    which makes sense since we want the address of 'arrayDataGbl' to be the first argument in the call to add_array().

    Are you seeing different code generated by the compiler for your example source code? If so, what options are you using to compile with?

    I am also confused about why you make a distinction in your earlier message between the library address and the main application address for 'arrayDataGbl'. There should only be one address associated with the exported data object 'arrayDataGbl', but that address will not be resolved until the library is dynamically loaded (a GOT entry will have been reserved for the address of 'arrayDataGbl' and a relocation will be attached to that GOT entry so that the dynamic linker can resolve the address at dynamic load time).

    Hope this helps.

    Regards,

    Todd Snider

  • Hello Todd,

    Thank you for your information. I'm now able to see the assembly code accessed global variable using GOT by adding --pic and --linux. Then out file is created. My option and linker file are below.

    compiler and linker option:

    -mv6600 --abi=eabi -k --pic=near --linux -z --dynamic=lib

    linker file:

    MEMORY
    {
    BLOB: o = 0h l = 10000000h
    }
    SECTIONS
    {
    .startFunc : 0x0
    .startData : BLOB
    .dsbt : BLOB
    }

    But other problem occur. I run bat file below after building out file to create binary file. The binary is read to appropriate address by main application using fread.

    test.bat:

    set CCS_INSTALL_ROOT=C:/ti/ccsv5
    set CG_TOOL_ROOT=%CCS_INSTALL_ROOT%/tools/compiler/c6000_7.4.7

    del dllAdd.dll
    "%CG_TOOL_ROOT%/bin/strip6x" -o dllAdd.dll dllAdd.out
    "%CCS_INSTALL_ROOT%/utils/tiobj2bin/tiobj2bin.bat" dllAdd.dll dllAdd.bin "%CG_TOOL_ROOT%/bin/ofd6x.exe" "%CG_TOOL_ROOT%/bin/hex6x.exe" "%CCS_INSTALL_ROOT%\utils\tiobj2bin\mkhex4bin.exe"

    error message:

    "strip6x" -o dllAdd.dll dllAdd.out
    error: corrupted object file: program segment contains a section whose vaddr
    (0x0000022f) is less than the program segments (0x00000240)
    error: corrupted object file: a single dynamic relocation table was requested,
    but the DT_JMPREL relocation table was not placed immediately after the
    DT_RELA table in memory and/or the section table; the .dynamic section

    Could you possibly give me advice?

    Regards,
    Kazu

  • Hello Kazu,

    In a dynamic linking scenario, you should not be using a linker command file. Target memory allocation and symbol resolution (for symbols in the .dll that is being loaded) and relocation of references to imported symbols must be resolved at load time by the dynamic loader application. There should be no reason for you to use a linker command file in creating the .dll. The code and data will be organized by the linker according to a dynamic linking segment model (please see the above referenced "C6000 Embedded Application Binary Interface" specification for more details). In general, you should see all code sections collected into a Read-Only program segment, and data sections collected into a Read-Write program segment. The R/W program segment will normally contain all data objects that are referenced via near-DP addressing at the front of the segment.

    It is unclear to me what your intention is from looking at the contents of the .bat file. Can you provide a more general description of what it is you are trying to accomplish?

    Regards,

    Todd Snider

  • Hello Todd,

    I remove linker file from CCS project. But my dynamic link library can not run correctly after the main application loads it. The main application as loader is not in linux system. Do I need to add the option with "Generate code for Linux"? By the way, do you have the example software environment of dynamic link library? Please give me it if you have.

    Regards,
    Kazu

  • Hello Todd,

    I saw the following descritpion. Then I try adding the compiler option with --dprel and --dsbt. So dynamic library accesses own global variable using DP. The program is running fine, but the address of the global variable is not correct but near. Do you know whether this approach for dynamic linking is correct?

    A Dynamic Library:
    Must use far DP or absolute addressing to access its own data as well as data that it imports from other modules
    http://processors.wiki.ti.com/index.php/C6000_Dynamic_Linking#Make_it_Dynamic

    Regards,
    Kazu

  • Hi Kazu,

    If you truly need dynamic linking, then you are on the right track in using the --dsbt option. I would recommend that you do not use the --dprel option.

    It sounds to me as if the bare-metal dynamic linking model may be the right approach for what you are doing. This means you will not be using the --linux compiler option.

    You can find a reference implementation of a bare-metal dynamic linker/loader here:

    https://gforge.ti.com/gf/project/ridl_oss/frs/

    An accompanying wiki page for dynamic linking on C6x can be found here:

    http://processors.wiki.ti.com/index.php/C6000_Dynamic_Linking

    On that wiki page, the section entitled "Lightweight (Bare Metal) Dynamic Linking Model" gives an introduction to the bare-metal dynamic linking model. Unfortunately, it has not been updated to include an adequate discussion of using the --dsbt model to manage the DP when calling imported functions. The previously mentioned "C6000 Embedded Application Binary Interface Application Report" contains a section entitled "Bare-Metal Dynamic Linking Model" which may also be useful to you.

    In the absence of an example of using --dsbt with bare-metal dynamic linking in the above wiki article, here is a description of a simple DSBT example:

    • If you need to call RTS functions from your DLL(s), then you will need to build a DSBT version of the RTS library that is linked with the main application and exports the functions that are needed by your DLL(s). For example, a C64+ DSBT RTS whould be compiled with an additional  "--dsbt" in addition to the default options that are used to build rts64plus_elf.lib
    • Let's assume that dl6x.6x is the main application that is capable of dynamic linking/loading. It is compiled with "-mv64+ --abi=eabi --dsbt" optoins and linked with the "--dynamic=exe" option and the DSBT version of the C64+ ELF RTS library built in the above step
    • Assume we want to build up a set of DLLs with the following dependencies:

                 driver.dll needs: dl6x.6x, a.dll, b.dll

                 a.dll         needs: dl6x.6x, c.dll, d.dll

                  b.dll        needs: dl6x.6x, a.dll, d.dll

                  c.dll        needs: dl6x.6x

                  d.dll        needs: dl6x.6x

    • We can then build the DLLs with the following commands:

                  cl6x -mv64+ --abi=eabi --dsbt c.c -z --dynamic=lib --dsbt_index=3 dl6x.6x -o c.dll

                  cl6x -mv64+ --abi=eabi --dsbt d.c -z --dynamic=lib --dsbt_index=4 dl6x.6x -o d.dll

                  cl6x -mv64+ --abi=eabi --dsbt a.c -z --dynamic=lib --dsbt_index=1 dl6x.6x c.dll d.dll -o a.dll

                  cl6x -mv64+ --abi=eabi --dsbt b.c -z --dynamic=lib --dsbt_index=2 dl6x.6x a.dll d.dll -o b.dll

                  cl6x -mv64+ --abi=eabi --dsbt drvier.c -z --dynamic=lib -e start --dsbt_index=5 dl6x.6x a.dll b.dll -o driver.dll

    • Now the dl6x.6x executable (main application) can be loaded and started running on the target to set up the runtime environment
    • At some point during execution, the main application will invoke a dynamic linker/loader function (the reference implementation of the dynamic loader supports a simplistic GUI to this end) that can load the driver.dll and all of the subordinate DLLs that it depends on
    • The main application can then branch to the entry point of the driver.dll: 'start'

    I hope that this will give you some guidance as to how to build your DLL(s) under the bare-metal dynamic linking model. Please let me know if the example is helpful and I will add it to the "C6000 Dynamic Linking" wiki that I cited earlier.

     

    Thanks and Regards,

    Todd Snider

    C6000 Code Generation Tools Team

    Texas Instruments Incorporated

  • Hello Todd,

    Thanks for kind reply. But I can't see to access global variable using DP without adding --dprel option. I'll continue to research it. Thank you anyway.

    Regards,
    Kazu