ppc: MakePEF - fix endian and 64bit issues

This commit is contained in:
Wolfgang Thaller 2015-08-30 15:27:06 +02:00
parent df8031a37e
commit 332bb90e52
3 changed files with 104 additions and 22 deletions

View File

@ -2,3 +2,5 @@ set(CMAKE_CXX_FLAGS "--std=c++11 -Wall -Werror=return-type -Wno-multichar")
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../CIncludes) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../CIncludes)
add_executable(MakePEF MakePEF.cc xcoff.h powerpc.h external.h) add_executable(MakePEF MakePEF.cc xcoff.h powerpc.h external.h)
install(TARGETS MakePEF RUNTIME DESTINATION bin)

View File

@ -8,11 +8,13 @@
#include <alloca.h> #include <alloca.h>
#include <assert.h> #include <assert.h>
#include <stdint.h>
#include "powerpc.h" #include "powerpc.h"
/* Provide minimal definitions from ConfitionalMacros.h. /* Provide minimal definitions from ConfitionalMacros.h.
* ConditionalMacros.h can't deal with our host C compiler.9 * ConditionalMacros.h can't deal with our host C compiler.
*/ */
#define __CONDITIONALMACROS__ #define __CONDITIONALMACROS__
#define TYPE_BOOL 1 #define TYPE_BOOL 1
@ -22,6 +24,20 @@
#define CALLBACK_API_C(ret,name) ret (*name) #define CALLBACK_API_C(ret,name) ret (*name)
#define ONEWORDINLINE(x) #define ONEWORDINLINE(x)
#define FOUR_CHAR_CODE(x) (x) #define FOUR_CHAR_CODE(x) (x)
#define PRAGMA_STRUCT_PACKPUSH 1
/* Can't use MacTypes.h either,
* as older versions are hardcoded to 32 bit platforms.
*/
#define __MACTYPES__
typedef uint8_t UInt8;
typedef int8_t SInt8;
typedef uint16_t UInt16;
typedef int16_t SInt16;
typedef uint32_t UInt32;
typedef int32_t SInt32;
typedef uint32_t OSType;
/* Definitions for PEF, from Apple's Universal Interfaces */ /* Definitions for PEF, from Apple's Universal Interfaces */
#include <PEFBinaryFormat.h> #include <PEFBinaryFormat.h>
@ -90,14 +106,55 @@ bool verboseFlag = false;
inline int getI16(char *x) inline int getI16(char *x)
{ {
return *(short*)x; return (((unsigned short)x[0]) << 8) | (unsigned short)x[1];
} }
inline int getI32(char *x) inline int getI32(char *x)
{ {
return *(int*)x; return (((unsigned char)x[0]) << 24) | (((unsigned char)x[1]) << 16)
| (((unsigned char)x[2]) << 8) | ((unsigned char)x[3]);
} }
template <typename T>
void eswap(T *data, const char * format)
{
int endianTest = 1;
if(*(char*)&endianTest == 0)
return;
char *p = reinterpret_cast<char*>(data);
const char *q = format;
while(char c = *q++)
{
if(c == 'L')
{
std::swap(p[0], p[3]);
std::swap(p[1], p[2]);
p += 4;
}
else if(c == 's')
{
std::swap(p[0], p[1]);
p += 2;
}
else
{
assert(c == '.');
++p;
}
}
//assert(p == reinterpret_cast<char*>(data+1));
assert(p == reinterpret_cast<char*>(data) + sizeof(T));
}
const char *SwapPEFContainerHeader = "LLLLLLLLssL";
const char *SwapPEFSectionHeader = "LLLLLL....";
const char *SwapPEFLoaderInfoHeader = "LLLLLLLLLLLLLL";
const char *SwapPEFImportedLibrary = "LLLLL..s";
const char *SwapPEFImportedSymbol = "L";
const char *SwapPEFLoaderRelocationHeader = "ssLL";
class ImportLib class ImportLib
{ {
public: public:
@ -124,6 +181,11 @@ void mkpef(std::istream& in, std::ostream& out, std::string mainSymbol = "__star
if(verboseFlag) if(verboseFlag)
std::cerr << "flags: " << std::hex << getI16(xcoffHeader.f_flags) << std::dec << std::endl; std::cerr << "flags: " << std::hex << getI16(xcoffHeader.f_flags) << std::dec << std::endl;
if(verboseFlag)
{
std::cerr << "symptr: " << getI32(xcoffHeader.f_symptr) << std::endl;
std::cerr << "nsyms: " << getI32(xcoffHeader.f_nsyms) << std::endl;
}
int nSections = getI16(xcoffHeader.f_nscns); int nSections = getI16(xcoffHeader.f_nscns);
@ -151,9 +213,13 @@ void mkpef(std::istream& in, std::ostream& out, std::string mainSymbol = "__star
external_scnhdr xcoffSection; external_scnhdr xcoffSection;
in.read((char*) &xcoffSection, sizeof(xcoffSection)); in.read((char*) &xcoffSection, sizeof(xcoffSection));
if(verboseFlag) if(verboseFlag)
{
std::cerr << "section: " << xcoffSection.s_name << std::endl; std::cerr << "section: " << xcoffSection.s_name << std::endl;
std::cerr << " at: " << getI32(xcoffSection.s_scnptr) << std::endl;
std::cerr << " sz: " << getI32(xcoffSection.s_size) << std::endl;
}
xcoffSections[xcoffSection.s_name] = xcoffSection; xcoffSections[xcoffSection.s_name] = xcoffSection;
xcoffSectionNumbers[xcoffSection.s_name] = i+1; xcoffSectionNumbers[xcoffSection.s_name] = i+1;
xcoffSectionNames[i+1] = xcoffSection.s_name; xcoffSectionNames[i+1] = xcoffSection.s_name;
@ -174,7 +240,8 @@ void mkpef(std::istream& in, std::ostream& out, std::string mainSymbol = "__star
in.read(loaderSectionPtr, getI32(xcoffLoaderSection.s_size)); in.read(loaderSectionPtr, getI32(xcoffLoaderSection.s_size));
xcoffLoaderHeader = *(internal_ldhdr*)loaderSectionPtr; xcoffLoaderHeader = *(internal_ldhdr*)loaderSectionPtr;
eswap(&xcoffLoaderHeader, "LLLLLLLLLL");
char *p = loaderSectionPtr + xcoffLoaderHeader.l_impoff; char *p = loaderSectionPtr + xcoffLoaderHeader.l_impoff;
for(unsigned i=0; i<xcoffLoaderHeader.l_nimpid; i++) for(unsigned i=0; i<xcoffLoaderHeader.l_nimpid; i++)
{ {
@ -232,7 +299,7 @@ void mkpef(std::istream& in, std::ostream& out, std::string mainSymbol = "__star
loaderInfoHeader.termSection = -1; loaderInfoHeader.termSection = -1;
{ {
in.seekg(getI32(xcoffHeader.f_symptr) + in.seekg(getI32(xcoffHeader.f_symptr) +
getI32(xcoffHeader.f_nsyms) * sizeof(external_syment)); getI32(xcoffHeader.f_nsyms) * sizeof(external_syment));
int stringTableLen = 0; int stringTableLen = 0;
@ -240,6 +307,8 @@ void mkpef(std::istream& in, std::ostream& out, std::string mainSymbol = "__star
if(verboseFlag) if(verboseFlag)
std::cerr << "tell: " << in.tellg() << std::endl; std::cerr << "tell: " << in.tellg() << std::endl;
in.read((char*)&stringTableLen, 4); in.read((char*)&stringTableLen, 4);
eswap(&stringTableLen, "L");
if(verboseFlag) if(verboseFlag)
std::cerr << "string table len: " << stringTableLen << std::endl; std::cerr << "string table len: " << stringTableLen << std::endl;
char *stringTable = new char[stringTableLen+1]; char *stringTable = new char[stringTableLen+1];
@ -302,8 +371,9 @@ void mkpef(std::istream& in, std::ostream& out, std::string mainSymbol = "__star
{ {
if(name == mainSymbol) if(name == mainSymbol)
{ {
loaderInfoHeader.mainSection = pefSectionNumbers[xcoffSectionNames[getI16(ent.e_scnum)]]; std::string secName = xcoffSectionNames[getI16(ent.e_scnum)];
loaderInfoHeader.mainOffset = getI32(ent.e_value); loaderInfoHeader.mainSection = pefSectionNumbers[secName];
loaderInfoHeader.mainOffset = getI32(ent.e_value) - getI32(xcoffSections[secName].s_vaddr);
} }
} }
} }
@ -486,30 +556,36 @@ void mkpef(std::istream& in, std::ostream& out, std::string mainSymbol = "__star
if(verboseFlag) if(verboseFlag)
std::cerr << "Writing Headers..." << std::flush; std::cerr << "Writing Headers..." << std::flush;
eswap(&pefHeader, SwapPEFContainerHeader);
out.write((char*)&pefHeader, sizeof(pefHeader)); out.write((char*)&pefHeader, sizeof(pefHeader));
eswap(&textSectionHeader, SwapPEFSectionHeader);
out.write((char*)&textSectionHeader, sizeof(textSectionHeader)); out.write((char*)&textSectionHeader, sizeof(textSectionHeader));
eswap(&dataSectionHeader, SwapPEFSectionHeader);
out.write((char*)&dataSectionHeader, sizeof(dataSectionHeader)); out.write((char*)&dataSectionHeader, sizeof(dataSectionHeader));
eswap(&loaderSectionHeader, SwapPEFSectionHeader);
out.write((char*)&loaderSectionHeader, sizeof(loaderSectionHeader)); out.write((char*)&loaderSectionHeader, sizeof(loaderSectionHeader));
if(verboseFlag) if(verboseFlag)
std::cerr << "done.\nCopying text and data..." << std::flush; std::cerr << "done.\nCopying text and data..." << std::flush;
{ {
char *buf = new char[textSectionHeader.containerLength]; char *buf = new char[textSize];
in.seekg(getI32(xcoffSections[".text"].s_scnptr)); in.seekg(getI32(xcoffSections[".text"].s_scnptr));
in.read(buf, textSectionHeader.containerLength); in.read(buf, textSize);
out.write(buf, textSectionHeader.containerLength); out.write(buf, textSize);
delete[] buf; delete[] buf;
} }
{ {
char *buf = new char[dataSectionHeader.containerLength]; char *buf = new char[dataSize];
in.seekg(getI32(xcoffSections[".data"].s_scnptr)); in.seekg(getI32(xcoffSections[".data"].s_scnptr));
in.read(buf, dataSectionHeader.containerLength); in.read(buf, dataSize);
out.write(buf, dataSectionHeader.containerLength); out.write(buf, dataSize);
delete[] buf; delete[] buf;
} }
if(verboseFlag) if(verboseFlag)
std::cerr << "done.\n"; std::cerr << "done.\n";
eswap(&loaderInfoHeader, SwapPEFLoaderInfoHeader);
out.write((char*)&loaderInfoHeader, sizeof(loaderInfoHeader)); out.write((char*)&loaderInfoHeader, sizeof(loaderInfoHeader));
int firstImportedSymbol = 0; int firstImportedSymbol = 0;
@ -528,6 +604,7 @@ void mkpef(std::istream& in, std::ostream& out, std::string mainSymbol = "__star
if(importLibs[i].weak) if(importLibs[i].weak)
impLib.options = kPEFWeakImportLibMask; impLib.options = kPEFWeakImportLibMask;
eswap(&impLib, SwapPEFImportedLibrary);
out.write((char*)&impLib, sizeof(impLib)); out.write((char*)&impLib, sizeof(impLib));
} }
for(unsigned i=1;i<importLibs.size();i++) for(unsigned i=1;i<importLibs.size();i++)
@ -537,6 +614,7 @@ void mkpef(std::istream& in, std::ostream& out, std::string mainSymbol = "__star
PEFImportedSymbol sym; PEFImportedSymbol sym;
sym.classAndName = PEFComposeImportedSymbol(kPEFTVectorSymbol /* ### */, sym.classAndName = PEFComposeImportedSymbol(kPEFTVectorSymbol /* ### */,
importLibs[i].symNameOffsets[j]); importLibs[i].symNameOffsets[j]);
eswap(&sym, SwapPEFImportedSymbol);
out.write((char*)&sym, sizeof(sym)); out.write((char*)&sym, sizeof(sym));
} }
} }
@ -545,10 +623,12 @@ void mkpef(std::istream& in, std::ostream& out, std::string mainSymbol = "__star
if(verboseFlag) if(verboseFlag)
std::cerr << "relocations..." << std::flush; std::cerr << "relocations..." << std::flush;
eswap(&dataRelocationHeader, SwapPEFLoaderRelocationHeader);
out.write((char*)&dataRelocationHeader, sizeof(dataRelocationHeader)); out.write((char*)&dataRelocationHeader, sizeof(dataRelocationHeader));
for(unsigned i=0;i<relocInstructions.size();i++) for(unsigned i=0;i<relocInstructions.size();i++)
{ {
short insn = relocInstructions[i]; short insn = relocInstructions[i];
eswap(&insn, "s");
out.write((char*)&insn, sizeof(insn)); out.write((char*)&insn, sizeof(insn));
} }
if(verboseFlag) if(verboseFlag)

View File

@ -132,7 +132,7 @@ struct internal_ldhdr
/* The version number: /* The version number:
1 : 32 bit 1 : 32 bit
2 : 64 bit */ 2 : 64 bit */
unsigned long l_version; unsigned int/*###*/ l_version;
/* The number of symbol table entries. */ /* The number of symbol table entries. */
bfd_size_type l_nsyms; bfd_size_type l_nsyms;
@ -176,11 +176,11 @@ struct internal_ldsym
struct struct
{ {
/* Zero if the symbol name is more than SYMNMLEN characters. */ /* Zero if the symbol name is more than SYMNMLEN characters. */
long _l_zeroes; int/*###*/ _l_zeroes;
/* The offset in the string table if the symbol name is more /* The offset in the string table if the symbol name is more
than SYMNMLEN characters. */ than SYMNMLEN characters. */
long _l_offset; int/*###*/ _l_offset;
} }
_l_l; _l_l;
} }
@ -240,7 +240,7 @@ struct xcoff_link_hash_entry
/* Symbol index in output file. Set to -1 initially. Set to -2 if /* Symbol index in output file. Set to -1 initially. Set to -2 if
there is a reloc against this symbol. */ there is a reloc against this symbol. */
long indx; int/*###*/ indx;
/* If we have created a TOC entry for this symbol, this is the .tc /* If we have created a TOC entry for this symbol, this is the .tc
section which holds it. */ section which holds it. */
@ -254,7 +254,7 @@ struct xcoff_link_hash_entry
/* If the TOC entry comes from an input file, this is set to the /* If the TOC entry comes from an input file, this is set to the
symbol index of the C_HIDEXT XMC_TC or XMC_TD symbol. */ symbol index of the C_HIDEXT XMC_TC or XMC_TD symbol. */
long toc_indx; int/*###*/ toc_indx;
} }
u; u;
@ -270,10 +270,10 @@ struct xcoff_link_hash_entry
/* If XCOFF_BUILT_LDSYM is set, this is the .loader symbol table /* If XCOFF_BUILT_LDSYM is set, this is the .loader symbol table
index. If XCOFF_BUILD_LDSYM is clear, and XCOFF_IMPORT is set, index. If XCOFF_BUILD_LDSYM is clear, and XCOFF_IMPORT is set,
this is the l_ifile value. */ this is the l_ifile value. */
long ldindx; int/*###*/ ldindx;
/* Some linker flags. */ /* Some linker flags. */
unsigned long flags; unsigned int/*###*/ flags;
/* The storage mapping class. */ /* The storage mapping class. */
unsigned char smclas; unsigned char smclas;
@ -363,7 +363,7 @@ struct xcoff_link_hash_table
struct xcoff_import_file *imports; struct xcoff_import_file *imports;
/* Required alignment of sections within the output file. */ /* Required alignment of sections within the output file. */
unsigned long file_align; unsigned int/*###*/ file_align;
/* Whether the .text section must be read-only. */ /* Whether the .text section must be read-only. */
bfd_boolean textro; bfd_boolean textro;