On Monday, June 12, 2023 at 3:57:20 PM UTC+1, Frederick Virchanza Gotham wrote:
>
> So I'm thinking that in order to do something after glibc has shut down,
> I will have to override _exit so that I can put a line or two of code right
> before the syscall to exit.
When my program first starts, before it calls '__libc_start_main', I print out the contents of "/proc/self/status".
And then when my program ends, after all the 'atexit' functions and destructors have been called, I again want to print out the contents of "/proc/self/status".
In order to print the file contents *without* using glibc, I use syscalls in x86_64 assembler.
Here's the x86_64 assembler I've written to print out "/proc/self/status". I'm already able to call this function before jumping into "_start", but I also need to find out some way of calling it right before the "syscall(exit)" is invoked inside '__libc_start_main'. If anyone has any ideas on how to do this then please tell me.
global PrintStatus:function
PrintStatus:
push r15 ; callee-saved - we shall restore later
; On the next 6 lines, I push the string "/proc/self/status"
; onto the stack 8 bytes at a time in Little Endian
mov r15, 0x0000000000000073 ; "s" (with a null terminator)
push r15
mov r15, 0x75746174732f666c ; "lf/statu"
push r15
mov r15, 0x65732f636f72702f ; "/proc/se"
push r15
; On the next 5 lines, I do a 'syscall(read)' to open "/proc/self/status"
mov rax, 2 ; open
mov rdi, rsp ; path
mov rsi, 0 ; flags
mov rdx, 0 ; mode
syscall
; The return value in RAX is the file descriptor, which I will save in r15
mov r15, rax
; If file descriptor is negative then bail out
test r15, r15
js end_of_func
start_loop:
; The next 5 lines read exactly 1 byte from the file
mov rax, 0 ; read
mov rdi, r15 ; fd
mov rsi, rsp ; char *
mov rdx, 1 ; count
syscall
; The next two lines break out of the loop if less than 1 byte was read
cmp rax, 1
jl end_of_func
; The next 5 lines write 1 byte to stdout
mov rax, 1 ; write
mov rdi, 1 ; fd = stdout
mov rsi, rsp ; char const *
mov rdx, 1 ; len
syscall
jmp start_loop
end_of_func:
add rsp, 24 ; take the string "/proc/self/status" back off the stack
pop r15 ; restore the caller's original value of r15
ret