mirror of
https://github.com/reactos/RosBE.git
synced 2024-11-23 03:19:40 +00:00
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:
parent
69a6079c11
commit
2850c14671
@ -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
42
RosBE-PPC/elfpe/coff.cpp
Executable 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 §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());
|
||||
}
|
22
RosBE-PPC/elfpe/coff.h
Normal file
22
RosBE-PPC/elfpe/coff.h
Normal 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
|
@ -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 §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<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;
|
||||
|
46
RosBE-PPC/elfpe/exports.cpp
Normal file
46
RosBE-PPC/elfpe/exports.cpp
Normal 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
14
RosBE-PPC/elfpe/exports.h
Normal 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
|
@ -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> §ionRvaSet, 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 § = 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<section_mapping_t> &mapping) const
|
||||
{
|
||||
return std::make_pair(0,0);
|
||||
return getNamedSectionInfo(eof, mapping, ".reloc");
|
||||
}
|
||||
|
||||
u32pair_t ElfPeHeader::getDebugInfo() const
|
||||
|
@ -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;
|
||||
|
43
RosBE-PPC/elfpe/imports.cpp
Normal file
43
RosBE-PPC/elfpe/imports.cpp
Normal 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
14
RosBE-PPC/elfpe/imports.h
Normal 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
|
@ -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;
|
||||
|
@ -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
192
RosBE-PPC/elfpe/reloc.cpp
Executable 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 §ion,
|
||||
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
22
RosBE-PPC/elfpe/reloc.h
Executable 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 §ion,
|
||||
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
16
RosBE-PPC/elfpe/section.h
Normal 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
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user