NM(1)

πŸ¦‹ NAME πŸ¦‹

nm β€” list symbols from object files ✨

(yes bestie, this is the NM(1) page from the GNU Development Tools set β€” welcome, you're in the right group chat πŸ’–)


🌸 SYNOPSIS 🌸

nm [-A|-o|--print-file-name]
   [-a|--debug-syms]
   [-B|--format=bsd]
   [-C|--demangle[=style]]
   [-D|--dynamic]
   [-fformat|--format=format]
   [-g|--extern-only]
   [-h|--help]
   [--ifunc-chars=CHARS]
   [-j|--format=just-symbols]
   [-l|--line-numbers] [--inlines]
   [-n|-v|--numeric-sort]
   [-P|--portability]
   [-p|--no-sort]
   [-r|--reverse-sort]
   [-S|--print-size]
   [-s|--print-armap]
   [-t radix|--radix=radix]
   [-u|--undefined-only]
   [-U|--defined-only]
   [-V|--version]
   [-W|--no-weak]
   [-X 32_64]
   [--no-demangle]
   [--no-recurse-limit|--recurse-limit]]
   [--plugin name]
   [--size-sort]
   [--special-syms]
   [--synthetic]
   [--target=bfdname]
   [--unicode=method]
   [--with-symbol-versions]
   [--without-symbol-versions]
   [objfile...]

πŸ’… DESCRIPTION πŸ’…

okay so GNU nm lists the symbols from object files objfile... . That's the whole thing. That's her job πŸ’β€β™€οΈ

And if you don't pass any object files as arguments at all? She just assumes the file a.out. no cap, she's got a default, she's lowkey self-sufficient like that.

For each symbol, nm shows you:

  • The symbol value, in the radix selected by options (see below), or hexadecimal by default. It's giving "here's the number bestie" ✨
  • The symbol type. At least the following types are used β€” others are too, depending on the object file format. So like, lowercase usually means the symbol is local, uppercase means it's global (external). But there are a few lowercase symbols that get shown for special global symbols ("u", "v" and "w") β€” those are the exceptions, the little rebels πŸ™ˆ
    • A β€” the symbol's value is absolute, and further linking will not change it. Locked in. Immovable. Queen behaviour πŸ‘‘
    • B, b β€” the symbol is in the BSS data section. That section typically contains zero-initialized or uninitialized data, although the exact behavior is system dependent. So like… it depends, iykyk.
    • C, 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. The lower case c character is used when the symbol is in a special section for small commons. Tiny commons, iconic πŸ’–
    • D, d β€” the symbol is in the initialized data section. Initialized. Ready. Put together. Main character energy πŸ’…
    • 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. Small but mighty πŸ“
    • 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.

Note β€” the actual symbols display for GNU indirect symbols is controlled by the --ifunc-chars command line option. If this option has been provided then the first character in the string will be used for global indirect function symbols. If the string contains a second character then that will be used for local indirect function symbols. Two characters, two jobs, she's flexible like that 😭

  • I β€” the symbol is an indirect reference to another symbol. Not the symbol itself, just pointing at one. It's giving "check her instead" 🫢
  • N β€” the symbol is a debugging symbol. πŸ›βœ¨
  • n β€” the symbol is in a non-data, non-code, non-debug read-only section. So basically none of the things. Just vibes.
  • p β€” the symbol is in a stack unwind section.
  • R, r β€” the symbol is in a read only data section. Look but don't touch πŸ’œ
  • 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. The actual code bestie!! πŸ”₯
  • U β€” the symbol is undefined. She's just a concept rn 😭
  • 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. One of one. Exclusive. No duplicates allowed βœ¨πŸ‘‘
  • 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. Weak but never messy 🌸
  • 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. Different flavour of weak, same soft launch energy πŸ’€
  • - β€” 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. Three extra values, she's thorough, she's not doing anything halfway πŸ™ˆ
  • ? β€” the symbol type is unknown, or object file format specific. Mystery girl. We don't know her and honestly neither does nm πŸ’€
  • The symbol name. If a symbol has version information associated with it, then the version information is displayed as well. If the versioned symbol is undefined or hidden from linker, the version string is displayed as a suffix to the symbol name, preceded by an @ character. For example foo@VER_1. If the version is the default version to be used when resolving unversioned references to the symbol, then it is displayed as a suffix preceded by two @ characters. For example foo@@VER_2. One @ or two @, that's the whole plot twist and it MATTERS bestie, do not skim it 😀

