Linux - nm命令

news/2024/12/28 12:41:36/
这里的nm命令指的是GNU Linux版本,Ubuntu20.04,是name的缩写。
nm是一个命令行工具,用来列出object文件、库文件或可执行文件中的符号列表(name list, the symbol table of nlist structures)。
nm命令的输出结果为三列,symbol virtual address,symbol type和symbol name,即符号虚拟地址,类型和名字。
显示内容
举例:
testnm.c
#include <stdio.h>
int value;
static void func()
{
  printf("value is %d.\n", value);
}
int main()
{
  value = 1;
  func();
  return 0;
}
$ gcc -c testnm.c
$ nm  testnm.o
0000000000000000 t func
                 U _GLOBAL_OFFSET_TABLE_
0000000000000024 T main
                 U printf
0000000000000004 C value
用一个字符表示类型,如果是小写字符,则是本地符号(local),如果是大写,则是外部符号(external)。类型符号表示的意义如下。
类型字符
含义
Decription
A
全局不可变符号,比如原文件名。
Global absolute symbol.
a
本地不可变符号
Local absolute symbol.
B
全局bss段符号(未初始化的全局或static变量)
Global bss symbol.
b
本地bss段符号
Local bss symbol.
D
全局变量(已初始化的全局或static变量)符号
Global data symbol.
d
本地变量符号
Local data symbol.
T
全局符号,比如全局函数名
Global text symbol.
t
本地符号,比如文件内static函数名
Local text symbol.
U
未定义符号
Undefined symbol.
。。。。。。
用途
这个命令看起来很酷,但只有合理的使用这个命令,这个命令才有存在的意义。那什么时候使用呢?
假设你有一个由许多不同object文件组成的可执行文件。现在假设在编译代码的时候,链接器给出了关于一个未解决的符号'temp'的错误。现在,如果代码规模太大,包括很多头文件,要找到代码中的符号'temp'的位置将成为一场噩梦。在这里,这个工具就起到了拯救作用。通过一些选项的配置,这个工具可以找到该符号所在的文件。
语法:
$ nm [options(s)]  [file(s)]
列出参数[file(s)]的文件中的符号,可以给出多个文件,如果没有指定文件名,则默认文件是a.out。
各个选项的使用:(同一个选项存在短格式和长格式形式则一并列出)
1,列出object文件里的全局(extern)符号,包括函数和变量:
nm -g <path/to/file.o>
nm --extern-only <path/to/file.o>
举例:
$ nm -g testnm.o
                 U _GLOBAL_OFFSET_TABLE_
0000000000000024 T main
                 U printf
0000000000000004 C value
$ nm  testnm.o
0000000000000000 t func
                 U _GLOBAL_OFFSET_TABLE_
0000000000000024 T main
                 U printf
0000000000000004 C value
2,列出obj文件内的未定义符号:
nm -u <path/to/file.o>
nm --undefined-only <path/to/file.o>
举例:
$ nm -u testnm.o
                 U _GLOBAL_OFFSET_TABLE_
                 U printf
3,列出obj文件中所有的符号,包括debug所使用的符号,否则默认情况下不显示调试用的符号。
nm -a <path/to/file.o>
nm --debug-syms <path/to/file.o>
举例:
$ nm -a testnm.o
0000000000000000 b .bss
0000000000000000 n .comment
0000000000000000 d .data
0000000000000000 r .eh_frame
0000000000000000 t func
                 U _GLOBAL_OFFSET_TABLE_
0000000000000024 T main
0000000000000000 r .note.gnu.property
0000000000000000 n .note.GNU-stack
                 U printf
