1

I want to allocate some nodes for a linked list. I have an alloc_pair function which seems to work. I included comments to explain the intent of each line in regards to linked lists. My code is giving me a segmentation fault somewhere, but I can't figure out where. GDB is unhelpful as seen here:

Thread 2 hit Breakpoint 1, 0x0000000100003f63 in main ()
(gdb) c
Continuing.

Thread 2 hit Breakpoint 2, 0x0000000100003f4e in alloc_pair ()
(gdb) ni
0x0000000100003f55 in alloc_pair ()
(gdb) ni
0x0000000100003f59 in alloc_pair ()
(gdb) disassemble
Dump of assembler code for function alloc_pair:
   0x0000000100003f4e <+0>: mov    rdi,0x10
   0x0000000100003f55 <+7>: sub    rsp,0x8
=> 0x0000000100003f59 <+11>:    call   0x100003f96
   0x0000000100003f5e <+16>:    add    rsp,0x8
   0x0000000100003f62 <+20>:    ret    
End of assembler dump.
(gdb) c
Continuing.

Thread 2 received signal SIGSEGV, Segmentation fault.
0x00007fff731d970a in ?? ()
(gdb) bt
#0  0x00007fff731d970a in ?? ()
#1  0x00007ffeefbff828 in ?? ()
#2  0x0000000100008008 in ?? ()
#3  0x0000000000000000 in ?? ()
(gdb) 

If you know the mistake that I am making, please let me know.

    .global _main
    .text

alloc_pair:
    push rbp
    mov rbp, rsp
    mov rdi, 16
    sub rsp, 8
    call _malloc
    add rsp, 8
    mov rsp, rbp
    pop rbp
    ret

_main:
    call alloc_pair

    mov r13, rax  # r13 stores the initial pair allocated

    mov qword ptr [rax], 29  # the node 1 head contains 29
    mov r12, [rax + 8]  # r12 stores the memory location of the node 1 tail

    call alloc_pair

    mov qword ptr [rax], 7  # the node 2 head contains 7
    mov qword ptr [r12], rax  # the node 1 tail points to the node 2 head

    mov rdi, 0
    mov rax, 0x2000001
    syscall
trincot
  • 317,000
  • 35
  • 244
  • 286
Caspian Ahlberg
  • 934
  • 10
  • 19
  • You load r12 from uninitialized memory. Perhaps you meant to use LEA? – prl Oct 22 '20 at 17:42
  • You need to save and restore r12 and r13. – prl Oct 22 '20 at 17:43
  • @prl What do you mean by "save and restore"? – Caspian Ahlberg Oct 22 '20 at 17:56
  • @MichaelPetch this source (https://stackoverflow.com/questions/18024672/what-registers-are-preserved-through-a-linux-x86-64-function-call) tells me that `r12` through `r15` are preserved across function calls. Are you right or is this source right? I'm curious. – Caspian Ahlberg Oct 22 '20 at 18:01
  • Yes, r12..r15 are call-preserved. If your `main` returned, it should preserver its caller's values in those registers. But if you're just going to exit without returning, that doesn't matter so it's fine for `main` to use them without pushing them first. – Peter Cordes Oct 23 '20 at 01:50

1 Answers1

2

This line:

mov r12, [rax + 8]  # r12 stores the memory location of the node 1 tail

doesn't do what your comment says it does. This instruction moves the 64-bit contents of memory at [rax+8] to R12. It doesn't move the address of [rax+8] to R12. What you want is to Load Effective Address (LEA) to get the address of [rax+8] into R12. The instruction would look like:

lea r12, [rax + 8]  # r12 stores the memory location of the node 1 tail
Michael Petch
  • 46,082
  • 8
  • 107
  • 198