NASM - The Netwide Assembler
NASM Forum => Programming with NASM => Topic started by: ironzorg 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:
; 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:
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:
/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.
-
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
-
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.
-
I seems that the answer was in the manuals since the beginning!
I tried using the get_GOT macro defined here (9.2) (http://www.nasm.us/doc/nasmdoc9.html), 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.
-
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
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
-
The following link provides a nice short-n-sweet treatment of x64 PIC:
http://www.technovelty.org/code/c/amd64-pic.html (http://www.technovelty.org/code/c/amd64-pic.html)
-
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
call printf wrt ..plt
I guess that would still be required in 64-bit?
This link (http://www.technovelty.org/code/c/amd64-pic.html) sums it up pretty well.
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:
;; 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 (http://www.technovelty.org/code/c/amd64-pic.html)
Thanks for the link, it was helpful helping me understand where/why my code failed.