Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to list all externally-undefined symbols of a static library on Linux?

I have a static library libfoo.a, which is just a compression of multiple .o files. I am looking for a way to list all symbols that

  • appear in the static library as UND
  • have no definition in this static library

So that I can find out all external symbol dependencies of this library.

like image 416
lz96 Avatar asked Jul 19 '18 16:07

lz96


People also ask

What commands can be used to list the symbols stored in a static library?

To list the symbols stored in the static library we can use the command “nm”, which lists each symbol's symbol value, symbol type, and symbol name from object files.

Which of the following command can list the symbols defined in a library?

The nm(1) command can report the list of symbols in a given library. It works on both static and shared libraries. For a given library nm(1) can list the symbol names defined, each symbol's value, and the symbol's type.

Do static libraries have symbols?

A .o file inside a library might contain symbols (functions, variables etc.) that are not used by your program. At link time, a static library can have unresolved symbols in it, as long as you don't need the unresolved symbols, and you don't need any symbol that is in a .o file that contains an unresolved symbol.


2 Answers

You can use this method:

ld -r -o deleteme.o --whole-archive libfoo.a
nm -C --undefined-only deleteme.o       # `-C` if you might have C++ archive members
rm deleteme.o

Demo:

one.c

extern void two(void);

void one()
{
    two();
}

two.c

extern void three(void);

void two()
{
    three();
}

Make a static library libonetwo.a:

$ gcc -Wall -c one.c two.c
$ ar rcs libonetwo.a one.o two.o

nm parses the static library as if it were just a commandline list of its members:

$ nm --undefined-only libonetwo.a 

one.o:
                 U _GLOBAL_OFFSET_TABLE_
                 U two

two.o:
                 U _GLOBAL_OFFSET_TABLE_
                 U three

So incrementally link them all into a temporary object file:

$ ld -r -o deleteme.o --whole-archive libonetwo.a

Then see the residual undefined symbols of that object file and delete it:

$ nm --undefined-only deleteme.o && rm deleteme.o 
                 U _GLOBAL_OFFSET_TABLE_
                 U three
like image 95
Mike Kinghan Avatar answered Oct 04 '22 02:10

Mike Kinghan


There is no single command (that I know of) that will do that.

But it's trivial to construct two commands, one for all undefined, and one for all defined symbols, and then show only the difference between them.

comm -13 \
 <(nm libfoobar.a | egrep ' [BDTW] ' | sed -e 's/.* [BDTW] //' | sort -u) \
 <(nm libfoobar.a | grep ' U ' | sed -e 's/.* U //' | sort -u)

First nm prints only defined symbols. Second nm prints only undefined symbols (which may be defined in another file in the same library).

The comm -13 prints only lines from second nm which do not occur in the output from the first nm.

like image 23
Employed Russian Avatar answered Oct 04 '22 02:10

Employed Russian