✨ OPTIONS ✨

okay bestie, one thing before we get into it: the long form and the short form of every option down here are literally the same thing. same behaviour, just a different amount of typing. pick whichever one makes your fingers happy πŸ’…

  • -A, -o, --print-file-name β€” slaps the name of the input file (or the archive member) in front of every single symbol it found in there, instead of naming the file just once up top before all of its symbols. it's giving individual name tags instead of one group label ✨
  • -a, --debug-syms β€” shows all the symbols, even the debugger-only ones. normally those get left out of the party entirely πŸ™ˆ
  • -B β€” same as --format=bsd (this one exists purely so it plays nice with the MIPS nm).
  • -C, --demangle[=style] β€” decodes (demangles) those low-level symbol names back into human-readable, user-level names. it also strips off any leading underscore the system glued on, and it makes C++ function names actually make sense. different compilers mangle in different styles, so you can optionally hand it a demangling style argument to pick the right one for your compiler πŸŽ€
  • --no-demangle β€” do not demangle low-level symbol names. this is the default, bestie.
  • --recurse-limit, --no-recurse-limit, --recursion-limit, --no-recursion-limit β€” turns a limit on recursion during demangling on or off. here's the tea: the name mangling formats allow infinite recursion, so it's totally possible to build strings whose decoding will gobble up every last bit of stack space on your machine and trigger a memory fault 😭 the limit exists to stop that by capping recursion at 2048 levels of nesting.

it's enabled by default, but you might need to disable it to demangle truly complicated names.

