diff --git a/src/readelf/readelf.cpp b/src/readelf/readelf.cpp index ef80ab2..357a20f 100644 --- a/src/readelf/readelf.cpp +++ b/src/readelf/readelf.cpp @@ -4,17 +4,15 @@ #include "readelf.hpp" #include "./readelf_internal.h" -static uintptr_t readelf_find_load_addr(Process *process, - uintptr_t start, - uintptr_t faddr) { - ELF_HDR elf; +static uintptr_t readelf_find_load_addr(Process *process, uintptr_t start, uintptr_t faddr) { + ELF::HDR elf; process->readData(&elf, start, sizeof(elf)); uintptr_t phdr_base = start + elf.phoff, phdr; - uintptr_t phdr_top = phdr_base + elf.phnum * sizeof(ELF64_PROG); - ELF64_PROG prog; - for (phdr = phdr_base; phdr < phdr_top; phdr += sizeof(ELF64_PROG)) { - process->readData(&prog, phdr, sizeof(ELF64_PROG)); - if ((prog.type == PT_LOAD) && + uintptr_t phdr_top = phdr_base + elf.phnum * sizeof(ELF64::PROG); + ELF64::PROG prog; + for (phdr = phdr_base; phdr < phdr_top; phdr += sizeof(ELF64::PROG)) { + process->readData(&prog, phdr, sizeof(ELF64::PROG)); + if ((prog.type == ELF64::PROG::PT_LOAD) && (prog.offset <= faddr) && (prog.offset + prog.filesz > faddr)) break; } @@ -23,24 +21,24 @@ static uintptr_t readelf_find_load_addr(Process *process, } static bool readelf_dylink_fix_phdr(Process *process, uintptr_t start) { - ELF_HDR elf; + ELF::HDR elf; process->readData(&elf, start, sizeof(elf)); uintptr_t phdr_base = start + elf.phoff, phdr; - uintptr_t phdr_top = phdr_base + elf.phnum * sizeof(ELF64_PROG); - ELF64_PROG prog; + uintptr_t phdr_top = phdr_base + elf.phnum * sizeof(ELF64::PROG); + ELF64::PROG prog; - for (phdr = phdr_base; phdr < phdr_top; phdr += sizeof(ELF64_PROG)) { - process->readData(&prog, phdr, sizeof(ELF64_PROG)); - if (prog.type == PT_NULL) continue; + for (phdr = phdr_base; phdr < phdr_top; phdr += sizeof(ELF64::PROG)) { + process->readData(&prog, phdr, sizeof(ELF64::PROG)); + if (prog.type == ELF64::PROG::PT_NULL) continue; switch (prog.type) { - case PT_NULL: - case PT_LOAD: + case ELF64::PROG::PT_NULL: + case ELF64::PROG::PT_LOAD: break; default: prog.vaddr = readelf_find_load_addr(process, start, prog.offset); if (prog.vaddr == 0) return 0; - process->writeData(phdr, &prog, sizeof(ELF64_PROG)); + process->writeData(phdr, &prog, sizeof(ELF64::PROG)); break; } } @@ -49,7 +47,7 @@ static bool readelf_dylink_fix_phdr(Process *process, uintptr_t start) { } static bool readelf_dylink_fix_entry(Process *process, uintptr_t start) { - ELF_HDR elf; + ELF::HDR elf; process->readData(&elf, start, sizeof(elf)); elf.entry = readelf_find_load_addr(process, start, elf.entry); if (elf.entry == 0) return 0; @@ -58,27 +56,25 @@ static bool readelf_dylink_fix_entry(Process *process, uintptr_t start) { return 1; } -static bool readelf_dylink_fix_dynamic_table(Process *process, - uintptr_t start, - uintptr_t dyntbl, - size_t dynsz) { +static bool readelf_dylink_fix_dynamic_table(Process *process, uintptr_t start, + uintptr_t dyntbl, size_t dynsz) { uintptr_t dyntop = dyntbl + dynsz, dynptr; - ELF64_DYN dyn; - for (dynptr = dyntbl; dynptr < dyntop; dynptr += sizeof(ELF64_DYN)) { - process->readData(&dyn, dynptr, sizeof(ELF64_DYN)); + ELF64::DYN dyn; + for (dynptr = dyntbl; dynptr < dyntop; dynptr += sizeof(ELF64::DYN)) { + process->readData(&dyn, dynptr, sizeof(ELF64::DYN)); switch (dyn.tag) { - case DT_PLTGOT: - case DT_HASH: - case DT_STRTAB: - case DT_SYMTAB: - case DT_RELA: - case DT_INIT: - case DT_FINI: - case DT_REL: - case DT_DEBUG: - case DT_JMPREL: - case DT_INIT_ARRAY: - case DT_FINI_ARRAY: + case ELF64::DYN::DT_PLTGOT: + case ELF64::DYN::DT_HASH: + case ELF64::DYN::DT_STRTAB: + case ELF64::DYN::DT_SYMTAB: + case ELF64::DYN::DT_RELA: + case ELF64::DYN::DT_INIT: + case ELF64::DYN::DT_FINI: + case ELF64::DYN::DT_REL: + case ELF64::DYN::DT_DEBUG: + case ELF64::DYN::DT_JMPREL: + case ELF64::DYN::DT_INIT_ARRAY: + case ELF64::DYN::DT_FINI_ARRAY: dyn.val = readelf_find_load_addr(process, start, dyn.val); if (dyn.val == 0) return 0; process->writeData(dynptr, &dyn, sizeof(dyn)); @@ -90,33 +86,30 @@ static bool readelf_dylink_fix_dynamic_table(Process *process, return 1; } -static uint64_t readelf_dylink_dynamic_find(Process *process, - uintptr_t dyntbl, - size_t dynsz, - ELF64_DYN_TAG tag) { +static uint64_t readelf_dylink_dynamic_find(Process *process, uintptr_t dyntbl, + size_t dynsz, ELF64::DYN::TAG tag) { uintptr_t dyntop = dyntbl + dynsz, dynptr; - ELF64_DYN dyn; - for (dynptr = dyntbl; dynptr < dyntop; dynptr += sizeof(ELF64_DYN)) { - process->readData(&dyn, dynptr, sizeof(ELF64_DYN)); + ELF64::DYN dyn; + for (dynptr = dyntbl; dynptr < dyntop; dynptr += sizeof(ELF64::DYN)) { + process->readData(&dyn, dynptr, sizeof(ELF64::DYN)); if (dyn.tag != tag) continue; return dyn.val; } return 0; } -static bool readelf_dylink_process_reloc(Process *process, uintptr_t start, const ELF64RELA &ent, +static bool readelf_dylink_process_reloc(Process *process, uintptr_t start, const ELF64::RELA &ent, uintptr_t symtab, uintptr_t syment, uintptr_t strtab) { if (ent.sym == 0) return 0; - ELF64SYM sym; + ELF64::SYM sym; process->readData(&sym, symtab + syment * ent.sym, sizeof(sym)); if (!sym.name) return 0; uintptr_t addr = 0; char *name = process->readString(strtab + sym.name); - ELF64_SYM_BIND bind = ELF64_SYM_BIND(sym.info >> 4); uintptr_t ptr = readelf_find_load_addr(process, start, ent.addr); - bool allownull = bind == STB_WEAK; + bool allownull = sym.bind == ELF64::SYM::STB_WEAK; addr = process->getSymbolByName(name); if (!addr) addr = process->linkLibrary(name); @@ -129,8 +122,8 @@ static bool readelf_dylink_process_reloc(Process *process, uintptr_t start, cons addr += ent.add; switch (ent.type) { - case R_X86_64_JUMP_SLOT: - case R_X86_64_GLOB_DAT: + case ELF64::R_X86_64_JUMP_SLOT: + case ELF64::R_X86_64_GLOB_DAT: process->writeData(ptr, &addr, sizeof(addr)); break; default: @@ -140,105 +133,77 @@ static bool readelf_dylink_process_reloc(Process *process, uintptr_t start, cons return 1; } -static bool readelf_dylink_handle_dynamic_jmprel(Process *process, - uintptr_t start, - uintptr_t dyntbl, - size_t dynsz, - uintptr_t jmprel) { - uintptr_t symtab = readelf_dylink_dynamic_find(process, dyntbl, dynsz, DT_SYMTAB); - uintptr_t pltrel = readelf_dylink_dynamic_find(process, dyntbl, dynsz, DT_PLTREL); - uintptr_t pltrelsz = readelf_dylink_dynamic_find(process, dyntbl, dynsz, DT_PLTRELSZ); - uintptr_t syment = readelf_dylink_dynamic_find(process, dyntbl, dynsz, DT_SYMENT); - uintptr_t strtab = readelf_dylink_dynamic_find(process, dyntbl, dynsz, DT_STRTAB); - if (syment == 0) syment = sizeof(ELF64SYM); +static bool readelf_dylink_handle_dynamic_jmprel(Process *process, uintptr_t start, + uintptr_t dyntbl, size_t dynsz, uintptr_t jmprel) { + uintptr_t symtab = readelf_dylink_dynamic_find(process, dyntbl, dynsz, ELF64::DYN::DT_SYMTAB); + uintptr_t pltrel = readelf_dylink_dynamic_find(process, dyntbl, dynsz, ELF64::DYN::DT_PLTREL); + uintptr_t pltrelsz = readelf_dylink_dynamic_find(process, dyntbl, dynsz, ELF64::DYN::DT_PLTRELSZ); + uintptr_t syment = readelf_dylink_dynamic_find(process, dyntbl, dynsz, ELF64::DYN::DT_SYMENT); + uintptr_t strtab = readelf_dylink_dynamic_find(process, dyntbl, dynsz, ELF64::DYN::DT_STRTAB); + if (syment == 0) syment = sizeof(ELF64::SYM); if (jmprel == 0 || symtab == 0) return 0; + size_t entsz; switch (pltrel) { - case DT_REL: - if ((pltrelsz % sizeof(ELF64REL)) != 0) return 0; - break; - case DT_RELA: - if ((pltrelsz % sizeof(ELF64RELA)) != 0) return 0; - break; + case ELF64::DYN::DT_REL: entsz = sizeof(ELF64::REL); break; + case ELF64::DYN::DT_RELA: entsz = sizeof(ELF64::RELA); break; default: return 0; } - ELF64RELA rel; + if ((pltrelsz % entsz) != 0) return 0; + ELF64::RELA rel; Memory::zero(&rel, sizeof(rel)); while (pltrelsz) { - switch (pltrel) { - case DT_REL: - process->readData(&rel, jmprel, sizeof(ELF64REL)); - jmprel += sizeof(ELF64REL); - pltrelsz -= sizeof(ELF64REL); - break; - case DT_RELA: - process->readData(&rel, jmprel, sizeof(ELF64RELA)); - jmprel += sizeof(ELF64RELA); - pltrelsz -= sizeof(ELF64RELA); - break; - default: return 0; - } + process->readData(&rel, jmprel, entsz); + jmprel += entsz; + pltrelsz -= entsz; if (!readelf_dylink_process_reloc(process, start, rel, symtab, syment, strtab)) return 0; } return 1; } -static bool readelf_dylink_handle_dynamic_rel(Process *process, - uintptr_t start, - uintptr_t dyntbl, - size_t dynsz, - uintptr_t rel) { - uintptr_t sz = readelf_dylink_dynamic_find(process, dyntbl, dynsz, DT_RELSZ); - uintptr_t entsz = readelf_dylink_dynamic_find(process, dyntbl, dynsz, DT_RELENT); - uintptr_t symtab = readelf_dylink_dynamic_find(process, dyntbl, dynsz, DT_SYMTAB); - uintptr_t syment = readelf_dylink_dynamic_find(process, dyntbl, dynsz, DT_SYMENT); - uintptr_t strtab = readelf_dylink_dynamic_find(process, dyntbl, dynsz, DT_STRTAB); - if (sz == 0 || entsz != sizeof(ELF64REL)) return 0; - ELF64RELA ent; +static bool readelf_dylink_handle_dynamic_rel(Process *process, uintptr_t start, + uintptr_t dyntbl, size_t dynsz, uintptr_t rel) { + uintptr_t sz = readelf_dylink_dynamic_find(process, dyntbl, dynsz, ELF64::DYN::DT_RELSZ); + uintptr_t entsz = readelf_dylink_dynamic_find(process, dyntbl, dynsz, ELF64::DYN::DT_RELENT); + uintptr_t symtab = readelf_dylink_dynamic_find(process, dyntbl, dynsz, ELF64::DYN::DT_SYMTAB); + uintptr_t syment = readelf_dylink_dynamic_find(process, dyntbl, dynsz, ELF64::DYN::DT_SYMENT); + uintptr_t strtab = readelf_dylink_dynamic_find(process, dyntbl, dynsz, ELF64::DYN::DT_STRTAB); + if (sz == 0 || entsz != sizeof(ELF64::REL)) return 0; + ELF64::RELA ent; ent.add = 0; while (sz) { - process->readData(&ent, rel, sizeof(ELF64REL)); - - if (!readelf_dylink_process_reloc(process, start, ent, symtab, syment, strtab)) return 0; - + process->readData(&ent, rel, sizeof(ELF64::REL)); rel += entsz; sz -= entsz; + if (!readelf_dylink_process_reloc(process, start, ent, symtab, syment, strtab)) return 0; } return 1; } -static bool readelf_dylink_handle_dynamic_rela(Process *process, - uintptr_t start, - uintptr_t dyntbl, - size_t dynsz, - uintptr_t rela) { - uintptr_t sz = readelf_dylink_dynamic_find(process, dyntbl, dynsz, DT_RELASZ); - uintptr_t entsz = readelf_dylink_dynamic_find(process, dyntbl, dynsz, DT_RELAENT); - uintptr_t symtab = readelf_dylink_dynamic_find(process, dyntbl, dynsz, DT_SYMTAB); - uintptr_t syment = readelf_dylink_dynamic_find(process, dyntbl, dynsz, DT_SYMENT); - uintptr_t strtab = readelf_dylink_dynamic_find(process, dyntbl, dynsz, DT_STRTAB); - if (sz == 0 || entsz != sizeof(ELF64RELA)) return 0; - ELF64RELA ent; +static bool readelf_dylink_handle_dynamic_rela(Process *process, uintptr_t start, + uintptr_t dyntbl, size_t dynsz, uintptr_t rela) { + uintptr_t sz = readelf_dylink_dynamic_find(process, dyntbl, dynsz, ELF64::DYN::DT_RELASZ); + uintptr_t entsz = readelf_dylink_dynamic_find(process, dyntbl, dynsz, ELF64::DYN::DT_RELAENT); + uintptr_t symtab = readelf_dylink_dynamic_find(process, dyntbl, dynsz, ELF64::DYN::DT_SYMTAB); + uintptr_t syment = readelf_dylink_dynamic_find(process, dyntbl, dynsz, ELF64::DYN::DT_SYMENT); + uintptr_t strtab = readelf_dylink_dynamic_find(process, dyntbl, dynsz, ELF64::DYN::DT_STRTAB); + if (sz == 0 || entsz != sizeof(ELF64::RELA)) return 0; + ELF64::RELA ent; while (sz) { process->readData(&ent, rela, sizeof(ent)); - - if (!readelf_dylink_process_reloc(process, start, ent, symtab, syment, strtab)) return 0; - rela += entsz; sz -= entsz; + if (!readelf_dylink_process_reloc(process, start, ent, symtab, syment, strtab)) return 0; } return 1; } -static bool readelf_dylink_handle_dynamic_symtab(Process *process, - uintptr_t start, - uintptr_t dyntbl, - size_t dynsz, - uintptr_t symtab) { - uintptr_t syment = readelf_dylink_dynamic_find(process, dyntbl, dynsz, DT_SYMENT); - uintptr_t strtab = readelf_dylink_dynamic_find(process, dyntbl, dynsz, DT_STRTAB); - uintptr_t hashtab = readelf_dylink_dynamic_find(process, dyntbl, dynsz, DT_HASH); +static bool readelf_dylink_handle_dynamic_symtab(Process *process, uintptr_t start, + uintptr_t dyntbl, size_t dynsz, uintptr_t symtab) { + uintptr_t syment = readelf_dylink_dynamic_find(process, dyntbl, dynsz, ELF64::DYN::DT_SYMENT); + uintptr_t strtab = readelf_dylink_dynamic_find(process, dyntbl, dynsz, ELF64::DYN::DT_STRTAB); + uintptr_t hashtab = readelf_dylink_dynamic_find(process, dyntbl, dynsz, ELF64::DYN::DT_HASH); if (syment == 0 || strtab == 0 || hashtab == 0) return 0; - ELF64SYM sym; + ELF64::SYM sym; struct { uint32_t nbucket, nchain; } PACKED hashhdr; @@ -249,56 +214,50 @@ static bool readelf_dylink_handle_dynamic_symtab(Process *process, process->readData(&idx, hashtab, sizeof(idx)); hashtab += sizeof(idx); if (idx == 0) continue; - process->readData(&sym, symtab + syment * idx, sizeof(ELF64SYM)); + process->readData(&sym, symtab + syment * idx, sizeof(ELF64::SYM)); if (sym.name == 0) continue; uintptr_t ptr = readelf_find_load_addr(process, start, sym.value); if (ptr == 0) continue; char *name = process->readString(strtab + sym.name); - if (name && name[0] != 0) { - uint8_t bind = sym.info >> 4; - if (bind == STB_GLOBAL) - process->addSymbol(name, ptr); - } + if (name && name[0] != 0) process->addSymbol(name, ptr); delete name; } return 1; } -static bool readelf_dylink_handle_dynamic_table(Process *process, - uintptr_t start, - uintptr_t dyntbl, - size_t dynsz) { +static bool readelf_dylink_handle_dynamic_table(Process *process, uintptr_t start, + uintptr_t dyntbl, size_t dynsz) { uintptr_t dyntop = dyntbl + dynsz, dynptr; - ELF64_DYN dyn; - for (dynptr = dyntbl; dynptr < dyntop; dynptr += sizeof(ELF64_DYN)) { - process->readData(&dyn, dynptr, sizeof(ELF64_DYN)); + ELF64::DYN dyn; + for (dynptr = dyntbl; dynptr < dyntop; dynptr += sizeof(ELF64::DYN)) { + process->readData(&dyn, dynptr, sizeof(ELF64::DYN)); switch (dyn.tag) { - case DT_JMPREL: + case ELF64::DYN::DT_JMPREL: if (!readelf_dylink_handle_dynamic_jmprel(process, start, dyntbl, dynsz, dyn.val)) return 0; break; - case DT_REL: + case ELF64::DYN::DT_REL: if (!readelf_dylink_handle_dynamic_rel(process, start, dyntbl, dynsz, dyn.val)) return 0; break; - case DT_RELA: + case ELF64::DYN::DT_RELA: if (!readelf_dylink_handle_dynamic_rela(process, start, dyntbl, dynsz, dyn.val)) return 0; break; - case DT_PLTGOT: - case DT_PLTREL: - case DT_PLTRELSZ: - case DT_RELASZ: - case DT_RELAENT: - case DT_RELSZ: - case DT_RELENT: - case DT_SYMENT: - case DT_HASH: - case DT_GNU_HASH: - case DT_STRTAB: - case DT_STRSZ: - break; - case DT_SYMTAB: + case ELF64::DYN::DT_SYMTAB: if (!readelf_dylink_handle_dynamic_symtab(process, start, dyntbl, dynsz, dyn.val)) return 0; break; - case DT_NULL: break; + case ELF64::DYN::DT_PLTGOT: + case ELF64::DYN::DT_PLTREL: + case ELF64::DYN::DT_PLTRELSZ: + case ELF64::DYN::DT_RELASZ: + case ELF64::DYN::DT_RELAENT: + case ELF64::DYN::DT_RELSZ: + case ELF64::DYN::DT_RELENT: + case ELF64::DYN::DT_SYMENT: + case ELF64::DYN::DT_HASH: + case ELF64::DYN::DT_GNU_HASH: + case ELF64::DYN::DT_STRTAB: + case ELF64::DYN::DT_STRSZ: + case ELF64::DYN::DT_NULL: + break; default: printf("DYN%03lu: %016lx\n", dyn.tag, dyn.val); break; @@ -308,17 +267,17 @@ static bool readelf_dylink_handle_dynamic_table(Process *process, } static bool readelf_dylink_handle_dynamic(Process *process, uintptr_t start) { - ELF_HDR elf; + ELF::HDR elf; process->readData(&elf, start, sizeof(elf)); uintptr_t phdr_base = start + elf.phoff; - uintptr_t phdr_top = phdr_base + elf.phnum * sizeof(ELF64_PROG); + uintptr_t phdr_top = phdr_base + elf.phnum * sizeof(ELF64::PROG); uintptr_t phdr; - ELF64_PROG prog; + ELF64::PROG prog; - for (phdr = phdr_base; phdr < phdr_top; phdr += sizeof(ELF64_PROG)) { - process->readData(&prog, phdr, sizeof(ELF64_PROG)); - if (prog.type != PT_DYNAMIC) continue; + for (phdr = phdr_base; phdr < phdr_top; phdr += sizeof(ELF64::PROG)) { + process->readData(&prog, phdr, sizeof(ELF64::PROG)); + if (prog.type != ELF64::PROG::PT_DYNAMIC) continue; if (!readelf_dylink_fix_dynamic_table(process, start, prog.vaddr, prog.filesz) || !readelf_dylink_handle_dynamic_table(process, start, prog.vaddr, prog.filesz)) return 0; @@ -335,56 +294,56 @@ static bool readelf_dylink(Process *process, uintptr_t start) { } size_t readelf(Process *process, Stream *stream) { - ELF_HDR elf; + ELF::HDR elf; size_t size = 0; - ELF64_PROG *progs = nullptr, *progs_top, *prog; + ELF64::PROG *progs = nullptr, *progs_top, *prog; char *buf = nullptr; SectionType type; uintptr_t vaddr, offset_load, vaddr_start = 0; // Read ELF header size_t off = 0; - if (stream->read(&elf, sizeof(ELF_HDR)) != sizeof(ELF_HDR)) goto err; - off += sizeof(ELF_HDR); + if (stream->read(&elf, sizeof(ELF::HDR)) != sizeof(ELF::HDR)) goto err; + off += sizeof(ELF::HDR); // Identify ELF - if ((elf.ident.magic != ELF_MAGIC) // '\x7FELF' - || (elf.ident.eclass != EC_64) - || (elf.ident.data != ED_2LSB) - || (elf.ident.version != EVF_CURRENT) + if ((elf.ident.magic != ELF::IDENT::MAGIC) // '\x7FELF' + || (elf.ident.eclass != ELF::EC_64) + || (elf.ident.data != ELF::ED_2LSB) + || (elf.ident.version != ELF::EVF_CURRENT) || (elf.ident.osabi != 0) || (elf.ident.abiversion != 0)) goto err; // Check ELF type - if ((elf.machine != EM_AMD64) - || (elf.type != ET_DYN) - || (elf.version != EV_CURRENT) + if ((elf.machine != ELF::EM_AMD64) + || (elf.type != ELF::ET_DYN) + || (elf.version != ELF::EV_CURRENT) || (elf.flags != 0) - || (elf.ehsize != sizeof(ELF_HDR)) - || (elf.phoff != sizeof(ELF_HDR))) goto err; + || (elf.ehsize != sizeof(ELF::HDR)) + || (elf.phoff != sizeof(ELF::HDR))) goto err; // Init variables size = elf.shoff + elf.shentsize * elf.shnum; - progs = new ELF64_PROG[elf.phnum](); + progs = new ELF64::PROG[elf.phnum](); progs_top = progs + elf.phnum; // Read linker program - if (stream->read(progs, sizeof(ELF64_PROG) * elf.phnum) != sizeof(ELF64_PROG) * elf.phnum) + if (stream->read(progs, sizeof(ELF64::PROG) * elf.phnum) != sizeof(ELF64::PROG) * elf.phnum) goto err; - off += sizeof(ELF64_PROG) * elf.phnum; + off += sizeof(ELF64::PROG) * elf.phnum; for (prog = progs; prog < progs_top; prog++) { switch (prog->type) { - case PT_NULL: break; - case PT_PHDR: - if ((prog->offset != elf.phoff) || (prog->filesz != sizeof(ELF64_PROG) * elf.phnum)) + case ELF64::PROG::PT_NULL: break; + case ELF64::PROG::PT_PHDR: + if ((prog->offset != elf.phoff) || (prog->filesz != sizeof(ELF64::PROG) * elf.phnum)) goto err; break; - case PT_LOAD: - if (prog->flags & PF_X) { - if (prog->flags & PF_W) goto err; + case ELF64::PROG::PT_LOAD: + if (prog->flags & ELF64::PROG::PF_X) { + if (prog->flags & ELF64::PROG::PF_W) goto err; type = SectionTypeCode; } else { - if (prog->flags & PF_W) + if (prog->flags & ELF64::PROG::PF_W) type = SectionTypeData; else type = SectionTypeROData; @@ -394,8 +353,8 @@ size_t readelf(Process *process, Stream *stream) { offset_load = 0; if (prog->offset == 0) { vaddr_start = vaddr; - process->writeData(vaddr, &elf, sizeof(ELF_HDR)); - offset_load = sizeof(ELF_HDR) + sizeof(ELF64_PROG) * elf.phnum; + process->writeData(vaddr, &elf, sizeof(ELF::HDR)); + offset_load = sizeof(ELF::HDR) + sizeof(ELF64::PROG) * elf.phnum; } if (prog->offset + offset_load < off) goto err; if (prog->offset + offset_load > off) { @@ -410,15 +369,15 @@ size_t readelf(Process *process, Stream *stream) { prog->vaddr = vaddr; } break; - case PT_DYNAMIC: break; + case ELF64::PROG::PT_DYNAMIC: break; default: - if (prog->type >= PT_LOOS && prog->type <= PT_HIOS) break; - if (prog->type >= PT_LOPROC && prog->type <= PT_HIPROC) break; + if (prog->type >= ELF64::PROG::PT_LOOS && prog->type <= ELF64::PROG::PT_HIOS) break; + if (prog->type >= ELF64::PROG::PT_LOPROC && prog->type <= ELF64::PROG::PT_HIPROC) break; goto err; } } - process->writeData(vaddr_start + sizeof(ELF_HDR), progs, sizeof(ELF64_PROG) * elf.phnum); + process->writeData(vaddr_start + sizeof(ELF::HDR), progs, sizeof(ELF64::PROG) * elf.phnum); goto done; err: diff --git a/src/readelf/readelf_internal.h b/src/readelf/readelf_internal.h index fbb86ae..b5cae55 100644 --- a/src/readelf/readelf_internal.h +++ b/src/readelf/readelf_internal.h @@ -1,234 +1,221 @@ -static const uint32_t ELF_MAGIC = 0x464C457F; // '\x7fELF' - -enum ELF_CLASS: uint8_t { - EC_NONE = 0, - EC_32 = 1, - EC_64 = 2 -}; - -enum ELF_DATA: uint8_t { - ED_NONE = 0, - ED_2LSB = 1, - ED_2MSB = 2 -}; - -enum ELF_FILE_VERSION: uint8_t { - EVF_NONE = 0, - EVF_CURRENT = 1 -}; - -enum ELF_OSABI: uint8_t { }; - -enum ELF_ABIVERSION: uint8_t { }; - -struct ELF_IDENT { - uint32_t magic; - ELF_CLASS eclass; - ELF_DATA data; - ELF_FILE_VERSION version; - ELF_OSABI osabi; - ELF_ABIVERSION abiversion; - uint8_t pad[7]; -} PACKED; - -enum ELF_TYPE: uint16_t { - ET_NONE = 0, - ET_REL = 1, - ET_EXEC = 2, - ET_DYN = 3, - ET_CORE = 4 -}; - -enum ELF_MACHINE: uint16_t { - EM_NONE = 0, - EM_386 = 3, - EM_AMD64 = 62 -}; - -enum ELF_VERSION: uint32_t { - EV_NONE = 0, - EV_CURRENT = 1 -}; - -struct ELF_HDR { - ELF_IDENT ident; - ELF_TYPE type; - ELF_MACHINE machine; - ELF_VERSION version; - uint64_t entry, phoff, shoff; - uint32_t flags; - uint16_t ehsize, phentsize, phnum, shentsize, shnum, shstrndx; -} PACKED; - -enum ELF64_PROG_TYPE: uint32_t { - PT_NULL, - PT_LOAD, - PT_DYNAMIC, - PT_INTERP, - PT_NOTE, - PT_SHLIB, - PT_PHDR, - PT_TLS, - PT_LOOS = 0x60000000, - PT_HIOS = 0x6FFFFFFF, - PT_LOPROC = 0x70000000, - PT_HIPROC = 0x7FFFFFFF -}; - -enum ELF64_PROG_FLAGS: uint32_t { - PF_X = 1, - PF_W = 2, - PF_R = 4 -}; - -struct ELF64_PROG { - ELF64_PROG_TYPE type; - ELF64_PROG_FLAGS flags; - uint64_t offset; - uint64_t vaddr; - uint64_t paddr; - uint64_t filesz; - uint64_t memsz; - uint64_t align; -} PACKED; - -enum ELF64_SECT_TYPE: uint32_t { - SHT_NULL, - SHT_PROGBITS, - SHT_SYMTAB, - SHT_STRTAB, - SHT_RELA, - SHT_HASH, - SHT_DYNAMIC, - SHT_NOTE, - SHT_NOBITS, - SHT_REL, - SHT_SHLIB, - SHT_DYNSYM -}; - -enum ELF64_SECT_FLAGS: uint64_t { - SHF_WRITE = 1, - SHF_ALLOC = 2, - SHF_EXECINSTR = 4 -}; - -struct ELF64_SECT { - uint32_t name; - ELF64_SECT_TYPE type; - ELF64_SECT_FLAGS flags; - uint64_t addr, offset, size; - uint32_t link, info; - uint64_t addralign, entsize; -} PACKED; - -enum ELF64_DYN_TAG: uint64_t { - DT_NULL, - DT_NEEDED, - DT_PLTRELSZ, - DT_PLTGOT, - DT_HASH, - DT_STRTAB, - DT_SYMTAB, - DT_RELA, - DT_RELASZ, - DT_RELAENT, - DT_STRSZ, - DT_SYMENT, - DT_INIT, - DT_FINI, - DT_SONAME, - DT_RPATH, - DT_SYMBOLIC, - DT_REL, - DT_RELSZ, - DT_RELENT, - DT_PLTREL, - DT_DEBUG, - DT_TEXTREL, - DT_JMPREL, - DT_BIND_NOW, - DT_INIT_ARRAY, - DT_FINI_ARRAY, - DT_INIT_ARRAYSZ, - DT_FINI_ARRAYSZ, - DT_RUNPATH, - DT_FLAGS, - DT_ENCODING, - DT_PREINIT_ARRAY, - DT_PREINIT_ARRAYSZ, - DT_MAXPOSTAGS, - DT_LOOS = 0x60000000, - DT_GNU_HASH = 0x6FFFFEF5, - DT_HIOS = 0x6FFFFFFF, - DT_LOPROC = 0x70000000, - DT_HIPROC = 0x7FFFFFFF -}; - -enum ELF64_RELOC_TYPE: uint32_t { - R_X86_64_NONE, // No reloc - R_X86_64_64, // Direct 64 bit - R_X86_64_PC32, // PC relative 32 bit signed - R_X86_64_GOT32, // 32 bit GOT entry - R_X86_64_PLT32, // 32 bit PLT address - R_X86_64_COPY, // Copy symbol at runtime - R_X86_64_GLOB_DAT, // Create GOT entry - R_X86_64_JUMP_SLOT, // Create PLT entry - R_X86_64_RELATIVE, // Adjust by program base - R_X86_64_GOTPCREL, // 32 bit signed pc relative offset to GOT - R_X86_64_32, // Direct 32 bit zero extended - R_X86_64_32S, // Direct 32 bit sign extended - R_X86_64_16, // Direct 16 bit zero extended - R_X86_64_PC16, // 16 bit sign extended pc relative - R_X86_64_8, // Direct 8 bit sign extended - R_X86_64_PC8 // 8 bit sign extended pc relative -}; - -enum ELF64_SYM_BIND: uint8_t { - STB_LOCAL = 0, - STB_GLOBAL = 1, - STB_WEAK = 2, - STB_LOOS = 10, - STB_HIOS = 12, - STB_LOPROC = 13, - STB_HIPROC = 15, -}; - -enum ELF64_SYM_TYPE: uint8_t { - STT_NOTYPE = 0, - STT_OBJECT = 1, - STT_FUNC = 2, - STT_SECTION = 3, - STT_FILE = 4, - STT_COMMON = 5, - STT_TLS = 6, - STT_LOOS = 10, - STT_HIOS = 12, - STT_LOPROC = 13, - STT_SPARC_REGISTER = 13, - STT_HIPROC = 15, -}; - -struct ELF64_DYN { - ELF64_DYN_TAG tag; - uint64_t val; -} PACKED; - -struct ELF64SYM { - uint32_t name; - uint8_t info, other; - uint16_t shndx; - uint64_t value; - uint64_t size; -} PACKED; -struct ELF64RELA { - uint64_t addr; - ELF64_RELOC_TYPE type; - uint32_t sym; - uint64_t add; -} PACKED; -struct ELF64REL { - uint64_t addr; - ELF64_RELOC_TYPE type; - uint32_t sym; -} PACKED; +namespace ELF { + enum CLASS: uint8_t { + EC_NONE = 0, + EC_32 = 1, + EC_64 = 2 + }; + enum DATA: uint8_t { + ED_NONE = 0, + ED_2LSB = 1, + ED_2MSB = 2 + }; + enum FILE_VERSION: uint8_t { + EVF_NONE = 0, + EVF_CURRENT = 1 + }; + enum OSABI: uint8_t { }; + enum ABIVERSION: uint8_t { }; + enum TYPE: uint16_t { + ET_NONE = 0, + ET_REL = 1, + ET_EXEC = 2, + ET_DYN = 3, + ET_CORE = 4 + }; + enum MACHINE: uint16_t { + EM_NONE = 0, + EM_386 = 3, + EM_AMD64 = 62 + }; + enum VERSION: uint32_t { + EV_NONE = 0, + EV_CURRENT = 1 + }; + + struct IDENT { + static const uint32_t MAGIC = 0x464C457F; // '\x7fELF' + uint32_t magic; + CLASS eclass; + DATA data; + FILE_VERSION version; + OSABI osabi; + ABIVERSION abiversion; + uint8_t pad[7]; + } PACKED; + struct HDR { + IDENT ident; + TYPE type; + MACHINE machine; + VERSION version; + uint64_t entry, phoff, shoff; + uint32_t flags; + uint16_t ehsize, phentsize, phnum, shentsize, shnum, shstrndx; + } PACKED; + + namespace _64 { + struct PROG { + enum TYPE: uint32_t { + PT_NULL, + PT_LOAD, + PT_DYNAMIC, + PT_INTERP, + PT_NOTE, + PT_SHLIB, + PT_PHDR, + PT_TLS, + PT_LOOS = 0x60000000, + PT_HIOS = 0x6FFFFFFF, + PT_LOPROC = 0x70000000, + PT_HIPROC = 0x7FFFFFFF + }; + enum FLAGS: uint32_t { + PF_X = 1, + PF_W = 2, + PF_R = 4 + }; + TYPE type; + FLAGS flags; + uint64_t offset; + uint64_t vaddr; + uint64_t paddr; + uint64_t filesz; + uint64_t memsz; + uint64_t align; + } PACKED; + + struct SECT { + enum TYPE: uint32_t { + SHT_NULL, + SHT_PROGBITS, + SHT_SYMTAB, + SHT_STRTAB, + SHT_RELA, + SHT_HASH, + SHT_DYNAMIC, + SHT_NOTE, + SHT_NOBITS, + SHT_REL, + SHT_SHLIB, + SHT_DYNSYM + }; + enum FLAGS: uint64_t { + SHF_WRITE = 1, + SHF_ALLOC = 2, + SHF_EXECINSTR = 4 + }; + uint32_t name; + TYPE type; + FLAGS flags; + uint64_t addr, offset, size; + uint32_t link, info; + uint64_t addralign, entsize; + } PACKED; + + struct DYN { + enum TAG: uint64_t { + DT_NULL, + DT_NEEDED, + DT_PLTRELSZ, + DT_PLTGOT, + DT_HASH, + DT_STRTAB, + DT_SYMTAB, + DT_RELA, + DT_RELASZ, + DT_RELAENT, + DT_STRSZ, + DT_SYMENT, + DT_INIT, + DT_FINI, + DT_SONAME, + DT_RPATH, + DT_SYMBOLIC, + DT_REL, + DT_RELSZ, + DT_RELENT, + DT_PLTREL, + DT_DEBUG, + DT_TEXTREL, + DT_JMPREL, + DT_BIND_NOW, + DT_INIT_ARRAY, + DT_FINI_ARRAY, + DT_INIT_ARRAYSZ, + DT_FINI_ARRAYSZ, + DT_RUNPATH, + DT_FLAGS, + DT_ENCODING, + DT_PREINIT_ARRAY, + DT_PREINIT_ARRAYSZ, + DT_MAXPOSTAGS, + DT_LOOS = 0x60000000, + DT_GNU_HASH = 0x6FFFFEF5, + DT_HIOS = 0x6FFFFFFF, + DT_LOPROC = 0x70000000, + DT_HIPROC = 0x7FFFFFFF + }; + TAG tag; + uint64_t val; + } PACKED; + + struct SYM { + enum BIND: uint8_t { + STB_LOCAL = 0, + STB_GLOBAL = 1, + STB_WEAK = 2, + STB_LOOS = 10, + STB_HIOS = 12, + STB_LOPROC = 13, + STB_HIPROC = 15, + }; + enum TYPE: uint8_t { + STT_NOTYPE = 0, + STT_OBJECT = 1, + STT_FUNC = 2, + STT_SECTION = 3, + STT_FILE = 4, + STT_COMMON = 5, + STT_TLS = 6, + STT_LOOS = 10, + STT_HIOS = 12, + STT_LOPROC = 13, + STT_SPARC_REGISTER = 13, + STT_HIPROC = 15, + }; + uint32_t name; + BIND bind:4; TYPE type:4; + uint8_t other; + uint16_t shndx; + uint64_t value; + uint64_t size; + } PACKED; + + enum RELOC_TYPE: uint32_t { + R_X86_64_NONE, // No reloc + R_X86_64_64, // Direct 64 bit + R_X86_64_PC32, // PC relative 32 bit signed + R_X86_64_GOT32, // 32 bit GOT entry + R_X86_64_PLT32, // 32 bit PLT address + R_X86_64_COPY, // Copy symbol at runtime + R_X86_64_GLOB_DAT, // Create GOT entry + R_X86_64_JUMP_SLOT, // Create PLT entry + R_X86_64_RELATIVE, // Adjust by program base + R_X86_64_GOTPCREL, // 32 bit signed pc relative offset to GOT + R_X86_64_32, // Direct 32 bit zero extended + R_X86_64_32S, // Direct 32 bit sign extended + R_X86_64_16, // Direct 16 bit zero extended + R_X86_64_PC16, // 16 bit sign extended pc relative + R_X86_64_8, // Direct 8 bit sign extended + R_X86_64_PC8 // 8 bit sign extended pc relative + }; + struct REL { + uint64_t addr; + RELOC_TYPE type; + uint32_t sym; + } PACKED; + struct RELA : public REL { + uint64_t add; + } PACKED; + } +} +namespace ELF64 = ELF::_64;