1

I'm playing with GAS assembly and linking it without using gcc. Instead I'm using the as assembler and linking with ld.

My code:

.section .text
.globl _start
_start:
    xorq %rax, %rax
    movb $60, %al
    movb $1, %dil
    int $0x80

The command I use to assemble and link:

 as -g -D -o test.o test.S && ld  --format elf64-x86-64 -o test test.o

And this is the gdb debugging before/after:

(gdb) disas _start
Dump of assembler code for function _start:
   0x0000000000400078 <+0>:     xor    %rax,%rax
   0x000000000040007b <+3>:     mov    $0x3c,%al
   0x000000000040007d <+5>:     mov    $0x1,%dil
   0x0000000000400080 <+8>:     int    $0x80
End of assembler dump.
(gdb) b *_start+8
Breakpoint 1 at 0x400080: file test.S, line 7.
(gdb) r
Starting program: /tmp/test

Breakpoint 1, _start () at test.S:7
7           int $0x80
(gdb) i r
rax            0x3c     60
rbx            0x0      0
rcx            0x0      0
rdx            0x0      0
rsi            0x0      0
rdi            0x1      1
rbp            0x0      0x0
rsp            0x7fffffffebc0   0x7fffffffebc0
r8             0x0      0
r9             0x0      0
r10            0x0      0
r11            0x0      0
r12            0x0      0
r13            0x0      0
r14            0x0      0
r15            0x0      0
rip            0x400080 0x400080 <_start+8>
eflags         0x246    [ PF ZF IF ]
cs             0x33     51
ss             0x2b     43
ds             0x0      0
es             0x0      0
fs             0x0      0
gs             0x0      0
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400082 in ?? ()
(gdb) i r
rax            0x12     18
rbx            0x0      0
rcx            0x0      0
rdx            0x0      0
rsi            0x0      0
rdi            0x1      1
rbp            0x0      0x0
rsp            0x7fffffffebc0   0x7fffffffebc0
r8             0x0      0
r9             0x0      0
r10            0x0      0
r11            0x0      0
r12            0x0      0
r13            0x0      0
r14            0x0      0
r15            0x0      0
rip            0x400082 0x400082
eflags         0x10246  [ PF ZF IF RF ]
cs             0x33     51
ss             0x2b     43
ds             0x0      0
es             0x0      0
fs             0x0      0
gs             0x0      0
(gdb) x/x $rip
0x400082:       0x00000000
(gdb) x/x $rip-2
0x400080 <_start+8>:    0x000080cd

%rip is continuing with his trip through the code to 0x40082 where no code exists. Any idea how can I avoid the SEGFAULT after executing exit() syscall?

Add Stracing the program:

$ strace ./test
execve("./test", ["./test"], [/* 18 vars */]) = 0
exit(1)                                 = 18
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x12} ---
+++ killed by SIGSEGV (core dumped) +++
Segmentation fault (core dumped)
Michael Petch
  • 46,082
  • 8
  • 107
  • 198
  • 4
    You really should use `syscall` rather than `int $0x80` with 64-bit code. The problem is that `int $0x80` system call uses 32-bit Linux system call numbers. Sysexit is 1 instead of 60. 32-bit system calls via `int $0x80` can be found here: http://syscalls.kernelgrok.com/ . As well 32-bit system calls like this (even in 64-bit code) follow the 32-bit convention of passing parameters via ebx, ecx, edx, esi, edi, ebp (in that order). But I reiterate with 64-bit code please use `syscall` instruction rather than `int $0x80` – Michael Petch Jun 20 '17 at 17:38
  • Using syscall fixed the problem. Although, exit syscall in unistd_64.h appears as **$60**: `/usr/include/asm/unistd_64.h:64:#define __NR_exit 60` –  Jun 20 '17 at 17:41
  • Yes, because `int $0x80` is the 32-bit system call interface, not the 64-bit one. unistd_64.h system calls apply to the `syscall` instruction, not `int $0x80`. I gave a link to the 32-bit system calls (and their syscall number) at the link in my first comment. As well parameters with `int $0x80` are via different registers than the 64-bit `syscall` ones as well. `syscall` and `int $0x80` have completely different conventions and numbering. – Michael Petch Jun 20 '17 at 17:43
  • 2
    Nitpicking: `as` is *not* a compiler. It's an *assembler*. Following from this, you can't *compile* things with it, only *assemble* them. – Ben Steffan Jun 20 '17 at 18:22
  • Sorry, you're right. I know the purpose of **as** but I was using the wrong name for it. Thanks –  Jun 20 '17 at 19:59

0 Answers0