bestie listen β€” if you disable the recursion limit, stack exhaustion is genuinely possible, and any bug report about that happening will be rejected. you have been warned πŸ’€
  • -D, --dynamic β€” shows the dynamic symbols instead of the normal ones. this only means anything for dynamic objects, like certain types of shared libraries πŸ‘‘
  • -f format, --format=format β€” use output format format, which can be "bsd", "sysv", "posix" or "just-symbols". the default is "bsd". only the first character of format actually matters, and it can be upper or lower case 🌸
  • -g, --extern-only β€” only shows external symbols, nothing else.
  • -h, --help β€” shows a summary of the options for nm and dips 🫢
  • --ifunc-chars=CHARS β€” when showing GNU indirect function symbols, nm defaults to using the "i" character for both local indirect functions and global indirect functions. this option lets you hand over a string with one or two characters: the first gets used for global indirect function symbols, and the second one (if you gave one) gets used for local indirect function symbols ✨
  • -j β€” same as --format=just-symbols.
  • -l, --line-numbers β€” for each symbol, it uses debugging info to try to find a filename and line number. for a defined symbol it looks for the line number of the symbol's address; for an undefined symbol it looks for the line number of a relocation entry that refers to the symbol. if it finds line number info, it prints it after the other symbol info πŸ’œ
  • --inlines β€” when -l is active, if the address belongs to a function that got inlined, this makes it print the source info for all the enclosing scopes all the way back to the first non-inlined function too. like, if "main" inlines "callee1" which inlines "callee2", and the address is from "callee2", then the source info for "callee1" and "main" gets printed as well. it's giving receipts all the way up the chain 😭
  • -n, -v, --numeric-sort β€” sorts symbols numerically by their addresses instead of alphabetically by their names πŸ“Š
  • -p, --no-sort β€” don't bother sorting the symbols into any order at all; just print them in the order you encountered them.
  • -P, --portability β€” uses the POSIX.2 standard output format instead of the default one. equivalent to -f posix ⭐
  • -r, --reverse-sort β€” flips the sort order around (whether it's numeric or alphabetic). last comes first, bestie πŸ”„
  • -S, --print-size β€” prints both the value and the size of defined symbols for the "bsd" output style. this option does nothing for object formats that don't record symbol sizes β€” unless --size-sort is also in play, in which case a calculated size gets displayed instead πŸ’…
  • -s, --print-armap β€” when listing symbols from archive members, this includes the index: that's a mapping (stored in the archive by ar or ranlib) of which modules contain definitions for which names πŸ”
  • -t radix, --radix=radix β€” uses radix as the radix for printing symbol values. it has to be d for decimal, o for octal, or x for hexadecimal. no other letters, bestie, it will not accept your vibes πŸ”’
  • -u, --undefined-only β€” shows only undefined symbols (the ones external to each object file). by default both defined and undefined symbols get displayed.
  • -U, --defined-only β€” shows only defined symbols for each object file. by default both defined and undefined symbols get displayed.
  • -V, --version β€” shows the version number of nm and exits πŸ‘‘
  • -X β€” this one is just ignored, kept around for compatibility with the AIX version of nm. it takes one parameter which must be the string 32_64. the default mode of AIX nm corresponds to -X 32, and GNU nm does not support that 🚫
  • --plugin name β€” loads the plugin called name to add support for extra target types. this option only exists if your toolchain was built with plugin support enabled.

if --plugin isn't given but plugin support is enabled, then nm iterates over the files in ${libdir}/bfd-plugins in alphabetic order, and the first plugin that claims the object in question gets used.

heads up bestie: this plugin search directory is not the same one that ld's -plugin option uses. to make nm use the linker plugin, you have to copy it into the ${libdir}/bfd-plugins directory. for GCC based compilations the linker plugin is called liblto_plugin.so.0.0.0. for Clang based compilations it's called LLVMgold.so. the GCC plugin is always backwards compatible with earlier versions, so just copying the newest one is enough πŸ’–
  • --size-sort β€” sorts symbols by size. for ELF objects the symbol sizes are read straight from the ELF; for other object types the sizes get computed as the difference between the value of the symbol and the value of the symbol with the next higher value. if the "bsd" output format is used, the size of the symbol gets printed rather than the value, and -S must be used if you want both size and value printed together.

note β€” this option does not work if --undefined-only has been enabled, because undefined symbols have no size πŸ’€

  • --special-syms β€” displays symbols that have a target-specific special meaning. these symbols are usually used by the target for some special processing and aren't normally helpful when they show up in the normal symbol lists. for example, for ARM targets this option would skip the mapping symbols used to mark transitions between ARM code, THUMB code and data 🧚
  • --synthetic β€” includes synthetic symbols in the output. these are special symbols the linker created for various purposes, and they're not shown by default since they aren't part of the binary's original source code ✨
  • --unicode=[default|invalid|locale|escape|hex|highlight] β€” controls how UTF-8 encoded multibyte characters in strings get displayed. the default (--unicode=default) is to give them no special treatment at all. --unicode=locale displays the sequence in the current locale, which may or may not support them. --unicode=hex and --unicode=invalid display them as hex byte sequences, wrapped in either angle brackets or curly braces.

--unicode=escape displays them as escape sequences (\uxxxx), and --unicode=highlight displays them as escape sequences highlighted in red (if your output device supports it). the colouring is meant to draw attention to unicode sequences showing up where you might not expect them πŸ‘€

  • -W, --no-weak β€” does not display weak symbols. they're just not invited 🚫
  • --with-symbol-versions, --without-symbol-versions β€” turns the display of symbol version information on or off. the version string shows up as a suffix on the symbol name, preceded by an @ character. for example foo@VER_1. if the version is the default version used when resolving unversioned references to the symbol, then it's shown as a suffix preceded by two @ characters. for example foo@@VER_2. by default, symbol version information is displayed 🌈
  • --target=bfdname β€” specifies an object code format other than your system's default format.
  • @file β€” reads command-line options from file. the options that get read are inserted right in place of the original @file option. if file doesn't exist, or can't be read, then the option gets treated literally and isn't removed.

options inside file are separated by whitespace. a whitespace character can be included in an option by wrapping the entire option in either single or double quotes. any character (including a backslash) can be included by prefixing the character you want with a backslash. and file may itself contain additional @file options β€” any of those get processed recursively, bestie, it's files all the way down πŸŒ€


🌸 SEE ALSO 🌸


Copyright (c) 1991-2026 Free Software Foundation, Inc.

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".


and that's a wrap, bestie πŸ’– this whole lil masterpiece is from binutils-2.47, dated 2026-09-12 β€” go forth and demangle your symbols with main character energy βœ¨πŸ‘‘

πŸ“¦ where this page comes from