Assembly segmentation fault in example code

40 Views Asked by At

I am new to assembly and I have an AMD processor, so I've been learning x64 assembly from books and tutorials. After inspecting the code in GDB and LDD I see that GLibC is included in the linked libraries, as is ld-linux.so; but I'm not sure if I'm missing something. That or I'm not calling the functions properly with arguments. I was also wondering if I should have added any '[]' around any variables. But the weird thing is that the code is saying that something is missing. But what?

prime.asm

%include "asm_io.inc"
%macro prologue 0
    push    rbp
    mov     rbp,rsp
    push    rbx
    push    r12
    push    r13
    push    r14
    push    r15
    pushfq
%endmacro ; end of  prologue
%macro epilogue 0
    popfq
    pop     r15
    pop     r14
    pop     r13
    pop     r12
    pop     rbx
    leave
    ret
%endmacro ; end of epilogue

section .rodata
    prompt1 db  "Find primes upto: "

section .bss
    guess   resd 1    ; uninitialized integer
    limit   resd 1    ; uninitialized integer

section .text
    global main

    main:
        prologue

        ; enter a value in the variable limit
        mov     rdi, prompt1
        call    print_string
        mov     rdi, dword limit
        call    read_int

        ; print the first 2 prime numbers
        mov     rdi, 0x2
        call    print_int
        call    print_nl
        mov     rdi, 0x3
        call    print_int
        call    print_nl
        mov     [guess],dword 0x5

while_limit:
        mov     eax, [guess] ; since we are dealing with integers, we use the 32-bit register to move data
        mov     edx, [limit] ; since we are dealing with integers
        cmp     eax, edx

        jnbe    end_of_while_limit ; jump if not below or equal

        mov     rcx, 3       ; RCX holds the variable factor

while_factor:
        mov     rax, rcx
        mul     rax           ; calculate factor*factor.  we could use EAX here,
                              ; but using RAX will reduce chances of an overflow

        jo      end_of_while_factor ; we still check for overflow though with jump if overflow

        cmp     eax,[guess]   ; we compare with EAX, otherwise if we use RAX here,
                              ; 8 bytes will be read from the address of the variable guess

        jge     end_of_while_factor ; jump if greater than or equal

        mov     eax,[guess]   ; moving 4 bytes only
        cqo
        div     rcx           ; guess / factor
        cmp     rdx,0         ; guess % factor is in RDX
        je      end_of_while_factor ; jump if equal
        add     rcx,2         ; factor+=2
        jmp     while_factor  ; loop

end_of_while_factor:
        mov     eax,[guess]
        cqo
        div     rcx
        cmp     rdx,0         ; guess%factor is in RDX
        je      end_of_if     ; jump if equal
        mov     edi, [guess]  ; move the value in guess into EDI for printing
        call    print_int
        call    print_nl

end_of_if:
        mov     eax, [guess]
        add     rax, 2          ; guess+=2
        mov     [guess],eax
        jmp     while_limit     ; loop

end_of_while_limit:
        epilogue

asm_io.inc

        extern  print_string2, print_nl2, print_int, read_int, print_string, print_nl

asm_io.asm

%macro prologue 0
                push    rbp
                mov             rbp,rsp
                push    rbx
                push    r12
                push    r13
                push    r14
                push    r15
%endmacro
%macro epilogue 0
                pop             r15
                pop             r14
                pop             r13
                pop             r12
                pop             rbx
                leave
                ret
%endmacro
section .rodata
        int_format      db      "%i",0
    string_format db "%s",0
section .text
        global  print_string2, print_nl2, print_int, read_int
        global print_string, print_nl
        extern printf, scanf, putchar
        print_string2:
                prologue
                ; argument is already in rdi
                mov             rcx,dword -1
                xor             al,al
                cld
                repnz   scasb
                mov             rdx,dword -2
                sub             rdx,rcx
                mov             rsi,rdi
                push    0x1
                pop             rax
                mov             rdi,rax
                syscall
                epilogue

        print_nl2:
                prologue
                ; print 0xa is only one byte
                push    0xA
                mov             rsi,rsp
                push    0x1
                pop             rdx
                mov             rdi,rdx
                mov             rax,rdx
                syscall
                pop             rcx
                epilogue
        print_string:
                prologue
                mov             rsi,rdi
                mov             rdi,dword string_format
                xor             rax,rax
                call    printf
                epilogue
        print_nl:
                prologue
                mov             rdi,0xA
                xor             rax,rax
                call    putchar
                epilogue
        print_int:
                prologue
                ;arg is in rdi
                mov             rsi, rdi
                mov             rdi, dword int_format
                xor             rax,rax
                call    printf
                epilogue

        read_int:
                prologue
                ;rdi is assumed to have the address of the int to be read in
                mov             rsi, rdi
                mov             rdi, dword int_format
                xor     rax,rax
                call    scanf
                epilogue

