Hubbry Logo
Nm (Unix)Nm (Unix)Main
Open search
Nm (Unix)
Community hub
Nm (Unix)
logo
7 pages, 0 posts
0 subscribers
Be the first to start a discussion here.
Be the first to start a discussion here.
Nm (Unix)
Nm (Unix)
from Wikipedia
nm
Original authorsDennis Ritchie,
Ken Thompson
(AT&T Bell Laboratories)
DevelopersVarious open-source and commercial developers
Initial releaseNovember 3, 1971; 54 years ago (1971-11-03)
Written inC
Operating systemUnix, Unix-like, Plan 9
PlatformCross-platform
TypeCommand
LicensePlan 9: MIT License

nm is a Unix command used to dump the symbol table and their attributes from a binary executable file (including libraries, compiled object modules, shared-object files, and standalone executables).

The output from nm distinguishes between various symbol types. For example, it differentiates between a function that is supplied by an object module and a function that is required by it. nm is used as an aid for debugging, to help resolve problems arising from name conflicts and C++ name mangling, and to validate other parts of the toolchain.

This command is shipped with a number of later versions of Unix and similar operating systems including Plan 9. The GNU Project ships an implementation of nm as part of the GNU Binutils package.

The etymology is that in the old Version 7 Unix, nm's manpage used the term name list instead of symbol table.[1]

nm output sample

[edit]
/*
 * File name: test.c
 * For C code compile with: 
 * gcc -c test.c
 *
 * For C++ code compile with:
 * g++ -c test.cpp
 */

int global_var;
int global_var_init = 26;

static int static_var;
static int static_var_init = 25;

static int static_function()
{
	return 0;
}

int global_function(int p)
{
	static int local_static_var;
	static int local_static_var_init=5;

	local_static_var = p;

	return local_static_var_init + local_static_var;
}

int global_function2()
{
	int x;
	int y;
	return x+y;
}

#ifdef __cplusplus
extern "C"
#endif
void non_mangled_function()
{
	// I do nothing
}

int main(void)
{
	global_var = 1;
	static_var = 2;

	return 0;
}

If the previous code is compiled with the gcc C compiler, the output of the nm command is the following:

# nm test.o
0000000a T global_function
00000025 T global_function2
00000004 C global_var
00000000 D global_var_init
00000004 b local_static_var.1255
00000008 d local_static_var_init.1256
0000003b T main
00000036 T non_mangled_function
00000000 t static_function
00000000 b static_var
00000004 d static_var_init

When the C++ compiler is used, the output differs:

# nm test.o
0000000a T _Z15global_functioni
00000025 T _Z16global_function2v
00000004 b _ZL10static_var
00000000 t _ZL15static_functionv
00000004 d _ZL15static_var_init
00000008 b _ZZ15global_functioniE16local_static_var
00000008 d _ZZ15global_functioniE21local_static_var_init
         U __gxx_personality_v0
00000000 B global_var
00000000 D global_var_init
0000003b T main
00000036 T non_mangled_function

The differences between the outputs also show an example of solving the name mangling problem by using extern "C" in C++ code.

Symbol types
Symbol type Description
A Global absolute symbol
a Local absolute symbol
B Global bss symbol
b Local bss symbol
D Global data symbol
d Local data symbol
f Source file name symbol
R Global read-only symbol
r Local read-only symbol
T Global text symbol
t Local text symbol
U Undefined symbol

See also

[edit]

References

