Base build not working on Mac (x86_64 + Lion)?

here is the code (exit.s):

.section .data, .section .text, .globl _start _start: movl $1, %eax movl $32, %ebx syscall 

when I execute " as exit.s -o exit.o && ld exit.o -o exit -e _start && ./exit"

returns "Bus Error: 10" and the output " echo $? " is 138

I also tried an example of the correct answer in this question: Process command line on Linux 64 bit

stil get "bus error" ...

+5
source share
1 answer

Firstly, you are using the old 32-bit Linux kernel kernel convention on Mac OS X - this absolutely does not work.

Secondly, system calls in Mac OS X are structured differently - they all have a leading class identifier and syscall number. The class can be Mach, BSD or something else (see here in the XNU source) and is shifted 24 bits to the left. Normal BSD system calls are class 2 and thus start at 0x2000000 . Syscalls in class 0 are not valid.

According to ยงA.2.1 SysV AMD64 ABI , and then Mac OS X, syscall id (together with its class on XNU!) Goes to %rax (or to %eax , since 32-bit bits are not used in XNU). The fist argument is in %rdi . Next comes %rsi . Etc. %rcx used by the kernel, and its value is destroyed, and therefore all functions from libc.dyld store it in %r10 before executing syscalls (similar to the kernel_trap from syscall_sw.h ).

Thirdly, sections of code in Mach-O __text are called __text , not .text , as in Linux ELF, and are also in the __text segment, collectively called (__TEXT,__text) ( nasm automatically translates .text > if it necessary if Mach-O is selected as the target type) - see Mac OS X ABI Mach-O File Reference . Even if you receive assembly instructions correctly, placing them in the wrong segment / section will result in a bus error. You can either use the .section __TEXT,__text directive (see here for the directive syntax), or you can also use the (more simplified) .text directive, or you can refuse it altogether, as it is assumed that the -n parameter is not specified in as (see as man page).

Fourth, the default entry point for Mach-O ld is called start (although, as you already understood, it can be changed using the -e linker option).

Given all of the above, you should change the assembler source as follows:

 ; You could also add one of the following directives for completeness ; .text ; or ; .section __TEXT,__text .globl start start: movl $0x2000001, %eax movl $32, %edi syscall 

Here it works, as expected:

 $ as -o exit.o exit.s; ld -o exit exit.o $ ./exit; echo $? 32 
+14
source

All Articles