Fix us back up to use PE-COFF again. This is getting ridiculous, but I now

really understand everything, and freeldr moved the image mapping code to
a common area.

svn path=/trunk/tools/RosBE/; revision=688
This commit is contained in:
Art Yerkes 2008-03-07 06:53:55 +00:00
parent 69a6079c11
commit 2850c14671
17 changed files with 663 additions and 81 deletions

View File

@ -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:

42
RosBE-PPC/elfpe/coff.cpp Executable file
View File

@ -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 &section = *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 &section = 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());
}

22
RosBE-PPC/elfpe/coff.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef COMPDVR_COFF_H
#define COMPDVR_COFF_H
#include <vector>
#include <utility>
#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

View File

@ -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<std::string> &args )
{
@ -57,6 +62,26 @@ void possibly_define
args.insert(args.begin(), the_definition + "=" + body);
}
std::vector<uint8_t>
ProcessRelocSections
(const ElfObjectFile &eof,
uint32_t imageBase,
const std::vector<section_mapping_t> &rvas)
{
std::vector<uint8_t> relocData;
uint32_t relocAddr = (uint32_t)-1;
int i, j;
for (i = 1; i < eof.getNumSections(); i++)
{
const ElfObjectFile::Section &section = 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<section_mapping_t> 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<uint8_t> 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;

View File

@ -0,0 +1,46 @@
#include "exports.h"
#include "objectfile.h"
#include "section.h"
void ExportFixup
(ElfObjectFile &eof,
const std::vector<section_mapping_t> &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));
}

14
RosBE-PPC/elfpe/exports.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef COMPDVR_EXPORTS_H
#define COMPDVR_EXPORTS_H
#include <vector>
#include <utility>
#include "pedef.h"
#include "util.h"
#include "objectfile.h"
#include "section.h"
void ExportFixup
(ElfObjectFile &eof, const std::vector<section_mapping_t> &mapping);
#endif//COMPDVR_EXPORTS_H

View File

@ -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<section_mapping_t> &sectionRvaSet, uint32_t imageSize)
{
std::vector<section_mapping_t> 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<section_mapping_t> &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 &sect = 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(), &sect, 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(&sect, 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<section_mapping_t> &mapping) const
{
return std::make_pair(0,0);
return getNamedSectionInfo(eof, mapping, ".reloc");
}
u32pair_t ElfPeHeader::getDebugInfo() const

View File

@ -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<section_mapping_t> &rvas) const;
void createHeaderSection(const std::vector<section_mapping_t> &rvas, uint32_t imageSize);
private:
void createHeaderSection();
uint32_t getSectionRvas(std::vector<section_mapping_t> &rvas) const;
uint32_t getEntryPoint(const std::vector<section_mapping_t> &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<section_mapping_t> &rvas) const;
u32pair_t getExceptionInfo() const;
u32pair_t getSecurityInfo() const;
u32pair_t getRelocInfo() const;
u32pair_t getRelocInfo(const std::vector<section_mapping_t> &rvas) const;
u32pair_t getDebugInfo() const;
u32pair_t getDescrInfo() const;
u32pair_t getMachInfo() const;

View File

@ -0,0 +1,43 @@
#include "imports.h"
#include "objectfile.h"
#include "section.h"
void ImportFixup
(ElfObjectFile &eof,
const std::vector<section_mapping_t> &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);
}

14
RosBE-PPC/elfpe/imports.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef COMPDVR_IMPORTS_H
#define COMPDVR_IMPORTS_H
#include <vector>
#include <utility>
#include "pedef.h"
#include "util.h"
#include "objectfile.h"
#include "section.h"
void ImportFixup
(ElfObjectFile &eof, const std::vector<section_mapping_t> &mapping);
#endif//COMPDVR_IMPORTS_H

View File

@ -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;

View File

@ -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<Section*> sections;
std::map<std::string, const Section *> sections_by_name;
std::vector<Symbol*> symbols;
std::map<std::string, const Symbol *> symbols_by_name;
void init();
void finalize();
void populateSymbolTable();
void populateSections();
};
#endif//COMPDVR_ELFOBJECT_H

192
RosBE-PPC/elfpe/reloc.cpp Executable file
View File

@ -0,0 +1,192 @@
#include "objectfile.h"
#include "reloc.h"
#include "section.h"
#include "util.h"
#include <assert.h>
void AddReloc
(std::vector<uint8_t> &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<section_mapping_t> &rvas,
const ElfObjectFile::Section &symbols,
const ElfObjectFile::Section &target,
std::vector<uint8_t> &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 &section,
const std::vector<section_mapping_t> &rvas,
std::vector<uint8_t> &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);
}
}

22
RosBE-PPC/elfpe/reloc.h Executable file
View File

@ -0,0 +1,22 @@
#ifndef _ELFPE_RELOC_H
#define _ELFPE_RELOC_H
#include <vector>
#include "section.h"
#include "objectfile.h"
void SingleRelocSection
(const ElfObjectFile &obf,
const ElfObjectFile::Section &section,
const std::vector<section_mapping_t> &rvas,
std::vector<uint8_t> &relocData,
uint32_t imageBase,
uint32_t &relocAddr);
void AddReloc
(std::vector<uint8_t> &reloc,
uint32_t imageBase,
uint32_t &relocAddrOff,
uint32_t newReloc, int type);
#endif//_ELFPE_RELOC_H

16
RosBE-PPC/elfpe/section.h Normal file
View File

@ -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

View File

@ -1,4 +1,5 @@
#include "util.h"
#include <assert.h>
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<section_mapping_t> &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<section_mapping_t> &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<uint8_t> &reloc, uint32_t off)
{
return (uint32_t *)(&reloc[0] + off);
}

View File

@ -1,8 +1,11 @@
#ifndef COMPDVR_UTIL_H
#define COMPDVR_UTIL_H
#include <vector>
#include <utility>
#include <stdint.h>
#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<section_mapping_t> &mapping, int secnum);
uint8_t *TargetPtr
(const std::vector<section_mapping_t> &mapping,
const ElfObjectFile::Section &target, uint32_t va);
uint32_t *GetRelocTarget(const std::vector<uint8_t> &reloc, uint32_t off);
#endif//COMPDVR_UTIL_H