[edit]
[edit]
Revisions and contributorsEdit on WikipediaRead on Wikipedia
from Grokipedia
nm is a command-line in operating systems used to display the contents of object files, files, shared libraries, or object-file archives. It lists symbols such as functions, global variables, and their attributes including type, value, and size, aiding developers in , linking analysis, and understanding binary structures. Defined as an optional under the POSIX.1-2017 standard in the Utilities option group, nm originated from early systems and is implemented in various forms across distributions like , BSD, and Solaris. The tool processes input files in formats such as ELF (Executable and Linkable Format) or COFF (Common Object File Format), extracting symbolic information unless stripped during compilation. By default, it sorts output by symbol name and uses a BSD-style format showing the symbol's address, type (e.g., T for text/code, for data, U for undefined), and name; alternative formats like or SysV can be specified for portability or detailed views. Common options include -g to show only external (global) symbols, -u for undefined symbols, and -A to prefix each line with the file or library name, facilitating analysis of dependencies in large projects. In the GNU implementation, part of the Binutils package maintained by the , nm supports dynamic symbols via -D for shared objects and demangling of C++ names, enhancing usability in modern . While mandates basic functionality like portable output with -P, extensions in specific systems (e.g., XSI options like -e for external/static symbols) provide additional flexibility without breaking compatibility. If no symbolic information is present—common in optimized or stripped binaries—nm reports this without error, returning success status zero. Overall, nm remains a fundamental tool for , build troubleshooting, and ensuring symbol resolution in Unix environments.

Overview

Purpose and Functionality

The nm command is a standard command-line utility in operating systems designed to list s—such as functions, global variables, and other identifiers—from object files, static libraries, or binaries. It extracts and displays information from the symbol tables embedded in these files, providing developers with visibility into the program's structure without executing it. This tool is part of the GNU Binutils suite in most Linux distributions and is available across various Unix variants, including BSD and Solaris implementations. Symbol tables in object files serve as repositories for essential metadata used during compilation, linking, and processes. These tables contain entries detailing names (stored as strings), types (e.g., , or section), values (such as addresses or offsets), and sizes (in bytes, if applicable). In the (ELF), the predominant standard for systems, tables are organized into sections like .symtab for general symbols and .dynsym for dynamic linking, enabling the linker to resolve references and the to map addresses to meaningful names. This structure facilitates both static analysis and runtime support, ensuring symbols can be relocated or inspected as needed. The primary applications of nm revolve around software development and analysis tasks. In debugging, it helps identify undefined symbols (marked as type 'U'), which signal linking errors or missing dependencies, allowing developers to troubleshoot unresolved references early. It also supports reverse engineering by revealing the exported and imported symbols in a binary, aiding in understanding proprietary or obfuscated code without source access. Additionally, nm verifies compilation outputs by confirming that expected symbols from source code are correctly generated and preserved in the resulting artifacts, which is crucial for build system validation and toolchain integrity checks. The utility supports multiple formats aligned with Unix standards, with a primary focus on ELF for relocatable objects, executables, and shared libraries in and other POSIX-compliant systems; different implementations support various formats: for example, version handles COFF (used in some historical Unix environments) and ELF, while the macOS version handles (prevalent in Darwin-based systems like macOS). As a non-interactive tool, nm produces plain text output to standard output (stdout), making it suitable for scripting and integration with other commands via for automated analysis workflows.

History and Development

The nm command originated in , released in May 1975 by [Bell Labs](/page/Bell Labs), where it formed part of the core for examining tables in object files generated by assemblers and linkers. This early implementation allowed developers to list symbols such as functions and variables along with their addresses and types, facilitating and program analysis in the resource-constrained environment of PDP-11 systems. Developed by engineers, nm was tailored to the a.out executable format, the default binary structure in pre-BSD Unix distributions, which organized code into text, data, and segments. As Unix spread beyond , the command evolved alongside system variants; it was incorporated into the Berkeley Software Distribution (BSD) starting from early releases like 1BSD in 1977, adapting to Berkeley's enhancements like support while retaining compatibility with a.out. efforts culminated in its inclusion in POSIX.2 (IEEE Std 1003.2-1992), which defined its core interface for portability across conforming systems, with refinements in subsequent versions like POSIX.1-2008 to address evolving utility behaviors. It is defined as an optional utility in POSIX.1-2017 within the Utilities option group. Key milestones in the open-source era began in 1987, when the (FSF) launched the GNU nm as part of its broader initiative to build a complete Unix-compatible operating system, emphasizing freedom to modify and redistribute software tools. By the early 1990s, GNU nm was integrated into the GNU Binutils suite, a collection of binary manipulation utilities that became essential for GCC-based development environments. This period also saw significant adaptations, as Unix-like systems transitioned from a.out to the (ELF) in the mid-1990s—starting with Solaris in 1992 and adopted by in 1996—requiring nm to parse new structures for dynamic linking and shared libraries. Despite the rise of comprehensive disassemblers, nm maintains relevance in contemporary distributions, macOS (adapted for binaries), and embedded systems like those using , where its lightweight symbol inspection supports debugging and build verification.

