Author Topic: Linker Error: Undefined Reference To 'printf'  (Read 64357 times)

Offline monsterhunter445

  • Jr. Member
  • *
  • Posts: 8
Linker Error: Undefined Reference To 'printf'
« on: February 14, 2011, 01:17:45 AM »
Hi everyone, I am writing a simple NASM program that invokes a C function. It compiles with no errors both the NASM and C code, but when I link the object files I get my favorite linker error *sarcasm* which is an undefined reference to 'printf'. Is there a step I am missing, here is code below:

Code: [Select]
// print.c
#include "/usr/include/stdio.h"
void print(const char* msg)
{
printf(msg);
return;
}

Code: [Select]
[extern print]
section .data
msg: db 'Hello World!', 10
section .text
global _start
_start:
mov eax, msg
push eax
call print

; Exiting
mov eax, 1
mov ebx, 0
int 80h

Code: [Select]
nasm -f elf print.asm
Code: [Select]
gcc -m32 -c print.c
Code: [Select]
ld -melf_i386 -o print asm.o print.o


Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Linker Error: Undefined Reference To 'printf'
« Reply #1 on: February 14, 2011, 01:53:36 AM »
I think you need:

Code: [Select]
ld -melf_i386 -o print asm.o print.o -lc

The "-l" switch to tell ld to look in "libc" (the "lib" is silent :) ).

Alternatively, I think you could do:

Code: [Select]
gcc -m32 -o print print.c asm.o

and let gcc invoke ld for you (with the "correct" command line). You might need "-nostartfiles"... for that way. The C startup files (crt0.o or so) already contain the "_start" label, and call "main"... which you don't want doing it this way.

Not tested, but I think that'll do it.

Best,
Frank


Offline monsterhunter445

  • Jr. Member
  • *
  • Posts: 8
Re: Linker Error: Undefined Reference To 'printf'
« Reply #2 on: February 14, 2011, 02:30:01 AM »
Thanks for the reply; now I don't get the undefined reference to printf. But consequently, I am getting another undefined reference, this time to the print function. I tried add an underscore but it still produces the same problem. It also continues to complain about multiple definitions. Here is the errors below:

Code: [Select]
danny@ubuntu:~/Desktop$ ld -melf_i386 -o print asm.o print.o -lc
print.o: In function `_start':
print.asm:(.text+0x0): multiple definition of `_start'
asm.o:print.asm:(.text+0x0): first defined here
asm.o: In function `_start':
print.asm:(.text+0x7): undefined reference to `print'
print.o: In function `_start':
print.asm:(.text+0x7): undefined reference to `_print'

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Linker Error: Undefined Reference To 'printf'
« Reply #3 on: February 14, 2011, 05:17:05 AM »
Oh, my. The "multiple definition of '_start'" sounds like you've got that "C startup" file linked in. I don't know what the problem is with not being able to find "print" or "_print". Possibly a "cascading error" from the "_start" error?

I'm running a 32-bit system, so I don't need "-m32" or "-melf_i386". There may be other relevant differences. I can get a working program out of your two files in two ways. (I renamed the files slightly) First, assemble the .asm file:

Code: [Select]
nasm -f elf32 print_asm.asm

Then, I can:

Code: [Select]
gcc -o print print_c.c print_asm.o -nostartfiles

Or, I can:

Code: [Select]
gcc -c print_c.c

At this point, if I do what I told you (-lc), in spite of producing the output file, when I try to run it, I get "no such file of directory"(!). I know what this is from. ld, by default, looks for "/lib/ld-linux.so.1"... which doesn't exist. In addition to -lc, I need to tell ld to look for "lib/ld-linux.so.2"... The "-I"(interpreter) or "--dynamic_linker" switch. I forgot to mention that until I actually tried it. Sorry.

Code: [Select]
ld -o print2 print_c.o print_asm.o -lc -I/lib/ld-linux.so.2

Success, a second way. "print2" is a couple bytes smaller, but I think they're basically the same thing. Since the location of the proper interpreter/dynamic loader may differ on your system, it may be easier to let gcc invoke the linker. If "-nostartfiles" isn't working for you, you can always use "main" instead of "_start". Maybe that'll help?

Best,
Frank


Offline monsterhunter445

  • Jr. Member
  • *
  • Posts: 8
Re: Linker Error: Undefined Reference To 'printf'
« Reply #4 on: February 14, 2011, 08:40:34 PM »
Thanks, it links now properly.

Offline monsterhunter445

  • Jr. Member
  • *
  • Posts: 8
Re: Linker Error: Undefined Reference To 'printf'
« Reply #5 on: February 14, 2011, 10:32:05 PM »
Sorry to bother you again, you helped me so much in pointing out my beginner mistakes. But when I type ./print in the terminal, it prompts file or directory not found. I have made sure it was in the right directory and I have tried isolating it in a folder and then using the cd command. But it stills gives that error; I think that it might be because the executable is invalid.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Linker Error: Undefined Reference To 'printf'
« Reply #6 on: February 15, 2011, 12:18:43 AM »
Look at the executable in an editor. A hex-editor would be good, but an ordinary text editor will do. Not too far from the beginning of the file (244 bytes?), you should see something like "lib/ld-linux.so.2". That's the file that's not being found, I strongly suspect. See if you can find such a file, or similar - version number might be different. I suspect, on a 64-bit system, you probably have two versions - one for 64-bit and one for 32-bit. You want the 32-bit version, for this. That's the "interpreter" or "dynamic linker" which allows your program to find "printf", or anything else we're using from a dynamic library. That's the parameter we should be using to the "-I" switch - I told you "-I/lib/ld-linux.so.2" but that might not be right for your system... maybe /lib32/... or something(?).

That's a very confusing error, "no such file or directory", when you can see the file right there! I don't recall who tipped me off to use the "-I" switch - it isn't something you're likely to "figure out" or read in the Friendly Manual.

This isn't the way we're "supposed" to do it. C expects to run that "startup" code which contains the "_start" label and calls "main". It is reasonable to think that we "need" that startup code before "printf" or other libc (or other dynamic library) functions are going to work correctly. My experience is that it works fine without it - I haven't found a case yet where it doesn't, but I keep expecting to. Maybe this is one...

FWIW, a really "invalid" executable (a dos .com file or a Windows executable, say) produces "can't execute binary file", from what I've seen. Linux has got lots of error messages - every so often it coughs up one I haven't seen before. I'm pretty sure "no such file or directory" is from not finding the dynamic linker, but there may be other reasons, too - I'm not familiar with a 64-bit system... gotta upgrade my hardware, one of these days!

Don't worry about "bothering" me! I'm not forced to reply unless I feel like it...

Best,
Frank


Offline monsterhunter445

  • Jr. Member
  • *
  • Posts: 8
Re: Linker Error: Undefined Reference To 'printf'
« Reply #7 on: February 15, 2011, 01:54:06 AM »
Thanks so much for helping me, it works now. You are starting to make me love low-level languages.  ;D