This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Forcing armlinker to include symbols from a library that are not referenced.

I'm working on a project where I need to pull out some test specific information into an "meta-data" object file which will get parsed during a later process. This test data consists of a number of structures which will be scattered though a number of different source files, depending on how the software is configured different source files will be built and thus different test data will be available.

There is a hierarchy to these structures, but the most important is the base structure. I've put all these base test structures into a specific section (via __attribute__((section("test_data"))) and have a linker map with a length marker which I can use to determine the number of tests within a specific build of the software, as follows:

test1.c

struct base_test __attribute__((section("test_data"))) test1 = {

     ...

}

test2.c

struct base_test __attribute__((section("test_data"))) test2 = {

     ...

}

test_builder.c

const unsigned int __attribute__((section("test_end_marker"))) test_end_marker = 0x5a5a5a5a;

const unsigned int __attribute__((section("test_length")))*test_length = &test_end_marker;

...

scattermap

LoadRegion 0x0

{

    TEST_HEADER 0x0

    {

        *.o (test_length)

    }

   TEST_APPS +0x0

    {

        *.o (test_data)

    }

   TEST_APPS_END +0x0

    {

        *.o (test_end_marker)

    }

...

The build process is as follows:

1) Compile application sources into a library (--partial)

2) Link the produced library into the application (as the test structures are not referenced they should be discarded)

3) Link the produced library with the compiled test_builder.o and force section "test_data" to be kept.

It's the last step I'm having an issue with. It would seem that --keep is what I wanted, but after doing some testing with --info unused it would seem that libraries are treated differently and only referenced symbols will be processed from the library where as for the .o files everything gets processed. If I reference the test structures in test_build.c then everything works as expected, but it means that I have to know which tests are built under the different configurations which is what I was trying to avoid in the first place. One workaround could be to skip building the library and just pass all the objects into armlink, I'll check that this works but it seems like a bit of a nasty hack.

Parents
  • I've hit this in the past.  The --keep option isn't working because they were not really there to start with.

    To understand why not you need to know a little about how the linker works.  At link time the linker will parse the passed in _objects_ to build up a list of symbol declarations and references.  Then use the declarations to try to resolve the references.  If (and only if) there are unsatisfied references after this step will then look at libraries. 

    As libraries are only pulled in to satisfy unresolved references, --keep doesn't work.  As far as the linker is concerned it was never part of the build for it to be kept.

    This is a simplified description, but it gives you the idea.

    There are a couple of ways to work around this.  One is to put in dummy references.  This is not particularly elegant, and you have to be careful that the tools doesn't optimize the dummy references away,  The other approach is to tell the linker to treat part of the library as an object...

    If you had a library (mylib.a), containing three objects (myObj1.o, myObj2.o and myObj3.o) you could do the following:

      armlink startup.o main.o mylib.a(myObj1.o) mylib.a ....

    This tells the linker to treat myObj1.o from mylib.a as if it were a regular object.  At this point you can use --keep.  The remaining objects in mylib.a will only be pulled in if required to satisfy references.

Reply
  • I've hit this in the past.  The --keep option isn't working because they were not really there to start with.

    To understand why not you need to know a little about how the linker works.  At link time the linker will parse the passed in _objects_ to build up a list of symbol declarations and references.  Then use the declarations to try to resolve the references.  If (and only if) there are unsatisfied references after this step will then look at libraries. 

    As libraries are only pulled in to satisfy unresolved references, --keep doesn't work.  As far as the linker is concerned it was never part of the build for it to be kept.

    This is a simplified description, but it gives you the idea.

    There are a couple of ways to work around this.  One is to put in dummy references.  This is not particularly elegant, and you have to be careful that the tools doesn't optimize the dummy references away,  The other approach is to tell the linker to treat part of the library as an object...

    If you had a library (mylib.a), containing three objects (myObj1.o, myObj2.o and myObj3.o) you could do the following:

      armlink startup.o main.o mylib.a(myObj1.o) mylib.a ....

    This tells the linker to treat myObj1.o from mylib.a as if it were a regular object.  At this point you can use --keep.  The remaining objects in mylib.a will only be pulled in if required to satisfy references.

Children