Usage

Command Syntax

The nm command follows the POSIX-specified syntax for listing symbols from s, with the general form nm [options] file..., where file denotes one or more pathnames to s, files, or object-file libraries (such as those in format). s typically have a .o extension, archives use .a, and executables are standalone binaries containing symbol tables. In POSIX-compliant systems, if no files are specified, nm writes a diagnostic message to and exits with a non-zero ; implementations like nm instead default to processing a.out, the conventional name for the default or in environments. When multiple files are specified, nm processes them sequentially, producing output for each and prefixing the results with the filename (or full pathname if the -A option is used) to distinguish symbols from different inputs. This behavior ensures clear separation in the output stream, though the exact formatting adheres to the chosen output style (default or with -P). The command does not read from standard input as a file operand; instead, it expects explicit file arguments or the a.out fallback. Upon encountering errors, such as invalid or unreadable files, nm terminates with a non-zero (typically 1), indicating failure, while successful execution returns 0. The core syntax is POSIX-compliant, ensuring portability across conforming Unix systems, but implementations like nm introduce extensions such as additional options for handling dynamic symbols or specific object formats without altering the basic invocation pattern.

Key Options and Flags

The nm command supports a variety of options to control the symbols displayed, their formatting, sorting, and filtering, allowing users to tailor output for , , or scripting needs. These options are largely standardized in but include implementation-specific extensions, particularly in and BSD variants. Common options focus on symbol selection and basic output modifications, while advanced flags handle demangling, dynamic symbols, and sorting behaviors.

Common Options

  • The -a or --debug-syms flag includes all symbols in the output, even those typically used only by debuggers, providing a complete view of the symbol table.
  • In POSIX and GNU implementations, -g or --extern-only restricts output to external (global) symbols, excluding local ones to focus on inter-module references; in some BSD variants like OpenBSD, -g instead displays undefined symbols (use -e for external).
  • In POSIX and GNU implementations, the -u or --undefined-only option displays only undefined symbols, useful for identifying unresolved dependencies during linking; in some BSD variants like OpenBSD, -u provides extended symbol information, while -g shows undefined symbols.
  • -t radix or --radix=radix specifies the base for numeric symbol values, where d uses decimal, o octal, and x hexadecimal, enabling compatibility with different output preferences.

Sorting and Formatting

  • The -n or --numeric-sort flag sorts symbols by their in ascending order, facilitating analysis of code layout.
  • -p or --no-sort outputs symbols in the order they appear in the file, preserving the original without imposing any sorting.
  • The -C or --demangle[=style] option decodes mangled symbol names, such as those from C++ compilers, into readable form (e.g., converting _Z3foov to foo()), with styles like gnu or auto for flexibility.

Filtering

  • -D or --dynamic displays symbols from the dynamic , relevant for shared libraries and runtime loading.
  • The -A or --print-file-name flag prefixes each line with the full pathname of the or , aiding in multi-file inspections.
  • -l or --line-numbers appends source file names and line numbers for symbols, if information is available, enhancing (note: in some BSD variants like , -l instead shows indices).

GNU-Specific Options

In the GNU implementation, additional flags extend functionality:
  • --defined-only (or -U in some contexts) shows only symbols defined in the file, excluding undefined ones.
  • --no-demangle disables name demangling, outputting raw mangled names as the default behavior.
  • --size-sort sorts symbols by their sizes (requiring -S for size display in BSD-style output), useful for identifying large functions or data.

Deprecated or Variant Options

