void map() { if (library[library_index].is_mapped == 0) { library[library_index]._elf_header = (Elf64_Ehdr *) library[library_index].array; library[library_index]._elf_program_header = (Elf64_Phdr *)((unsigned long)library[library_index]._elf_header + library[library_index]._elf_header->e_phoff); /* the very first thing we do is obtain the base address Base Address The virtual addresses in the program headers might not represent the actual virtual addresses of the program's memory image. Executable files typically contain absolute code. To let the process execute correctly, the segments must reside at the virtual addresses used to build the executable file. On the other hand, shared object segments typically contain position-independent code. This lets a segment's virtual address change from one process to another, without invalidating execution behavior. Though the system chooses virtual addresses for individual processes, it maintains the segments’ relative positions. Because position-independent code uses relative addressing between segments, the difference between virtual addresses in memory must match the difference between virtual addresses in the file. The difference between the virtual address of any segment in memory and the corresponding virtual address in the file is thus a single constant value for any one executable or shared object in a given process. This difference is the base address. One use of the base address is to relocate the memory image of the program during dynamic linking. An executable or shared object file's base address is calculated during execution from three values: the virtual memory load address, the maximum page size, and the lowest virtual address of a program's loadable segment. To compute the base address, one determines the memory address associated with the lowest p_vaddr value for a PT_LOAD segment. This address is truncated to the nearest multiple of the maximum page size. The corresponding p_vaddr value itself is also truncated to the nearest multiple of the maximum page size. The base address is the difference between the truncated memory address and the truncated p_vaddr value. */ // aquire the first and last PT_LOAD'S int PT_LOADS=0; for (int i = 0; i < library[library_index]._elf_header->e_phnum; ++i) { switch(library[library_index]._elf_program_header[i].p_type) { case PT_LOAD: // if (bytecmpq(global_quiet, "no") == 0) fprintf(stderr, "i = %d\n", i); // if (bytecmpq(global_quiet, "no") == 0) fprintf(stderr, "PT_LOADS = %d\n", PT_LOADS); if (!PT_LOADS) { // if (bytecmpq(global_quiet, "no") == 0) fprintf(stderr, "saving first load\n"); library[library_index].First_Load_Header_index = i; } if (PT_LOADS) { // if (bytecmpq(global_quiet, "no") == 0) fprintf(stderr, "saving last load\n"); library[library_index].Last_Load_Header_index = i; } PT_LOADS=PT_LOADS+1; break; } } size_t span = library[library_index]._elf_program_header[library[library_index].Last_Load_Header_index].p_vaddr + library[library_index]._elf_program_header[library[library_index].Last_Load_Header_index].p_memsz - library[library_index]._elf_program_header[library[library_index].First_Load_Header_index].p_vaddr; read_fast_verifyb(library[library_index].array, library[library_index].len, &library[library_index].mapping_start, span, library[library_index]._elf_program_header[library[library_index].First_Load_Header_index], library[library_index]._elf_program_header[library[library_index].Last_Load_Header_index]); fprintf(stderr, "library[library_index]._elf_program_header[library[library_index].Last_Load_Header_index].p_vaddr = %014p\n", library[library_index]._elf_program_header[library[library_index].Last_Load_Header_index].p_vaddr); // aquire the lowest PT_LOAD'S Elf64_Addr lowest_p_vaddr = 0; int lowest_idx = -1; for (int i = 0; i < library[library_index]._elf_header->e_phnum; ++i) { switch(library[library_index]._elf_program_header[i].p_type) { case PT_LOAD: if (!lowest_p_vaddr) { lowest_p_vaddr = library[library_index]._elf_program_header[i].p_vaddr; lowest_idx = i; } if (lowest_p_vaddr < library[library_index]._elf_program_header[i].p_memsz) { lowest_p_vaddr = library[library_index]._elf_program_header[i].p_vaddr; lowest_idx = i; } break; } } size_t pagesize = 0x1000; if (bytecmpq(global_quiet, "no") == 0) fprintf(stderr, "library[library_index]._elf_program_header[lowest_idx].p_paddr = %014p\nlibrary[library_index]._elf_program_header[lowest_idx].p_vaddr = %014p\n",library[library_index]._elf_program_header[lowest_idx].p_paddr, library[library_index]._elf_program_header[lowest_idx].p_vaddr); Elf64_Addr truncated_physical_address = round_down(library[library_index]._elf_program_header[lowest_idx].p_paddr, pagesize); Elf64_Addr truncated_virtual_address = round_down(library[library_index]._elf_program_header[lowest_idx].p_vaddr, pagesize); library[library_index].base_address = truncated_physical_address - truncated_virtual_address; library[library_index].align = round_nearest(library[library_index]._elf_program_header[library[library_index].Last_Load_Header_index].p_vaddr, pagesize); library[library_index].mapping_end = library[library_index].mapping_start+span; if (bytecmpq(global_quiet, "no") == 0) fprintf(stderr, "base address range = %014p - %014p\nmapping = %014p\nbase address = %014p\n", library[library_index].mapping_start, library[library_index].mapping_end, library[library_index].mapping_start, library[library_index].base_address); // abort_(); // base address aquired, map all PT_LOAD segments adjusting by base address then continue with the rest if (bytecmpq(global_quiet, "no") == 0) fprintf(stderr, "\n\n\nfind %014p, %014p, (int) 1239\n\n\n\n", library[library_index].mapping_start, library[library_index].mapping_end); if (library[library_index].mapping_start == 0x00000000) abort_(); int PT_LOADS_CURRENT = 0; for (int i = 0; i < library[library_index]._elf_header->e_phnum; ++i) { switch(library[library_index]._elf_program_header[i].p_type) { case PT_LOAD: PT_LOADS_CURRENT = PT_LOADS_CURRENT + 1; // if (bytecmpq(global_quiet, "no") == 0) fprintf(stderr, "mapping PT_LOAD number %d\n", PT_LOADS_CURRENT); // if (bytecmpq(global_quiet, "no") == 0) fprintf(stderr, "\t\tp_flags: %014p\n", library[library_index]._elf_program_header[i].p_flags); // if (bytecmpq(global_quiet, "no") == 0) fprintf(stderr, "\t\tp_offset: %014p\n", library[library_index]._elf_program_header[i].p_offset); // if (bytecmpq(global_quiet, "no") == 0) fprintf(stderr, "\t\tp_vaddr: %014p\n", library[library_index]._elf_program_header[i].p_vaddr+library[library_index].mapping_start); // if (bytecmpq(global_quiet, "no") == 0) fprintf(stderr, "\t\tp_paddr: %014p\n", library[library_index]._elf_program_header[i].p_paddr); // if (bytecmpq(global_quiet, "no") == 0) fprintf(stderr, "\t\tp_filesz: %014p\n", library[library_index]._elf_program_header[i].p_filesz); // if (bytecmpq(global_quiet, "no") == 0) fprintf(stderr, "\t\tp_memsz: %014p\n", library[library_index]._elf_program_header[i].p_memsz); // if (bytecmpq(global_quiet, "no") == 0) fprintf(stderr, "\t\tp_align: %014p\n\n", library[library_index]._elf_program_header[i].p_align); // // if (bytecmpq(global_quiet, "no") == 0) fprintf(stderr, "\tp_flags: %014p", library[library_index]._elf_program_header[i].p_flags); // if (bytecmpq(global_quiet, "no") == 0) fprintf(stderr, " p_offset: %014p", library[library_index]._elf_program_header[i].p_offset); // if (bytecmpq(global_quiet, "no") == 0) fprintf(stderr, " p_vaddr: %014p", library[library_index]._elf_program_header[i].p_vaddr+library[library_index].mapping_start); // if (bytecmpq(global_quiet, "no") == 0) fprintf(stderr, " p_paddr: %014p", library[library_index]._elf_program_header[i].p_paddr); // if (bytecmpq(global_quiet, "no") == 0) fprintf(stderr, " p_filesz: %014p", library[library_index]._elf_program_header[i].p_filesz); // if (bytecmpq(global_quiet, "no") == 0) fprintf(stderr, " p_memsz: %014p", library[library_index]._elf_program_header[i].p_memsz); // if (bytecmpq(global_quiet, "no") == 0) fprintf(stderr, " p_align: %014p\n\n\n", library[library_index]._elf_program_header[i].p_align); if (bytecmpq(global_quiet, "no") == 0) fprintf(stderr, "mprotect(%014p+round_down(%014p, %014p), %014p, ", library[library_index].mapping_start, library[library_index]._elf_program_header[i].p_vaddr, library[library_index]._elf_program_header[i].p_align, library[library_index]._elf_program_header[i].p_memsz); prot_from_phdr(library[library_index]._elf_program_header[i].p_flags); if (bytecmpq(global_quiet, "no") == 0) fprintf(stderr, ");\n"); errno = 0; int check_mprotect_success = mprotect(library[library_index].mapping_start+round_down(library[library_index]._elf_program_header[i].p_vaddr, library[library_index]._elf_program_header[i].p_align), round_up(library[library_index]._elf_program_header[i].p_memsz, library[library_index]._elf_program_header[i].p_align), library[library_index]._elf_program_header[i].p_flags); if (errno == 0) { if (bytecmpq(global_quiet, "no") == 0) fprintf(stderr, "mprotect on %014p succeded with size: %014p\n", library[library_index].mapping_start+round_down(library[library_index]._elf_program_header[i].p_vaddr, library[library_index]._elf_program_header[i].p_align), round_up(library[library_index]._elf_program_header[i].p_memsz, library[library_index]._elf_program_header[i].p_align)); print_maps(); } else { if (bytecmpq(global_quiet, "no") == 0) fprintf(stderr, "mprotect failed with: %s (errno: %d, check_mprotect_success = %d)\n", strerror(errno), errno, check_mprotect_success); print_maps(); abort_(); } break; } } library[library_index].is_mapped = 1; } }