1

I'm trying to access the stdin C FILE* type so i can call fgets to get input and echo it back. I can use plt section to access C functions but can't use .got section (which if i understand right is like plt but for data) in the same way for for stdin as a segmentation fault always result from mov instruction after lea

section .bss 
    BUFFERLEN equ 100
    BUFFER: resb BUFFERLEN
section .text
global main
extern stdin, fgets
main: 
default rel
    push rbp             
    mov rbp, rsp          
        ; First get input to print
    
    mov rdi, [rel BUFFER]
    mov rsi, BUFFERLEN
   
    mov rdx, [rel stdin wrt ..gotpc] 
    
    call fgets wrt ..plt
    
    pop rbp
    ret         ; return back to caller   

built and linked with makefile as

proj13: proj13.o
    gcc -pie -fpie -o proj13 proj13.o
proj13.o: proj13.asm
    nasm -g -F DWARF -f elf64 -o proj13.o proj13.asm
KMG
  • 1,433
  • 1
  • 8
  • 19
  • Are you sure dereferencing is the right thing to do here... – Antti Haapala -- Слава Україні Oct 07 '20 at 06:04
  • off-topic, use `lea rdx, [rel BUFFER]` instead of a 64 bit absolute address, otherwise don't bother going through the GOT for libc symbols. (Even for PIE executables, you don't have to, though. Only to support symbol interposition for libraries, like `gcc -fPIC`. https://godbolt.org/z/Kz1oEe shows the GAS `.intel_syntax` equivalent.) – Peter Cordes Oct 07 '20 at 06:04
  • @peterCordes yeah you are right didn't think of it. just wanted to make an example but does it have an effect on outcome ? – KMG Oct 07 '20 at 06:07
  • @AnttiHaapala: yes, it is. `FILE *stdin` is a pointer stored in static storage. You do need to load a pointer from memory and pass it to `fgets`. Not sure why this doesn't work, unless that's the wrong syntax. In a debugger, it seems that `lea` puts `-40` into RCX with an absolute addressing mode. Oh, perhaps that's the problem? Missing `default rel` – Peter Cordes Oct 07 '20 at 06:10
  • @peterCordes the code above is exactly what i use without printing part gonna edit with build and assemble part – KMG Oct 07 '20 at 06:12
  • @peterCordes ```default rel``` seems to still cause segmentation fault, do you get different result. also edited question with build and link makefile if it can help – KMG Oct 07 '20 at 06:17
  • Yeah, I tried that on my machine. It still puts an address very nearby into RCX, different from what GDB shows for `print &stdin` to show the symbol address, or `print (void*)stdin` to show the value. Related: [Access .data section in Position Independent Code](https://stackoverflow.com/q/36223182) for going through the GOT to get to your own data, hopefully works unless `stdin` is special. Probably `wrt ..got` is giving us the offset relative to the start of the GOT, not to the GOT entry from here. – Peter Cordes Oct 07 '20 at 06:24
  • Oh, `fgets()` takes the FILE* as the 3rd arg, in RDX not RDI. https://man7.org/linux/man-pages/man3/fgets.3.html. (Unlike `read()` with an fd.). Wish I'd noticed that sooner, would have saved a bunch of debugging with NASM syntax for GOT-relative. – Peter Cordes Oct 07 '20 at 06:32
  • @peterCordes where in the man page does it link to which registers it takes it parameters since I still can't tell where to put BUFFER address. – KMG Oct 07 '20 at 06:39
  • All libc functions (and all compiler-generated functions) follow the x86-64 System V calling convention. [What are the calling conventions for UNIX & Linux system calls (and user-space functions) on i386 and x86-64](https://stackoverflow.com/q/2535989) – Peter Cordes Oct 07 '20 at 06:39
  • Wish there was some assembler shortcut for the ABI argument registers :D – Antti Haapala -- Слава Україні Oct 07 '20 at 06:59
  • @PeterCordes I still dont know why the error occures if ```rdi->BUFFET```, ```rsi->BUFFERLEN ``` ```rdx->stdin``` segmentation fault still occuer . – KMG Oct 07 '20 at 07:38
  • As in the linked duplicate, `mov rdx, [rel stdin]` works for me, and so does `mov rdx, [rel stdin wrt ..gotpc]` / `mov rdx, [rdx]`. – Peter Cordes Oct 07 '20 at 07:51
  • That's *not* the same as my last comment. You forgot the `mov rdx, [rdx]`. In C terms, you're doing `fgets(..., &stdin)`, just loading its address from the GOT but not dereferencing. (I updated the answer on the linked duplicate to show loading as well, as a reminder you need another load to dereference.) You really don't need to make it this complicated; also as described in [Access .data section in Position Independent Code](//stackoverflow.com/q/36223182), you can do `mov rdx, [rel stdin]` like compilers do in a PIE executable. You only need to go through the GOT for symbol interposition – Peter Cordes Oct 07 '20 at 08:01

0 Answers0