The -o flag, historically used for octal output in and traditional Unix systems, is deprecated in in favor of -t o; in , -o now aliases --print-file-name for but may produce warnings. Options can be combined for targeted use, such as nm -C -D to demangle and display dynamic symbols readably.

Output Interpretation

Format Components

The standard output format of the nm command, used across Unix implementations, follows the BSD style by default, consisting of lines with fields separated by spaces: an (or value), a type indicator, an optional size, and the symbol name. This format can vary based on options and the chosen output style, such as SysV or , but the BSD format remains the most common for displaying symbol information from object files, executables, or archives. The address field represents the memory or offset of the within the , padded to a fixed width depending on the architecture (e.g., 8 digits for 32-bit systems or 16 digits for 64-bit ELF files); for undefined , it displays as 000000 or a similar zero value. The type field is a single-letter indicating the section or attributes (e.g., T for text section, D for , U for undefined), with uppercase typically denoting global and lowercase for local ones. The size field, which shows the byte length of the symbol, is optional and appears only when specified via options like -S or --print-size in BSD format, or inherently in format; it is absent for undefined symbols. The name field contains the symbol's identifier, which may include version information (e.g., @VER suffix); if the -C or --demangle option is used, C++ mangled names are decoded into readable form, though this can be disabled with --no-demangle. For output involving multiple files or archive members, options like -A, -o, or --print-file-name prepend the or archive path to each line (e.g., filename: address type name), facilitating distinction between symbols from different sources. Architecture-specific variations affect field widths, such as longer hexadecimal addresses in 64-bit ELF binaries compared to 32-bit a.out formats, ensuring compatibility with the target's layout. Other output formats, like (invoked with -P or --format=posix), rearrange fields to name type value size (with prefix if applicable) and support radices like or via -t, promoting portability across Unix systems.

Symbol Types and Meanings

In the output of the nm command, symbol types are indicated by single-letter codes that distinguish between local and global symbols, as well as their sections and attributes. Lowercase letters denote symbols, which are not visible outside the , while uppercase letters indicate global or external symbols that can be referenced across files during linking. This distinction aids in understanding symbol visibility and linkage requirements. Local symbols include types such as t for symbols in the text (code) section, d for initialized data sections, and b for uninitialized (BSS) data sections. These represent internally defined elements like static functions or variables that do not require external resolution. Global symbols, conversely, feature T for text sections (indicating executable code locations that may be called from other modules), D for initialized , and U for undefined external references, which signal that the linker must resolve them from other object files or libraries. The U type is particularly useful for identifying dependencies during the build process, as unresolved U symbols can lead to linking errors if not provided. Special symbol types provide additional context for non-standard or auxiliary symbols. These include N for debugging symbols (used in symbol tables for tools like debuggers), W for weak external symbols (which prefer a strong definition if available but do not cause errors otherwise), and G for symbols in small initialized data sections (optimized for certain architectures). In implementations, I denotes an indirect reference to another , while i marks indirect functions as a GNU extension; V indicates weak object symbols, often for common blocks in dynamic contexts. File-specific types encompass a for local absolute symbols (with fixed values independent of relocation) and ? for unknown or format-specific types that do not fit standard categories. When examining dynamic symbols (via specific output modes), types like V may appear for common blocks in shared libraries, highlighting shared data allocations. Implementations vary slightly: BSD variants, such as , use similar conventions but omit GNU-specific extensions like G, I, and i, instead relying on core types like R/r for read-only data and lacking explicit indirect indicators. These differences ensure compatibility within their respective ecosystems while maintaining the fundamental purpose of symbol classification for and linking analysis.
TypeDescription (GNU/BSD Common)ScopeExample Implication
T / tText/code sectionGlobal/LocalT marks callable functions; t for static ones.
D / dInitialized data sectionGlobal/LocalGlobal D for shared variables; local d for file-internal.
B / bUninitialized (BSS) dataGlobal/LocalZero-filled at runtime; used for global/local uninitialized static data.
UUndefined externalGlobalRequires linker resolution; indicates .
A / aGlobal/LocalFixed address, no relocation needed.
NDebugging symbolSpecialUsed by debuggers; not executable code.
W / wWeak externalGlobal/LocalOverridable by symbols without error.
?Unknown typeSpecialFormat-specific or unrecognized.

