Author Topic: [64bits] Unable to link library (relocation error)  (Read 24267 times)

Offline ironzorg

  • Jr. Member
  • *
  • Posts: 4
[64bits] Unable to link library (relocation error)
« on: February 22, 2012, 09:34:03 PM »
Hi,

The title is pretty much self explanatory: I'm having trouble compiling a library off of a single object.
Here is the code:
Code: [Select]
; my_strlen.S

bits 64

global my_strlen
extern printf

section .rodata
s db "%d", 0x0A, 0

section .text
my_strlen:
push rbp
mov rbp, rsp

mov rdi, s
mov rsi, 0x2A
call printf

xor rax, rax
inc rax

leave
ret

Compilation commands:
Code: [Select]
nasm -f elf64 -o my_strlen.o my_strlen.S
gcc -shared -o libfoo.so my_strlen.o

That last command dies with the following error:
Code: [Select]
/usr/bin/ld: my_strlen.o: relocation R_X86_64_PC32 against undefined symbol `printf@@GLIBC_2.2.5' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
collect2: ld returned 1 exit status

I have no idea how to fix this, I tried using the default instruction (default rel) as it was suggested previously in this forum, but it didn't help.

I could use some help, thanks in advance.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: [64bits] Unable to link library (relocation error)
« Reply #1 on: February 22, 2012, 10:05:45 PM »
I don't know much about 64-bit code, but I understand we need to use both "-shared" and "-fpic". Does that help?

Best,
Frank

Edit: "-fpic" turned out to be the (apparent) solution to this very long thread (different environment, however):
http://forum.nasm.us/index.php?topic=1257.0
« Last Edit: February 22, 2012, 10:22:49 PM by Frank Kotler »

Offline ironzorg

  • Jr. Member
  • *
  • Posts: 4
Re: [64bits] Unable to link library (relocation error)
« Reply #2 on: February 23, 2012, 10:11:46 AM »
I don't know much about 64-bit code, but I understand we need to use both "-shared" and "-fpic". Does that help?

Best,
Frank

Edit: "-fpic" turned out to be the (apparent) solution to this very long thread (different environment, however):
http://forum.nasm.us/index.php?topic=1257.0

Hi Frank,

Yea, I would have used the -fPIC compiler option with gcc if I had control over the object generation, but there's no such option in nasm, so I'm stuck here.

I tried to make a shared library with the above code on Debian and Fedora as well (with the same versions of nasm/gcc, give or take 1 patch), and I had the same error.

However, compiling the my_strlen.S file without the libc call (with the -fPIC flag this time) doesn't throw any error.
« Last Edit: February 23, 2012, 10:18:05 AM by ironzorg »

Offline ironzorg

  • Jr. Member
  • *
  • Posts: 4
Re: [64bits] Unable to link library (relocation error)
« Reply #3 on: February 23, 2012, 04:31:37 PM »
I seems that the answer was in the manuals since the beginning!

I tried using the get_GOT macro defined here (9.2), and it solved my issue.

However, I still find it hard to believe that although the issue is documented in the official manual, nobody has ever talked about it in the forums.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: [64bits] Unable to link library (relocation error)
« Reply #4 on: February 23, 2012, 05:56:35 PM »
Always RTFM. :)

As Zasti points out in that other thread, the manual doesn't mention "-fPIC". Apparently that's a "new" requirement. I don't know when it came in. Seems to me that "-shared" would always imply "-fPIC", but apparently not...

As I see it, your code, as posted, would have two addresses it needs to find: your format string "s", and printf itself. In 32-bit code, we need to do the call/pop "get_GOT" for "s". I would have expected that in 64-bit code, "default rel" would take care of "s"... but perhaps not. For printf, the manual says:
http://www.nasm.us/xdoc/2.10rc8/html/nasmdoc9.html#section-9.2.5
Code: [Select]
call printf wrt ..plt

I guess that would still be required in 64-bit?

Your code, as posted, doesn't actually implement "strlen", of course. I would expect a "real strlen" to be position independent by default, no? In any case, we should know how to call a libc function if we need to.

Please feel free to talk about it here - post up a working example, if you've got one. Forum participants aren't "experts" with all the answers, we're "learners", trying to help one another. Please "be the teacher", when and if you can (everybody!). As it says about Nasm in section 1.1.1 of the manual - we know it ain't perfect, but with your help we'll try to improve it...

Best,
Frank


Offline Rob Neff

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 429
  • Country: us
Re: [64bits] Unable to link library (relocation error)
« Reply #5 on: February 23, 2012, 06:02:34 PM »

The following link provides a nice short-n-sweet treatment of x64 PIC:

http://www.technovelty.org/code/c/amd64-pic.html

Offline ironzorg

  • Jr. Member
  • *
  • Posts: 4
Re: [64bits] Unable to link library (relocation error)
« Reply #6 on: February 24, 2012, 10:54:47 AM »
Quote
As I see it, your code, as posted, would have two addresses it needs to find: your format string "s", and printf itself. In 32-bit code, we need to do the call/pop "get_GOT" for "s". I would have expected that in 64-bit code, "default rel" would take care of "s"... but perhaps not. For printf, the manual says:
http://www.nasm.us/xdoc/2.10rc8/html/nasmdoc9.html#section-9.2.5
Code: [Select]
call printf wrt ..plt

I guess that would still be required in 64-bit?

This link sums it up pretty well.

Quote
Your code, as posted, doesn't actually implement "strlen", of course. I would expect a "real strlen" to be position independent by default, no? In any case, we should know how to call a libc function if we need to.

Yes, here's my implementation of the strlen function:
Code: [Select]
;; my_strlen.S

bits 64

global my_strlen:function

section .text
;; size_t my_strlen(char const*);
my_strlen:
xor al, al

xor rcx, rcx
not rcx

cld
repne scasb

not rcx
dec rcx

mov rax, rcx

ret

I just needed a name for the function I wanted to call printf from, so I picked my_strlen.

The following link provides a nice short-n-sweet treatment of x64 PIC:
http://www.technovelty.org/code/c/amd64-pic.html

Thanks for the link, it was helpful helping me understand where/why my code failed.