Como faço para listar os símbolos em um arquivo .so
-
09-06-2019 - |
Pergunta
Como faço para listar os símbolos que estão sendo exportados de um arquivo .so?Se possível, também gostaria de saber a origem deles (por ex.se eles forem extraídos de uma biblioteca estática).
Estou usando o gcc 4.0.2, se isso faz diferença.
Solução
A ferramenta padrão para listar símbolos é nm
, você pode usá-lo simplesmente assim:
nm -g yourLib.so
Se você quiser ver os símbolos de uma biblioteca C++, adicione a opção "-C" que desmonta os símbolos (é muito mais legível desmontado).
nm -gC yourLib.so
Se o seu arquivo .so estiver no formato elf, você terá duas opções:
Qualquer objdump
(-C
também é útil para desmontar C++):
$ objdump -TC libz.so
libz.so: file format elf64-x86-64
DYNAMIC SYMBOL TABLE:
0000000000002010 l d .init 0000000000000000 .init
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 free
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 __errno_location
0000000000000000 w D *UND* 0000000000000000 _ITM_deregisterTMCloneTable
Ou use readelf
:
$ readelf -Ws libz.so
Symbol table '.dynsym' contains 112 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000002010 0 SECTION LOCAL DEFAULT 10
2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND free@GLIBC_2.2.5 (14)
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __errno_location@GLIBC_2.2.5 (14)
4: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable
Outras dicas
Se seu .so
arquivo está no formato elf, você pode usar o programa readelf para extrair informações de símbolo do binário.Este comando lhe dará a tabela de símbolos:
readelf -Ws /usr/lib/libexample.so
Você só deve extrair aqueles que estão definidos neste .so
arquivo, não nas bibliotecas referenciadas por ele.A sétima coluna deve conter um número neste caso.Você pode extraí-lo usando um regex simples:
readelf -Ws /usr/lib/libstdc++.so.6 | grep '^\([[:space:]]\+[^[:space:]]\+\)\{6\}[[:space:]]\+[[:digit:]]\+'
ou, como proposto por Caspin,:
readelf -Ws /usr/lib/libstdc++.so.6 | awk '{print $8}';
objdump -TC /usr/lib/libexample.so
Para bibliotecas compartilhadas libNAME.so a opção -D foi necessária para ver os símbolos no meu Linux
nm -D libNAME.so
e para biblioteca estática conforme relatado por outros
nm -g libNAME.a
Fiquei me perguntando por que -fvisibilidade=oculto e #pragma Visibilidade do CCG não parecia ter qualquer influência, pois todos os símbolos estavam sempre visíveis com nm - até que encontrei esse post que me indicou leia-se e objdump, o que me fez perceber que parece realmente haver dois tabelas de símbolos:
- Aquele com o qual você pode listar nm
- Aquele com o qual você pode listar leia-se e objdump
Acho que o primeiro contém símbolos de depuração que podem ser removidos com faixa ou a opção -s que você pode fornecer ao vinculador ou ao instalar comando.E mesmo que nm não liste mais nada, seus símbolos exportados ainda serão exportados porque estão na "tabela de símbolos dinâmicos" ELF, que é a última.
Tente adicionar -l aos sinalizadores nm para obter a origem de cada símbolo.Se a biblioteca for compilada com informações de depuração (gcc -g), este deverá ser o arquivo fonte e o número da linha.Como Konrad disse, o arquivo de objeto/biblioteca estática provavelmente é desconhecido neste momento.
Para Android .so
arquivos, o conjunto de ferramentas do NDK vem com as ferramentas necessárias mencionadas nas outras respostas: readelf
, objdump
e nm
.
Para C++ .so
arquivos, o melhor nm
comando é nm --demangle --dynamic --defined-only --extern-only <my.so>
# nm --demangle --dynamic --defined-only --extern-only /usr/lib64/libqpid-proton-cpp.so | grep work | grep add
0000000000049500 T proton::work_queue::add(proton::internal::v03::work)
0000000000049580 T proton::work_queue::add(proton::void_function0&)
000000000002e7b0 W proton::work_queue::impl::add_void(proton::internal::v03::work)
000000000002b1f0 T proton::container::impl::add_work_queue()
000000000002dc50 T proton::container::impl::container_work_queue::add(proton::internal::v03::work)
000000000002db60 T proton::container::impl::connection_work_queue::add(proton::internal::v03::work)
Você pode usar o nm -g
ferramenta do conjunto de ferramentas binutils.No entanto, sua fonte nem sempre está prontamente disponível.e nem tenho certeza de que essas informações sempre possam ser recuperadas.Talvez objcopy
revela mais informações.
/EDITAR:O nome da ferramenta é claro nm
.A bandeira -g
é usado para mostrar apenas símbolos exportados.
nm -g lista a variável externa, que não é necessariamente um símbolo exportado.Qualquer variável de escopo de arquivo não estático (em C) são todas variáveis externas.
nm -D listará o símbolo na tabela dinâmica, cujo endereço você pode encontrar por dlsym.
nm --versão
GNUnm 2.17.50.0.6-12.el5 20061020
Se você apenas quer saber se existem símbolos presente você pode usar
objdump -h /path/to/object
ou para listar as informações de depuração
objdump -g /path/to/object