static void scan_notes(int fd, loff_t start, loff_t lsize) { char *buf, *last, *note, *next; size_t size; ssize_t ret; if (lsize > SSIZE_MAX) { fprintf(stderr, "Unable to handle note section of %llu bytes\n", (unsigned long long)lsize); exit(20); } size = lsize; buf = malloc(size); if (!buf) { fprintf(stderr, "Cannot malloc %zu bytes\n", size); exit(21); } last = buf + size - 1; ret = pread(fd, buf, size, start); if (ret != (ssize_t)size) { fprintf(stderr, "Cannot read note section @ 0x%llx of %zu bytes: %s\n", (unsigned long long)start, size, strerror(errno)); exit(22); } for (note = buf; (note + sizeof(Elf_Nhdr)) < last; note = next) { Elf_Nhdr *hdr; char *n_name, *n_desc; size_t n_namesz, n_descsz, n_type; hdr = (Elf_Nhdr *)note; n_namesz = file32_to_cpu(hdr->n_namesz); n_descsz = file32_to_cpu(hdr->n_descsz); n_type = file32_to_cpu(hdr->n_type); n_name = note + sizeof(*hdr); n_desc = n_name + ((n_namesz + 3) & ~3); next = n_desc + ((n_descsz + 3) & ~3); if (next > (last + 1)) break; if ((memcmp(n_name, "VMCOREINFO", 11) != 0) || (n_type != 0)) continue; scan_vmcoreinfo(n_desc, n_descsz); } free(buf); }
static uint64_t read_file_pointer(int fd, uint64_t addr) { uint64_t result; ssize_t ret; if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) { uint64_t scratch; ret = pread(fd, &scratch, sizeof(scratch), addr); if (ret != sizeof(scratch)) { fprintf(stderr, "Failed to read pointer @ 0x%llx: %s\n", (unsigned long long)addr, strerror(errno)); exit(40); } result = file64_to_cpu(scratch); } else { uint32_t scratch; ret = pread(fd, &scratch, sizeof(scratch), addr); if (ret != sizeof(scratch)) { fprintf(stderr, "Failed to read pointer @ 0x%llx: %s\n", (unsigned long long)addr, strerror(errno)); exit(40); } result = file32_to_cpu(scratch); } return result; }
// return 0 if error static long unsigned int read_elf32(int fd) { Elf32_Ehdr ehdr32; Elf32_Shdr shdr32; off_t last_shdr_offset; ssize_t ret; unsigned long sht_end, last_section_end; ret = pread(fd, &ehdr32, sizeof(ehdr32), 0); if (ret < 0 || (size_t)ret != sizeof(ehdr)) return 0; ehdr.e_shoff = file32_to_cpu(ehdr32.e_shoff); ehdr.e_shentsize = file16_to_cpu(ehdr32.e_shentsize); ehdr.e_shnum = file16_to_cpu(ehdr32.e_shnum); last_shdr_offset = ehdr.e_shoff + (ehdr.e_shentsize * (ehdr.e_shnum - 1)); ret = pread(fd, &shdr32, sizeof(shdr32), last_shdr_offset); if (ret < 0 || (size_t)ret != sizeof(shdr32)) return 0; /* ELF ends either with the table of section headers (SHT) or with a section. */ sht_end = ehdr.e_shoff + (ehdr.e_shentsize * ehdr.e_shnum); last_section_end = file64_to_cpu(shdr32.sh_offset) + file64_to_cpu(shdr32.sh_size); return sht_end > last_section_end ? sht_end : last_section_end; }
static uint32_t read_file_u32(int fd, uint64_t addr) { uint32_t scratch; ssize_t ret; ret = pread(fd, &scratch, sizeof(scratch), addr); if (ret != sizeof(scratch)) { fprintf(stderr, "Failed to read value @ 0x%llx: %s\n", (unsigned long long)addr, strerror(errno)); exit(41); } return file32_to_cpu(scratch); }
static void read_elf32(int fd) { Elf32_Ehdr ehdr32; Elf32_Phdr *phdr32; size_t phdrs32_size; ssize_t ret, i; ret = pread(fd, &ehdr32, sizeof(ehdr32), 0); if (ret != sizeof(ehdr32)) { fprintf(stderr, "Read of Elf header from %s failed: %s\n", fname, strerror(errno)); exit(10); } ehdr.e_type = file16_to_cpu(ehdr32.e_type); ehdr.e_machine = file16_to_cpu(ehdr32.e_machine); ehdr.e_version = file32_to_cpu(ehdr32.e_version); ehdr.e_entry = file32_to_cpu(ehdr32.e_entry); ehdr.e_phoff = file32_to_cpu(ehdr32.e_phoff); ehdr.e_shoff = file32_to_cpu(ehdr32.e_shoff); ehdr.e_flags = file32_to_cpu(ehdr32.e_flags); ehdr.e_ehsize = file16_to_cpu(ehdr32.e_ehsize); ehdr.e_phentsize = file16_to_cpu(ehdr32.e_phentsize); ehdr.e_phnum = file16_to_cpu(ehdr32.e_phnum); ehdr.e_shentsize = file16_to_cpu(ehdr32.e_shentsize); ehdr.e_shnum = file16_to_cpu(ehdr32.e_shnum); ehdr.e_shstrndx = file16_to_cpu(ehdr32.e_shstrndx); if (ehdr.e_version != EV_CURRENT) { fprintf(stderr, "Bad Elf header version %u\n", ehdr.e_version); exit(11); } if (ehdr.e_phentsize != sizeof(Elf32_Phdr)) { fprintf(stderr, "Bad Elf progra header size %u expected %zu\n", ehdr.e_phentsize, sizeof(Elf32_Phdr)); exit(12); } phdrs32_size = ehdr.e_phnum * sizeof(Elf32_Phdr); phdr32 = calloc(ehdr.e_phnum, sizeof(Elf32_Phdr)); if (!phdr32) { fprintf(stderr, "Calloc of %u phdrs32 failed: %s\n", ehdr.e_phnum, strerror(errno)); exit(14); } phdr = calloc(ehdr.e_phnum, sizeof(Elf64_Phdr)); if (!phdr) { fprintf(stderr, "Calloc of %u phdrs failed: %s\n", ehdr.e_phnum, strerror(errno)); exit(15); } ret = pread(fd, phdr32, phdrs32_size, ehdr.e_phoff); if (ret < 0 || (size_t)ret != phdrs32_size) { fprintf(stderr, "Read of program header @ 0x%llu for %zu bytes failed: %s\n", (unsigned long long)ehdr.e_phoff, phdrs32_size, strerror(errno)); exit(16); } for (i = 0; i < ehdr.e_phnum; i++) { phdr[i].p_type = file32_to_cpu(phdr32[i].p_type); phdr[i].p_offset = file32_to_cpu(phdr32[i].p_offset); phdr[i].p_vaddr = file32_to_cpu(phdr32[i].p_vaddr); phdr[i].p_paddr = file32_to_cpu(phdr32[i].p_paddr); phdr[i].p_filesz = file32_to_cpu(phdr32[i].p_filesz); phdr[i].p_memsz = file32_to_cpu(phdr32[i].p_memsz); phdr[i].p_flags = file32_to_cpu(phdr32[i].p_flags); phdr[i].p_align = file32_to_cpu(phdr32[i].p_align); } free(phdr32); }
static inline uint32_t struct_val_u32(char *ptr, unsigned int offset) { return(file32_to_cpu(*(uint32_t *)(ptr + offset))); }