std::vector<Container *> &SegmentContainer::getInnerContainers() { if (innerContainers.empty()) { ELFFile *efile = dynamic_cast<ELFFile *>(getFile()); #ifdef DEBUG assert(efile != nullptr); #endif ELFIO::elfio *interpretor = efile->getELFIO(); ELFIO::segment *segment = interpretor->segments[index]; std::vector<Container *> &topLevel = efile->getTopLevelContainers(); SectionContentsContainer *sectionContents = dynamic_cast<SectionContentsContainer *>(topLevel[4]); #ifdef DEBUG assert(sectionContents != nullptr); #endif std::vector<Container *> §ions = sectionContents->getInnerContainers(); for (unsigned int i = 0; i < segment->get_sections_num(); ++i) addInnerContainer(sections[segment->get_section_index_at(i)]); } return innerContainers; }
// Build the infrastructure for symbol lookup via name TInt E32ImageFile_ELF::DoSymbolLookupHeader(ELFFile &aElfFile, TInt aBaseOffset) { if(!IsNamedLookupEnabled()) return 0; aElfFile.SetLookupTblBase(aBaseOffset); return aElfFile.GetLookupTblSize(); }
TInt E32ImageFile_ELF::CopyCode(char *p, ELFFile &aElfFile) // // Copies the files code sections to p // returns the number of bytes copied or KErrGeneral // { TInt size=aElfFile.GetCodeSize(); memcpy(p, (char *)aElfFile.GetCode(), size); p+=ALIGN4(size); return iHdr->iCodeSize = size; }
// Partially parse the shared object file so that we can call // getSoName on this object. template <class ELFT> void SharedFile<ELFT>::parseSoName() { typedef typename ELFT::Dyn Elf_Dyn; typedef typename ELFT::uint uintX_t; const Elf_Shdr *DynamicSec = nullptr; const ELFFile<ELFT> Obj = this->ELFObj; for (const Elf_Shdr &Sec : Obj.sections()) { switch (Sec.sh_type) { default: continue; case SHT_DYNSYM: this->Symtab = &Sec; break; case SHT_DYNAMIC: DynamicSec = &Sec; break; case SHT_SYMTAB_SHNDX: this->SymtabSHNDX = check(Obj.getSHNDXTable(Sec)); break; case SHT_GNU_versym: this->VersymSec = &Sec; break; case SHT_GNU_verdef: this->VerdefSec = &Sec; break; } } this->initStringTable(); // DSOs are identified by soname, and they usually contain // DT_SONAME tag in their header. But if they are missing, // filenames are used as default sonames. SoName = sys::path::filename(this->getName()); if (!DynamicSec) return; ArrayRef<Elf_Dyn> Arr = check(Obj.template getSectionContentsAsArray<Elf_Dyn>(DynamicSec), getFilename(this) + ": getSectionContentsAsArray failed"); for (const Elf_Dyn &Dyn : Arr) { if (Dyn.d_tag == DT_SONAME) { uintX_t Val = Dyn.getVal(); if (Val >= this->StringTable.size()) fatal(getFilename(this) + ": invalid DT_SONAME entry"); SoName = StringRef(this->StringTable.data() + Val); return; } } }
// Partially parse the shared object file so that we can call // getSoName on this object. template <class ELFT> void SharedFile<ELFT>::parseSoName() { const Elf_Shdr *DynamicSec = nullptr; const ELFFile<ELFT> Obj = this->getObj(); ArrayRef<Elf_Shdr> Sections = check(Obj.sections(), toString(this)); // Search for .dynsym, .dynamic, .symtab, .gnu.version and .gnu.version_d. for (const Elf_Shdr &Sec : Sections) { switch (Sec.sh_type) { default: continue; case SHT_DYNSYM: this->initSymtab(Sections, &Sec); break; case SHT_DYNAMIC: DynamicSec = &Sec; break; case SHT_SYMTAB_SHNDX: this->SymtabSHNDX = check(Obj.getSHNDXTable(Sec, Sections), toString(this)); break; case SHT_GNU_versym: this->VersymSec = &Sec; break; case SHT_GNU_verdef: this->VerdefSec = &Sec; break; } } if (this->VersymSec && this->Symbols.empty()) error("SHT_GNU_versym should be associated with symbol table"); // Search for a DT_SONAME tag to initialize this->SoName. if (!DynamicSec) return; ArrayRef<Elf_Dyn> Arr = check(Obj.template getSectionContentsAsArray<Elf_Dyn>(DynamicSec), toString(this)); for (const Elf_Dyn &Dyn : Arr) { if (Dyn.d_tag == DT_SONAME) { uint64_t Val = Dyn.getVal(); if (Val >= this->StringTable.size()) fatal(toString(this) + ": invalid DT_SONAME entry"); SoName = this->StringTable.data() + Val; return; } } }
TInt E32ImageFile_ELF::DoCodeHeader(ELFFile &aElfFile) // // Calculate the code parts of the ELFFile // { TInt size=ALIGN4(aElfFile.GetCodeSize()); iHdr->iCodeSize = iHdr->iTextSize = size; // make it the offset from the beginning of the file..... if(iHdr->iExportDirCount==0) iHdr->iExportDirOffset = 0; else iHdr->iExportDirOffset = aElfFile.GetExportTableOffset() + iHdr->iCodeOffset; return size; }
std::vector<typename ELFFile<T>::Elf_Shdr> elf_sections(const ELFFile<T> &elf) { typedef typename ELFFile<T>::Elf_Shdr hdr; auto er_hdrs = elf.sections(); if (!er_hdrs) return std::vector<hdr>(); auto hdrs = er_hdrs.get(); return std::vector<hdr>(hdrs.begin(), hdrs.end()); }
std::vector<typename ELFFile<T>::Elf_Phdr> elf_program_headers(const ELFFile<T> &elf) { typedef typename ELFFile<T>::Elf_Phdr hdr; auto er_hdrs = elf.program_headers(); if (!er_hdrs) return std::vector<hdr>(); auto hdrs = er_hdrs.get(); return std::vector<hdr>(hdrs.begin(), hdrs.end()); }
TBool E32ImageFile_ELF::SetUpLookupTable(ELFFile &aElfFile) // Symbol lookup by name is enabled. Create the symbol table with names // and their values. { if(!aElfFile.SetUpLookupTable() ) return FALSE; SetSymNameLookup(TRUE); return TRUE; }
template <class ELFT> std::vector<StringRef> LazyObjectFile::getElfSymbols() { typedef typename ELFT::Shdr Elf_Shdr; typedef typename ELFT::Sym Elf_Sym; typedef typename ELFT::SymRange Elf_Sym_Range; const ELFFile<ELFT> Obj = createELFObj<ELFT>(this->MB); for (const Elf_Shdr &Sec : Obj.sections()) { if (Sec.sh_type != SHT_SYMTAB) continue; Elf_Sym_Range Syms = Obj.symbols(&Sec); uint32_t FirstNonLocal = Sec.sh_info; StringRef StringTable = check(Obj.getStringTableForSymtab(Sec)); std::vector<StringRef> V; for (const Elf_Sym &Sym : Syms.slice(FirstNonLocal)) if (Sym.st_shndx != SHN_UNDEF) V.push_back(check(Sym.getName(StringTable))); return V; } return {}; }
// Partially parse the shared object file so that we can call // getSoName on this object. template <class ELFT> void SharedFile<ELFT>::parseSoName() { typedef typename ELFT::Dyn Elf_Dyn; typedef typename ELFT::uint uintX_t; const Elf_Shdr *DynamicSec = nullptr; const ELFFile<ELFT> Obj = this->ELFObj; for (const Elf_Shdr &Sec : Obj.sections()) { switch (Sec.sh_type) { default: continue; case SHT_DYNSYM: this->Symtab = &Sec; break; case SHT_DYNAMIC: DynamicSec = &Sec; break; case SHT_SYMTAB_SHNDX: this->SymtabSHNDX = check(Obj.getSHNDXTable(Sec)); break; } } this->initStringTable(); SoName = this->getName(); if (!DynamicSec) return; auto *Begin = reinterpret_cast<const Elf_Dyn *>(Obj.base() + DynamicSec->sh_offset); const Elf_Dyn *End = Begin + DynamicSec->sh_size / sizeof(Elf_Dyn); for (const Elf_Dyn &Dyn : make_range(Begin, End)) { if (Dyn.d_tag == DT_SONAME) { uintX_t Val = Dyn.getVal(); if (Val >= this->StringTable.size()) fatal("invalid DT_SONAME entry"); SoName = StringRef(this->StringTable.data() + Val); return; } } }
TInt E32ImageFile_ELF::DoDataHeader(ELFFile &aElfFile, TUint aDataBase) { if (aDataBase==0 && aElfFile.iDataSegmentHdr) aDataBase=aElfFile.iDataSegmentHdr->p_vaddr; TInt size=0; iHdr->iDataBase=aDataBase; if (aElfFile.HasInitialisedData()) { size=ALIGN4(aElfFile.GetDataSize()); iHdr->iDataOffset = iHdr->iCodeOffset + iHdr->iCodeSize; iHdr->iDataSize = size; } if (aElfFile.HasBssData()) { iHdr->iBssSize = ALIGN4(aElfFile.GetBssSize()); } return size; }
std::vector<typename ELFFile<T>::Elf_Shdr> elf_sections(const ELFFile<T> &elf) { typedef typename ELFFile<T>::Elf_Shdr hdr; auto secs = elf.sections(); return std::vector<hdr>(secs.begin(), secs.end()); }
error_or<std::string> elf_section_name(const ELFFile<T> &elf, const typename ELFFile<T>::Elf_Shdr *sec) { auto er_name = elf.getSectionName(sec); if (!er_name) return failure(toString(er_name.takeError())); return success(er_name.get().str()); }
TUint E32ImageFile_ELF::CopyExportSymInfo(char *p, ELFFile &aElfFile) { iHdr->iCodeSize += aElfFile.GetLookupTblSize(); iHdr->iTextSize = iHdr->iCodeSize ; return aElfFile.GetSymLookupSection(p); }
error_or<std::string> elf_section_name(const ELFFile<T> &elf, const typename ELFFile<T>::Elf_Shdr *sec) { auto er_name = elf.getSectionName(sec); if (error_code er = er_name) return failure(er.message()); return success(er_name->str()); }
std::vector<typename ELFFile<T>::Elf_Phdr> elf_program_headers(const ELFFile<T> &elf) { typedef typename ELFFile<T>::Elf_Phdr hdr; return std::vector<hdr>(elf.begin_program_headers(), elf.end_program_headers()); }
std::vector<typename ELFFile<T>::Elf_Shdr> elf_sections(const ELFFile<T> &elf) { typedef typename ELFFile<T>::Elf_Shdr hdr; return std::vector<hdr>(elf.begin_sections(), elf.end_sections()); }
void E32ImageFile_ELF::SetUpExceptions(ELFFile &aElfFile) { aElfFile.GetExceptionIndexInfo(iHdr->iExceptionDescriptor); }
std::vector<Container *> &SHTEntryContainer::getInnerContainers() { if (innerContainers.empty()) { Container *container; ELFFile *efile = dynamic_cast<ELFFile *>(getFile()); ELFIO::elfio *elfData = efile->getELFIO(); ELFIO::section *entry = elfData->sections[index]; int offset = elfData->get_sections_offset() + index * elfData->get_section_entry_size(); container = new Container(getFile(), false, std::make_pair(offset, offset + sizeof(ELFIO::Elf32_Word))); container->setName("sh_name: " + ("\"" + std::string(entry->get_name())) + "\""); addInnerContainer(container); offset += sizeof(ELFIO::Elf32_Word); container = new Container(getFile(), false, std::make_pair(offset, offset + sizeof(ELFIO::Elf32_Word))); int sh_type = entry->get_type(); std::string sh_type_string = ""; switch(sh_type) { case SHT_NULL: sh_type_string = "SHT_NULL"; break; case SHT_PROGBITS: sh_type_string = "SHT_PROGBITS"; break; case SHT_SYMTAB : sh_type_string = "SHT_SYMTAB"; break; case SHT_STRTAB: sh_type_string = "SHT_STRTAB"; break; case SHT_RELA: sh_type_string = "SHT_RELA"; break; case SHT_HASH: sh_type_string = "SHT_HASH"; break; case SHT_DYNAMIC: sh_type_string = "SHT_DYNAMIC"; break; case SHT_NOTE : sh_type_string = "SHT_NOTE"; break; case SHT_NOBITS: sh_type_string = "SHT_NOBITS"; break; case SHT_REL: sh_type_string = "SHT_REL"; break; case SHT_SHLIB: sh_type_string = "SHT_SHLIB"; break; case SHT_DYNSYM: sh_type_string = "SHT_DYNSYM"; break; case SHT_INIT_ARRAY: sh_type_string = "SHT_INIT_ARRAY"; break; case SHT_FINI_ARRAY: sh_type_string = "SHT_FINI_ARRAY"; break; case SHT_PREINIT_ARRAY: sh_type_string = "SHT_PREINIT_ARRAY"; break; case SHT_GROUP: sh_type_string = "SHT_GROUP"; break; case SHT_SYMTAB_SHNDX: sh_type_string = "SHT_SYMTAB_SHNDX"; break; case SHT_LOOS: sh_type_string = "SHT_LOOS"; break; case SHT_HIOS: sh_type_string = "SHT_HIOS"; break; case SHT_LOPROC: sh_type_string = "SHT_LOPROC"; break; case SHT_HIPROC: sh_type_string = "SHT_HIPROC"; break; case SHT_LOUSER: sh_type_string = "SHT_LOUSER"; break; case SHT_HIUSER: sh_type_string = "SHT_HIUSER"; break; default: sh_type_string = printHex(sh_type); break; } container->setName("sh_type: " + sh_type_string); addInnerContainer(container); offset += sizeof(ELFIO::Elf32_Word); container = new Container(getFile(), false, std::make_pair(offset, offset + sizeof(ELFIO::Elf32_Word))); std::string sh_flags_string = ""; ELFIO::Elf_Xword flags = entry->get_flags(); if (flags & SHF_WRITE) sh_flags_string += "SHF_WRITE "; if (flags & SHF_ALLOC) sh_flags_string += "SHF_ALLOC "; if (flags & SHF_EXECINSTR) sh_flags_string += "SHF_EXECINSTR "; if (flags & SHF_MERGE) sh_flags_string += "SHF_MERGE "; if (flags & SHF_STRINGS) sh_flags_string += "SHF_STRINGS "; if (flags & SHF_INFO_LINK) sh_flags_string += "SHF_INFO_LINK "; if (flags & SHF_LINK_ORDER) sh_flags_string += "SHF_LINK_ORDER "; if (flags & SHF_OS_NONCONFORMING) sh_flags_string += "SHF_OS_NONCONFORMING "; if (flags & SHF_GROUP) sh_flags_string += "SHF_GROUP "; if (flags & SHF_TLS) sh_flags_string += "SHF_TLS "; if (flags & SHF_COMPRESSED) sh_flags_string += "SHF_COMPRESSED "; if (flags & SHF_MASKOS) sh_flags_string += "SHF_MASKOS "; if (flags & SHF_MASKPROC) sh_flags_string += "SHF_MASKPROC "; container->setName("sh_flags: " + sh_flags_string); addInnerContainer(container); offset += sizeof(ELFIO::Elf32_Word); container = new Container(getFile(), false, std::make_pair(offset, offset + sizeof(ELFIO::Elf32_Addr))); container->setName("sh_addr: " + printHex(entry->get_address())); addInnerContainer(container); offset += sizeof(ELFIO::Elf32_Addr); container = new Container(getFile(), false, std::make_pair(offset, offset + sizeof(ELFIO::Elf32_Off))); container->setName("sh_offset: " + printHex(entry->get_offset())); addInnerContainer(container); offset += sizeof(ELFIO::Elf32_Off); container = new Container(getFile(), false, std::make_pair(offset, offset + sizeof(ELFIO::Elf32_Word))); container->setName("sh_size: " + std::to_string(entry->get_size())); addInnerContainer(container); offset += sizeof(ELFIO::Elf32_Word); container = new Container(getFile(), false, std::make_pair(offset, offset + sizeof(ELFIO::Elf32_Word))); container->setName("sh_link: " + std::to_string(entry->get_link())); addInnerContainer(container); offset += sizeof(ELFIO::Elf32_Word); container = new Container(getFile(), false, std::make_pair(offset, offset + sizeof(ELFIO::Elf32_Word))); container->setName("sh_info: " + std::to_string(entry->get_info())); addInnerContainer(container); offset += sizeof(ELFIO::Elf32_Word); container = new Container(getFile(), false, std::make_pair(offset, offset + sizeof(ELFIO::Elf32_Word))); container->setName("sh_addralign: " + std::to_string(entry->get_addr_align())); addInnerContainer(container); offset += sizeof(ELFIO::Elf32_Word); container = new Container(getFile(), false, std::make_pair(offset, offset + sizeof(ELFIO::Elf32_Word))); container->setName("sh_entsize: " + std::to_string(entry->get_entry_size())); addInnerContainer(container); offset += sizeof(ELFIO::Elf32_Word); } return innerContainers; }
TInt E32ImageFile_ELF::Translate(const char* aFileName, TUint aDataBase, TBool aAllowDllData, \ TBool aSymLkupEnabled) // // Translate a ELF format file to a E32Image file // { iSource = EElfFile; ELFFile elffile; if (!elffile.Init((const TText * const)aFileName)) return KErrGeneral; iFileName = strdup(aFileName); Adjust(ALIGN4(sizeof(E32ImageHeaderV))); // fixed for now because holes not supported SetDefaultHeader(); iHdr->iDllRefTableCount = elffile.NumberOfImportDlls(); iHdr->iExportDirCount = elffile.NumberOfExports(); iHdr->iCodeBase = elffile.iLinkedBase; if(aSymLkupEnabled) { if( !SetUpLookupTable(elffile) ) return KErrGeneral; } TInt size = ALIGN4(sizeof(E32ImageHeaderV)); // fixed for now because holes not supported iHdr->iCodeOffset = size; TInt pos = size; size+=DoCodeHeader(elffile); size += DoSymbolLookupHeader(elffile, size - pos); TInt nimports=elffile.NumberOfImports(); TInt importSectionSize; char *newImportSection=CreateImportSection(elffile, importSectionSize); TInt t=DoDataHeader(elffile, aDataBase); if (t>0) { iHdr->iDataOffset = size; size += t; } if (importSectionSize!=0) { iHdr->iImportOffset=size; size+=ALIGN4(importSectionSize); } char *newCodeRelocs=NULL; char *newDataRelocs=NULL; TInt codeRelocSize=0, dataRelocSize=0; TInt nCodeRelocs=elffile.NumberOfCodeRelocs(); TInt nDataRelocs=elffile.NumberOfDataRelocs(); if (nCodeRelocs + nDataRelocs) { Elf32_Rel **codeRelocs=new Elf32_Rel * [nCodeRelocs]; Elf32_Rel **dataRelocs=new Elf32_Rel * [nDataRelocs]; if (!elffile.GetRelocs(codeRelocs, dataRelocs)) return KErrGeneral; FixRelocs(elffile, codeRelocs, dataRelocs); if (elffile.iCodeSegmentHdr) newCodeRelocs=CreateRelocs(elffile, codeRelocs, nCodeRelocs, codeRelocSize, elffile.iCodeSegmentHdr->p_vaddr); if (elffile.iDataSegmentHdr) newDataRelocs=CreateRelocs(elffile, dataRelocs, nDataRelocs, dataRelocSize, elffile.iDataSegmentHdr->p_vaddr); if (codeRelocSize) { iHdr->iCodeRelocOffset = size; size += codeRelocSize; } if (dataRelocSize) { iHdr->iDataRelocOffset = size; size += dataRelocSize; } delete [] codeRelocs; delete [] dataRelocs; } Adjust(size); t=CopyCode(iData + pos, elffile); if (t<0) return KErrGeneral; pos += t; t = CopyExportSymInfo(iData+pos, elffile); if (t<0) return KErrGeneral; pos += t; pos += CopyData(iData + pos, elffile); if (nimports) { memcpy(iData + pos, newImportSection, importSectionSize); pos += ALIGN4(importSectionSize); } if (codeRelocSize) { memcpy(iData + pos, newCodeRelocs, codeRelocSize); pos += codeRelocSize; } if (dataRelocSize) { memcpy(iData + pos, newDataRelocs, dataRelocSize); pos += dataRelocSize; } // locate the entry point TUint entryPointOffset=elffile.GetEntryPointOffset(); // Arrange a header for this E32 Image iHdr->iCpuIdentifier = (TUint16)ECpuArmV4; // Import format is ELF-derived iHdr->iFlags |= KImageImpFmt_ELF; // ABI is ARM EABI iHdr->iFlags |= KImageABI_EABI; if (ImageIsDll(elffile)) { iHdr->iFlags |= KImageDll; if (iHdr->iDataSize && !aAllowDllData) return Print(EError, "Dll '%s' has initialised data.\n", iFileName); if (iHdr->iBssSize && !aAllowDllData) return Print(EError, "Dll '%s' has uninitialised data.\n", iFileName); } iHdr->iHeapSizeMin = elffile.iHeapCommittedSize; iHdr->iHeapSizeMax = elffile.iHeapReservedSize; iHdr->iStackSize = elffile.iStackCommittedSize; iHdr->iEntryPoint = entryPointOffset; TInt r = DetermineEntryPointType(); if (r == KErrCorrupt) return Print(EError, "File '%s': Bad Entry Point.\n", iFileName); else if (r == KErrNotSupported) return Print(EError, "File '%s': Bad Entry Point Type.\n", iFileName); SetUpExceptions(elffile); delete [] newImportSection; delete [] newCodeRelocs; delete [] newDataRelocs; return KErrNone; }
TInt E32ImageFile_ELF::CopyData(char *p, ELFFile &aElfFile) { TInt size=aElfFile.GetDataSize(); if (size) memcpy(p, (char *)aElfFile.GetData(), size); return size; }
TBool E32ImageFile_ELF::ImageIsDll(ELFFile& aElfFile) { return aElfFile.ImageIsDll(); }