Finding the rendezvous (struct r_debug) structure of a process? - c

I'm trying to access the "rendezvous structure" (struct r_debug *)
in order to find the link map of a process.
But I keep running into invalid adresses and I really can't figure out
what's going on.
Here's how I go on trying to find it:
1. Get the AT_PHDR value from the auxiliary vector
2. Go through the program headers until I find the PT_DYNAMIC segment
3. Try to access the vaddr of that segment (PT_DYNAMIC) to get the dynamic tags
4. Iterate through the dynamic tags until I find DT_DEBUG. If I get here I should be done
The issue is I can't get past step 3 because the vaddr of the PT_DYNAMIC
segment always points to an invalid address.
What am I doing wrong ? Do I need to find the relocation of the vaddr ?
I have looked at the LLDB sources but I can't figure out how they got the address.
UPDATE: #EmployedRussian was right, I was looking at a position-independent executable.
His solution to calculate the relocation worked wonderfully.

What am I doing wrong ?
Most likely you are looking at position-independent executable. If your readelf -Wl a.out looks like this:
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000040 0x0000000000000040 0x0000000000000040 0x0001f8 0x0001f8 R 0x8
INTERP 0x000238 0x0000000000000238 0x0000000000000238 0x00001c 0x00001c R 0x1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x016d28 0x016d28 R E 0x200000
LOAD 0x017250 0x0000000000217250 0x0000000000217250 0x0010d0 0x001290 RW 0x200000
DYNAMIC 0x017df8 0x0000000000217df8 0x0000000000217df8 0x0001e0 0x0001e0 RW 0x8
then you need to adjust Phdr_pt_dynamic.p_vaddr by the executable relocation address (the key is that the first Phdr_pt_load.p_vaddr == 0).
You can find this relocation address as the delta between AT_PHDR value in the aux vector and Phdr_pt_phdr.p_vaddr.
(Above I use Phdr_xxx as a shorthand for Phdr[j] with .p_type == xxx).
You are also doing it in much more complicated way than you have to: the address of the dynamic array is trivially available as _DYNAMIC[]. See this answer.

Related

Why are instructions addresses on the top of the memory user space contrary to the linux process memory layout?

#include <stdio.h>
void func() {}
int main() {
printf("%p", &func);
return 0;
}
This program outputted 0x55c4cda9464a
Supposing that func will be stored in the .text section, and according to this figure, from CS:APP:
I suppose that the address of func would be somewhere near the starting address of the .text section, but this address is somewhere in the middle. Why is this the case? Local variables stored on the stack have addresses near 2^48 - 1, but I tried to disassemble different C codes and the instructions were always located somewhere around that 0x55... address.
gcc, when configured with --enable-default-pie1 (which is the default), produces Position Independent Executables(PIE). Which means the load address isn't same as what linker specified at compile-time (0x400000 for x86_64). This is a security mechanism so that Address Space Layout Randomization (ASLR) 2 can be enabled. That is, gcc compiles with -pie option by default.
If you compile with -no-pie option (gcc -no-pie file.c), then you can see the address of func is closer to 0x400000.
On my system, I get:
$ gcc -no-pie t.c
$ ./a.out
0x401132
You can also check the load address with readelf:
$ readelf -Wl a.out | grep LOAD
LOAD 0x000000 0x0000000000400000 0x0000000000400000 0x000478 0x000478 R 0x1000
LOAD 0x001000 0x0000000000401000 0x0000000000401000 0x0001f5 0x0001f5 R E 0x1000
LOAD 0x002000 0x0000000000402000 0x0000000000402000 0x000158 0x000158 R 0x1000
LOAD 0x002e10 0x0000000000403e10 0x0000000000403e10 0x000228 0x000230 RW 0x1000
1 you can check this with gcc --verbose.
2 You may also notice that address printed by your program is different in each run. That's because of ASLR. You can disable it with:
$ echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
ASLR is enabled on Linux by default.

Where in object file does the code of function "main" starts?

