I want to compile the following program on Linux:
.global _start
.text
_start:
mov $1, %rax
mov $1, %rdi
mov $msg, %rsi
mov $13, %rdx
syscall
mov $60, %rax
xor %rdi, %rdi
syscall
msg:
.ascii "Hello World!\n"
However, it gives me the following linker error:
$ gcc -nostdlib hello.s
/usr/bin/ld: /tmp/ccMNQrOF.o: relocation R_X86_64_32S against `.text' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status
I figured that the reason it doesn't work is because gcc is using -pie to generate a shared object by default. Thus, using -no-pie fixes it:
$ gcc -no-pie -nostdlib hello.s
$ ./a.out
Hello World!
How do I configure gcc to use -no-pie by default? I'm using Arch Linux.
I guess just don't configure gcc with --enable-default-pie.
See this blog post: http://nanxiao.me/en/gccs-enable-enable-default-pie-option-make-you-stuck-at-relocation-r_x86_64_32s-against-error/, and Arch patch that enabled pie by default: https://git.archlinux.org/svntogit/packages.git/commit/trunk?h=packages/gcc&id=5936710c764016ce306f9cb975056e5b7605a65b.
For this purpose you have to re-compile gcc to disable default PIE. Or you will need -no-pie each time you want to compile position dependent assembly code.
However, just for the example you provided, a better way is to use relative addressing like label_name(%rip).
Relative addressing allows PIE to function properly.
I modified yours into this: (see the leaq line)
.global _start
.text
_start:
movq $1, %rax
movq $1, %rdi
leaq msg(%rip), %rsi
movq $13, %rdx
syscall
movq $60, %rax
xorq %rdi, %rdi
syscall
.section .rodata
msg:
.ascii "Hello World!\n"
(I added .section .rodata just because usually this should be put into rodata section. Your version works fine, but output of objdump -d contains meaningless instructions from msg label.)
Related
This is the code in hello.s
.data
hello_str:
.string "Hello, world!\n"
.set hello_str_length, . - hello_str - 1
.text
.globl main
.type main, #function
main:
movl $4, %eax
movl $1, %ebx
movl $hello_str, %ecx
movl $hello_str_length, %edx
int $0x80
movl $1, %eax
movl $0, %ebx
int $0x80
.size main, . - main
I run gcc hello.s -o hello and get this error:
/usr/bin/ld: /tmp/cc6ILJpd.o: relocation R_X86_64_32 against '.data' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status
Then I've tried running gcc hello.s -fPIC -o hello, but it didn't do anything, the error is the same.
What am I doing wrong? Ubuntu 17.04, GCC 6.3.0.
You're trying to compile i386 code in amd64 mode, which doesn't work. Try this instead:
gcc -m32 hellos. -o hello
...to force i386 mode.
Edit: I recognised this because I know what i386 and amd64 code looks like, but a better clue is in the relocation name, R_X86_64_32. X86_64 is another name for the amd64 architecture; so what this is saying is that it's a 32 bit relocation for the X86_64 architecture. Given that you're not writing code for that architecture, that's a reasonable sign that it's the wrong compiler.
I wrote the code below. I want to compile it using gcc on mac OS X,
but I get a message saying "PIE disabled. Absolute addressing" when I run gcc.
I googled it, but cannot find a solution.
Please advise.
hello.s file:
.data
hello: .string "Hello World!\n"
.text
.globl _main
_main:
push %rbp
mov %rsp, %rbp
movabs $hello, %rdi
call _printf
leave
ret
The error:
ld: warning: PIE disabled. Absolute addressing (perhaps -mdynamic-no-pic) not allowed in
code signed PIE, but used in _main from /var/folders/xs/4z9kr_n93111fhv9_j1dd9gw0000gn/T/ex2_64-369300.o.
To fix this warning, don't compile with -mdynamic-no-pic or link with -Wl,-no_pie
Looks like there are a couple solutions:
Link with -Wl,-no_pie:
clang -o hello hello.s -Wl,-no_pie
Don't use absolute addressing.
.data
hello: .string "Hello World!\n"
.text
.globl _main
_main:
push %rbp
mov %rsp, %rbp
lea hello(%rip), %rdi
mov $0, %rax
call _printf
leave
ret
Then you can compile and run:
host % clang -o hello hello.s
host % ./hello
Hello World!
The bit about zeroing out al is mentioned in section 3.5.7 of System V Application Binary Interface. Here's the relevant excerpt:
When a function taking variable-arguments is called, %al must be set
to the total num- ber of floating point parameters passed to the
function in vector registers.
In your case this is zero. You are passing in zero floating point parameters.
I've run into an issue after following this tutorial - https://www.youtube.com/watch?v=RvvRO_gWYIg
A few possible issues:
it looks like the processor architecture and operating system may differ quite heavily from the one I'm working on. In the video it seems to be an i386 linux box, and I'm working on an x64 OSX machine.
When commenting out the helloWorldStr reference, it starts working again.
Assembling on a 64 bit machine with 32 bit instructions
Posted below is the broken code, any help would be greatly appreciated!
# Hello World Program:
.data
HelloWorldStr:
.ascii "Hello World"
.text
.globl start
start:
# Load all the arguments for write():
# write(output, string, string_size)
movl $4, %eax # Load write()
movl $1, %ebx # Arg Output of write() :: STDOUT
movl $HelloWorldStr, %ecx # Referencing the Memory Loc. of the String
movl $11, %edx # Byte length of the String "Hello World"
int $0x80
# Call Exit:
movl $1, %eax
movl $0, %ebx
int $0x80
Also, here are some errors that have arisen:
Undefined symbols for architecture x86_64:
"_main", referenced from:
start in crt1.10.6.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
So I changed _start to _main and then that passed on to the next error:
gcc HelloWorldProgram.s -m32
ld: warning: PIE disabled. Absolute addressing (perhaps -mdynamic-no-pic) not allowed in code signed PIE, but used in _main from /var/folders/8t/7639_vls58lgd1nnwx4dpbh40000gn/T//cc3wDW8K.o. To fix this warning, don't compile with -mdynamic-no-pic or link with -Wl,-no_pie
You might check out this answer from a previous question. The user was also using Mac OS X and following a similar tutorial that was taught using Linux.
Here's an example hello world generated with a slightly newer compiler than the linked to answer (it's still quite similar).
hello.s
.section __TEXT,__cstring,cstring_literals
L_.str:
.asciz "Hello world!\n"
.section __TEXT,__text,regular,pure_instructions
.globl _main
.align 4, 0x90
_main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
movl $L_.str, (%esp)
call _puts
xorl %eax, %eax
addl $8, %esp
popl %ebp
ret
.subsections_via_symbols
I'm trying to follow the book Professional Asssembly Language on Mac OS X Montain Lion.
On google I found a port for Mac OS X at the following url: Assembly on MacOS X
Created the file with Vim and compiled it with GAS:
as -g -arch i386 -o cpuid.o cpuid.s
Linked the code using gcc:
gcc -m32 -arch i386 -o cpuid cpuid.o
The resulting executable cpuid, runs without errors but if I try to debug it with gdb at the end it says Program exited with code 044 instead of Program exited normally.
Trying to find a way to make it exit correctly I've created an hello world example in C and generated assembly code it with:
gcc -Wall -03 -m32 -fno-PIC hello_pf.c -S -o hello_pf.s
The resulting assembly code is bellow:
.section __TEXT,__text,regular,pure_instructions
.globl _main
.align 4, 0x90
_main:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
leal L_.str, %eax
movl %eax, (%esp)
call _puts
movl $0, -8(%ebp)
movl -8(%ebp), %eax
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
addl $24, %esp
popl %ebp
ret
.section __TEXT,__cstring,cstring_literals
L_.str:
.asciz "Hello world!\n"
.subsections_via_symbols
Can someone provide any help regarding this issue?
How can I make a working version of cpuid from the link provided above using IA-32 mac ox s assembly?
Where can I look for a detailed description of stack align problem in Mac OS X? I've read what's on Apple site but for a beginner is not very helpful.
What are for the instructions after call _puts from the above sample code?
How does calling libc functions from assembly really works? Any good detailed articles on this topic?
Thank you!
First you need to understand the register usage in the calling conventions, a good place for that is
http://www.agner.org/optimize/calling_conventions.pdf
You will find that on Mac OS X 64-bit the return value for a function returning an "int" - such as main() - is in %rax. You seem to want to use a 32-bit executable, in which case the return value is in %eax. One convenient way to zero out a register is to XOR it with itself, so you should add this to the end of your routine:
xorl %eax,%eax
That'll set %eax to zero, and that will be your exit code.
.text
.globl _start
_start:
pushq %rbp
movq %rsp,%rbp
movq $2, %rax
leaveq
retq
I'm compiling with -nostdlib:
[root# test]# gcc -nostdlib -Wall minimal.S &&./a.out
Segmentation fault
What's wrong here?
BTW,is it possible to make the entry point other names than main and _start?
As #jaquadro mentions, you can specify the entry point on the command line to the linker (or use a link script): gcc -Wall -Wextra -nostdlib -Wl,-eMyEntry minimal.S && ./a.out
The reason your program segfaults is, that since you're not using the standard library there is nowhere to return back to (retq). Instead call exit using the correct syscall (in this case it is 60, which is put into rax, the first (and only) parameter is put into rdi.
Example:
.text
.globl MyEntry
MyEntry:
# Use Syscall 60 (exit) to exit with error code 42
movq $60, %rax
movq $42, %rdi
syscall
Related question on how to perform syscalls on x86_64
You can set the entry point by passing an option to the linker
http://sca.uwaterloo.ca/coldfire/gcc-doc/docs/ld_24.html
To do this with gcc, you would do something like...
gcc all_my_other_gcc_commands -Wl,-e,start_symbol
main is different, it is not the entry point to your compiled application, although it is the function that will be called from the entry point. The entry point itself, if you're compiling C or C++ code, is defined in something like Start.S deep in the source tree of glibc, and is platform-dependent. If you're programming straight assembly, I don't know what actually goes on.