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.

CCS/F28M36H33B2: Mapping .lib to different locations using linker command

Part Number: F28M36H33B2

Tool/software: Code Composer Studio

Hello,

NOTE: Please ignore part number in the post, this issue was seen on a product yet to be PG'ed.

During validation of security module we had a requirement to map the same .library to two different memory zones in SRAM. Used something like below. lib_Z1 gets mapped as expected, but for lib_z2 only partial mapping is done. As the sub-functions are common among both libraries, linker optimizes it.

how can we force the linker to map both libraries fully in both memory zones. this is needed because once security is enabled each zone will need its full copy of library.

 flashapi1 : >> RAMGS8 | RAMGS9, PAGE = 1
    { lib_Z1.lib(.text)
 lib__Z1.lib(.econst)
lib__Z1.lib(.cinit)
 lib__Z1.lib(.ebss)

}

 flashapi2 : >> RAMGS4 | RAMGS5, PAGE = 1
    {
 lib__Z2.lib(.text)
lib__Z2.lib(.econst)
 lib__Z2.lib(.cinit)
 lib__Z2.lib(.ebss)
    }

Best Regards,

-PrashJ

  • If I understand correctly, both libraries lib_Z1 and lib_Z2 contain some of the same functions and data.  And you want the linker to include these functions and data from both libraries.  The linker does not support that.  I'll explain with a contrived example.  First, I'll discuss how it works now.  Then, I'll discuss how the linker might be changed, and the problems that result.

    How it works now ... Suppose lib_Z1 and lib_Z2 both define a function named lib_fxn.  The main application calls lib_fxn.  This creates an open reference to lib_fxn.  The linker sees lib_Z1 first.  Because of the open reference to lib_fxn, and lib_Z1 has it, the file which defines lib_fxn is brought in.  This closes the reference to lib_fxn.  When lib_Z2 is seen, there is no open reference to lib_fxn, so the file in it which defines lib_fxn is not brought in.  

    How the linker might be changed ... Suppose there is some way to force the linker to bring in lib_fxn from both lib_Z1 and lib_Z2.  Now you have one symbol with two addresses.  One in RAMGS8 and another in RAMGS4.  Consider the call to lib_fxn in the main application.  What address does it use when calling lib_fxn?  How would that work?

    Thanks and regards,

    -George

  • Hi George,

    I understand why and how the linker is removing duplicate functions. also agree that totally makes sense. But what we have here is a sort of a unique case, think its a valid one and user should to be able to tell the linker with a special command to allow duplication.

    The valid reason is Device security, which when enabled on the device, code executing from RAMGS8 will not be able to access any code residing in RAMGS4 and vice versa. Right now what I see is when executing from GS8 and call a function which apparently the linker has put in GS4, code just hangs.

    one workaround, a tedious one, is to maintain two copies of source code for lib1 and lib2, making sure to have different names for the functions/variables (basically all symbols) although they would be doing the same thing.

    Let me know your thoughts.

    Thanks and Best Regards,

    -PrashJ

  • kjk said:
    But what we have here is a sort of a unique case, think its a valid one and user should to be able to tell the linker with a special command to allow duplication.

    You can.  But not with C, as it is typically used.  I first considered recommending a solution that uses C++ namespaces.  But as I thought it through, I realized you can do a similar thing in C.

    One caveat … I have never used this method.  I am certain the main idea is sound.  But the details may need some tweaks.

    Here is how you can, in effect, implement one function named lib_fxn at two different addresses.

    First, the library implementation source file has something similar to …

    #ifdef BUILDING_LIB_Z1
    int lib_z1_lib_fxn(int arg1, int arg2)
    #elif BUILDING_LIB_Z2
    int lib_z2_lib_fxn(int arg1, int arg2)
    #else
    #error Must define preprocessor symbol BUILDING_LIB_Z1 or BUILDING_LIB_Z2
    #endif
    {
        // code here
    }

    When building this source file for lib_z1, use the command line option –DBUILDING_LIB_Z1.  When building this source file for lib_z2, use –DBUILDING_LIB_Z2.

    In either your main application code, or in yet another library, you need an interface to lib_fxn.  It looks like …

    int interface_lib_fxn(int arg1, int arg2)
    {
        if (using_lib_z1)  /* I presume such a runtime test is possible */
            lib_z1_lib_fxn(arg1, arg2);
        else
            lib_z2_lib_fxn(arg1, arg2);
    }

    In your main application code, where you presently write lib_fxn, write instead …

    interface_lib_fxn(arg1, arg2);

    I prefer to make this interface explicit. Of course, if you prefer, you could name the function interface_lib_fxn just lib_fxn, and then calls in your main application code do not need to change.

    With this method, users of your library have a consistent interface, while the tools see two different functions in different locations.

    Thanks and regards,

    -George

  • Hi George,

    Correct, I already have #ifdef for interfacing functions in the library. As I mentioned in the earlier post that

    " one workaround, a tedious one, is to maintain two copies of source code for lib1 and lib2, making sure to have different names for the functions/variables (basically all symbols) although they would be doing the same thing."

    But the problem is slightly more involved as what the linker is optimizing all the sub function that lib_z1_lib_fxn and lib_z2_lib_fxn are calling. So in effect I have to re-declare with _z1/_z2 suffix for every symbol (functions and variables, structures, enums etc).


    is this the only way out?

    Thanks and Best Regards,

    -Prashanth JayaPrakash

  • The prime rule you must follow: Every global symbol (whether for a function or for data) must correspond to only one address.  This rule must be followed for all global symbols, whether they are defined in the main application code, or in a library.  This rule comes from the C language.  All of the tools infrastructure depends on it.

    Using the techniques we have discussed only makes it easier to keep things organized, and avoid some of the repetition.  C++ namespaces is another solution along these lines.  

    Thanks and regards,

    -George

  • Thanks George, will have to resort to suffixing symbols. But I still think we should have a switch in the linker, a special command to duplicate functions intentionally. ( note that while executing from one secure, function calls cannot go to the same function duplicated in the other zone). This would actually mean the linker should become aware of secure memory zones, a way of indicating it user SECTIONS{}. This would ease out development, specially with Security having become an integral part of MCUs.

    We can close this post. Thanks for all the time. Happy New Year.

    Thanks and Best Regards,

    -Prashanth JayaPrakash