load warning: cannot find entry symbol _start
Use the label _start
instead of main
for the ELF entry point. main
implies it's like the C main
function, but this isn't even a function (e.g. you can't ret
).
You don't say, but from the warning messages and code I assume you're building your 32-bit code with nasm -felf32 hello32.asm && ld -melf_i386 -o hello32 hello32.o
(If you're actually building 64-bit code, you're lucky that it happens to work, but it'll break as soon as you do anything with esp
instead of rsp
.)
The warning message is from ld
, not from nasm
. It says so right in the message. Tim's comment is correct: ld
looks for a _start
symbol in the files it links, but sets the entry point to the beginning of the text segment if it doesn't find one. (That's why this is a warning, not an error. If you had put some other code earlier in the file, execution would start there without global _start
/ _start:
)
It doesn't matter what other global/external symbols you define. main
has no relevance at all here, and could point anywhere you want. It's only useful for a disassembly output and stuff like that. Your code would work exactly the same if you took out the global main
/ main:
lines, or changed them to any other name.
Labelling that as main
is unwise because the ELF entry point is not a function. It's not main()
, and doesn't receive argc
and argv
arguments in the standard way, and can't ret
because ESP is pointing at argc
instead of a return address.
Only use main
if you link with gcc / glibc's CRT startup code that looks for a main
symbol and calls it after initializing libc. (So functions like printf work. Technically dynamic linker hooks let libc initialize itself before your _start
if you linked it, but generally don't do that unless you understand exactly what you're doing). Related: Assembling 32-bit binaries on a 64-bit system (GNU toolchain)
e.g. gcc -m32 -no-pie -o hello main.o
if you do define a main:
instead of gcc -m32 -static -nostdlib -o hello start.o
(which is equivalent to your bare ld
).
(For the past few years, Linux distros have configured GCC with -pie
as the default, which wants position-independent code. But that's really inconvenient in 32-bit mode where you don't have x86-64 RIP-relative addressing (look at GCC asm output for example), and means ld
won't convert call printf
into call printf@plt
for you. So for most hand-written asm following most tutorials, you want traditional non-PIE executables so no text relocations are needed.)
ld: warning: cannot find entry symbol _start; defaulting to 0000000000401000
ld
by itself links no libraries or startup code. It's suitable for a program where you use _start
as an entry point and do I/O via direct calls to the kernel instead of standard C library functions. But your program uses main
as its entry point, so it expects to be called by C startup code, and it calls library functions like printf
. Hence you should link it like a C program:
gcc -no-pie -o quadratic quadratic.o
The -no-pie
option is needed because your code makes absolute references to static data, e.g. fld qword[b]
. gcc by default assumes you want to build a position-independent executable, which can't do that; you'd need to write fld qword[rel b]
to produce an rip-relative effective address. So -no-pie
asks gcc to link a non-position-independent executable. See Why use RIP-relative addressing in NASM? for more on this.
warning: cannot find entry symbol _start; defaulting to 0000000008048060
It's really only in C (and C++) that the starting point is named main
.
The default linker script usually uses start
or _start
for the actual entry point. If you rename or add the correct symbol then the linker should not complain about that.
warning: cannot find entry symbol _start - while compiling to .so
Removing -fPIE
and -pie
flags solved my problem.-pie
shouldn't be used when you are trying to create shared library,
and also -fPIE
shouldn't be used in most of the cases.
ld: warning: cannot find entry symbol main; not setting start address
You are trashing your os.o
(input same as output)
Change:
ld -m elf_i386 -nmagic -T os.ld os.o -o os.o
Into:
ld -m elf_i386 -nmagic -T os.ld os.o -o osx
Thanks, that fixed it. I was trying to overwrite it on purpose. Can you explain why it caused that error? – Felix B.
ld
[and most such build commands] do not allow an input file to be specified as an output file.
ld
may have to read os.o
several times while writing the -o osx
output file.
The simple construction is that we open a file for read and an output file for writing when the program starts.
For what you wanted, the program would have to detect that infile and outfile are the same and create a temp copy of infile.
Too difficult to guarantee in the general case. It's rarely used and would slow things down.
Also, if you put the commands in a makefile:
all: osx
os.o: os.c
gcc -ffreestanding -nostdlib -gdwarf-4 -m32 -ggdb3 -c os.c -o os.o
osx: os.o os.ld
ld -m elf_i386 -nmagic -T os.ld os.o -o osx
If ld
produced an error, make
would remove the osx
file.
Consider that if os.o
was the the output file, this would mess up the dependencies that make
relies on.
Related Topics
How to Get Errno When Epoll_Wait Returns Epollerr
How to Pass Env Variables Between Make Targets
How to Install Google Test on Ubuntu Without Root Access
File Format Differences Between a Static Library (.A) and a Shared Library (.So)
How to Idiomatically Package Dependencies for a Qt Application Using Cpack
How to Send Signal from One Program to Another
Checking for Null String in Bash
How to Curl Using Ipv6 Address
Running Docker on Google Colab
How to Make Ssh Command Execution to Timeout
How to Route Tcp/Ip Responses Through a Different Interface
How Can Beaglebone Black Be Used as Mass Storage Device
Jenkins Failed to Start in Linux
Jenkins/Hudson Ci Minimum Requirements for a Linux Rh Installation