Examples and Applications

Basic Usage Examples

The nm command is commonly used to inspect symbols in object files after compilation, helping developers verify that functions and variables have been correctly defined or to identify entry points like the main function. A basic lists all symbols from a compiled , such as main.o, displaying their addresses, types, and names in a tabular format. For example:

nm main.o

nm main.o

This might produce output like:

0000000000000000 T main 0000000000000027 t helper_function U [printf](/page/Printf)

0000000000000000 T main 0000000000000027 t helper_function U [printf](/page/Printf)

Here, the T indicates a in the text () section, t a text , and U an undefined requiring resolution during linking; such output aids in post-compilation verification. To diagnose linking issues, the -u option filters for only undefined in an or object, as in nm -u program. For a program referencing external functions, the output could be:

U printf U malloc

U printf U malloc

This reveals dependencies on libraries, essential for troubleshooting unresolved references before final linking. For shared libraries, combining -C (demangle) with -D (dynamic symbols) provides readable listings of exported functions, such as nm -DC libexample.so. A sample output might include:

0000000000000a50 T example_function(int) 0000000000000b20 T another_export

0000000000000a50 T example_function(int) 0000000000000b20 T another_export

Demangling converts mangled C++ names to human-readable form, facilitating inspection of dynamic symbols for library integration. Users often pipe nm output to grep for targeted searches, like nm main.o | grep main, yielding only relevant lines such as 0000000000000000 T main to quickly locate specific entry points.

Advanced Scenarios

In advanced debugging scenarios, particularly for linked executables, the nm -D option is employed to examine dynamic symbols, revealing undefined symbols (marked as type 'U') that indicate dependencies on external shared libraries. This allows developers to verify runtime linking behavior without executing the program, such as identifying missing or unresolved external references in a binary like /path/to/binary. For instance, running nm -D /path/to/binary lists symbols from the dynamic symbol table, helping diagnose issues in large projects where dynamic linking introduces potential conflicts. When handling static archives, nm inspects library members directly; applying it to a file like libarchive.a enumerates all symbols across the archive's object files, prefixed with member names when using the -A or --print-file-name flag. This is crucial for auditing static libraries in multi-module builds, ensuring no unintended symbol overlaps occur before linking. The output format facilitates targeted analysis, with each symbol's value, type, and originating member clearly delineated. Cross-platform development, such as for embedded systems, leverages the --target=bfdname option to specify the object format, enabling nm to process binaries from non-native architectures like bare-metal targets. For example, nm --target=elf32-littlearm /path/to/arm-binary decodes symbols in ARM format, supporting verification of cross-compiled code without a full switch. This capability is essential in heterogeneous environments, where developers analyze images for symbol integrity across architectures. Integration with scripting tools enhances nm's utility for automated symbol extraction in complex workflows; the output can be piped to or for filtering, such as extracting only undefined symbols with nm binary.o | awk '/ U / {print $3}'. The -p or --no-sort flag ensures symbols appear in file order, preserving context for scripts processing large outputs and avoiding sorting overhead. This approach is common in build scripts for selective symbol reporting in version control or CI pipelines. Troubleshooting multi-module builds often involves detecting duplicate symbols or version mismatches using nm's detailed output; duplicates manifest as repeated entries across files (visible with -A), while the --with-symbol-versions option appends version tags (e.g., symbol@VER_2) to reveal incompatibilities between library versions. In scenarios like merging modules from disparate sources, this helps preempt linker errors by identifying conflicting definitions early. Additionally, -C or --demangle aids in interpreting mangled names for clearer duplicate identification. For performance considerations with large files, such as massive object dumps in enterprise-scale projects, the --no-sort option skips symbol sorting, significantly reducing processing time by outputting in encounter order—ideal for quick inspections where full is unnecessary. This flag is particularly beneficial when combined with output redirection or scripting, maintaining efficiency without compromising accessibility.