0000000000000000 r .rodata
0000000000000000 a testnm.c
0000000000000000 t .text
0000000000000004 C value
4,列出符号表示,前面显示obj文件名。
$ nm -A <path/to/file.o>
$ nm --print-file-name <path/to/file.o>
这个选项在显示多个多个obj文件的符号时会需要。
举例:
$ nm -A testnm.o
testnm.o:0000000000000000 t func
testnm.o:                 U _GLOBAL_OFFSET_TABLE_
testnm.o:0000000000000024 T main
testnm.o:                 U printf
testnm.o:0000000000000004 C value
5,恢复C++符号的名称改变,使其具有更好可读性:
nm -C <path/to/file.o>
nm --demangle <path/to/file.o>
nm --demangle[=STYLE] <path/to/file.o>
将编译器级的low-level的符号名,转换成用户可理解的名字类型。可以指定obj文件所使用的名称改编风格,有auto(默认), gnu, lucid, arm, hp, edg, gnu-v3, java 和gnat。
注意,这个参数对C语言编译出来的obj文件是无效的,上面的C语言的例子,使用-C选项,输出内容并没有变化。
举例:
testnm.cpp
#include <iostream>
static int value;
static void func(int a, int b)
{
if(a > b){
   std::cout<<"the value is " << value << std::endl;
}
}
int main()
{
  value = 3;
  func(2, 1);
  return 0;
}
$ g++ -c testnm.cpp
$ nm testnm.o
                 U __cxa_atexit
                 U __dso_handle
                 U _GLOBAL_OFFSET_TABLE_
00000000000000cd t _GLOBAL__sub_I_main
0000000000000058 T main
0000000000000080 t _Z41__static_initialization_and_destruction_0ii
0000000000000000 t _ZL4funcii
0000000000000004 b _ZL5value
                 U _ZNSolsEi
                 U _ZNSolsEPFRSoS_E
                 U _ZNSt8ios_base4InitC1Ev
                 U _ZNSt8ios_base4InitD1Ev
                 U _ZSt4cout
                 U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
0000000000000000 r _ZStL19piecewise_construct
0000000000000000 b _ZStL8__ioinit
                 U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
$ nm --demangle testnm.o
                 U __cxa_atexit
                 U __dso_handle
                 U _GLOBAL_OFFSET_TABLE_
00000000000000cd t _GLOBAL__sub_I_main
0000000000000058 T main
0000000000000080 t __static_initialization_and_destruction_0(int, int)
0000000000000000 t func(int, int)
0000000000000004 b value
                 U std::ostream::operator<<(int)
                 U std::ostream::operator<<(std::ostream& (*)(std::ostream&))
                 U std::ios_base::Init::Init()
                 U std::ios_base::Init::~Init()
                 U std::cout
                 U std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)
0000000000000000 r std::piecewise_construct
0000000000000000 b std::__ioinit
                 U std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)
可以看到上面的例子,除了前面的下划线去掉了,C++的函数名字也变得可读性更好。不同的编译器使用不同的名称改变风格(mangling styles),可以使用上面提到的改变风格的选项来选择一种适合当前编译器。
6,显示动态链接的符号。
nm -D <path/to/file.o>
nm --dynamic <path/to/file.o>
举例:
$ gcc -o testnm testnm.c
$ ldd testnm
    linux-vdso.so.1 (0x00007ffd7dff0000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff2c819a000)
    /lib64/ld-linux-x86-64.so.2 (0x00007ff2c83a3000)
$ nm -D testnm
                 w __cxa_finalize
                 w __gmon_start__
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 U __libc_start_main
                 U printf
$ g++ -o testnmplus testnm.cpp
$ ldd testnmplus
    linux-vdso.so.1 (0x00007ffd82bd0000)
    libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007ff7716a4000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff7714b2000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007ff771363000)
    /lib64/ld-linux-x86-64.so.2 (0x00007ff77189d000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007ff771348000)
$ nm -D testnmplus
                 U __cxa_atexit
                 w __cxa_finalize
                 w __gmon_start__
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 U __libc_start_main
                 U _ZNSolsEi
                 U _ZNSolsEPFRSoS_E
                 U _ZNSt8ios_base4InitC1Ev
                 U _ZNSt8ios_base4InitD1Ev
0000000000004040 B _ZSt4cout
                 U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
                 U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
