1

I'm watching a video in an attempt to better understand object files. The presenter uses the following as an example of a program that produces a very simple object file:

extern "C" void _start() {
    asm("mov $60, %eax\n"
        "mov $24567837, %edi\n"
        "syscall\n");
}

The program is compiled via

clang++ -c step0.cpp -O1 -o step0.o

and linked via

ld -static step0.o -o step0

I get this error message when trying to link:

Undefined symbols for architecture x86_64:
  "start", referenced from:
     -u command line option
     (maybe you meant: __start)
ld: symbol(s) not found for inferred architecture x86_64

I don't pass the -u command line option, so I'm not sure why I'm getting that error message.

lane0335
  • 124
  • 12

1 Answers1

2

clang isn't removing an underscore, it's adding an underscore. Your program is actually exporting a __start symbol, but ld expects you to have a start symbol for your entry point, i.e. ld runs with -u start by default for your architecture.

You could disable this check in ld with -U start (which suppresses the error from the start symbol being undefined) or via -undefined suppress (which suppresses all undefined symbol errors). However, you will end up with an executable that does not have an entry point for your architecture, so the program won't actually work.

Instead of suppressing the error, I suggest controlling the symbol that clang chooses directly. You can tell clang what symbol to generate by using a standalone asm declaration:

void _start() asm ("start");

Make sure this standalone declaration is separate from the function definition.

You can read more about controlling the symbols generated by gcc here: https://stackoverflow.com/a/1035937/12928775

Also, as was pointed out in a comment to a similar answer, you will most likely want to use __attribute__((naked)) on the function definition to prevent clang from generating a stack frame on entry. See: https://stackoverflow.com/a/60311490/12928775

Sofia Faro
  • 51
  • 3