Implementations and Variants

GNU nm Features

The GNU implementation of nm, as part of the GNU Binutils collection, has been integrated since version 2.1 released in 1993, providing comprehensive support for multiple object file formats and architectures including ELF, COFF, and Mach-O across various hosts and targets. This integration allows nm to leverage the broader Binutils ecosystem, such as the BFD (Binary File Descriptor) library for portable object file handling, enabling analysis of binaries from diverse platforms without requiring separate tools. GNU nm extends the standard functionality with several options not mandated by POSIX, including --dynamic (or -D) to display the dynamic symbol table of shared object files, which lists symbols relevant to runtime linking such as those in PLT entries or GOT references. The --extern-only option (or -g) filters output to show only globally defined symbols, aiding in the inspection of exported interfaces in libraries. Additionally, the --format (or -f) option supports customizable output styles like bsd, gnu, or sysv, allowing users to choose between traditional BSD-like listings with symbol types in uppercase or SysV-style with additional section details for enhanced readability. Demangling in GNU nm is handled via the -C or --demangle[=style] option, which fully complies with the C++ ABI used by GCC, decoding mangled names from low-level into human-readable C++ identifiers including templates, namespaces, and overloaded functions. This feature integrates with the accompanying c++filt tool for advanced filtering, ensuring accurate reversal of compiler-generated names while supporting styles like gnu-v3 for modern C++ standards. Target specification is facilitated by the --target=bfdname option, permitting analysis of non-native formats such as Windows PE executables via nm --target=pe-i386 executable.exe, which extends nm's utility beyond Unix-like systems to cross-platform scenarios. GNU nm also includes enhancements for ELF files, such as improved parsing for indirect function symbols (marked with 'i') and unique global symbols ('u'), along with options like --ifunc-chars=CHARS to customize their display characters, facilitating better handling of large tables in modern binaries. In contrast to POSIX specifications, which limit radix options to hexadecimal or octal via -t, GNU nm adds --radix=decimal support for sorting addresses and sizes in decimal notation, providing flexibility for users preferring base-10 output in reports or scripts.

BSD and Other Unix Variants

In BSD-derived systems such as and , the nm utility retains traditional Unix characteristics with a focus on simplicity and compatibility with a.out and object formats, displaying symbol tables without demangling by default. The -g option limits output to external (global) symbols only, similar to the GNU implementation. Options like -n enable numeric sorting by symbol value, -u shows undefined symbols exclusively, and -a includes symbol table entries; in NetBSD, -C provides optional demangling for low-level names such as those from C++, while OpenBSD lacks this option. Output uses a BSD-style format by default, listing the symbol value in , a single-letter type indicator (e.g., 'T' for global text section symbols, 'U' for undefined, 'D' for data, with lowercase for local equivalents), and the name, sorted alphabetically unless modified. FreeBSD's nm implementation, derived from GNU binutils but configured for BSD defaults, supports ELF files and emphasizes portability across architectures, with options like --extern-only (equivalent to -g) for global symbols and --format=bsd for traditional output. It includes GNU extensions such as --demangle for name decoding and --dynamic for shared library symbols, but lacks native Mach-O support, focusing instead on Unix-like binaries. NetBSD similarly adopts binutils nm with added compatibility for weak and indirect symbols, using type letters like 'w' for weak defined and 'i' for indirect references, which may vary in interpretation from pure BSD implementations. In System V derivatives like Solaris and , nm targets ELF object files with SVR4 extensions, integrating closely with the link editor (ld) for symbol resolution and supporting symbol versioning through output fields indicating bind types (local or global). Legacy System V/ versions emphasized a.out format with limited options, such as -n for numeric sorting and -g for global symbols only, without built-in demangling or dynamic symbol handling. Modern Solaris nm adds -D for dynamic symbols, -p for parseable output (value, type, , section index, name), and -t for radix specification (, , ), with type letters including 'T' for text, 'R' for read-only data, and 'v' for weak versions. These variants prioritize terse, machine-readable formats over verbose , reflecting SVR4's emphasis on production linking workflows. The Darwin implementation in macOS and tools adapts nm for binaries, using llvm-nm by default since 8, with options like -m to display section symbols as (segment_name, section_name) followed by visibility (external or non-external). It supports multi-architecture files via -arch (e.g., -arch arm64 for or ), -g for global symbols only, and -n for numeric sorting, without automatic demangling unless specified. Symbol types follow conventions, such as 'S' for section symbols and 'I' for indirect, differing from BSD ELF types in handling fat binaries and code-signing metadata. Portability challenges arise from inconsistent symbol type letters across variants; for instance, BSD systems like use 'i' or 'I' for indirect symbols in a manner tied to a.out/ELF specifics, while nm employs 'i' for indirect functions and adds types like 'G' for unique globals not present in traditional BSD. These differences can affect script parsing, requiring format flags like -P for POSIX-compatible output in mixed environments.