这里编出来的obj文件,没有动态链接符号,而编出的可执行文件里才有。
这些动态链接的符号,只有在运行时(run time)才会解析。
7,更改输出内容的格式。
nm -f <FORMAT> <path/to/file.o>
nm --format=FORMAT <path/to/file.o>
可选的输出格式为bsd,sysv或posix,默认是bsd模式。
举例:
$ nm -f posix testnm.o
func t 0 24
_GLOBAL_OFFSET_TABLE_ U         
main T 24 23
printf U         
value C 4 4
$ nm --format posix testnm.o
func t 0 24
_GLOBAL_OFFSET_TABLE_ U         
main T 24 23
printf U         
value C 4 4
$ nm --format=posix testnm.o
func t 0 24
_GLOBAL_OFFSET_TABLE_ U         
main T 24 23
printf U         
value C 4 4
$ nm --format=sysv testnm.o
Symbols from testnm.o:
Name                  Value           Class        Type         Size             Line  Section
func                |0000000000000000|   t  |              FUNC|0000000000000024|     |.text
_GLOBAL_OFFSET_TABLE_|                |   U  |            NOTYPE|                |     |*UND*
main                |0000000000000024|   T  |              FUNC|0000000000000023|     |.text
printf              |                |   U  |            NOTYPE|                |     |*UND*
value               |0000000000000004|   C  |            OBJECT|0000000000000004|     |*COM*
8,使用排序选项。
默认情况下,符号列表根据字母顺序进行排序,但你可以选择根据地址进行排序。
nm -n <path/to/file.o>
nm --numeric-sort <path/to/file.o>
举例:
$ nm  -n  testnm.o
                 U _GLOBAL_OFFSET_TABLE_
                 U printf
0000000000000000 t func
0000000000000004 C value
0000000000000024 T main
默认使用的是字母排序,也可以不使用排序功能。
nm -p <path/to/file.o>
nm --no-sort <path/to/file.o>
举例:
$ nm  -p  testnm.o
0000000000000000 t func
0000000000000004 C value
                 U _GLOBAL_OFFSET_TABLE_
                 U printf
0000000000000024 T main
$ nm  testnm.o
0000000000000000 t func
                 U _GLOBAL_OFFSET_TABLE_
0000000000000024 T main
                 U printf
0000000000000004 C value
还可以按照符号占用空间的大小排序。
nm --size-sort <path/to/file.o>
如果想使用相反的顺序,使用-r选项。
nm -r <path/to/file.o>
nm --reverse-sort <path/to/file.o>
举例:
$ nm -n testnm.o
                 U _GLOBAL_OFFSET_TABLE_
                 U printf
0000000000000000 t func
0000000000000004 C value
0000000000000024 T main
$ nm -rn testnm.o
0000000000000024 T main
0000000000000004 C value
0000000000000000 t func
                 U printf
                 U _GLOBAL_OFFSET_TABLE_
9,只显示未定义的符号。
nm -u <path/to/file.o>
nm --undefined-only <path/to/file.o>
举例:
$ nm -u testnm.o
                 U _GLOBAL_OFFSET_TABLE_
                 U printf
如果在一个可执行文件中发现未定义的符号,可能是这个符号存在于动态链接库中(shared libraries)。
10,只显示已定义的符号。
nm --defined-only <path/to/file.o>
举例:
$ nm --defined-only testnm.o
0000000000000000 t func
0000000000000024 T main
0000000000000004 C value
11,显示符号占用空间的大小
nm -S <path/to/file.o>
nm --print-size <path/to/file.o>
举例:
$ nm  testnm.o
0000000000000000 t func
                 U _GLOBAL_OFFSET_TABLE_
0000000000000024 T main
                 U printf
0000000000000004 C value
$ nm -S testnm.o
0000000000000000 0000000000000024 t func
                 U _GLOBAL_OFFSET_TABLE_
0000000000000024 0000000000000023 T main
                 U printf
0000000000000004 0000000000000004 C value
12,使用文件来指定选项。
nm命令还有一个功能,可以从一个文件里读取命令行的选项。
举例:
$ cat file
-S testnm.o
$ nm @file
0000000000000000 0000000000000024 t func
                 U _GLOBAL_OFFSET_TABLE_
