Merge branch 'ppc'.

Retro68 is now actually Retro68+RetroPPC+RetroCarbon.
This commit is contained in:
Wolfgang Thaller 2015-10-07 02:13:08 +02:00
commit d8065be04b
146 changed files with 2419 additions and 122 deletions

View File

@ -18,7 +18,7 @@
cmake_minimum_required(VERSION 2.8)
project(Retro)
if(CMAKE_SYSTEM_NAME MATCHES Retro68)
if(CMAKE_SYSTEM_NAME MATCHES Retro.*)
set( REZ_TEMPLATES_PATH ${CMAKE_CURRENT_SOURCE_DIR}/libretro)
@ -35,21 +35,31 @@ link_directories(${CMAKE_CURRENT_BINARY_DIR}/libretro)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/libretro)
set(REZ_INCLUDE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/libretro:${CMAKE_INSTALL_PREFIX}/RIncludes" )
if(NOT (CMAKE_SYSTEM_NAME MATCHES RetroCarbon))
add_subdirectory(Console)
add_subdirectory(TestApps)
add_subdirectory(Samples/HelloWorld)
add_subdirectory(Samples/Raytracer)
add_subdirectory(Samples/Launcher)
add_subdirectory(Samples/Dialog)
endif()
add_subdirectory(Samples/Raytracer)
if(CMAKE_SYSTEM_NAME MATCHES Retro68)
add_subdirectory(Samples/Launcher)
add_subdirectory(Samples/SystemExtension)
endif()
else()
set(RETRO68_ROOT ${CMAKE_INSTALL_PREFIX})
configure_file(cmake/intree.toolchain.cmake.in cmake/intree.toolchain.cmake @ONLY)
configure_file(cmake/intreeppc.toolchain.cmake.in cmake/intreeppc.toolchain.cmake @ONLY)
configure_file(cmake/intreecarbon.toolchain.cmake.in cmake/intreecarbon.toolchain.cmake @ONLY)
add_subdirectory(ResourceFiles)
add_subdirectory(MakeAPPL)
add_subdirectory(Rez)
add_subdirectory(PEFTools)
endif()

View File

@ -27,3 +27,8 @@ add_library(RetroConsole
install(TARGETS RetroConsole DESTINATION lib)
add_application(ConsoleTest
ConsoleTest.cc
)
target_link_libraries(ConsoleTest RetroConsole)

View File

@ -21,6 +21,7 @@
#include "MacUtils.h"
#include "Events.h"
#include "Fonts.h"
#include "Processes.h"
#include <algorithm>
@ -30,7 +31,9 @@ Console *Console::currentInstance = NULL;
Console::Console(GrafPtr port, Rect r)
: consolePort(port), bounds(r), dirtyRect()
{
{
if(currentInstance == NULL)
currentInstance = (Console*) -1;
PortSetter setport(consolePort);
InsetRect(&bounds, 2,2);
@ -42,7 +45,9 @@ Console::Console(GrafPtr port, Rect r)
rows = (bounds.bottom - bounds.top) / cellSizeY;
cols = (bounds.right - bounds.left) / cellSizeX;
chars = std::vector<char>(rows*cols, ' ');
onscreen = chars;
cursorX = cursorY = 0;

View File

@ -36,6 +36,9 @@ namespace Retro
std::string ReadLine();
static Console *currentInstance;
short GetRows() const { return rows; }
short GetCols() const { return cols; }
private:
GrafPtr consolePort;
Rect bounds;

16
Console/ConsoleTest.cc Normal file
View File

@ -0,0 +1,16 @@
#include "Console.h"
#include <string.h>
namespace Retro
{
void InitConsole();
}
int main()
{
Retro::InitConsole();
const char *s = "Hello, world.\n";
Retro::Console::currentInstance->write(s, strlen(s));
Retro::Console::currentInstance->ReadLine();
return 0;
}

View File

@ -63,6 +63,8 @@ extern "C" ssize_t _consolewrite(int fd, const void *buf, size_t count)
{
if(!Console::currentInstance)
InitConsole();
if(Console::currentInstance == (Console*)-1)
return 0;
Console::currentInstance->write((const char*)buf, count);
return count;
@ -72,6 +74,8 @@ extern "C" ssize_t _consoleread(int fd, void *buf, size_t count)
{
if(!Console::currentInstance)
InitConsole();
if(Console::currentInstance == (Console*)-1)
return 0;
static std::string consoleBuf;
if(consoleBuf.size() == 0)

View File

@ -0,0 +1,8 @@
Import Libraries
================
These import libraries are generated using the MakeImport tool.
They are derived from Apple's Universal Interfaces 3.4.1; however,
since all they contain are the names of the exported symbols, I
believe that no copyright restrictions apply.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
ImportLibraries/libHIDLib.a Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
ImportLibraries/libPCILib.a Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
ImportLibraries/libvecLib.a Normal file

Binary file not shown.

11
PEFTools/CMakeLists.txt Normal file
View File

@ -0,0 +1,11 @@
set(CMAKE_CXX_FLAGS "--std=c++11 -Wall -Werror=return-type -Wno-multichar")
find_package(Boost COMPONENTS filesystem system REQUIRED)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../CIncludes)
add_executable(MakePEF MakePEF.cc rs6000.h PEF.h)
add_executable(MakeImport MakeImport.cc PEF.h)
target_link_libraries(MakeImport ResourceFiles ${Boost_LIBRARIES})
install(TARGETS MakePEF MakeImport RUNTIME DESTINATION bin)

279
PEFTools/MakeImport.cc Executable file
View File

@ -0,0 +1,279 @@
#include <iostream>
#include <fstream>
#include <utility>
#include <vector>
#include <string>
#include <algorithm>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>
#include "PEF.h"
#include "ResourceFile.h"
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
namespace fs = boost::filesystem;
using std::cout;
using std::cerr;
using std::endl;
using std::pair;
using std::make_pair;
using std::vector;
using std::string;
using std::ofstream;
using std::ios_base;
void RunCommand(const char *command, std::vector<std::string> args)
{
std::vector<const char*> ptrs;
ptrs.push_back(command);
for(auto& s : args)
ptrs.push_back(s.c_str());
ptrs.push_back(NULL);
pid_t pid = fork();
if(pid == -1)
{
perror(command);
exit(1);
}
if(pid)
{
int status = 0;
while(waitpid(pid, &status, 0) == -1 && errno == EINTR)
;
if(!WIFEXITED(status) || WEXITSTATUS(status) != 0)
{
std::cerr << command << " failed.\n";
exit(1);
}
}
else
{
execvp(command, const_cast<char *const*>(ptrs.data()));
perror("exec");
exit(1);
}
}
void MakeImportLibrary(char *pefptr, size_t pefsize, fs::path dest, fs::path tmpdir)
{
PEFContainerHeader *containerHeader = (PEFContainerHeader*) pefptr;
eswap(containerHeader);
assert(containerHeader->tag1 == 'Joy!');
assert(containerHeader->tag2 == 'peff');
PEFSectionHeader *sectionHeaders
= (PEFSectionHeader*) (pefptr + kPEFFirstSectionHeaderOffset);
PEFSectionHeader *loaderHeader = NULL;
UInt16 n = containerHeader->sectionCount;
for(UInt16 i=0; i < n; i++)
{
eswap(&sectionHeaders[i]);
if(sectionHeaders[i].sectionKind == kPEFLoaderSection)
loaderHeader = &sectionHeaders[i];
}
PEFLoaderInfoHeader *loaderInfoHeader
= (PEFLoaderInfoHeader*) (pefptr + loaderHeader->containerOffset);
eswap(loaderInfoHeader);
UInt32 hashTableSize = 1;
UInt32 hashTablePower = loaderInfoHeader->exportHashTablePower;
while(hashTablePower--)
hashTableSize *= 2;
UInt32 nSymbols = loaderInfoHeader->exportedSymbolCount;
const char *symbols /* use char pointer to avoid packing issues */
= (pefptr + loaderHeader->containerOffset
+ loaderInfoHeader->exportHashOffset
+ hashTableSize * sizeof(PEFExportedSymbolHashSlot)
+ nSymbols * sizeof(PEFExportedSymbolKey));
const char *stringTable = pefptr
+ loaderHeader->containerOffset
+ loaderInfoHeader->loaderStringsOffset;
/*const char *stringTableEnd = pefptr
+ loaderHeader->containerOffset
+ loaderInfoHeader->exportHashOffset;*/
vector< pair< const char *, UInt8 > > classesAndNamePtrs;
for(UInt32 i=0; i < nSymbols; i++)
{
PEFExportedSymbol *sym = (PEFExportedSymbol*) (symbols + 10*i);
eswap(sym);
UInt8 symclass = PEFExportedSymbolClass(sym->classAndName);
UInt32 nameoffset = PEFExportedSymbolNameOffset(sym->classAndName);
const char *nameptr
= stringTable + nameoffset;
classesAndNamePtrs.push_back( make_pair(nameptr, symclass) );
}
std::sort(classesAndNamePtrs.begin(), classesAndNamePtrs.end());
vector< pair<string, UInt8> > exportedSymbols;
for(UInt32 i=0; i < nSymbols; i++)
{
UInt8 symclass = classesAndNamePtrs[i].second;
const char *namestart = classesAndNamePtrs[i].first;
string name;
if(i + 1 < nSymbols)
{
const char *nameend = classesAndNamePtrs[i+1].first;
name = string(namestart,nameend);
}
else
name = string(namestart);
exportedSymbols.push_back( make_pair( name, symclass ) );
}
std::sort(exportedSymbols.begin(), exportedSymbols.end());
fs::path stub_exp(tmpdir / "__stub.exp"),
stub_s(tmpdir / "__stub.s"),
stub_o(tmpdir / "__stub.o");
{
fs::ofstream expFile(stub_exp);
fs::ofstream sFile(stub_s);
sFile << "\t.toc\n";
for(UInt32 i=0; i< nSymbols; i++)
{
string& sym = exportedSymbols[i].first;
if(exportedSymbols[i].second == kPEFTVectorSymbol)
{
expFile << sym << endl;
sFile << ".text" << endl;
sFile << "\t.globl " << sym << endl;
sFile << "\t.globl ." << sym << endl;
sFile << "\t.csect " << sym << "[DS]" << endl;
sFile << sym << ':' << endl;
sFile << ".long ." << sym << ", TOC[tc0], 0" << endl;
sFile << ".text" << endl;
sFile << '.' << sym << ':' << endl;
sFile << "\tblr" << endl;
}
else if(exportedSymbols[i].second == kPEFDataSymbol)
{
expFile << sym << endl;
sFile << "\t.globl " << sym << endl;
sFile << "\t.csect .data[RW],3" << endl;
sFile << "\t.align 2" << endl;
sFile << sym << ':' << endl;
sFile << "\t.long\t42" << endl;
}
}
//cerr << "Generating: " << name << " -> " << libname << endl;
RunCommand("powerpc-apple-macos-as", std::vector<std::string> {
stub_s.string(), "-o", stub_o.string()
});
RunCommand("powerpc-apple-macos-ld", std::vector<std::string> {
"-shared", "--no-check-sections", "-bexport:" + stub_exp.string(),
"-o", dest.string(), stub_o.string()
});
}
}
void MakeImportLibraryMulti(fs::path path, fs::path libname)
{
ResourceFile resFile(path.string());
assert(resFile.read());
std::vector<char> data(resFile.data.begin(), resFile.data.end());
char *dataPtr = data.data();
Resource& cfrgRes = resFile.resources.resources[ResRef("cfrg",0)];
fs::path tmpdir = libname.parent_path() / fs::unique_path("makeimport-tmp-%%%%-%%%%-%%%%-%%%%");
fs::create_directory(tmpdir);
try
{
CFragResource *cfrg = (CFragResource *)cfrgRes.getData().data();
eswap(cfrg);
CFragResourceMember *member = &(cfrg -> firstMember);
fs::path archiveTmp(tmpdir / "__archive.a");
std::vector<string> arArguments { "cq", archiveTmp.string() };
for(UInt16 i = 0; i < cfrg->memberCount; i++)
{
eswap(member);
string membername =
string(member->name+1, member->name+1+member->name[0]);
if(member->architecture == 'pwpc'
|| member->architecture == '\?\?\?\?')
{
if(member->usage == 0 /* import library */
|| member->usage == 3 /* stub library */)
;
else if(member->usage == 4 /* weak stub library */)
membername += "__weak";
else
{
std::cerr << "Inappropriate usage flag: "
<< (int)member->usage << endl;
continue;
}
fs::path shlib_file(tmpdir / (membername + ".o"));
MakeImportLibrary(dataPtr + member->offset, member->length,
shlib_file, tmpdir);
arArguments.push_back(shlib_file.string());
}
member = (CFragResourceMember*) (((char*)member) + member->memberSize);
}
RunCommand("powerpc-apple-macos-ar", arArguments);
fs::rename(archiveTmp, libname);
}
catch(...)
{
fs::remove_all(tmpdir);
throw;
}
fs::remove_all(tmpdir);
}
int main (int argc, char * const argv[])
{
//printf("%d\n",argc);
if(argc != 3)
{
cerr << "Usage: makeimport <peflib> <libname>" << endl;
return 1;
}
int fd = open(argv[1], O_RDONLY, 0);
if(fd < 0)
{
perror(argv[1]);
return 1;
}
MakeImportLibraryMulti(argv[1], argv[2]);
close(fd);
return 0;
}

520
PEFTools/MakePEF.cc Executable file
View File

@ -0,0 +1,520 @@
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <fstream>
#include <set>
#include <string.h>
#include <alloca.h>
#include <assert.h>
#include <stdint.h>
#include "PEF.h"
typedef unsigned bfd_size_type;
typedef unsigned bfd_vma;
#define SYMNMLEN 8
#define PARAMS(x) x
struct bfd_link_hash_entry {};
struct bfd_link_hash_table {};
typedef int bfd;
typedef int asection;
typedef int bfd_boolean;
typedef char bfd_byte;
#define AOUTHDR external_aouthdr
#include "rs6000.h"
bool verboseFlag = false;
inline int getI16(const void *xx)
{
const unsigned char *x = (const unsigned char*)xx;
return (x[0] << 8) | x[1];
}
inline int getI32(const void *xx)
{
const unsigned char *x = (const unsigned char*)xx;
return (x[0] << 24) | (x[1] << 16) | (x[2] << 8) | x[3];
}
inline int getI8(const void *xx)
{
return *(const unsigned char*)xx;
}
template<typename ch, int n>
inline int get(const ch (&x) [n])
{
switch(n)
{
case 1: return getI8(x);
case 2: return getI16(x);
case 4: return getI32(x);
default: abort();
}
}
class ImportLib
{
public:
std::string path, base, mem;
std::vector<std::string> imports;
std::vector<int> xcoffImportIndices;
int nameOffset;
bool weak;
std::vector<int> symNameOffsets;
ImportLib(std::string path, std::string base, std::string mem)
: path(path), base(base), mem(mem), weak(false)
{
}
};
void mkpef(const std::string& inFn, const std::string& outFn)
{
std::ifstream in(inFn);
external_filehdr xcoffHeader;
external_aouthdr aoutHeader;
in.read((char*) &xcoffHeader, sizeof(xcoffHeader));
assert((size_t)get(xcoffHeader.f_opthdr) >= sizeof(aoutHeader));
in.read((char*)&aoutHeader, sizeof(aoutHeader));
in.seekg(get(xcoffHeader.f_opthdr) - sizeof(aoutHeader),std::ios_base::cur);
if(verboseFlag)
{
std::cerr << "flags: " << std::hex << get(xcoffHeader.f_flags) << std::dec << std::endl;
std::cerr << "symptr: " << get(xcoffHeader.f_symptr) << std::endl;
std::cerr << "nsyms: " << get(xcoffHeader.f_nsyms) << std::endl;
}
std::map<std::string,external_scnhdr> xcoffSections;
std::map<std::string, int> xcoffSectionNumbers;
int nSections = get(xcoffHeader.f_nscns);
for(int i=0;i<nSections;i++)
{
external_scnhdr xcoffSection;
in.read((char*) &xcoffSection, sizeof(xcoffSection));
if(verboseFlag)
{
std::cerr << "section: " << xcoffSection.s_name << std::endl;
std::cerr << " at: " << get(xcoffSection.s_scnptr) << std::endl;
std::cerr << " sz: " << get(xcoffSection.s_size) << std::endl;
}
xcoffSections[xcoffSection.s_name] = xcoffSection;
xcoffSectionNumbers[xcoffSection.s_name] = i+1;
}
std::vector<ImportLib> importLibs;
std::vector<int> importedSymbolIndices;
int totalImportedSyms = 0;
std::vector<unsigned short> relocInstructions;
{
external_scnhdr xcoffLoaderSection = xcoffSections[".loader"];
external_ldhdr xcoffLoaderHeader;
char * loaderSectionPtr = (char*)alloca(get(xcoffLoaderSection.s_size));
in.seekg(get(xcoffLoaderSection.s_scnptr));
in.read(loaderSectionPtr, get(xcoffLoaderSection.s_size));
xcoffLoaderHeader = *(external_ldhdr*)loaderSectionPtr;
char *p = loaderSectionPtr + get(xcoffLoaderHeader.l_impoff);
for(int i=0; i<get(xcoffLoaderHeader.l_nimpid); i++)
{
std::string path = p;
p += strlen(p) + 1;
std::string base = p;
p += strlen(p) + 1;
std::string mem = p;
p += strlen(p) + 1;
importLibs.push_back(ImportLib(path,base,mem));
if(verboseFlag)
std::cerr << "Import: " << path << ", " << base << ", " << mem << '\n';
}
external_ldsym *syms = (external_ldsym*) (loaderSectionPtr + sizeof(external_ldhdr));
for(int i=0; i<get(xcoffLoaderHeader.l_nsyms); i++)
{
std::string name;
external_ldsym& sym = syms[i];
if(get(sym._l._l_l._l_zeroes) == 0)
{
name = loaderSectionPtr + get(xcoffLoaderHeader.l_stoff)
+ get(sym._l._l_l._l_offset);
}
else
name = sym._l._l_name;
if(verboseFlag)
std::cerr << "Loader Symbol: " << name << std::endl;
if((get(sym.l_smtype) & 0xF8) == 0x40 /*L_IMPORT*/)
{
assert((get(sym.l_smtype) & 3) == 0 /*XTY_ER*/);
if(verboseFlag)
std::cerr << "... from file: " << get(sym.l_ifile) << std::endl;
importLibs[get(sym.l_ifile)].imports.push_back(name);
importLibs[get(sym.l_ifile)].xcoffImportIndices.push_back(i);
totalImportedSyms++;
}
}
importedSymbolIndices.resize(get(xcoffLoaderHeader.l_nsyms));
{
int symbolIndex = 0;
for(unsigned i=1;i<importLibs.size();i++)
{
for(unsigned j=0;j<importLibs[i].xcoffImportIndices.size();j++)
{
importedSymbolIndices[importLibs[i].xcoffImportIndices[j]] = symbolIndex;
symbolIndex++;
}
}
}
int xcoffDataSecNumber = xcoffSectionNumbers[".data"];
external_ldrel *rels = (external_ldrel*) (loaderSectionPtr + sizeof(external_ldhdr) + get(xcoffLoaderHeader.l_nsyms) * sizeof(external_ldsym));
for(int i=0; i<get(xcoffLoaderHeader.l_nreloc); i++)
{
external_ldrel& rel = rels[i];
if(verboseFlag)
{
std::cerr << "[" << i << "] reloc: " << std::hex << get(rel.l_vaddr) << " " << get(rel.l_symndx) << " " << get(rel.l_rtype) << " " << get(rel.l_rsecnm) << "\n";
}
assert(get(rel.l_rtype) == 0x1f00);
assert(get(rel.l_rsecnm) == xcoffDataSecNumber);
int vaddr = get(rel.l_vaddr);
relocInstructions.push_back(
PEFRelocComposeSetPosition_1st(vaddr));
relocInstructions.push_back(
PEFRelocComposeSetPosition_2nd(vaddr));
if(get(rel.l_symndx) == 0)
relocInstructions.push_back(PEFRelocComposeBySectC(1));
else if(get(rel.l_symndx) == 1 || get(rel.l_symndx) == 2)
relocInstructions.push_back(PEFRelocComposeBySectD(1));
else
{
int importIndex = importedSymbolIndices[get(rel.l_symndx) - 3];
relocInstructions.push_back(
PEFRelocComposeLgByImport_1st(importIndex));
relocInstructions.push_back(
PEFRelocComposeLgByImport_2nd(importIndex));
}
}
}
PEFContainerHeader pefHeader;
memset(&pefHeader,0,sizeof(pefHeader));
pefHeader.tag1 = kPEFTag1;
pefHeader.tag2 = kPEFTag2;
pefHeader.architecture = 'pwpc';
pefHeader.formatVersion = kPEFVersion;
pefHeader.sectionCount = 3; // .text, .data, .loader
pefHeader.instSectionCount = 2; // .text, .data
PEFLoaderInfoHeader loaderInfoHeader;
memset(&loaderInfoHeader, 0, sizeof(loaderInfoHeader));
loaderInfoHeader.mainSection = -1;
loaderInfoHeader.initSection = -1;
loaderInfoHeader.termSection = -1;
loaderInfoHeader.mainSection = 1;
loaderInfoHeader.mainOffset = get(aoutHeader.entry);
PEFSectionHeader textSectionHeader, dataSectionHeader, loaderSectionHeader;
memset(&textSectionHeader, 0, sizeof(textSectionHeader));
memset(&dataSectionHeader, 0, sizeof(dataSectionHeader));
memset(&loaderSectionHeader, 0, sizeof(loaderSectionHeader));
int textSize = get(xcoffSections[".text"].s_size);
textSectionHeader.nameOffset = -1;
textSectionHeader.defaultAddress = 0;
textSectionHeader.totalLength = textSize;
textSectionHeader.unpackedLength = textSize;
textSectionHeader.containerLength = textSize;
textSectionHeader.containerOffset = sizeof(PEFContainerHeader) + 3*sizeof(PEFSectionHeader);
textSectionHeader.sectionKind = kPEFCodeSection;
textSectionHeader.shareKind = kPEFGlobalShare;
textSectionHeader.alignment = 2;
int dataSize = get(xcoffSections[".data"].s_size);
dataSectionHeader.nameOffset = -1;
dataSectionHeader.defaultAddress = 0;
dataSectionHeader.totalLength = dataSize + get(xcoffSections[".bss"].s_size);
dataSectionHeader.unpackedLength = dataSize;
dataSectionHeader.containerLength = dataSize;
dataSectionHeader.containerOffset = sizeof(PEFContainerHeader) + 3*sizeof(PEFSectionHeader) + textSize;
dataSectionHeader.sectionKind = kPEFUnpackedDataSection;
dataSectionHeader.shareKind = kPEFProcessShare;
dataSectionHeader.alignment = 2;
std::vector<std::string> loaderStringTable;
int loaderStringTableSize = 0;
for(unsigned i=1;i<importLibs.size();i++)
{
ImportLib& imp = importLibs[i];
std::string name;
if(imp.mem != "")
name = imp.mem;
else
name = imp.base;
if(verboseFlag)
{
std::cerr << "XCOFF name \"" << name << '"';
}
int dotIndex = name.rfind('.');
if(dotIndex)
{
name = name.substr(0,dotIndex);
if(name.substr(0,3) == "lib")
name = name.substr(3);
}
if(name.length() > 6)
{
if(name.substr(name.length()-6,6) == "__weak")
{
name = name.substr(0,name.length()-6);
imp.weak = true;
}
}
if(verboseFlag)
{
std::cerr << "PEF name \"" << name << '"';
if(imp.weak)
std::cerr << " (weak)";
std::cerr << " at " << std::hex << loaderStringTableSize << std::dec
<< std::endl;
}
importLibs[i].nameOffset = loaderStringTableSize;
loaderStringTable.push_back(name);
loaderStringTableSize += name.length() + 1;
for(unsigned j=0;j<importLibs[i].imports.size();j++)
{
name = importLibs[i].imports[j];
if(verboseFlag)
std::cerr << "Sym name \"" << name << "\" at " << std::hex
<< loaderStringTableSize << std::dec << std::endl;
importLibs[i].symNameOffsets.push_back(loaderStringTableSize);
loaderStringTable.push_back(name);
loaderStringTableSize += name.length() + 1;
}
}
loaderInfoHeader.importedLibraryCount = importLibs.size()-1;
loaderInfoHeader.totalImportedSymbolCount = totalImportedSyms;
loaderInfoHeader.relocSectionCount = 1; // data only
loaderInfoHeader.relocInstrOffset = sizeof(PEFLoaderInfoHeader)
+ sizeof(PEFImportedLibrary)*(importLibs.size()-1)
+ sizeof(PEFImportedSymbol)*totalImportedSyms
+ sizeof(PEFLoaderRelocationHeader);
if(verboseFlag)
{
std::cerr << "reloc instr offset: " << loaderInfoHeader.relocInstrOffset
<< " = " << sizeof(PEFLoaderInfoHeader)
<< " + " << sizeof(PEFImportedLibrary)*(importLibs.size()-1)
<< " + " << sizeof(PEFImportedSymbol)*totalImportedSyms
<< " + " << sizeof(PEFLoaderRelocationHeader)
<< std::endl;
}
loaderInfoHeader.loaderStringsOffset = loaderInfoHeader.relocInstrOffset
+ relocInstructions.size() * 2;
loaderInfoHeader.exportHashOffset = loaderInfoHeader.loaderStringsOffset
+ loaderStringTableSize;
PEFLoaderRelocationHeader dataRelocationHeader;
dataRelocationHeader.sectionIndex = 1;
dataRelocationHeader.reservedA = 0;
dataRelocationHeader.relocCount = relocInstructions.size();
dataRelocationHeader.firstRelocOffset = 0;
loaderSectionHeader.nameOffset = -1;
loaderSectionHeader.defaultAddress = 0;
loaderSectionHeader.totalLength = 0;
loaderSectionHeader.unpackedLength = 0;
loaderSectionHeader.containerLength = loaderInfoHeader.exportHashOffset + 4;
loaderSectionHeader.containerOffset = sizeof(PEFContainerHeader) + 3*sizeof(PEFSectionHeader)
+ textSize + dataSize;
loaderSectionHeader.sectionKind = kPEFLoaderSection;
loaderSectionHeader.shareKind = kPEFGlobalShare;
loaderSectionHeader.alignment = 2;
std::ofstream out(outFn);
if(verboseFlag)
std::cerr << "Writing Headers..." << std::flush;
eswap(&pefHeader);
out.write((char*)&pefHeader, sizeof(pefHeader));
eswap(&textSectionHeader);
out.write((char*)&textSectionHeader, sizeof(textSectionHeader));
eswap(&dataSectionHeader);
out.write((char*)&dataSectionHeader, sizeof(dataSectionHeader));
eswap(&loaderSectionHeader);
out.write((char*)&loaderSectionHeader, sizeof(loaderSectionHeader));
if(verboseFlag)
std::cerr << "done.\nCopying text and data..." << std::flush;
{
char *buf = new char[textSize];
in.seekg(get(xcoffSections[".text"].s_scnptr));
in.read(buf, textSize);
out.write(buf, textSize);
delete[] buf;
}
{
char *buf = new char[dataSize];
in.seekg(get(xcoffSections[".data"].s_scnptr));
in.read(buf, dataSize);
out.write(buf, dataSize);
delete[] buf;
}
if(verboseFlag)
std::cerr << "done.\n";
eswap(&loaderInfoHeader);
out.write((char*)&loaderInfoHeader, sizeof(loaderInfoHeader));
int firstImportedSymbol = 0;
if(verboseFlag)
std::cerr << "imports..." << std::flush;
for(unsigned i=1;i<importLibs.size();i++)
{
PEFImportedLibrary impLib;
memset(&impLib,0,sizeof(impLib));
impLib.nameOffset = importLibs[i].nameOffset;
impLib.importedSymbolCount = importLibs[i].imports.size();
impLib.firstImportedSymbol= firstImportedSymbol;
firstImportedSymbol += impLib.importedSymbolCount;
if(importLibs[i].weak)
impLib.options = kPEFWeakImportLibMask;
eswap(&impLib);
out.write((char*)&impLib, sizeof(impLib));
}
for(unsigned i=1;i<importLibs.size();i++)
{
for(unsigned j=0;j<importLibs[i].imports.size();j++)
{
PEFImportedSymbol sym;
sym.classAndName = PEFComposeImportedSymbol(kPEFTVectorSymbol /* ### */,
importLibs[i].symNameOffsets[j]);
eswap(&sym);
out.write((char*)&sym, sizeof(sym));
}
}
if(verboseFlag)
std::cerr << "done.\n";
if(verboseFlag)
std::cerr << "relocations..." << std::flush;
eswap(&dataRelocationHeader);
out.write((char*)&dataRelocationHeader, sizeof(dataRelocationHeader));
for(unsigned i=0;i<relocInstructions.size();i++)
{
short insn = relocInstructions[i];
eswap(&insn, "s");
out.write((char*)&insn, sizeof(insn));
}
if(verboseFlag)
{
std::cerr << "done.\n";
std::cerr << "strings..." << std::flush;
}
for(unsigned i=0;i<loaderStringTable.size();i++)
{
out.write(loaderStringTable[i].c_str(),loaderStringTable[i].length()+1);
}
if(verboseFlag)
std::cerr << "done.\n";
{
int zero = 0;
out.write((char*)&zero, 4);
}
}
int main (int argc, char * const argv[]) {
bool hadInput = false;
std::string inputFn;
bool hadOutput = false;
std::string outputFn = "";
for(int i=1;i<argc;i++)
{
std::string arg = argv[i];
if(arg == "-v")
verboseFlag = true;
else if(arg == "-o")
{
i++;
if(i >= argc)
{
std::cerr << "makepef: -o requires an argument.\n";
return 1;
}
if(hadOutput)
{
std::cerr << "makepef: -o can only be used once.\n";
return 1;
}
outputFn = argv[i];
hadOutput = true;
}
else
{
if(hadInput)
{
std::cerr << "makepef: can only handle one input file.\n";
return 1;
}
inputFn = argv[i];
hadInput = true;
}
}
if(!hadInput)
{
std::cerr << "makepef: no input file specified.\n";
return 1;
}
if(!hadOutput)
{
std::cerr << "makepef: no output file specified.\n";
return 1;
}
mkpef(inputFn, outputFn);
return 0;
}

146
PEFTools/PEF.h Normal file
View File

@ -0,0 +1,146 @@
#ifndef PEF_H
#define PEF_H
/* Provide minimal definitions from ConfitionalMacros.h.
* ConditionalMacros.h can't deal with our host C compiler.
*/
#define __CONDITIONALMACROS__
#define TYPE_BOOL 1
#define EXTERN_API(x) x
#define EXTERN_API_C(x) x
#define CALLBACK_API(ret,name) ret (*name)
#define CALLBACK_API_C(ret,name) ret (*name)
#define ONEWORDINLINE(x)
#define TWOWORDINLINE(x,y)
#define THREEWORDINLINE(x,y,z)
#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;
typedef int16_t OSErr;
typedef const unsigned char ConstStr63Param[64];
typedef const unsigned char ConstStr255Param[256];
typedef unsigned char Str255[256];
typedef unsigned char *StringPtr;
typedef char* Ptr;
typedef int16_t Boolean;
typedef void *LogicalAddress;
#define __FILES__
typedef struct {} FSSpec, *FSSpecPtr;
/* Definitions for PEF, from Apple's Universal Interfaces */
#include <PEFBinaryFormat.h>
/* Deal with differences between versions of PEFBinaryFormat.h */
#ifndef PEFRelocComposeSetPosition_1st
#define PEFRelocComposeSetPosition_1st(fullOffset) \
( 0xA000 | ((UInt16) (((UInt32)(fullOffset)) >> 16) ) )
#define PEFRelocComposeSetPosition_2nd(fullOffset) \
( (UInt16) ((UInt32)(fullOffset) & 0xFFFF) )
#define PEFRelocComposeLgByImport_1st(fullIndex) \
( 0xA400 | ((UInt16) (((UInt32)(fullIndex)) >> 16) ) )
#define PEFRelocComposeLgByImport_2nd(fullIndex) \
( (UInt16) ((UInt32)(fullIndex) & 0xFFFF) )
#endif
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++)
{
assert(p <= reinterpret_cast<char*>(data) + sizeof(T));
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 if(c == '*')
{
return;
}
else
{
assert(c == '.');
++p;
}
}
assert(p == reinterpret_cast<char*>(data) + sizeof(T));
}
#define DEFINE_ESWAP(T, S) \
inline void eswap(T* data) { eswap(data, S); }
DEFINE_ESWAP(PEFContainerHeader, "LLLLLLLLssL")
DEFINE_ESWAP(PEFSectionHeader, "LLLLLL....")
DEFINE_ESWAP(PEFLoaderInfoHeader, "LLLLLLLLLLLLLL")
DEFINE_ESWAP(PEFImportedLibrary, "LLLLL..s")
DEFINE_ESWAP(PEFImportedSymbol, "L")
DEFINE_ESWAP(PEFLoaderRelocationHeader, "ssLL")
DEFINE_ESWAP(PEFExportedSymbol, "LLs")
struct CFragResourceMember {
uint32_t architecture;
uint16_t reservedA;
uint8_t reservedB;
uint8_t updateLevel;
uint32_t currentVersion;
uint32_t oldDefVersion;
uint32_t uUsage1;
uint16_t uUsage2;
uint8_t usage;
uint8_t where;
uint32_t offset;
uint32_t length;
uint32_t uWhere1;
uint16_t uWhere2;
uint16_t extensionCount;
uint16_t memberSize;
unsigned char name[16];
};
struct CFragResource {
uint32_t reservedA;
uint32_t reservedB;
uint16_t reservedC;
uint16_t version;
uint32_t reservedD;
uint32_t reservedE;
uint32_t reservedF;
uint32_t reservedG;
uint16_t reservedH;
uint16_t memberCount;
CFragResourceMember firstMember;
};
DEFINE_ESWAP(CFragResource, "LLssLLLLss*")
DEFINE_ESWAP(CFragResourceMember, "Ls..LLLs..LLLsss*")
#endif // PEF_H

353
PEFTools/rs6000.h Normal file
View File

@ -0,0 +1,353 @@
/* IBM RS/6000 "XCOFF" file definitions for BFD.
Copyright (C) 1990-2014 Free Software Foundation, Inc.
Written by Mimi Phuong-Thao Vo of IBM
and John Gilmore of Cygnus Support.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
/********************** FILE HEADER **********************/
struct external_filehdr {
char f_magic[2]; /* magic number */
char f_nscns[2]; /* number of sections */
char f_timdat[4]; /* time & date stamp */
char f_symptr[4]; /* file pointer to symtab */
char f_nsyms[4]; /* number of symtab entries */
char f_opthdr[2]; /* sizeof(optional hdr) */
char f_flags[2]; /* flags */
};
/* IBM RS/6000 */
#define U802WRMAGIC 0730 /* writeable text segments **chh** */
#define U802ROMAGIC 0735 /* readonly sharable text segments */
#define U802TOCMAGIC 0737 /* readonly text segments and TOC */
#define BADMAG(x) \
((x).f_magic != U802ROMAGIC && (x).f_magic != U802WRMAGIC && \
(x).f_magic != U802TOCMAGIC)
#define FILHDR struct external_filehdr
#define FILHSZ 20
/********************** AOUT "OPTIONAL HEADER" **********************/
typedef struct
{
unsigned char magic[2]; /* type of file */
unsigned char vstamp[2]; /* version stamp */
unsigned char tsize[4]; /* text size in bytes, padded to FW bdry */
unsigned char dsize[4]; /* initialized data " " */
unsigned char bsize[4]; /* uninitialized data " " */
unsigned char entry[4]; /* entry pt. */
unsigned char text_start[4]; /* base of text used for this file */
unsigned char data_start[4]; /* base of data used for this file */
unsigned char o_toc[4]; /* address of TOC */
unsigned char o_snentry[2]; /* section number of entry point */
unsigned char o_sntext[2]; /* section number of .text section */
unsigned char o_sndata[2]; /* section number of .data section */
unsigned char o_sntoc[2]; /* section number of TOC */
unsigned char o_snloader[2]; /* section number of .loader section */
unsigned char o_snbss[2]; /* section number of .bss section */
unsigned char o_algntext[2]; /* .text alignment */
unsigned char o_algndata[2]; /* .data alignment */
unsigned char o_modtype[2]; /* module type (??) */
unsigned char o_cputype[2]; /* cpu type */
unsigned char o_maxstack[4]; /* max stack size (??) */
unsigned char o_maxdata[4]; /* max data size (??) */
unsigned char o_resv2[12]; /* reserved */
}
AOUTHDR;
#define AOUTSZ 72
#define SMALL_AOUTSZ (28)
#define AOUTHDRSZ 72
/********************** SECTION HEADER **********************/
struct external_scnhdr {
char s_name[8]; /* section name */
char s_paddr[4]; /* physical address, aliased s_nlib */
char s_vaddr[4]; /* virtual address */
char s_size[4]; /* section size */
char s_scnptr[4]; /* file ptr to raw data for section */
char s_relptr[4]; /* file ptr to relocation */
char s_lnnoptr[4]; /* file ptr to line numbers */
char s_nreloc[2]; /* number of relocation entries */
char s_nlnno[2]; /* number of line number entries*/
char s_flags[4]; /* flags */
};
#define SCNHDR struct external_scnhdr
#define SCNHSZ 40
/********************** LINE NUMBERS **********************/
/* 1 line number entry for every "breakpointable" source line in a section.
* Line numbers are grouped on a per function basis; first entry in a function
* grouping will have l_lnno = 0 and in place of physical address will be the
* symbol table index of the function name.
*/
struct external_lineno {
union {
char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/
char l_paddr[4]; /* (physical) address of line number */
} l_addr;
char l_lnno[2]; /* line number */
};
#define LINENO struct external_lineno
#define LINESZ 6
/********************** SYMBOLS **********************/
#define E_SYMNMLEN 8 /* # characters in a symbol name */
#define E_FILNMLEN 14 /* # characters in a file name */
#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */
struct external_syment
{
union {
char e_name[E_SYMNMLEN];
struct {
char e_zeroes[4];
char e_offset[4];
} e;
} e;
char e_value[4];
char e_scnum[2];
char e_type[2];
char e_sclass[1];
char e_numaux[1];
};
#define N_BTMASK (017)
#define N_TMASK (060)
#define N_BTSHFT (4)
#define N_TSHIFT (2)
union external_auxent {
struct {
char x_tagndx[4]; /* str, un, or enum tag indx */
union {
struct {
char x_lnno[2]; /* declaration line number */
char x_size[2]; /* str/union/array size */
} x_lnsz;
char x_fsize[4]; /* size of function */
} x_misc;
union {
struct { /* if ISFCN, tag, or .bb */
char x_lnnoptr[4]; /* ptr to fcn line # */
char x_endndx[4]; /* entry ndx past block end */
} x_fcn;
struct { /* if ISARY, up to 4 dimen. */
char x_dimen[E_DIMNUM][2];
} x_ary;
} x_fcnary;
char x_tvndx[2]; /* tv index */
} x_sym;
struct {
union {
char x_fname[E_FILNMLEN];
struct {
char x_zeroes[4];
char x_offset[4];
} x_n;
} x_n;
char x_ftype[1];
} x_file;
struct {
char x_scnlen[4]; /* section length */
char x_nreloc[2]; /* # relocation entries */
char x_nlinno[2]; /* # line numbers */
} x_scn;
struct {
char x_tvfill[4]; /* tv fill value */
char x_tvlen[2]; /* length of .tv */
char x_tvran[2][2]; /* tv range */
} x_tv; /* info about .tv section (in auxent of symbol .tv)) */
struct {
unsigned char x_scnlen[4];
unsigned char x_parmhash[4];
unsigned char x_snhash[2];
unsigned char x_smtyp[1];
unsigned char x_smclas[1];
unsigned char x_stab[4];
unsigned char x_snstab[2];
} x_csect;
};
#define SYMENT struct external_syment
#define SYMESZ 18
#define AUXENT union external_auxent
#define AUXESZ 18
#define DBXMASK 0x80 /* for dbx storage mask */
#define SYMNAME_IN_DEBUG(symptr) ((symptr)->n_sclass & DBXMASK)
/********************** RELOCATION DIRECTIVES **********************/
struct external_reloc {
char r_vaddr[4];
char r_symndx[4];
char r_size[1];
char r_type[1];
};
#define RELOC struct external_reloc
#define RELSZ 10
#define DEFAULT_DATA_SECTION_ALIGNMENT 4
#define DEFAULT_BSS_SECTION_ALIGNMENT 4
#define DEFAULT_TEXT_SECTION_ALIGNMENT 4
/* For new sections we havn't heard of before */
#define DEFAULT_SECTION_ALIGNMENT 4
/* The ldhdr structure. This appears at the start of the .loader
section. */
struct external_ldhdr
{
bfd_byte l_version[4];
bfd_byte l_nsyms[4];
bfd_byte l_nreloc[4];
bfd_byte l_istlen[4];
bfd_byte l_nimpid[4];
bfd_byte l_impoff[4];
bfd_byte l_stlen[4];
bfd_byte l_stoff[4];
};
#define LDHDRSZ (8 * 4)
struct external_ldsym
{
union
{
bfd_byte _l_name[E_SYMNMLEN];
struct
{
bfd_byte _l_zeroes[4];
bfd_byte _l_offset[4];
} _l_l;
} _l;
bfd_byte l_value[4];
bfd_byte l_scnum[2];
bfd_byte l_smtype[1];
bfd_byte l_smclas[1];
bfd_byte l_ifile[4];
bfd_byte l_parm[4];
};
#define LDSYMSZ (8 + 3 * 4 + 2 + 2)
struct external_ldrel
{
bfd_byte l_vaddr[4];
bfd_byte l_symndx[4];
bfd_byte l_rtype[2];
bfd_byte l_rsecnm[2];
};
#define LDRELSZ (2 * 4 + 2 * 2)
struct external_exceptab
{
union {
bfd_byte e_symndx[4];
bfd_byte e_paddr[4];
} e_addr;
bfd_byte e_lang[1];
bfd_byte e_reason[1];
};
#define EXCEPTSZ (4 + 2)
/******************** Core files *************************/
struct external_core_dumpx
{
unsigned char c_signo[1];
unsigned char c_flag[1];
unsigned char c_entries[2];
unsigned char c_version[4];
unsigned char c_fdsinfox[8];
unsigned char c_loader[8];
unsigned char c_lsize[8];
unsigned char c_n_thr[4];
unsigned char c_reserved0[4];
unsigned char c_thr[8];
unsigned char c_segs[8];
unsigned char c_segregion[8];
unsigned char c_stack[8];
unsigned char c_stackorg[8];
unsigned char c_size[8];
unsigned char c_data[8];
unsigned char c_dataorg[8];
unsigned char c_datasize[8];
unsigned char c_sdorg[8];
unsigned char c_sdsize[8];
unsigned char c_vmmregions[8];
unsigned char c_vmm[8];
unsigned char c_impl[4];
unsigned char c_pad[4];
unsigned char c_cprs[8];
unsigned char c_reserved[7 * 8];
/* Followed by:
- context of the faulting thread.
- user structure. */
};
/* Core file verion. */
#define CORE_DUMPX_VERSION 0x0feeddb1
#define CORE_DUMPXX_VERSION 0x0feeddb2
struct external_ld_info32
{
unsigned char ldinfo_next[4];
unsigned char core_offset[4];
unsigned char ldinfo_textorg[4];
unsigned char ldinfo_textsize[4];
unsigned char ldinfo_dataorg[4];
unsigned char ldinfo_datasize[4];
unsigned char ldinfo_filename[2];
};

Some files were not shown because too many files have changed in this diff Show More