When assembling an object using nasm
, I'm finding that all labels are included as symbols in the resultant .o
file, as well as the final binary.
This makes sense for function entry points that I've declared GLOBAL
, and for section start parts (e.g., for the .text
section), but it seems odd that labels simply used as loop entry points and such all near to appear in the output file. In addition to leaking internal implementation details, it wastes space in the symbol table.
For example, given this short assembly program:
GLOBAL _start
_start:
xor eax, eax
normal_label:
xor eax, eax
.local_label:
xor eax, eax
xor edi, edi
mov eax, 231 ; exit(0)
syscall
... built using:
nasm -f elf64 label-test.s
ld label-test.o -o label-test
Results in l
(i.e., local) symbols in both the object file and linked executable:
objdump --syms label-test.o
label-test.o: file format elf64-x86-64
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 label-test.s
0000000000000000 l d .text 0000000000000000 .text
0000000000000002 l .text 0000000000000000 normal_label
0000000000000004 l .text 0000000000000000 normal_label.local_label
0000000000000000 g .text 0000000000000000 _start
Note that both normal_label
and the local label local_label
ended up in the symbol table. All of them end up in the symbol table of the executable also.
I don't want to emit these symbols to the final executable. Can I tell nasm not to include them? There are some options I could pass to ld
, such as --strip-all
, which will remove those symbols, but also every other symbol in the executable. That makes it quite the cudgel: it eliminates the symbols I really want to keep for readable stack traces, debugging, etc.
FWIW, as mentioned by Peter Cordes, yasm
doesn't have exactly the same issue. With an elf64 .o
file built in exactly the same way as above (but with yasm
substituted for nasm
, we get:
objdump --syms label-test-yasm.o
label-test-yasm.o: file format elf64-x86-64
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 label-test.s
0000000000000004 l .text 0000000000000000
0000000000000002 l .text 0000000000000000
0000000000000000 l d .text 0000000000000000 .text
0000000000000000 g .text 0000000000000000 _start
The global _start
label is still included, but the other two labels aren't named - they are still there though, they are the unnamed symbols at offset 4 and 2 (lines 2 and 3 in the list above). This is confirmed by adding more labels - more unnammed symbols are produced.
As far as I can tell, it's just a limitation in nasm. See for example this forum post where the poster has approximately the same issue (although 32-bit rather than 64-bit ELF), and no solution is provided other than using a stripping tool.
In my case, it seems stripping the object file like:
strip --discard-all label-test.o
should do the trick. Despite the name of the --discard-all
option, it only strips local symbols and leaves global symbols alone. Here's the symbol table before stripping the file:
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 label-test.s
0000000000000000 l d .text 0000000000000000 .text
0000000000000002 l .text 0000000000000000 normal_label
0000000000000004 l .text 0000000000000000 normal_label.local_label
0000000000000000 g .text 0000000000000000 _start
and after:
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 label-test.s
0000000000000000 l d .text 0000000000000000 .text
0000000000000000 g .text 0000000000000000 _start
Note in particular that it was smart enough to leave the .text
section symbol alone, even though it is local. Of course this strip option can't really distinguish between useless (loop label) and potentially useful symbols, for example local function entry points which are needed to give correct stack traces with various tools.
If you wanted to be smarter about it, you could selectively strip only the asm-local (i.e., labels starting with a .
) using the --wildcard
and --strip-symbol
options to selectively strip only labels with an embedded .
.
I'm still looking for a better answer if one is lurking out there.
A little late, but I had this problem and wrote a patch for nasm 2.15 that fixes this. It adds a command-line switch called —discard-labels. You can get it here: https://forum.nasm.us/index.php?topic=2666.0
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With