0000000000000024 0000000000000023 T main
                 U printf
0000000000000004 0000000000000004 C value
$ nm -S testnm.o
0000000000000000 0000000000000024 t func
                 U _GLOBAL_OFFSET_TABLE_
0000000000000024 0000000000000023 T main
                 U printf
0000000000000004 0000000000000004 C value
13,使用案例
在当前文件夹的obj文件中,找寻包含func字符串的符号名称。
$ nm  -A ./*.o | grep func
./hello2.o:0000000000000000 T func_1
./hello3.o:0000000000000000 T func_2
./hello4.o:0000000000000000 T func_3
./main.o:                   U func
./reloc.o:                  U func
./reloc.o:0000000000000000  T func1
./test1.o:0000000000000000  T func
./test.o:                   U func
上面介绍的各个功能选项可以组合使用来满足自己的需求。比如:
$ nm -g -S testnm.o
$ nm -gS testnm.o
                 U _GLOBAL_OFFSET_TABLE_
0000000000000024 0000000000000023 T main
                 U printf
0000000000000004 0000000000000004 C value
另外,输出内容里的符号地址,其基数(radix)是可变的,默认是16进制(hexadecimal),使用的参数是:  
-t, --radix=RADIX      // Use RADIX for printing symbol values
备注1:
可以在linux源码中查询到符号列表条目的类型定义nlist结构体:
struct nlist {
union {
     char *n_name;
     struct nlist *n_next;
     long n_strx;
} n_un;
unsigned char n_type;
char n_other;
short n_desc;
unsigned long n_value;
};
备注2:
nm命令的简单help信息:
$ nm --help
Usage: nm [option(s)] [file(s)]
List symbols in [file(s)] (a.out by default).
The options are:
  -a, --debug-syms       Display debugger-only symbols
  -A, --print-file-name  Print name of the input file before every symbol
  -B                     Same as --format=bsd
  -C, --demangle[=STYLE] Decode low-level symbol names into user-level names
                          The STYLE, if specified, can be `auto' (the default),
                          `gnu', `lucid', `arm', `hp', `edg', `gnu-v3', `java'
                          or `gnat'
      --no-demangle      Do not demangle low-level symbol names
      --recurse-limit    Enable a demangling recursion limit.  This is the default.
      --no-recurse-limit Disable a demangling recursion limit.
  -D, --dynamic          Display dynamic symbols instead of normal symbols
      --defined-only     Display only defined symbols
  -e                     (ignored)
  -f, --format=FORMAT    Use the output format FORMAT.  FORMAT can be `bsd',
                           `sysv' or `posix'.  The default is `bsd'
  -g, --extern-only      Display only external symbols
  -l, --line-numbers     Use debugging information to find a filename and
                           line number for each symbol
  -n, --numeric-sort     Sort symbols numerically by address
  -o                     Same as -A
  -p, --no-sort          Do not sort the symbols
  -P, --portability      Same as --format=posix
  -r, --reverse-sort     Reverse the sense of the sort
      --plugin NAME      Load the specified plugin
  -S, --print-size       Print size of defined symbols
  -s, --print-armap      Include index for symbols from archive members
      --size-sort        Sort symbols by size
      --special-syms     Include special symbols in the output
      --synthetic        Display synthetic symbols as well
  -t, --radix=RADIX      Use RADIX for printing symbol values
      --target=BFDNAME   Specify the target object format as BFDNAME
  -u, --undefined-only   Display only undefined symbols
      --with-symbol-versions  Display version strings after symbol names
  -X 32_64               (ignored)
  @FILE                  Read options from FILE
  -h, --help             Display this information
  -V, --version          Display this program's version number
nm: supported targets: elf64-x86-64 elf32-i386 elf32-iamcu elf32-x86-64 pei-i386 pei-x86-64 elf64-l1om elf64-k1om elf64-little elf64-big elf32-little elf32-big pe-x86-64 pe-bigobj-x86-64 pe-i386 srec symbolsrec verilog tekhex binary ihex plugin
Report bugs to <http://www.sourceware.org/bugzilla/>.
备注3:
Ubuntu中的manual中关于符号意义的解释:
       •   The symbol type.  At least the following types are used; others are, as well, depending on the object file format.  If lowercase, the symbol is usually local; if uppercase, the symbol is
           global (external).  There are however a few lowercase symbols that are shown for special global symbols ("u", "v" and "w").
           "A" The symbol's value is absolute, and will not be changed by further linking.
           "B"
           "b" The symbol is in the BSS data section.  This section typically contains zero-initialized or uninitialized data, although the exact behavior is system dependent.
           "C" The symbol is common.  Common symbols are uninitialized data.  When linking, multiple common symbols may appear with the same name.  If the symbol is defined anywhere, the common
               symbols are treated as undefined references.
           "D"
           "d" The symbol is in the initialized data section.
           "G"
           "g" The symbol is in an initialized data section for small objects.  Some object file formats permit more efficient access to small data objects, such as a global int variable as opposed
               to a large global array.
           "i" For PE format files this indicates that the symbol is in a section specific to the implementation of DLLs.  For ELF format files this indicates that the symbol is an indirect
               function.  This is a GNU extension to the standard set of ELF symbol types.  It indicates a symbol which if referenced by a relocation does not evaluate to its address, but instead
               must be invoked at runtime.  The runtime execution will then return the value to be used in the relocation.
           "I" The symbol is an indirect reference to another symbol.
           "N" The symbol is a debugging symbol.
           "n" The symbol is in the read-only data section.
           "p" The symbol is in a stack unwind section.
           "R"
           "r" The symbol is in a read only data section.
           "S"
           "s" The symbol is in an uninitialized or zero-initialized data section for small objects.
           "T"
           "t" The symbol is in the text (code) section.
           "U" The symbol is undefined.
           "u" The symbol is a unique global symbol.  This is a GNU extension to the standard set of ELF symbol bindings.  For such a symbol the dynamic linker will make sure that in the entire
               process there is just one symbol with this name and type in use.
           "V"
           "v" The symbol is a weak object.  When a weak defined symbol is linked with a normal defined symbol, the normal defined symbol is used with no error.  When a weak undefined symbol is
               linked and the symbol is not defined, the value of the weak symbol becomes zero with no error.  On some systems, uppercase indicates that a default value has been specified.
           "W"
           "w" The symbol is a weak symbol that has not been specifically tagged as a weak object symbol.  When a weak defined symbol is linked with a normal defined symbol, the normal defined
               symbol is used with no error.  When a weak undefined symbol is linked and the symbol is not defined, the value of the symbol is determined in a system-specific manner without error.
               On some systems, uppercase indicates that a default value has been specified.
           "-" The symbol is a stabs symbol in an a.out object file.  In this case, the next values printed are the stabs other field, the stabs desc field, and the stab type.  Stabs symbols are
               used to hold debugging information.
           "?" The symbol type is unknown, or object file format specific.
备注4:
在Ubuntu里,使用PC平台的nm命令,也可以解析cross toolchain编译的程序。
$ cat testuart.c
include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
int main()
{
int fd;
fd = open("/dev/ttyS3", O_RDWR | O_NOCTTY | O_CLOEXEC);
printf("fd is %d.\n", fd);
return 0;
}
使用工具链进行编译:
X86:
$ gcc -o testuartgcc testuart.c
ARM:
$ /opt/poky/SDK220804V0/sysroots/x86_64-pokyXXXsdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-g++ -o testuartarm testuart.c --sysroot=/opt/poky/SDK220804V0/sysroots/cortexa7t2hf-neon-poky-linux-gnueabi/ -march=armv7ve -marm -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a7
MIPS:
$ ~/x2000br/buildroot/buildroot/output/host/usr/bin/mipsel-linux-gcc -o testuartmips testuart.c
得到可执行文件:
$ file testuartgcc
testuartgcc: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=7502376cbab0f5ea2a13197d89a126dffdc32876, for GNU/Linux 3.2.0, not stripped
$ file testuartarm
testuartarm: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, BuildID[sha1]=aeea22788a340f6862e60c02021fc5718dbb1d12, for GNU/Linux 3.2.0, with debug_info, not stripped
$ file testuartmips
testuartmips: ELF 32-bit LSB shared object, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-mipsn8.so.1, for GNU/Linux 5.4.0, not stripped
$ which nm
/usr/bin/nm
$ ll /usr/bin/nm
lrwxrwxrwx 1 root root 19 10月 20  2021 /usr/bin/nm -> x86_64-linux-gnu-nm*
使用X86平台, mips toolchain和arm toolchain的nm命令分别读取x86程序的符号列表:
ARM不能读,其他两个结果一样。
$ ~/x2000br/buildroot/buildroot/output/host/usr/bin/mipsel-linux-nm -g -n testuartgcc
                 w __cxa_finalize@@GLIBC_2.2.5
                 w __gmon_start__
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 U __libc_start_main@@GLIBC_2.2.5
                 U open@@GLIBC_2.2.5
                 U printf@@GLIBC_2.2.5
0000000000001080 T _start
0000000000001169 T main
00000000000011b0 T __libc_csu_init
0000000000001220 T __libc_csu_fini
0000000000001228 T _fini
0000000000002000 R _IO_stdin_used
0000000000004000 D __data_start
0000000000004000 W data_start
0000000000004008 D __dso_handle
0000000000004010 B __bss_start
0000000000004010 D _edata
0000000000004010 D __TMC_END__
0000000000004018 B _end
$ nm -g -n testuartgcc
                 w __cxa_finalize@@GLIBC_2.2.5
                 w __gmon_start__
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 U __libc_start_main@@GLIBC_2.2.5
                 U open@@GLIBC_2.2.5
                 U printf@@GLIBC_2.2.5
0000000000001080 T _start
0000000000001169 T main
00000000000011b0 T __libc_csu_init
0000000000001220 T __libc_csu_fini
0000000000001228 T _fini
0000000000002000 R _IO_stdin_used
0000000000004000 D __data_start
0000000000004000 W data_start
0000000000004008 D __dso_handle
0000000000004010 B __bss_start
0000000000004010 D _edata
0000000000004010 D __TMC_END__
0000000000004018 B _end
$ /opt/poky/SDK220804V0/sysroots/x86_64-pokyXXXsdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-nm -g -n testuartgcc
/opt/poky/SDK220804V0/sysroots/x86_64-pokyXXXsdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-nm: testuartgcc: file format not recognized
使用X86平台, mips toolchain和arm toolchain的nm命令分别读取mips程序的符号列表:
都可以读,内容一样。
$ nm -g -n testuartmips
         w __cxa_finalize@GLIBC_2.2
         w __gmon_start__
         w _ITM_deregisterTMCloneTable
         w _ITM_registerTMCloneTable
         U __libc_start_main@GLIBC_2.34
         U open@GLIBC_2.0
         U printf@GLIBC_2.0
         U __stack_chk_fail@GLIBC_2.4
         U __stack_chk_guard@GLIBC_2.4
000005d0 T _init
00000660 T _ftext
00000660 T __start
00000840 T main
000009b0 T _fini
00000a00 R _IO_stdin_used
00011000 D __data_start
00011000 W data_start
00011000 D _fdata
00011010 D __RLD_MAP
00011074 B __bss_start
00011074 G _edata
00011074 B _fbss
00011090 B _end
$ ~/x2000br/buildroot/buildroot/output/host/usr/bin/mipsel-linux-nm -g -n testuartmips
         w __cxa_finalize@GLIBC_2.2
         w __gmon_start__
         w _ITM_deregisterTMCloneTable
         w _ITM_registerTMCloneTable
         U __libc_start_main@GLIBC_2.34
         U open@GLIBC_2.0
         U printf@GLIBC_2.0
         U __stack_chk_fail@GLIBC_2.4
         U __stack_chk_guard@GLIBC_2.4
000005d0 T _init
00000660 T _ftext
00000660 T __start
00000840 T main
000009b0 T _fini
00000a00 R _IO_stdin_used
00011000 D __data_start
00011000 W data_start
00011000 D _fdata
00011010 D __RLD_MAP
00011074 B __bss_start
00011074 D _edata
00011074 B _fbss
00011090 B _end
$ /opt/poky/SDK220804V0/sysroots/x86_64-pokyXXXsdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-nm -g -n testuartmips
         w __cxa_finalize@GLIBC_2.2
         w __gmon_start__
         w _ITM_deregisterTMCloneTable
         w _ITM_registerTMCloneTable
         U __libc_start_main@GLIBC_2.34
         U open@GLIBC_2.0
         U printf@GLIBC_2.0
         U __stack_chk_fail@GLIBC_2.4
         U __stack_chk_guard@GLIBC_2.4
000005d0 T _init
00000660 T _ftext
00000660 T __start
00000840 T main
000009b0 T _fini
00000a00 R _IO_stdin_used
00011000 D __data_start
00011000 W data_start
00011000 D _fdata
00011010 D __RLD_MAP
00011074 B __bss_start
00011074 D _edata
00011074 B _fbss
00011090 B _end
使用X86平台, mips toolchain和arm toolchain的nm命令分别读取arm程序的符号列表:
$ nm -g -n testuartarm
         U abort@@GLIBC_2.4
         U __aeabi_unwind_cpp_pr1@@GCC_3.5
         w __cxa_finalize@@GLIBC_2.4
         w __gmon_start__
         w _ITM_deregisterTMCloneTable
         w _ITM_registerTMCloneTable
         U __libc_start_main@@GLIBC_2.34
         U open@@GLIBC_2.4
         U printf@@GLIBC_2.4
00000444 T _init
000004ad T _start
000005a8 T main
00000600 T _fini
00000608 R _IO_stdin_used
00011038 D __data_start
00011038 W data_start
0001103c D __dso_handle
00011040 B __bss_start
00011040 B __bss_start__
00011040 D _edata
00011040 D __TMC_END__
00011044 B __bss_end__
00011044 B _bss_end__
00011044 B __end__
00011044 B _end
$ ~/x2000br/buildroot/buildroot/output/host/usr/bin/mipsel-linux-nm -g -n testuartarm
         U abort@@GLIBC_2.4
         U __aeabi_unwind_cpp_pr1@@GCC_3.5
         w __cxa_finalize@@GLIBC_2.4
         w __gmon_start__
         w _ITM_deregisterTMCloneTable
         w _ITM_registerTMCloneTable
         U __libc_start_main@@GLIBC_2.34
         U open@@GLIBC_2.4
         U printf@@GLIBC_2.4
00000444 T _init
000004ad T _start
000005a8 T main
00000600 T _fini
00000608 R _IO_stdin_used
00011038 D __data_start
00011038 W data_start
0001103c D __dso_handle
00011040 B __bss_start
00011040 B __bss_start__
00011040 D _edata
00011040 D __TMC_END__
00011044 B __bss_end__
00011044 B _bss_end__
00011044 B __end__
00011044 B _end
$ /opt/poky/SDK220804V0/sysroots/x86_64-pokyXXXsdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-nm -g -n testuartarm
         U abort@@GLIBC_2.4
         U __aeabi_unwind_cpp_pr1@@GCC_3.5
         w __cxa_finalize@@GLIBC_2.4
         w __gmon_start__
         w _ITM_deregisterTMCloneTable
         w _ITM_registerTMCloneTable
         U __libc_start_main@@GLIBC_2.34
         U open@@GLIBC_2.4
         U printf@@GLIBC_2.4
00000444 T _init
000004ac T _start
000005a8 T main
00000600 T _fini
00000608 R _IO_stdin_used
00011038 D __data_start
00011038 W data_start
0001103c D __dso_handle
00011040 B __bss_start
00011040 B __bss_start__
00011040 D _edata
00011040 D __TMC_END__
00011044 B __bss_end__
00011044 B _bss_end__
00011044 B __end__
00011044 B _end
结论就是,对于nm命令,不一定要使用cross-toolchain的版本,用Ubuntu里自带的nm也一样用,结果一样。如果有问题,再换成toolchain里面的nm命令。
因为nm查询的是符号名称,这部分功能可能和芯片类型关系不大,各个不同的toolchain,编译出来的格式是类似的,大致上是使用的相同的框架来管理符号。
参考:
nm man | Linux Command Library
https://www.howtoforge.com/linux-nm-command/
10 Practical Linux nm Command Examples
IBM Documentation

http://www.ppmy.cn/news/317375.html

相关文章

endl与\n的区别

看C++Primer的时候看到的,然后去百度了一下; 比较明白的解释: 1、区别在于: \n只代表换行的转义字符 endl除了代表换行,还紧跟着清出缓冲槽2、接下来我们看一下具体内容的辨析: 要明白\n和endl的区别,首先要明白一个概念: 输出流。 目前输出流的类型很多,有对文件作为目…

linux下nm,objdump和ldd三大工具使用

linux下进行C/C开发时经常需要使用nm&#xff0c;objdump&#xff0c;ldd工具来分析定位问题&#xff0c;本篇文章就对其做个总结&#xff1a; 1.测试程序 TestSo.h #pragma once #include <iostream>extern "C" int CTypeAdd(int x, int y); extern "…

SAP MM(物料管理)常用事务代码T-Code

MM01 - 创建物料主数据 XK01 - 创建供应商主数据 ME11 - 创建采购信息记录 ME01 - 维护货源清单 ME51N- 创建采购申请 ME5A - 显示采购申请清单 ME55 - 批准采购申请&#xff08;批准组&#xff1a;YH&#xff09; ME57 – 分配并处理采购申请 MB21 - 预留 MB24 - 显示…

【图像去模糊】Rethinking Coarse-to-Fine Approach in Single Image Deblurring

论文地址&#xff1a;https://arxiv.org/pdf/2108.05054.pdfhttps://arxiv.org/pdf/2108.05054.pdf 代码地址&#xff1a;https://github.com/chosj95/MIMO-UNethttps://github.com/chosj95/MIMO-UNet 粗到精细的策略已被广泛应用于单个图像去模糊网络的体系结构设计。传统的方…

数仓总结题

面试可能会遇到的问题 数仓怎么设计&#xff1f; 数仓分为ODS层&#xff0c;DW层和DM层&#xff0c;ODS层从数据源抽取数据&#xff0c;对数据进行清洗&#xff0c;并将数据加载到中间表。DW层通过维度建模建好事实表和维度表&#xff0c;将ODS层的数据加载到事实表和维度表中…

稳压二极管型号对照表

美标稳压二极管型号 1N4727 3V0 1N4728 3V3 1N4729 3V6 1N4730 3V9 1N4731 4V3 1N4732 4V7 1N4733 5V1 1N4734 5V6 1N4735 6V2 1N4736 6V8 1N4737 7V5 1N4738 8V2 1N4739 9V1 1N4740 10V 1N4741 11V 1N4742 12V 1N4743 13V 1N4744 15V 1N4745 16V 1N4746 18V 1N4747 20V 1N4748…

小师妹问沃什么是可执行程序?(全网最简洁,必看,错过后悔终生!!!)

相信很多同学知道Windows下的可执行程序是*.exe&#xff0c;但是除了*.exe之外&#xff0c;Windows下动态库*.dll和*.lib也是可执行程序。不过&#xff0c;小师妹问沃的是什么是Linux下的可执行程序&#xff1f; 为了不让小师妹伤心&#xff0c;师兄沃再次拿起《程序员的自我修…

C++全局对象的构造与析构

C全局对象构造与析构 先上代码&#xff1a; //simpleClass.cppclass A{int val; public:A(int n){val n;}~A(){val 0;} };A a1(1);int main(){A a2(2);return 0; }抛出问题&#xff1a;局部对象a2和全局对象a1分别在何处调用构造函数和析构函数&#xff1f; 将上述cpp文件…