Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

All asm labels becoming symbols in executable file

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.

like image 824
BeeOnRope Avatar asked Sep 23 '16 05:09

BeeOnRope


2 Answers

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.

like image 144
BeeOnRope Avatar answered Oct 29 '22 01:10

BeeOnRope


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

like image 40
ProphetOfDoom1982 Avatar answered Oct 29 '22 01:10

ProphetOfDoom1982