I have an object file of a C program which prints hello world, just for the question.
I am trying to understand using readelf utility or gdb or hexedit(I can't figure which tool is a correct one) where in the file does the code of function "main" starts.
I know using readelf that symbol _start & main occurs and the address where it is mapped in a virtual memory. Moreover, I also know what the size of .text section and the of coruse where entry point specified, i.e the address which the same of text section.
The question is - Where in the file does the code of function "main" starts? I tought that is the entry point and the offset of the text section but how I understand it the sections data, bss, rodata should be ran before main and it appears after section text in readelf.
Also I tought we should sum the size all the lines till main in symbol table, but I am not sure at all if it is correct.
Additional question which follow up this one is if I want to replace main function with NOP instrcutres or plant one ret instruction in my object file. how can I know the offset where I can do it using hexedit.
So, let's go through it step by step.
Start with this C file:
#include <stdio.h>
void printit()
{
puts("Hello world!");
}
int main(void)
{
printit();
return 0;
}
As the comments look like you are on x86, compile it as 32-bit non-PIE executable like this:
$ gcc -m32 -no-pie -o test test.c
The -m32 option is needed, because I am working at a x86-64 machine. As you already know, you can get the virtual memory address of main using readelf, objdump or nm, for example like this:
$ nm test | grep -w main
0804918d T main
Obviously, 804918d can not be an offset in the file that is just 15 kB big. You need to find the mapping between virtual memory addresses and file offsets. In a typical ELF file, the mapping is included twice. Once in a detailed form for linkers (as object files are also ELF files) and debuggers, and a second time in a condensed form that is used by the kernel for loading programs. The detailed form is the list of sections, consisting of section headers, and you can view it like this (the output is shortened a bit, to make the answer more readable):
$ readelf --section-headers test
There are 29 section headers, starting at offset 0x3748:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[...]
[11] .init PROGBITS 08049000 001000 000020 00 AX 0 0 4
[12] .plt PROGBITS 08049020 001020 000030 04 AX 0 0 16
[13] .text PROGBITS 08049050 001050 0001c1 00 AX 0 0 16
[14] .fini PROGBITS 08049214 001214 000014 00 AX 0 0 4
[15] .rodata PROGBITS 0804a000 002000 000015 00 A 0 0 4
[...]
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
p (processor specific)
Here you find that the .text section starts at (virtual) address 08049050 and has a size of 1c1 bytes, so it ends at address 08049211. The address of main, 804918d is in this range, so you know main is a member of the text section. If you subtract the base of the text section from the address of main, you find that main is 13d bytes into the text section. The section listing also contains the file offset where the data for the text section starts. It's 1050, so the first byte of main is at offset 0x1050 + 0x13d == 0x118d.
You can do the same calculation using program headers:
$ readelf --program-headers test
[...]
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x00160 0x00160 R 0x4
INTERP 0x000194 0x08048194 0x08048194 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
LOAD 0x000000 0x08048000 0x08048000 0x002e8 0x002e8 R 0x1000
LOAD 0x001000 0x08049000 0x08049000 0x00228 0x00228 R E 0x1000
LOAD 0x002000 0x0804a000 0x0804a000 0x0019c 0x0019c R 0x1000
LOAD 0x002f0c 0x0804bf0c 0x0804bf0c 0x00110 0x00114 RW 0x1000
[...]
The second load line tells you that the area 08049000 (VirtAddr) to 08049228 (VirtAddr + MemSiz) is readable and executable, and loaded from offset 1000 in the file. So again you can calculate that the address of main is 18d bytes into this load area, so it has to reside at offset 0x118d inside the executable. Let's test that:
$ ./test
Hello world!
$ echo -ne '\xc3' | dd of=test conv=notrunc bs=1 count=1 seek=$((0x118d))
1+0 records in
1+0 records out
1 byte copied, 0.0116672 s, 0.1 kB/s
$ ./test
$
Overwriting the first byte of main with 0xc3, the opcode for return (near) on x86, causes the program to not output anything anymore.
_start normally belongs to a module ( a *.o file) that is fixed (it is called differently on different systems, but a common name is crt0.o which is written in assembler.) That fixed code prepares the stack (normally the arguments and the environment are stored in the initial stack segment by the execve(2) system call) the mission of crt0.s is to prepare the initial C stack frame and call main(). Once main() ends, it is responsible of getting the return value from main and calling all the atexit() handlers to finish calling the _exit(2) system call.
The linking of crt0.o is normally transparent due to the fact that you always call the compiler to do the linking itself, so you normally don't have to add crt0.o as the first object module, but the compiler knows (lately, all this stuff has grown considerably, since we depend on architecture and ABIs to pass parameters between functions)
If you execute the compiler with the -v option, you'll get the exact command line it uses to call the linker and you'll get the secrets of the final memory map your program has on its first stages.

readelf 'Align' column unit

I have the following simple "hello world" program:
#include <stdio.h>
int main() {
printf("Hello world.\n");
return 0;
}
I compile it as
gcc -static -O0 -g -std=gnu11 -o test_helloworld test_helloworld.c -lpthread
Now, I want check its memory segment by issuing readelf -l and obtain the following output:
Elf file type is EXEC (Executable file)
Entry point 0x400890
There are 6 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x00000000000c96cf 0x00000000000c96cf R E 200000
LOAD 0x00000000000c9eb8 0x00000000006c9eb8 0x00000000006c9eb8
0x0000000000001c98 0x00000000000035b0 RW 200000
NOTE 0x0000000000000190 0x0000000000400190 0x0000000000400190
0x0000000000000044 0x0000000000000044 R 4
TLS 0x00000000000c9eb8 0x00000000006c9eb8 0x00000000006c9eb8
0x0000000000000020 0x0000000000000050 R 8
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 10
GNU_RELRO 0x00000000000c9eb8 0x00000000006c9eb8 0x00000000006c9eb8
0x0000000000000148 0x0000000000000148 R 1
I got confused by Align column: are those number in bytes or kilobytes? I thought align should be equal to the page size. Why am I getting those number?
Thanks!
This is what System V Application Binary Interface says this about p_align:
Values 0 and 1 mean no alignment is required. Otherwise, p_align should be a positive, integral power of 2, and p_vaddr should equal p_offset, modulo p_align.
So p_align doesn't need to be equal to the page size.

Why is there no stack segment in an object (ELF) files?

I am beginner of OS. This question is given by my professor and confused me a lot. I hope I can get some hints and helps here.
In my memory, ELF file can link each other. Is that a reason that ELF file cannot have stack segment?
Thanks a lot for any helps!
This is because stack is not something need to be saved in a file format, it is completely related to runtime execution. Just like you don't need to have a "heap segment" in your file.
On the other hand, stack belongs to an executing thread, not data or functions, and it doesn't has a fixed size. Consider a recursive function:
int foo() {
printf("Stack Overflow!\n");
return foo();
}
every recursion has its own frame in stack, there is no stack belong to foo() itself, only for its execution.
Of course you can reserve a stack segment in your file, just as a big block of static memory, and let the %rsp pointer(x64) pointing to it. But OS has already done for you, so it's not necessary.
Most GNU/Linux ELF programs do have stack segments because on all but very recent architectures, a stack segment in the program header is used to mark the stack as non-executable (which is a form of security hardening).
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x00000000000001f8 0x00000000000001f8 R E 0x8
INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238
0x000000000000001c 0x000000000000001c R 0x1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x00000000000ffd0c 0x00000000000ffd0c R E 0x200000
LOAD 0x0000000000100548 0x0000000000700548 0x0000000000700548
0x000000000000b6fc 0x0000000000015440 RW 0x200000
…
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 0x10
GNU_RELRO 0x0000000000100548 0x0000000000700548 0x0000000000700548
0x0000000000002ab8 0x0000000000002ab8 R 0x1
On certain GNU/Linux architectures (FDPIC), the size of the stack segment is even used by the kernel to set the stack size of the main thread.
(There are different kinds of program segments. Not all of them load bits from the file image.)

Understanding GCC generated map files

I'm trying to write a script that parses .map files generated by GCC and help me figure out what the footprints of various libraries are in memory. (Github repository of what I have so far)
I'm trying to understand what the following means / how it should be read :
.debug_line 0x00000000 0x67b1
*(.debug_line .debug_line.* .debug_line_end)
.debug_line 0x00000000 0x105 /opt/ti/gcc/bin/../lib/gcc/msp430-elf/4.9.1/../../../../msp430-elf/lib/crt0.o
.debug_line 0x00000105 0x4b5 CMakeFiles/firmware-msp430f5529.elf.dir/main.c.obj
.debug_line.text.bc_printf.constprop.1
0x000005ba 0x23 CMakeFiles/firmware-msp430f5529.elf.dir/main.c.obj
.debug_line.text.deferred_exec
0x000005dd 0x60 CMakeFiles/firmware-msp430f5529.elf.dir/main.c.obj
.debug_line.text.startup.main
0x0000063d 0xfc CMakeFiles/firmware-msp430f5529.elf.dir/main.c.obj
.debug_line_end
0x00000739 0x0 CMakeFiles/firmware-msp430f5529.elf.dir/main.c.obj
I've been assuming the first line, which is not indented, is some sort of section heading and that the address (0x0000000) somehow relates to where the contents of the section should be written. 0x00000000 somehow results in the contents being discarded.
The indented lines (those which start with .debug_line) also have an address. These addresses, when the symbol is going to be written to the binary, are absolute.
.text 0x000048d8 0x3312
0x000048d8 . = ALIGN (0x2)
*(.lower.text.* .lower.text)
0x000048d8 . = ALIGN (0x2)
*(.text .stub .text.* .gnu.linkonce.t.* .text:*)
.text 0x000048d8 0xa4 /opt/ti/gcc/bin/../lib/gcc/msp430-elf/4.9.1/crtbegin.o
.text.bc_printf.constprop.1
0x0000497c 0x1a CMakeFiles/firmware-msp430f5529.elf.dir/main.c.obj
How does the address in the section heading, or whatever the first line should be called, translate to the address in the actual symbols and so forth? i.e., How would 0x00000000 result in the symbols being discarded (even though the addresses they contain may indeed be valid writeable locations otherwise)
What does the indented line beginning with a *, i.e. *(.debug_line .debug_line.* .debug_line_end) mean? I'm fairly certain this line is critical to defining the treatment of the second last line in the first snippet, since .debug_line_end isn't defined all by itself in a way similar to how .debug_line is in the first line of the snippet. I can't seem to find any references to the structure of the file, though.
With those answers, I'd like to be able to understand how .eh_frame in the following snippet is resolved. I can post the full map file if it's necessary, but I suspect all the information needed is somehow encoded within the snippet, and at that within the top and bottom few lines only.
.rodata 0x00004400 0x464
0x00004400 . = ALIGN (0x2)
*(.plt)
0x00004400 . = ALIGN (0x2)
*(.lower.rodata.* .lower.rodata)
0x00004400 . = ALIGN (0x2)
*(.rodata .rodata.* .gnu.linkonce.r.* .const .const:*)
.rodata 0x00004400 0x11 CMakeFiles/firmware-msp430f5529.elf.dir/main.c.obj
*fill* 0x00004411 0x1
.rodata.tUsbRequestList
0x00004412 0x15c ../peripherals/USB_config/libusb-config-msp430f5529.a(descriptors.c.obj)
0x00004412 tUsbRequestList
.rodata.stUsbHandle
0x0000456e 0x40 ../peripherals/USB_config/libusb-config-msp430f5529.a(descriptors.c.obj)
0x0000456e stUsbHandle
.rodata.report_desc_HID0
0x000045ae 0x24 ../peripherals/USB_config/libusb-config-msp430f5529.a(descriptors.c.obj)
0x000045ae report_desc_HID0
.rodata.abromStringDescriptor
0x000045d2 0x146 ../peripherals/USB_config/libusb-config-msp430f5529.a(descriptors.c.obj)
0x000045d2 abromStringDescriptor
.rodata.abromConfigurationDescriptorGroup
0x00004718 0xef ../peripherals/USB_config/libusb-config-msp430f5529.a(descriptors.c.obj)
0x00004718 abromConfigurationDescriptorGroup
.rodata.abromDeviceDescriptor
0x00004807 0x12 ../peripherals/USB_config/libusb-config-msp430f5529.a(descriptors.c.obj)
0x00004807 abromDeviceDescriptor
*fill* 0x00004819 0x1
.rodata.report_desc_size
0x0000481a 0x2 ../peripherals/USB_config/libusb-config-msp430f5529.a(descriptors.c.obj)
0x0000481a report_desc_size
.rodata 0x0000481c 0x11 ../subsystem/libcontrol-iface-msp430f5529.a(control_iface.c.obj)
*fill* 0x0000482d 0x1
.rodata.GPIO_PORT_TO_BASE
0x0000482e 0x1c ../peripherals/driverlib/MSP430F5xx_6xx/libdriverlib-msp430f5529.a(gpio.c.obj)
.rodata 0x0000484a 0x7 ../lib/libprintf-msp430f5529.a(printf.c.obj)
*(.rodata1)
*(.eh_frame_hdr)
*(.eh_frame)
*fill* 0x00004851 0x3
.eh_frame 0x00004854 0x0 /opt/ti/gcc/bin/../lib/gcc/msp430-elf/4.9.1/crtbegin.o

Resources