diff --git a/RosBE-PPC/elfpe/Makefile b/RosBE-PPC/elfpe/Makefile index b0ab736..baa6cf6 100644 --- a/RosBE-PPC/elfpe/Makefile +++ b/RosBE-PPC/elfpe/Makefile @@ -1,6 +1,6 @@ elfpe: argparse.cpp argparse.h header.cpp header.h \ objectfile.cpp objectfile.h util.cpp util.h pedef.h \ - elfpe.cpp + elfpe.cpp reloc.cpp coff.cpp exports.cpp imports.cpp g++ -g -o $@ $^ -lelf clean: diff --git a/RosBE-PPC/elfpe/coff.cpp b/RosBE-PPC/elfpe/coff.cpp new file mode 100755 index 0000000..37cae26 --- /dev/null +++ b/RosBE-PPC/elfpe/coff.cpp @@ -0,0 +1,42 @@ +#include "coff.h" + +PECoffExecutable::PECoffExecutable +(const ElfObjectFile &elf, const std::string &file, uint32_t filealign) + : elf(elf), tempFile(file), filealign(filealign) +{ + int i; + FILE *f = fopen(tempFile.c_str(), "wb"); + if (!f) return; + + // Write PE Header + const ElfObjectFile::Section §ion = *elf.getNamedSection(".peheader"); + fwrite(section.getSectionData(), 1, section.logicalSize(), f); + + // Write out sections + uint32_t physSize; + uint32_t bytes = 0; + + for (i = 1; i < elf.getNumSections(); i++) + { + const ElfObjectFile::Section §ion = elf.getSection(i); + if (section.getName() == ".peheader") continue; + if (section.getType() != SHT_NOBITS && section.getFlags() & SHF_ALLOC) + { + physSize = roundup(section.logicalSize(), filealign); +#if 0 + printf("P %08x:%08x %s\n", + (int)ftell(f), + section.logicalSize(), + section.getName().c_str()); +#endif + bytes = fwrite(section.getSectionData(), 1, section.logicalSize(), f); + while(bytes++ < physSize) fputc(0, f); + } + } + fclose(f); +} + +void PECoffExecutable::Write(const std::string &resultFile) +{ + rename(tempFile.c_str(), resultFile.c_str()); +} diff --git a/RosBE-PPC/elfpe/coff.h b/RosBE-PPC/elfpe/coff.h new file mode 100644 index 0000000..dc9fdb5 --- /dev/null +++ b/RosBE-PPC/elfpe/coff.h @@ -0,0 +1,22 @@ +#ifndef COMPDVR_COFF_H +#define COMPDVR_COFF_H + +#include +#include +#include "pedef.h" +#include "util.h" +#include "objectfile.h" +#include "section.h" + +class PECoffExecutable { +public: + PECoffExecutable(const ElfObjectFile &elf, const std::string &tmpFile, uint32_t filealign); + void Write(const std::string &resultFile); + +private: + const ElfObjectFile &elf; + std::string tempFile; + uint32_t filealign; +}; + +#endif//COMPDVR_COFF_H diff --git a/RosBE-PPC/elfpe/elfpe.cpp b/RosBE-PPC/elfpe/elfpe.cpp index 4716729..f910cb5 100644 --- a/RosBE-PPC/elfpe/elfpe.cpp +++ b/RosBE-PPC/elfpe/elfpe.cpp @@ -12,8 +12,13 @@ #include "objectfile.h" #include "header.h" #include "argparse.h" +#include "reloc.h" +#include "coff.h" +#include "exports.h" +#include "imports.h" #define TYPE_PEHEADER (SHT_LOOS + 1) +#define TYPE_PERELOC (SHT_LOOS + 2) int execute_command( bool verbose, const std::vector &args ) { @@ -57,6 +62,26 @@ void possibly_define args.insert(args.begin(), the_definition + "=" + body); } +std::vector +ProcessRelocSections +(const ElfObjectFile &eof, + uint32_t imageBase, + const std::vector &rvas) +{ + std::vector relocData; + uint32_t relocAddr = (uint32_t)-1; + int i, j; + for (i = 1; i < eof.getNumSections(); i++) + { + const ElfObjectFile::Section §ion = eof.getSection(i); + if (section.getType() == SHT_REL || + section.getType() == SHT_RELA) + SingleRelocSection(eof, section, rvas, relocData, imageBase, relocAddr); + } + AddReloc(relocData, 0, relocAddr, 0, 0); + return relocData; +} + int main( int argc, char **argv ) { bool verbose = false, nostdlib = false, nostartfiles = false, compile_only = false, is_dll = false, entry, @@ -101,6 +126,11 @@ int main( int argc, char **argv ) { { entry_point = entry_point.substr(1); } + size_t at = entry_point.find('@'); + if (at != std::string::npos) + { + entry_point = entry_point.substr(0, at); + } if( !compile_only ) { gcc_args_str.push_back(std::string("-Wl,--entry=") + entry_point); @@ -142,7 +172,7 @@ int main( int argc, char **argv ) { if( verbose ) gcc_args_str.insert(gcc_args_str.begin(),"-v"); if (!compile_only) { - if( is_dll ) gcc_args_str.insert(gcc_args_str.begin(), "-Wl,-r"); + //gcc_args_str.insert(gcc_args_str.begin(), "-Wl,-r"); gcc_args_str.insert(gcc_args_str.begin(), "-Wl,-q"); gcc_args_str.insert(gcc_args_str.begin(), "-Wl,-d"); gcc_args_str.insert(gcc_args_str.begin(), "-Wl,--start-group"); @@ -160,30 +190,56 @@ int main( int argc, char **argv ) { } if (!compile_only) gcc_args_str.insert(gcc_args_str.end(), "-Wl,--end-group"); + std::vector sectionRvas; if ( !(status = execute_command( verbose, gcc_args_str )) && !compile_only && mkheader ) { /* Ok fixup the elf object file */ ElfObjectFile eof(output_file); + if(!eof) exit(1); + + uint32_t imageSize; const ElfObjectFile::Symbol *entry_sym; - - if(!eof) exit(1); - entry_sym = eof.getNamedSymbol(entry_point); - + + /* This computes the section RVAs */ ElfPeHeader header - (strtoul(image_base.c_str(), 0, 0), - strtoul(section_align.c_str(), 0, 0), - strtoul(file_align.c_str(), 0, 0), - entry_sym, - 0x10000, - 0x100000, - 0x10000, - 0x100000, - atoi(subsystem.c_str()), - is_dll, - &eof); + (strtoul(image_base.c_str(), 0, 0), + strtoul(section_align.c_str(), 0, 0), + strtoul(file_align.c_str(), 0, 0), + entry_sym, + 0x10000, + 0x100000, + 0x10000, + 0x100000, + atoi(subsystem.c_str()), + is_dll, + &eof); + + // Get base section layout + imageSize = header.getSectionRvas(sectionRvas); - eof.addSection(".peheader", header.getData(), TYPE_PEHEADER); + // Add relocation info + std::vector relocSection = + ProcessRelocSections + (eof, strtoul(image_base.c_str(), 0, 0), sectionRvas); + eof.addSection(".reloc", relocSection, SHT_PROGBITS); + eof.update(); + + // Recompute RVAs after adding reloc section + imageSize = header.getSectionRvas(sectionRvas); + header.createHeaderSection(sectionRvas, imageSize); + eof.addSection(".peheader", header.getData(), SHT_PROGBITS); + eof.update(); + + // Fixup exports + ExportFixup(eof, sectionRvas); + + // Fixup imports + ImportFixup(eof, sectionRvas); + eof.update(); + + PECoffExecutable cof(eof, output_file + ".tmp", strtoul(file_align.c_str(), 0, 0)); + cof.Write(output_file); } return status; diff --git a/RosBE-PPC/elfpe/exports.cpp b/RosBE-PPC/elfpe/exports.cpp new file mode 100644 index 0000000..5a41b15 --- /dev/null +++ b/RosBE-PPC/elfpe/exports.cpp @@ -0,0 +1,46 @@ +#include "exports.h" +#include "objectfile.h" +#include "section.h" + +void ExportFixup +(ElfObjectFile &eof, + const std::vector &mapping) +{ + const ElfObjectFile::Section *exportSect = eof.getNamedSection(".edata"); + if (!exportSect) return; + uint8_t *exportTable = exportSect->getSectionData(); + // Fixup the words of the export directory + uint8_t *exportTarget = exportTable; + uint32_t exportRva = FindRVA(mapping, exportSect->getNumber()); + + uint32_t nameRva, ordinalBase, numberOfAddress, numberOfNames, addressRva, + namePtrRva, ordinalTableRva; + int i; + + le32write_postinc(exportTarget, be32read(exportTarget)); + le32write_postinc(exportTarget, be32read(exportTarget)); + le16write_postinc(exportTarget, be16read(exportTarget)); + le16write_postinc(exportTarget, be16read(exportTarget)); + le32write_postinc(exportTarget, (nameRva = be32read(exportTarget))); + le32write_postinc(exportTarget, (ordinalBase = be32read(exportTarget))); + le32write_postinc(exportTarget, (numberOfAddress = be32read(exportTarget))); + le32write_postinc(exportTarget, (numberOfNames = be32read(exportTarget))); + le32write_postinc(exportTarget, (addressRva = be32read(exportTarget))); + le32write_postinc(exportTarget, (namePtrRva = be32read(exportTarget))); + le32write_postinc(exportTarget, (ordinalTableRva = be32read(exportTarget))); + + // Address Table + exportTarget = exportTable + addressRva - exportRva; + for (i = 0; i < numberOfAddress; i++) + le32write_postinc(exportTarget, be32read(exportTarget)); + + // Name table + exportTarget = exportTable + namePtrRva - exportRva; + for (i = 0; i < numberOfNames; i++) + le32write_postinc(exportTarget, be32read(exportTarget)); + + // Ordinal table + exportTarget = exportTable + ordinalTableRva - exportRva; + for (i = 0; i < numberOfAddress; i++) + le16write_postinc(exportTarget, be16read(exportTarget)); +} diff --git a/RosBE-PPC/elfpe/exports.h b/RosBE-PPC/elfpe/exports.h new file mode 100644 index 0000000..8f039ca --- /dev/null +++ b/RosBE-PPC/elfpe/exports.h @@ -0,0 +1,14 @@ +#ifndef COMPDVR_EXPORTS_H +#define COMPDVR_EXPORTS_H + +#include +#include +#include "pedef.h" +#include "util.h" +#include "objectfile.h" +#include "section.h" + +void ExportFixup +(ElfObjectFile &eof, const std::vector &mapping); + +#endif//COMPDVR_EXPORTS_H diff --git a/RosBE-PPC/elfpe/header.cpp b/RosBE-PPC/elfpe/header.cpp index 801d715..8b3a259 100644 --- a/RosBE-PPC/elfpe/header.cpp +++ b/RosBE-PPC/elfpe/header.cpp @@ -16,6 +16,7 @@ ElfPeHeader::ElfPeHeader ElfObjectFile *eof) : imagebase(imagebase), sectionalign(sectionalign), + filealign(filealign), stackreserve(stackreserve), stackcommit(stackcommit), heapreserve(heapreserve), @@ -25,19 +26,15 @@ ElfPeHeader::ElfPeHeader eof(eof) { data.resize(computeSize()); - createHeaderSection(); } int ElfPeHeader::computeSize() const { - return sectionalign; /* We'll compute it for real later */ + return roundup(0x80 + 0x200, filealign); /* We'll compute it for real later */ } -void ElfPeHeader::createHeaderSection() +void ElfPeHeader::createHeaderSection(const std::vector §ionRvaSet, uint32_t imageSize) { - std::vector sectionRvaSet; - uint32_t imageSize = getSectionRvas(sectionRvaSet); - data[0] = 'M'; data[1] = 'Z'; uint8_t *dataptr = &data[0x3c]; uint32_t coffHeaderSize, optHeaderSizeMember; @@ -88,7 +85,7 @@ void ElfPeHeader::createHeaderSection() le32pwrite_postinc(dataptr, getResourceInfo(sectionRvaSet)); le32pwrite_postinc(dataptr, getExceptionInfo()); le32pwrite_postinc(dataptr, getSecurityInfo()); - le32pwrite_postinc(dataptr, getRelocInfo()); + le32pwrite_postinc(dataptr, getRelocInfo(sectionRvaSet)); le32pwrite_postinc(dataptr, getDebugInfo()); le32pwrite_postinc(dataptr, getDescrInfo()); le32pwrite_postinc(dataptr, getMachInfo()); @@ -101,28 +98,37 @@ void ElfPeHeader::createHeaderSection() // size, but leaving out the other info. We write the section name // truncated into the name field and leave the section id in the // physical address bit + + uint32_t paddr = computeSize(); for (int i = 0; i < sectionRvaSet.size(); i++) { section_mapping_t mapping = sectionRvaSet[i]; const ElfObjectFile::Section *section = mapping.section; std::string name = section->getName(); uint32_t size = section->logicalSize(); + uint32_t psize = + section->getType() == SHT_NOBITS ? 0 : roundup(size, filealign); uint32_t rva = mapping.rva; for (int j = 0; j < 8; j++) { *dataptr++ = j < name.size() ? name[j] : '\000'; } + +#if 0 + printf("V %08x:%08x P %08x:%08x %s\n", + rva, size, paddr, psize, name.c_str()); +#endif + le32write_postinc(dataptr, size); le32write_postinc(dataptr, rva); - le32write_postinc(dataptr, size); - // Note: we put the index in the offset slot so we can find the - // real offset later in the loader - le32write_postinc(dataptr, sectionRvaSet[i].index); + le32write_postinc(dataptr, psize); + le32write_postinc(dataptr, paddr); le32write_postinc(dataptr, 0); le32write_postinc(dataptr, 0); le32write_postinc(dataptr, 0); // XXX Figure out the real flags le32write_postinc(dataptr, IMAGE_SCN_CNT_CODE); + paddr += psize; } } @@ -132,14 +138,17 @@ uint32_t ElfPeHeader::getSectionRvas(std::vector &rvas) const { uint32_t start = computeSize(); uint32_t limit = start; - for(int i = 0; i < eof->getNumSections(); i++) { + + rvas.clear(); + + for(int i = 1; i < eof->getNumSections(); i++) { { const ElfObjectFile::Section § = eof->getSection(i); if(sect.getFlags() & SHF_ALLOC) { limit = roundup(start + sect.logicalSize(), sectionalign); #if 0 - fprintf(stderr, "rva[%02d:%s] = (%x %x %d)\n", - rvas.size(), sect.getName().c_str(), §, start, i); + fprintf(stderr, "rva[%02d:-%20s] = (%08x %08x %08x %d)\n", + rvas.size(), sect.getName().c_str(), start, sect.getStartRva(), sect.logicalSize(), i); #endif rvas.push_back(section_mapping_t(§, start, i)); } @@ -198,9 +207,9 @@ u32pair_t ElfPeHeader::getSecurityInfo() const return std::make_pair(0,0); } -u32pair_t ElfPeHeader::getRelocInfo() const +u32pair_t ElfPeHeader::getRelocInfo(const std::vector &mapping) const { - return std::make_pair(0,0); + return getNamedSectionInfo(eof, mapping, ".reloc"); } u32pair_t ElfPeHeader::getDebugInfo() const diff --git a/RosBE-PPC/elfpe/header.h b/RosBE-PPC/elfpe/header.h index dd1f9f6..bda2fcd 100644 --- a/RosBE-PPC/elfpe/header.h +++ b/RosBE-PPC/elfpe/header.h @@ -6,18 +6,7 @@ #include "pedef.h" #include "util.h" #include "objectfile.h" - -typedef struct section_mapping_t { - const ElfObjectFile::Section *section; - uint32_t rva; - int index; - - section_mapping_t - (const ElfObjectFile::Section *sect, uint32_t rva, int index) : - section(sect), rva(rva), index(index) { } - section_mapping_t(const section_mapping_t &other) : - section(other.section), rva(other.rva), index(other.index) { } -} section_mapping_t; +#include "section.h" class ElfPeHeader { public: @@ -34,10 +23,10 @@ public: bool dll, ElfObjectFile *eof); const ElfObjectFile::secdata_t &getData() const; + uint32_t getSectionRvas(std::vector &rvas) const; + void createHeaderSection(const std::vector &rvas, uint32_t imageSize); private: - void createHeaderSection(); - uint32_t getSectionRvas(std::vector &rvas) const; uint32_t getEntryPoint(const std::vector &rvas, const ElfObjectFile::Symbol *entry) const; int computeSize() const; int getExeFlags() const { return 0; } @@ -47,7 +36,7 @@ private: u32pair_t getResourceInfo(const std::vector &rvas) const; u32pair_t getExceptionInfo() const; u32pair_t getSecurityInfo() const; - u32pair_t getRelocInfo() const; + u32pair_t getRelocInfo(const std::vector &rvas) const; u32pair_t getDebugInfo() const; u32pair_t getDescrInfo() const; u32pair_t getMachInfo() const; diff --git a/RosBE-PPC/elfpe/imports.cpp b/RosBE-PPC/elfpe/imports.cpp new file mode 100644 index 0000000..e2c80c9 --- /dev/null +++ b/RosBE-PPC/elfpe/imports.cpp @@ -0,0 +1,43 @@ +#include "imports.h" +#include "objectfile.h" +#include "section.h" + +void ImportFixup +(ElfObjectFile &eof, + const std::vector &mapping) +{ + const ElfObjectFile::Section *importSect = eof.getNamedSection(".idata"); + if (!importSect) return; + uint8_t *importTable = importSect->getSectionData(); + uint8_t *importTarget = importTable, *tableAddr, *hintName; + uint32_t importRva = FindRVA(mapping, importSect->getNumber()); + uint32_t tableRva, iatRva, hintNameEntry; + + do + { + le32write_postinc(importTarget, (tableRva = be32read(importTarget))); + le32write_postinc(importTarget, be32read(importTarget)); + le32write_postinc(importTarget, be32read(importTarget)); + le32write_postinc(importTarget, be32read(importTarget)); + le32write_postinc(importTarget, (iatRva = be32read(importTarget))); + + if (!tableRva) return; + + // Rewrite the import lookup table + tableAddr = importTable + tableRva - importRva; + while (hintNameEntry = be32read(tableAddr)) + { + le32write_postinc(tableAddr, hintNameEntry); + // Rewrite the hint/name element + //hintName = importTable + hintNameEntry - importRva; + //le16write(hintName, be16read(hintName)); + } + + // Do the second address table + tableAddr = importTable + iatRva - importRva; + while (hintNameEntry = be32read(tableAddr)) + { + le32write_postinc(tableAddr, hintNameEntry); + } + } while(1); +} diff --git a/RosBE-PPC/elfpe/imports.h b/RosBE-PPC/elfpe/imports.h new file mode 100644 index 0000000..63ab0a4 --- /dev/null +++ b/RosBE-PPC/elfpe/imports.h @@ -0,0 +1,14 @@ +#ifndef COMPDVR_IMPORTS_H +#define COMPDVR_IMPORTS_H + +#include +#include +#include "pedef.h" +#include "util.h" +#include "objectfile.h" +#include "section.h" + +void ImportFixup +(ElfObjectFile &eof, const std::vector &mapping); + +#endif//COMPDVR_IMPORTS_H diff --git a/RosBE-PPC/elfpe/objectfile.cpp b/RosBE-PPC/elfpe/objectfile.cpp index 1eb5123..a0bbf52 100644 --- a/RosBE-PPC/elfpe/objectfile.cpp +++ b/RosBE-PPC/elfpe/objectfile.cpp @@ -3,43 +3,71 @@ #include "util.h" #include "objectfile.h" -ElfObjectFile::ElfObjectFile(const std::string &filename) : fd(-1) +ElfObjectFile::ElfObjectFile(const std::string &filename) : fd(-1), filename(filename) +{ + init(); +} + +void ElfObjectFile::init() { - Elf_Scn *s = 0; Elf32_Ehdr *ehdr; - Section *sect; + elfHeader = NULL; + lastStr = NULL; + fd = open(filename.c_str(), O_RDWR, 0); if(fd >= 0) { - if(elf_version(EV_CURRENT) == EV_NONE) { - // Old version - return; - } - elfHeader = elf_begin(fd, ELF_C_RDWR, (Elf*)0); - if(elf_kind(elfHeader) != ELF_K_ELF) { - // Didn't get an elf object file + if(elf_version(EV_CURRENT) == EV_NONE) { + // Old version + return; + } + elfHeader = elf_begin(fd, ELF_C_RDWR, (Elf*)0); + if(elf_kind(elfHeader) != ELF_K_ELF) { + // Didn't get an elf object file elfHeader = NULL; - return; - } - ehdr = elf32_getehdr(elfHeader); - shnum = ehdr->e_shnum; - phnum = ehdr->e_phnum; - shstrndx = ehdr->e_shstrndx; - /* Populate section table */ - for(size_t i = 0; i < shnum; i++) - { - s = elf_nextscn(elfHeader, s); - if(!s) break; - sect = new Section(*this, i, s); - sections.push_back(sect); - sections_by_name.insert(std::make_pair(sect->getName(), sect)); - } + return; + } - populateSymbolTable(); + ehdr = elf32_getehdr(elfHeader); + phnum = ehdr->e_phnum; + shstrndx = ehdr->e_shstrndx; + + populateSections(); + populateSymbolTable(); + } +} + +void ElfObjectFile::populateSections() +{ + Section *sect; + Elf32_Ehdr *ehdr; + Elf_Scn *s = 0; + + ehdr = elf32_getehdr(elfHeader); + shnum = ehdr->e_shnum; + + /* ABS section */ + sections.clear(); + sections_by_name.clear(); + sections.push_back(new Section(*this, 0, NULL)); + + /* Populate section table */ + for(size_t i = 1; i < shnum; i++) + { + s = elf_nextscn(elfHeader, s); + if(!s) break; + sect = new Section(*this, i, s); + sections.push_back(sect); + sections_by_name.insert(std::make_pair(sect->getName(), sect)); } } ElfObjectFile::~ElfObjectFile() +{ + finalize(); +} + +void ElfObjectFile::finalize() { if(elfHeader) elf_end(elfHeader); if(fd >= 0) close(fd); @@ -55,7 +83,10 @@ void ElfObjectFile::populateSymbolTable() Elf32_Sym *sym; Symbol *ourSym; - for( i = 0; i < getNumSections(); i++ ) { + symbols.clear(); + symbols_by_name.clear(); + + for( i = 1; i < getNumSections(); i++ ) { type = getSection(i).getType(); link = getSection(i).getLink(); if( (type == SHT_SYMTAB) || (type == SHT_DYNSYM) ) { @@ -85,7 +116,7 @@ void ElfObjectFile::addSection(const std::string &name, const secdata_t &data, i /* Create data for the new section */ Elf_Data *edata = elf_newdata(newsect), *strdata = elf_getdata(strsect, 0), *newstrdata = elf_newdata(strsect); - edata->d_align = 0x1000; + edata->d_align = 1; edata->d_size = data.size(); edata->d_off = 0; edata->d_type = ELF_T_BYTE; @@ -93,10 +124,12 @@ void ElfObjectFile::addSection(const std::string &name, const secdata_t &data, i edata->d_buf = malloc(edata->d_size); memcpy(edata->d_buf, &data[0], edata->d_size); /* Add the name of the new section to the string table */ - newstrdata->d_off = strdata->d_off + strdata->d_size; + if (!lastStr) lastStr = strdata; + newstrdata->d_off = lastStr->d_off + lastStr->d_size; newstrdata->d_size = name.size() + 1; newstrdata->d_align = 1; newstrdata->d_buf = (void *)name.c_str(); + lastStr = newstrdata; /* Finish the section */ shdr->sh_name = newstrdata->d_off; shdr->sh_type = type; diff --git a/RosBE-PPC/elfpe/objectfile.h b/RosBE-PPC/elfpe/objectfile.h index 640893b..c5630ed 100644 --- a/RosBE-PPC/elfpe/objectfile.h +++ b/RosBE-PPC/elfpe/objectfile.h @@ -78,12 +78,16 @@ public: uint8_t *getSectionData() const { if(!have_data) { - data = *elf_getdata(section, NULL); + data = *elf_getdata(section, NULL); have_data = true; } return (uint8_t *)data.d_buf; } + void setDirty() const { + elf_flagscn(section, ELF_C_SET, ELF_F_DIRTY); + } + private: const ElfObjectFile *obj; int number; @@ -109,18 +113,30 @@ public: const Section *getNamedSection(const std::string &name) const; const Symbol &getSymbol(int n) const { return *symbols[n]; } const Symbol *getNamedSymbol(const std::string &symname) const; + void update() + { + elf_flagelf(elfHeader, ELF_C_SET, ELF_F_DIRTY); + elf_update(elfHeader, ELF_C_WRITE); + finalize(); + init(); + } private: int fd; int shnum, phnum; int shstrndx; Elf *elfHeader; + Elf_Data *lastStr; + std::string filename; std::vector sections; std::map sections_by_name; std::vector symbols; std::map symbols_by_name; + void init(); + void finalize(); void populateSymbolTable(); + void populateSections(); }; #endif//COMPDVR_ELFOBJECT_H diff --git a/RosBE-PPC/elfpe/reloc.cpp b/RosBE-PPC/elfpe/reloc.cpp new file mode 100755 index 0000000..a430e0e --- /dev/null +++ b/RosBE-PPC/elfpe/reloc.cpp @@ -0,0 +1,192 @@ +#include "objectfile.h" +#include "reloc.h" +#include "section.h" +#include "util.h" +#include + +void AddReloc +(std::vector &reloc, + uint32_t imageBase, + uint32_t &relocAddrOff, + uint32_t newReloc, int type) +{ + size_t oldsize = reloc.size(), oddsize = oldsize & sizeof(uint16_t); + uint8_t *relptr; + if (relocAddrOff == (uint32_t)-1) + { + reloc.resize(sizeof(uint32_t) * 2 + sizeof(uint16_t)); + relocAddrOff = 0; + *GetRelocTarget(reloc, relocAddrOff) = newReloc & ~0xfff; + relptr = &reloc[2 * sizeof(uint32_t)]; + } + else if (type != -1 && ((newReloc & ~0xfff) != *GetRelocTarget(reloc, relocAddrOff))) + { + reloc.resize(reloc.size() + 2 * sizeof(uint32_t) + sizeof(uint16_t) + oddsize); + relptr = &reloc[oldsize + oddsize]; + uint8_t *oldptr = (uint8_t*)GetRelocTarget(reloc, relocAddrOff); + le32write_postinc(oldptr, *GetRelocTarget(reloc, relocAddrOff) - imageBase); + le32write_postinc(oldptr, relptr - &reloc[0] - relocAddrOff); + relocAddrOff = relptr - &reloc[0]; + *GetRelocTarget(reloc, relocAddrOff) = newReloc & ~0xfff; + relptr += sizeof(uint32_t); + le32write_postinc(relptr, 0); + } + else + { + reloc.resize(reloc.size() + sizeof(uint16_t)); + relptr = &reloc[oldsize]; + } + + le16write(relptr, type << 12 | newReloc & 0xfff); +} + +#define ADDR24_MASK 0xfc000003 + +void SingleReloc +(const ElfObjectFile &eof, + uint8_t *relptr, int relocsize, + const std::vector &rvas, + const ElfObjectFile::Section &symbols, + const ElfObjectFile::Section &target, + std::vector &relocSect, + uint32_t imageBase, + uint32_t &relocAddr) +{ + int j; + Elf32_Rela reloc = { 0 }; + Elf32_Sym symbol; + uint8_t *symptr; + uint32_t S,A,P; + + /* Get the reloc */ + memcpy(&reloc, relptr, relocsize); +#if 0 + printf("RELOC: offset %08x info %08x addend %08x [%02x %06x]\n", + reloc.r_offset, reloc.r_info, reloc.r_addend, + ELF32_R_TYPE(reloc.r_info), ELF32_R_SYM(reloc.r_info)); +#endif + + /* Get the symbol */ + symptr = &symbols.getSectionData() + [ELF32_R_SYM(reloc.r_info) * sizeof(symbol)]; + memcpy(&symbol, symptr, sizeof(symbol)); + + /* Compute addends */ + S = symbol.st_value - + eof.getSection(symbol.st_shndx).getStartRva() + + FindRVA(rvas, symbol.st_shndx) + + imageBase; + A = reloc.r_addend; + P = reloc.r_offset + FindRVA(rvas, target.getNumber()) - target.getStartRva(); + //printf("start of target elf section %08x\n", target.getStartRva()); + +#if 0 + printf("SYMBOL: value %08x size %08x info %02x other %02x shndx %08x total %08x\n", + symbol.st_value, + symbol.st_size, + symbol.st_info, + symbol.st_other, + symbol.st_shndx, + S); +#endif + + uint8_t *Target = TargetPtr(rvas, target, P); + uint8_t *tword = TargetPtr(rvas, target, P & ~3); + uint8_t oldBytes[sizeof(uint32_t)]; + memcpy(oldBytes, tword, sizeof(oldBytes)); + + P += imageBase; + + switch (ELF32_R_TYPE(reloc.r_info)) + { + case R_PPC_NONE: + break; + case R_PPC_ADDR32: + //printf("ADDR32 S %08x A %08x P %08x\n", S, A, P); + be32write(Target, S + A); + AddReloc(relocSect, imageBase, relocAddr, P, 3); + break; + case R_PPC_REL32: + //printf("REL32 S %08x A %08x P %08x\n", S, A, P); + be32write(Target, S + A - P); + break; + case R_PPC_UADDR32: /* Special: Treat as RVA */ + //printf("UADDR32 S %08x A %08x P %08x\n", S, A, P); + be32write(Target, S + A - imageBase); + break; + case R_PPC_REL24: + //printf("REL24 S %08x A %08x P %08x\n", S, A, P); + //printf("New Offset: %08x to Addr %08x from %08x\n", S+A-P, S+A, P); + be32write(Target, ((S+A-P) & ~ADDR24_MASK) | (be32read(Target) & ADDR24_MASK)); + break; + case R_PPC_ADDR16_LO: + //printf("ADDR16_LO S %08x A %08x P %08x\n", S, A, P); + be16write(Target, S + A); + AddReloc(relocSect, imageBase, relocAddr, P, 2); + break; + case R_PPC_ADDR16_HA: + //printf("ADDR16_HA S %08x A %08x P %08x\n", S, A, P); + be16write(Target, (S + A + 0x8000) >> 16); + AddReloc(relocSect, imageBase, relocAddr, P, 4); + AddReloc(relocSect, imageBase, relocAddr, S + A, -1); + break; + default: + break; + } + + uint8_t newBytes[sizeof(uint32_t)]; + memcpy(newBytes, tword, sizeof(newBytes)); +#if 0 + printf("Reloc changed %08x [%02x %02x %02x %02x] --> [%02x %02x %02x %02x]\n", + P & ~3, + oldBytes[0], + oldBytes[1], + oldBytes[2], + oldBytes[3], + newBytes[0], + newBytes[1], + newBytes[2], + newBytes[3]); +#endif +} + +void SingleRelocSection +(const ElfObjectFile &obf, + const ElfObjectFile::Section §ion, + const std::vector &rvas, + std::vector &relocData, + uint32_t imageBase, + uint32_t &relocAddr) +{ + Elf32_Rela reloc = { }; + uint8_t *Target; + int numreloc, relstart, relsize, j; + uint8_t *sectionData = section.getSectionData(); + + relsize = section.getType() == SHT_RELA ? 12 : 8; + numreloc = section.logicalSize() / relsize; + const ElfObjectFile::Section &targetSection = obf.getSection(section.getInfo()); + + /* Don't relocate non-program section */ + if (!(targetSection.getFlags() & SHF_ALLOC)) + return; + + targetSection.setDirty(); + + /* Get the symbol section */ + const ElfObjectFile::Section &symbolSection = obf.getSection(section.getLink()); + + for(j = 0; j < numreloc; j++) + { + SingleReloc + (obf, + sectionData + j * relsize, + relsize, + rvas, + symbolSection, + targetSection, + relocData, + imageBase, + relocAddr); + } +} diff --git a/RosBE-PPC/elfpe/reloc.h b/RosBE-PPC/elfpe/reloc.h new file mode 100755 index 0000000..f11c5ba --- /dev/null +++ b/RosBE-PPC/elfpe/reloc.h @@ -0,0 +1,22 @@ +#ifndef _ELFPE_RELOC_H +#define _ELFPE_RELOC_H + +#include +#include "section.h" +#include "objectfile.h" + +void SingleRelocSection +(const ElfObjectFile &obf, + const ElfObjectFile::Section §ion, + const std::vector &rvas, + std::vector &relocData, + uint32_t imageBase, + uint32_t &relocAddr); + +void AddReloc +(std::vector &reloc, + uint32_t imageBase, + uint32_t &relocAddrOff, + uint32_t newReloc, int type); + +#endif//_ELFPE_RELOC_H diff --git a/RosBE-PPC/elfpe/section.h b/RosBE-PPC/elfpe/section.h new file mode 100644 index 0000000..87bf3ed --- /dev/null +++ b/RosBE-PPC/elfpe/section.h @@ -0,0 +1,16 @@ +#ifndef COMPDVR_SECTION_H +#define COMPDVR_SECTION_H + +typedef struct section_mapping_t { + const ElfObjectFile::Section *section; + uint32_t rva; + int index; + + section_mapping_t + (const ElfObjectFile::Section *sect, uint32_t rva, int index) : + section(sect), rva(rva), index(index) { } + section_mapping_t(const section_mapping_t &other) : + section(other.section), rva(other.rva), index(other.index) { } +} section_mapping_t; + +#endif//COMPDVR_SECTION_H diff --git a/RosBE-PPC/elfpe/util.cpp b/RosBE-PPC/elfpe/util.cpp index 85c5281..05ebb52 100644 --- a/RosBE-PPC/elfpe/util.cpp +++ b/RosBE-PPC/elfpe/util.cpp @@ -1,4 +1,5 @@ #include "util.h" +#include uint32_t roundup(uint32_t value, int round) { @@ -34,7 +35,29 @@ void le32pwrite_postinc(uint8_t *&dataptr, const u32pair_t &value) le32write_postinc(dataptr, value.second); } -uint16_t be16read(uint8_t *dataptr) +void be16write_postinc(uint8_t *&dataptr, uint16_t value) +{ + *dataptr++ = value >> 8; + *dataptr++ = value; +} + +void be16write(uint8_t *dataptr, uint16_t value) +{ + be16write_postinc(dataptr, value); +} + +void be32write_postinc(uint8_t *&dataptr, uint32_t value) +{ + be16write_postinc(dataptr, value >> 16); + be16write_postinc(dataptr, value); +} + +void be32write(uint8_t *dataptr, uint32_t value) +{ + be32write_postinc(dataptr, value); +} + +uint16_t be16read(uint8_t *dataptr) { return dataptr[0] << 8 | dataptr[1]; } @@ -48,7 +71,7 @@ uint16_t be16read_postinc(uint8_t *&dataptr) uint32_t be32read(uint8_t *dataptr) { - return be16read(dataptr) << 16 | be16read(dataptr+2); + return (be16read(dataptr) << 16) | be16read(dataptr+2); } uint32_t be32read_postinc(uint8_t *&dataptr) @@ -57,3 +80,35 @@ uint32_t be32read_postinc(uint8_t *&dataptr) dataptr += 4; return res; } + +uint32_t FindRVA(const std::vector &mapping, int secnum) +{ + int i; + for (i = 0; i < mapping.size(); i++) + if (mapping[i].section->getNumber() == secnum) return mapping[i].rva; + return 0; +} + +uint8_t *TargetPtr +(const std::vector &mapping, + const ElfObjectFile::Section &target, uint32_t va) +{ + uint32_t srva = FindRVA(mapping, target.getNumber()); + uint32_t off = va - srva; +#if 0 + printf + ("Relocating against VA %08x in section (%08x-%08x) %s\n", + va, + srva, + srva + target.logicalSize(), + target.getName().c_str()); +#endif + assert(off < target.logicalSize()); + return target.getSectionData() + off; +} + +uint32_t *GetRelocTarget(const std::vector &reloc, uint32_t off) +{ + return (uint32_t *)(&reloc[0] + off); +} + diff --git a/RosBE-PPC/elfpe/util.h b/RosBE-PPC/elfpe/util.h index 33ee8df..629472f 100644 --- a/RosBE-PPC/elfpe/util.h +++ b/RosBE-PPC/elfpe/util.h @@ -1,8 +1,11 @@ #ifndef COMPDVR_UTIL_H #define COMPDVR_UTIL_H +#include #include #include +#include "objectfile.h" +#include "section.h" void le16write(uint8_t *dataptr, uint16_t value); void le16write_postinc(uint8_t *&dataptr, uint16_t value); @@ -12,6 +15,10 @@ uint16_t le16read(uint8_t *dataptr); uint16_t le16read_postinc(uint8_t *&dataptr); uint32_t le32read(uint8_t *dataptr); uint32_t le32read_postinc(uint8_t *&dataptr); +void be16write(uint8_t *dataptr, uint16_t value); +void be16write_postinc(uint8_t *&dataptr, uint16_t value); +void be32write(uint8_t *dataptr, uint32_t value); +void be32write_postinc(uint8_t *&dataptr, uint32_t value); uint16_t be16read(uint8_t *dataptr); uint16_t be16read_postinc(uint8_t *&dataptr); uint32_t be32read(uint8_t *dataptr); @@ -21,4 +28,10 @@ void le32pwrite_postinc(uint8_t *&dataptr, const u32pair_t &pair); void le32pwrite(uint8_t *dataptr, const u32pair_t &pair); uint32_t roundup(uint32_t value, int round); +uint32_t FindRVA(const std::vector &mapping, int secnum); +uint8_t *TargetPtr +(const std::vector &mapping, + const ElfObjectFile::Section &target, uint32_t va); +uint32_t *GetRelocTarget(const std::vector &reloc, uint32_t off); + #endif//COMPDVR_UTIL_H