Build Script

I noticed the linker error for the non supplied section, but it doesn't seem required for the build to run.

└─$ make prime 
yasm -f elf64 prime.asm
yasm -f elf64 asm_io.asm 
ld -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 \
    /usr/lib/x86_64-linux-gnu/crt1.o  /usr/lib/x86_64-linux-gnu/crti.o \
asm_io.o prime.o /usr/lib/x86_64-linux-gnu/crtn.o -lc -o prime.out
ld: warning: prime.o: missing .note.GNU-stack section implies executable stack
ld: NOTE: This behaviour is deprecated and will be removed in a future version of the linker

Debug Inspection

I noticed that there was a missing file. Is it possible that GLibc is not linked correctly?

$ gdb prime.out 
GNU gdb (Debian 13.2-1) 13.2
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from prime.out...
(No debugging symbols found in prime.out)
(gdb) b main
Breakpoint 1 at 0x4011b4
(gdb) run
Starting program: /home/kali/Desktop/assembly/prime.out 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, 0x00000000004011b4 in main ()
(gdb) l 
1       ./elf/sofini.c: No such file or directory.
(gdb) s
Single stepping until exit from function main,
which has no line number information.
zRx
rogram received signal SIGSEGV, Segmentation fault.
0x00007ffff7e27f82 in __vfscanf_internal (s=0x7ffff7f9eaa0 <_IO_2_1_stdin_>, format=0x402004 "%i", 
    argptr=argptr@entry=0x7fffffffdc58, mode_flags=mode_flags@entry=0) at ./stdio-common/vfscanf-internal.c:339
339     ./stdio-common/vfscanf-internal.c: No such file or directory.
(gdb) q
A debugging session is active.

        Inferior 1 [process 70321] will be killed.

ldd output

└─$ ldd prime.out 
        linux-vdso.so.1 (0x00007fffebb91000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f88a63ee000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f88a65e8000)

So my guess is that there are possibly three errors with this tutorial code.

  1. GLibC might not be included properly with LD
  2. Using 32-bit registers improperly with 64-bit registers
  3. Variables not getting set properly.

Either way, I need help and to get out of this Segmentation fault. Please help.

Update

Compiling now with:

prime_gcc:
        yasm -f elf64 prime.asm
        yasm -f elf64 asm_io.asm
        gcc -Wall -m64 -no-pie prime.o asm_io.o -o prime_gcc.out 

GDB Logs

