void symbol_entries(const ELFObjectFile<T> &obj, ogre_doc &s) { typedef typename ELFFile<T>::Elf_Shdr sec_hdr; auto elf = obj.getELFFile(); symbol_entries(obj, obj.symbol_begin(), obj.symbol_end(), s); auto secs = prim::elf_sections(*elf); bool is_dyn = std::any_of(secs.begin(), secs.end(), [](const sec_hdr &hdr) { return (hdr.sh_type == ELF::SHT_DYNSYM); }); if (is_dyn) // preventing from llvm 3.8 fail in case of .dynsym absence symbol_entries(obj, obj.dynamic_symbol_begin(), obj.dynamic_symbol_end(), s); }
bool checked(const ELFObjectFile<T> &obj, SectionRef sec_ref) { typedef typename ELFObjectFile<T>::Elf_Shdr Elf_Shdr; auto &elf = *obj.getELFFile(); const Elf_Shdr *RelSec = obj.getSection(sec_ref.getRawDataRefImpl()); auto symsec = elf.getSection(RelSec->sh_link); if (!symsec) return false; uint32_t sec_typ = (*symsec)->sh_type; return (sec_typ == ELF::SHT_SYMTAB || sec_typ == ELF::SHT_DYNSYM); }
uint64_t section_offset(const ELFObjectFile<T> &obj, section_iterator it) { typedef typename ELFObjectFile<T>::Elf_Shdr_Iter elf_shdr_iterator; if (it == obj.end_sections()) return 0; // check for special elf sections auto elf = obj.getELFFile(); auto raw = it->getRawDataRefImpl(); auto elf_sec_it = elf_shdr_iterator(elf->getHeader()->e_shentsize, reinterpret_cast<const char *>(raw.p)); return elf_sec_it->sh_offset; }
std::vector<segment> read(const ELFObjectFile<T>& obj) { auto begin = obj.getELFFile()->begin_program_headers(); auto end = obj.getELFFile()->end_program_headers(); std::vector<segment> segments; segments.reserve(std::distance(begin, end)); for (int pos = 0; begin != end; ++begin, ++pos) { if (begin -> p_type == ELF::PT_LOAD) { segments.push_back(segment(*begin, pos)); } } return segments; }
static bool isObject(ELFObjectFile<ELFT> &Obj, symbol_iterator I) { typedef typename ELFObjectFile<ELFT>::Elf_Sym Elf_Sym; DataRefImpl Symb = I->getRawDataRefImpl(); const Elf_Sym *ESym = Obj.getSymbol(Symb); return ESym->getType() == ELF::STT_OBJECT; }
void relocations(const ELFObjectFile<T> &obj, ogre_doc &s) { for (auto sec : obj.sections()) { auto rel_sec = sec.getRelocatedSection(); if (!checked(obj, sec)) continue; for (auto rel : sec.relocations()) symbol_reference(obj, rel, rel_sec, s); } }
static char getSymbolNMTypeChar(ELFObjectFile<ELFT> &Obj, basic_symbol_iterator I) { typedef typename ELFObjectFile<ELFT>::Elf_Sym Elf_Sym; typedef typename ELFObjectFile<ELFT>::Elf_Shdr Elf_Shdr; // OK, this is ELF symbol_iterator SymI(I); DataRefImpl Symb = I->getRawDataRefImpl(); const Elf_Sym *ESym = Obj.getSymbol(Symb); const ELFFile<ELFT> &EF = *Obj.getELFFile(); const Elf_Shdr *ESec = EF.getSection(ESym); if (ESec) { switch (ESec->sh_type) { case ELF::SHT_PROGBITS: case ELF::SHT_DYNAMIC: switch (ESec->sh_flags) { case (ELF::SHF_ALLOC | ELF::SHF_EXECINSTR): return 't'; case (ELF::SHF_TLS | ELF::SHF_ALLOC | ELF::SHF_WRITE): case (ELF::SHF_ALLOC | ELF::SHF_WRITE): return 'd'; case ELF::SHF_ALLOC: case (ELF::SHF_ALLOC | ELF::SHF_MERGE): case (ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS): return 'r'; } break; case ELF::SHT_NOBITS: return 'b'; } } if (ESym->getType() == ELF::STT_SECTION) { StringRef Name; if (error(SymI->getName(Name))) return '?'; return StringSwitch<char>(Name) .StartsWith(".debug", 'N') .StartsWith(".note", 'n') .Default('?'); } return '?'; }
void section_headers(const ELFObjectFile<T> &obj, ogre_doc &s) { auto elf = obj.getELFFile(); auto base = base_address(obj); for (auto sec : prim::elf_sections(*elf)) { auto name = prim::elf_section_name(*elf, &sec); if (name) section_header(sec, *name, base, s); } }
void section_headers(const ELFObjectFile<T> &obj, ogre_doc &s) { auto elf = obj.getELFFile(); auto base = base_address(obj); for (auto it = elf->begin_sections(); it != elf->end_sections(); ++it) { auto name = elf->getSectionName(&*it); if (name) section_header(*it, (*name).str(), base, s); else s.fail(error_code(name).message()); } }
error_or<int64_t> symbol_address(const ELFObjectFile<T> &obj, const SymbolRef &sym) { auto sym_elf = obj.getSymbol(sym.getRawDataRefImpl()); if (is_rel(obj) && !is_abs_symbol(*sym_elf)) { // abs symbols does not affected by relocations return success(int64_t(0)); } else { auto addr = prim::symbol_address(sym); if (!addr) return addr; auto base = base_address(obj); return success(prim::relative_address(base, *addr)); } }
error_or<symbol_sizes> getSymbolSizes(const ELFObjectFile<ELFT> &obj) { typedef typename ELFFile<ELFT>::Elf_Shdr sec_hdr; symbol_sizes syms; for (auto sym : obj.symbols()) syms.push_back({sym, sym.getSize()}); auto sections = prim::elf_sections(*obj.getELFFile()); bool is_dyn = std::any_of(sections.begin(), sections.end(), [](const sec_hdr &hdr) { return (hdr.sh_type == ELF::SHT_DYNSYM); }); if (!syms.size() && !is_dyn) return success(symbol_sizes()); if (is_dyn) // we aren't able to rely on iterators because of bug in llvm for (auto sym : obj.getDynamicSymbolIterators()) syms.push_back({sym, sym.getSize()}); return success(syms); }
void symbol_entry(const ELFObjectFile<T> &obj, const SymbolRef &sym, ogre_doc &s) { auto sym_elf = obj.getSymbol(sym.getRawDataRefImpl()); if (is_abs_symbol(*sym_elf)) { return; } auto name = prim::symbol_name(sym); auto addr = symbol_address(obj, sym); auto off = symbol_file_offset(obj, sym); if (name && addr && off) { s.entry("symbol-entry") << *name << *addr << sym_elf->st_size << *off; if (sym_elf->getType() == ELF::STT_FUNC) s.entry("code-entry") << *name << *off << sym_elf->st_size ; } }
void symbol_reference(const ELFObjectFile<T> &obj, const RelocationRef &rel, section_iterator sec, ogre_doc &s) { auto it = rel.getSymbol(); if (it == prim::end_symbols(obj)) return; auto sym_elf = obj.getSymbol(it->getRawDataRefImpl()); auto sec_offset = section_offset(obj, sec); auto off = prim::relocation_offset(rel) + sec_offset; // relocation file offset if (is_external_symbol(*sym_elf)) { if (auto name = prim::symbol_name(*it)) s.entry("ref-external") << off << *name; } else { if (auto file_offset = symbol_file_offset(obj, *it)) s.entry("ref-internal") << *file_offset << off; } }
std::vector<symbol> read(const ELFObjectFile<ELFT>& obj) { int size1 = utils::distance(obj.begin_symbols(), obj.end_symbols()); int size2 = utils::distance(obj.begin_dynamic_symbols(), obj.end_dynamic_symbols()); std::vector<symbol> symbols; symbols.reserve(size1+size2); auto it = read(obj.begin_symbols(), obj.end_symbols(), std::back_inserter(symbols)); read(obj.begin_dynamic_symbols(), obj.end_dynamic_symbols(), it); return symbols; }
void program_headers(const ELFObjectFile<T> &obj, ogre_doc &s) { auto elf = obj.getELFFile(); program_headers(elf->begin_program_headers(), elf->end_program_headers(), s); }
uint64_t base_address(const ELFObjectFile<T> &obj) { auto elf = obj.getELFFile(); return base_address(elf->begin_program_headers(), elf->end_program_headers()); }
uint64_t section_offset(const ELFObjectFile<T> &obj, section_iterator it) { if (it == obj.section_end()) return 0; // check for special elf sections auto sec_elf = obj.getSection(it->getRawDataRefImpl()); return sec_elf->sh_offset; }
void program_headers(const ELFObjectFile<T> &obj, ogre_doc &s) { auto hdrs = prim::elf_program_headers(*obj.getELFFile()); program_headers(hdrs.begin(), hdrs.end(), s); }
uint64_t base_address(const ELFObjectFile<T> &obj) { auto hdrs = prim::elf_program_headers(*obj.getELFFile()); return base_address(hdrs.begin(), hdrs.end()); }
void symbol_entries(const ELFObjectFile<T> &obj, ogre_doc &s) { typedef typename ELFFile<T>::Elf_Shdr sec_hdr; auto elf = obj.getELFFile(); symbol_entries(obj, obj.begin_symbols(), obj.end_symbols(), s); symbol_entries(obj, obj.begin_dynamic_symbols(), obj.end_dynamic_symbols(), s); }
bool is_rel(const ELFObjectFile<T> &obj) { auto hdr = obj.getELFFile()->getHeader(); return (hdr->e_type == ELF::ET_REL); }
uint64_t image_entry(const ELFObjectFile<ELFT>& obj) { return obj.getELFFile()->getHeader()->e_entry; }
error_code getSymbolNMTypeChar(ELFObjectFile<ELFT> &Obj, symbol_iterator I, char &Result) { typedef typename ELFObjectFile<ELFT>::Elf_Sym Elf_Sym; typedef typename ELFObjectFile<ELFT>::Elf_Shdr Elf_Shdr; DataRefImpl Symb = I->getRawDataRefImpl(); const Elf_Sym *ESym = Obj.getSymbol(Symb); const ELFFile<ELFT> &EF = *Obj.getELFFile(); const Elf_Shdr *ESec = EF.getSection(ESym); char ret = '?'; if (ESec) { switch (ESec->sh_type) { case ELF::SHT_PROGBITS: case ELF::SHT_DYNAMIC: switch (ESec->sh_flags) { case(ELF::SHF_ALLOC | ELF::SHF_EXECINSTR) : ret = 't'; break; case(ELF::SHF_ALLOC | ELF::SHF_WRITE) : ret = 'd'; break; case ELF::SHF_ALLOC: case(ELF::SHF_ALLOC | ELF::SHF_MERGE) : case(ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS) : ret = 'r'; break; } break; case ELF::SHT_NOBITS: ret = 'b'; } } switch (EF.getSymbolTableIndex(ESym)) { case ELF::SHN_UNDEF: if (ret == '?') ret = 'U'; break; case ELF::SHN_ABS: ret = 'a'; break; case ELF::SHN_COMMON: ret = 'c'; break; } switch (ESym->getBinding()) { case ELF::STB_GLOBAL: ret = ::toupper(ret); break; case ELF::STB_WEAK: if (EF.getSymbolTableIndex(ESym) == ELF::SHN_UNDEF) ret = 'w'; else if (ESym->getType() == ELF::STT_OBJECT) ret = 'V'; else ret = 'W'; } if (ret == '?' && ESym->getType() == ELF::STT_SECTION) { StringRef Name; error_code EC = I->getName(Name); if (EC) return EC; Result = StringSwitch<char>(Name) .StartsWith(".debug", 'N') .StartsWith(".note", 'n') .Default('?'); return object_error::success; } Result = ret; return object_error::success; }
void file_header(const ELFObjectFile<T> &obj, ogre_doc &s) { auto hdr = obj.getELFFile()->getHeader(); auto base = base_address(obj); s.entry("relocatable") << is_rel(obj); s.entry("entry") << hdr->e_entry - base; }