/* * This function is slow because it doesn't use the memory. * It is useful at few calls like get_str_osrelease_from_vmlinux(). */ off_t vaddr_to_offset_slow(int fd, char *filename, unsigned long long vaddr) { off_t offset = 0; int i, phnum, flag_elf64, elf_format; unsigned int num_load; Elf64_Phdr load64; Elf32_Phdr load32; elf_format = check_elf_format(fd, filename, &phnum, &num_load); if (elf_format == ELF64) flag_elf64 = TRUE; else if (elf_format == ELF32) flag_elf64 = FALSE; else return 0; for (i = 0; i < phnum; i++) { if (flag_elf64) { /* ELF64 */ if (!get_elf64_phdr(fd, filename, i, &load64)) { ERRMSG("Can't find Phdr %d.\n", i); return 0; } if (load64.p_type != PT_LOAD) continue; if ((vaddr < load64.p_vaddr) || (load64.p_vaddr + load64.p_filesz <= vaddr)) continue; offset = load64.p_offset + (vaddr - load64.p_vaddr); break; } else { /* ELF32 */ if (!get_elf32_phdr(fd, filename, i, &load32)) { ERRMSG("Can't find Phdr %d.\n", i); return 0; } if (load32.p_type != PT_LOAD) continue; if ((vaddr < load32.p_vaddr) || (load32.p_vaddr + load32.p_filesz <= vaddr)) continue; offset = load32.p_offset + (vaddr - load32.p_vaddr); break; } } return offset; }
/* Note, the `start_addr' should NOT be NULL! */ BinParser* get_parser(const uint8_t* start_addr, uint64_t len) { assert(start_addr != NULL); bin_fmt_t bf = BF_UNKNOWN; bf = check_elf_format(start_addr, len); if (bf == BF_ELF64) return new Elf64Parser(start_addr, len); /* Doesn't matter whether it is an ELF32 shared library or not, * here we just make sure that the factory method won't return * NULL. */ return new Elf32Parser(start_addr, len); }
/* * Get ELF information about /proc/vmcore. */ int get_elf_info(int fd, char *filename) { int i, j, phnum, elf_format; Elf64_Phdr phdr; /* * Check ELF64 or ELF32. */ elf_format = check_elf_format(fd, filename, &phnum, &num_pt_loads); if (elf_format == ELF64) flags_memory |= MEMORY_ELF64; else if (elf_format != ELF32) return FALSE; if (!num_pt_loads) { ERRMSG("Can't get the number of PT_LOAD.\n"); return FALSE; } /* * The below file information will be used as /proc/vmcore. */ fd_memory = fd; name_memory = filename; pt_loads = calloc(sizeof(struct pt_load_segment), num_pt_loads); if (pt_loads == NULL) { ERRMSG("Can't allocate memory for the PT_LOAD. %s\n", strerror(errno)); return FALSE; } for (i = 0, j = 0; i < phnum; i++) { if (!get_phdr_memory(i, &phdr)) return FALSE; if (phdr.p_type == PT_NOTE) { set_pt_note(phdr.p_offset, phdr.p_filesz); } if (phdr.p_type != PT_LOAD) continue; if (j == 0) { offset_pt_load_memory = phdr.p_offset; if (offset_pt_load_memory == 0) { ERRMSG("Can't get the offset of page data.\n"); return FALSE; } } if (j >= num_pt_loads) return FALSE; if(!dump_Elf_load(&phdr, j)) return FALSE; j++; } max_file_offset = 0; for (i = 0; i < num_pt_loads; ++i) { struct pt_load_segment *p = &pt_loads[i]; max_file_offset = MAX(max_file_offset, p->file_offset + p->phys_end - p->phys_start); } if (!has_pt_note()) { ERRMSG("Can't find PT_NOTE Phdr.\n"); return FALSE; } if (!get_pt_note_info()) { ERRMSG("Can't get PT_NOTE information.\n"); return FALSE; } return TRUE; }