Comparison with

The objdump utility, part of the GNU Binutils suite, provides a comprehensive analysis of object files by disassembling executable code, displaying file and section headers, and extracting various metadata, whereas nm is specialized for listing symbols from the symbol table without additional disassembly or header details. Both tools support common object file formats such as ELF and COFF, enabling them to process the same input files like executables or relocatable objects. A key overlap exists in symbol handling: objdump's -t option dumps the symbol table in a manner similar to nm, but includes extra context such as symbol flags (e.g., local, global, weak), section names, and sizes, offering a more detailed view than nm's basic address-type-name format. nm excels in scenarios requiring rapid, targeted symbol queries due to its lightweight design and options like -u for undefined symbols only or sorting by name/address, producing concise output ideal for scripting and automation. objdump is preferable when disassembly is needed, such as with the --disassemble (or -d) option to view assembly instructions, or for inspecting section headers via --headers (or -h), which reveal layout and attributes not accessible in nm. One limitation of nm is its absence of relocation information—objdump can display relocation entries with -r—and it does not provide hexadecimal dumps of sections, which objdump handles via -s. For instance, to quickly identify undefined symbols in an object file that might cause linker errors, nm file.o | grep ' U ' suffices, but for a thorough binary inspection including code flow and relocations, objdump -d -r file.o is more appropriate.

Integration in Build Processes

In Unix build processes, the nm tool is commonly invoked within Makefile rules to verify the presence of key symbols, such as the entry point 'main', prior to linking object files into an . For example, a Makefile rule might execute nm $< | grep ' main ' to confirm the symbol is defined in the object file, failing the build if absent to prevent linking errors. This practice ensures symbol integrity early in the compilation pipeline. Automated CI/CD pipelines often incorporate nm with the -u or --undefined-only option to detect unresolved external in linked binaries, catching potential runtime linking issues before deployment. Such checks can be scripted to run post-compilation, for instance, nm -u output_executable piped to a failure condition if any undefined are found, thereby enforcing dependency completeness in continuous integration workflows. When combined with the GNU linker (ld) and make, nm facilitates the generation of maps by redirecting its output to .map files, as in nm linked_executable > symbols.map, which aids in relocation and resolution during the final linking stages. In the build system, nm is specifically used to extract from the binary via the command nm -n vmlinux | scripts/kallsyms, enabling the creation of a compressed for kernel and module loading. For static analysis, nm output is frequently processed with tools like grep or awk to construct symbol dependency graphs, such as nm object.o | awk '/ U / {print &#36;3}' to identify and map undefined symbols to their required libraries, helping developers visualize and resolve inter-file dependencies without full linking. In GCC and Clang-based toolchains, post-link invocation of nm with -D examines dynamic symbols in shared objects to generate export lists, ensuring only intended symbols are visible externally after the linking phase completes. Best practices recommend employing the --defined-only option in release builds to audit and limit exported symbols, reducing the binary's and improving load times; for instance, nm --defined-only --format=posix shared.so lists only locally defined symbols for verification against an approved . This selective filtering promotes modular designs and compliance with visibility controls in production artifacts.
Add your contribution
Related Hubs
User Avatar
No comments yet.