┌──(kali㉿kali)-[~/Desktop/assembly]
└─$ gdb prime_gcc.out
GNU gdb (Debian 13.2-1) 13.2
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from prime_gcc.out...
(No debugging symbols found in prime_gcc.out)
(gdb) b main
Breakpoint 1 at 0x401154
(gdb) run
Starting program: /home/kali/Desktop/assembly/prime_gcc.out 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, 0x0000000000401154 in main ()
(gdb) si
0x0000000000401155 in main ()
(gdb) si
0x0000000000401157 in main ()
(gdb) l
1       ./elf/sofini.c: No such file or directory.
(gdb) si
0x0000000000401159 in main ()
(gdb) l
1       in ./elf/sofini.c
(gdb) si
0x000000000040115b in main ()
(gdb) l
1       in ./elf/sofini.c
(gdb) si
0x000000000040115d in main ()
(gdb) l
1       in ./elf/sofini.c
(gdb) si
0x000000000040115e in main ()
(gdb) l
1       in ./elf/sofini.c
(gdb) si
0x0000000000401165 in main ()
(gdb) si
0x0000000000401230 in print_string2 ()
(gdb) l 
1       in ./elf/sofini.c
(gdb) si
0x0000000000401231 in print_string2 ()
(gdb) l
1       in ./elf/sofini.c
(gdb) si
0x0000000000401234 in print_string2 ()
(gdb) l
1       in ./elf/sofini.c
(gdb) si
0x0000000000401235 in print_string2 ()
(gdb) l
1       in ./elf/sofini.c
(gdb) si
0x0000000000401237 in print_string2 ()
(gdb) x/i $pc 
=> 0x401237 <print_string2+7>:  push   %r13
(gdb) si
0x0000000000401239 in print_string2 ()
(gdb) x/i $pc 
=> 0x401239 <print_string2+9>:  push   %r14
(gdb) si
0x000000000040123b in print_string2 ()
(gdb) x/i $pc 
=> 0x40123b <print_string2+11>: push   %r15
(gdb) si
0x000000000040123d in print_string2 ()
(gdb) x/i $pc 
=> 0x40123d <print_string2+13>: mov    $0xffffffffffffffff,%rcx
(gdb) si
0x0000000000401244 in print_string2 ()
(gdb) x/i $pc 
=> 0x401244 <print_string2+20>: xor    %al,%al
(gdb) si
0x0000000000401246 in print_string2 ()
(gdb) x/i $pc 
=> 0x401246 <print_string2+22>: cld
(gdb) si
0x0000000000401247 in print_string2 ()
(gdb) x/i $pc 
=> 0x401247 <print_string2+23>: repnz scas %es:(%rdi),%al
(gdb) si
0x0000000000401247 in print_string2 ()
(gdb) x/i $pc 
=> 0x401247 <print_string2+23>: repnz scas %es:(%rdi),%al
(gdb) si
0x0000000000401247 in print_string2 ()
(gdb) x/i $pc 
=> 0x401247 <print_string2+23>: repnz scas %es:(%rdi),%al
(gdb) si
0x0000000000401247 in print_string2 ()
(gdb) x/i $pc 
=> 0x401247 <print_string2+23>: repnz scas %es:(%rdi),%al
(gdb) si
0x0000000000401247 in print_string2 ()
(gdb) x/i $pc 
=> 0x401247 <print_string2+23>: repnz scas %es:(%rdi),%al
(gdb) si
0x0000000000401247 in print_string2 ()
(gdb) x/i $pc 
=> 0x401247 <print_string2+23>: repnz scas %es:(%rdi),%al
(gdb) si
0x0000000000401247 in print_string2 ()
(gdb) x/i $pc 
=> 0x401247 <print_string2+23>: repnz scas %es:(%rdi),%al
(gdb) si
0x0000000000401247 in print_string2 ()
(gdb) x/i $pc 
=> 0x401247 <print_string2+23>: repnz scas %es:(%rdi),%al
(gdb) si
0x0000000000401247 in print_string2 ()
(gdb) x/i $pc 
=> 0x401247 <print_string2+23>: repnz scas %es:(%rdi),%al
(gdb) si
0x0000000000401247 in print_string2 ()
(gdb) x/i $pc 
=> 0x401247 <print_string2+23>: repnz scas %es:(%rdi),%al
(gdb) si
0x0000000000401247 in print_string2 ()
(gdb) x/i $pc 
=> 0x401247 <print_string2+23>: repnz scas %es:(%rdi),%al
(gdb) si
0x0000000000401247 in print_string2 ()
(gdb) x/i $pc 
=> 0x401247 <print_string2+23>: repnz scas %es:(%rdi),%al
(gdb) si
0x0000000000401247 in print_string2 ()
(gdb) x/i $pc 
=> 0x401247 <print_string2+23>: repnz scas %es:(%rdi),%al
(gdb) si
0x0000000000401247 in print_string2 ()
(gdb) x/i $pc 
=> 0x401247 <print_string2+23>: repnz scas %es:(%rdi),%al
(gdb) si
0x0000000000401247 in print_string2 ()
(gdb) 
0x0000000000401247 in print_string2 ()
(gdb) si
0x0000000000401247 in print_string2 ()
(gdb) si
0x0000000000401247 in print_string2 ()
(gdb) si
0x0000000000401247 in print_string2 ()
(gdb) si
0x0000000000401249 in print_string2 ()
(gdb) si
0x0000000000401250 in print_string2 ()
(gdb) x/i $pc 
=> 0x401250 <print_string2+32>: sub    %rcx,%rdx
(gdb) si
0x0000000000401253 in print_string2 ()
(gdb) si
0x0000000000401256 in print_string2 ()
(gdb) x/i $pc 
=> 0x401256 <print_string2+38>: push   $0x1
(gdb) si
0x0000000000401258 in print_string2 ()
(gdb) x/i $pc 
=> 0x401258 <print_string2+40>: pop    %rax
(gdb) si
0x0000000000401259 in print_string2 ()
(gdb) x/i $pc 
=> 0x401259 <print_string2+41>: mov    %rax,%rdi
(gdb) si
0x000000000040125c in print_string2 ()
(gdb) x/i $pc 
=> 0x40125c <print_string2+44>: syscall
(gdb) si
%i%s$0x000000000040125e in print_string2 ()
(gdb) x/i $pc 
=> 0x40125e <print_string2+46>: pop    %r15
(gdb) si
0x0000000000401260 in print_string2 ()
(gdb) x/i $pc 
=> 0x401260 <print_string2+48>: pop    %r14
(gdb) si
0x0000000000401262 in print_string2 ()
(gdb) x/i $pc 
=> 0x401262 <print_string2+50>: pop    %r13
(gdb) si
0x0000000000401264 in print_string2 ()
(gdb) x/i $pc 
=> 0x401264 <print_string2+52>: pop    %r12
(gdb) si
0x0000000000401266 in print_string2 ()
(gdb) x/i $pc 
=> 0x401266 <print_string2+54>: pop    %rbx
(gdb) si
0x0000000000401267 in print_string2 ()
(gdb) x/i $pc 
=> 0x401267 <print_string2+55>: leave
(gdb) si
0x0000000000401268 in print_string2 ()
(gdb) x/i $pc 
=> 0x401268 <print_string2+56>: ret
(gdb) si
0x000000000040116a in main ()
(gdb) x/i $pc 
=> 0x40116a <main+26>:  mov    $0x404030,%rdi
(gdb) si
0x0000000000401171 in main ()
(gdb) x/i $pc 
=> 0x401171 <main+33>:  call   0x40130d <read_int>
(gdb) si
0x000000000040130d in read_int ()
(gdb) x/i $pc 
=> 0x40130d <read_int>: push   %rbp
(gdb) si
0x000000000040130e in read_int ()
(gdb) x/i $pc 
=> 0x40130e <read_int+1>:       mov    %rsp,%rbp
(gdb) si
0x0000000000401311 in read_int ()
(gdb) x/i $pc 
=> 0x401311 <read_int+4>:       push   %rbx
(gdb) si
0x0000000000401312 in read_int ()
(gdb) x/i $pc 
=> 0x401312 <read_int+5>:       push   %r12
(gdb) si
0x0000000000401314 in read_int ()
(gdb) x/i $pc 
=> 0x401314 <read_int+7>:       push   %r13
(gdb) si
0x0000000000401316 in read_int ()
(gdb) x/i $pc 
=> 0x401316 <read_int+9>:       push   %r14
(gdb) si
0x0000000000401318 in read_int ()
(gdb) x/i $pc 
=> 0x401318 <read_int+11>:      push   %r15
(gdb) si
0x000000000040131a in read_int ()
(gdb) x/i $pc 
=> 0x40131a <read_int+13>:      mov    %rdi,%rsi
(gdb) si
0x000000000040131d in read_int ()
(gdb) x/i $pc 
=> 0x40131d <read_int+16>:      mov    $0x402018,%rdi
(gdb) si
0x0000000000401324 in read_int ()
(gdb) x/i $pc 
=> 0x401324 <read_int+23>:      xor    %rax,%rax
(gdb) si
0x0000000000401327 in read_int ()
(gdb) x/i $pc 
=> 0x401327 <read_int+26>:      call   0x401050 <scanf@plt>
(gdb) si
0x0000000000401050 in scanf@plt ()
(gdb) x/i $pc 
=> 0x401050 <scanf@plt>:        jmp    *0x2fba(%rip)        # 0x404010 <[email protected]>
(gdb) si
0x0000000000401056 in scanf@plt ()
(gdb) x/i $pc 
=> 0x401056 <scanf@plt+6>:      push   $0x2
(gdb) si
0x000000000040105b in scanf@plt ()
(gdb) x/i $pc 
=> 0x40105b <scanf@plt+11>:     jmp    0x401020
(gdb) si
0x0000000000401020 in ?? ()
(gdb) x/i $pc 
=> 0x401020:    push   0x2fca(%rip)        # 0x403ff0
(gdb) 

0

There are 0 best solutions below