diff --git a/CMakeLists.txt b/CMakeLists.txt index 32f12fdf39..fc5759c1ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,6 +52,6 @@ add_subdirectory(ResourceFiles) add_subdirectory(MakeAPPL) add_subdirectory(Rez) -add_subdirectory(MakePEF) +add_subdirectory(PEFTools) endif() diff --git a/MakePEF/CMakeLists.txt b/PEFTools/CMakeLists.txt similarity index 61% rename from MakePEF/CMakeLists.txt rename to PEFTools/CMakeLists.txt index ae560e9958..31f2f2d841 100644 --- a/MakePEF/CMakeLists.txt +++ b/PEFTools/CMakeLists.txt @@ -1,6 +1,8 @@ set(CMAKE_CXX_FLAGS "--std=c++11 -Wall -Werror=return-type -Wno-multichar") 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 PEF.h) + +add_executable(MakeImport MakeImport.cc PEF.h) install(TARGETS MakePEF RUNTIME DESTINATION bin) diff --git a/PEFTools/MakeImport.cc b/PEFTools/MakeImport.cc new file mode 100755 index 0000000000..b388cd8428 --- /dev/null +++ b/PEFTools/MakeImport.cc @@ -0,0 +1,350 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "PEF.h" + +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; + +// Change this to support little-endian hosts: +UInt16 eu16(UInt16 x) { return x; } +UInt32 eu32(UInt32 x) { return x; } +SInt16 es16(SInt16 x) { return x; } +SInt32 es32(SInt32 x) { return x; } + +void MakeImportLibrary(char *pefptr, size_t pefsize, string libname, string name) +{ + PEFContainerHeader *containerHeader = (PEFContainerHeader*) pefptr; + + assert(eu32(containerHeader->tag1) == 'Joy!'); + assert(eu32(containerHeader->tag2) == 'peff'); + + PEFSectionHeader *sectionHeaders + = (PEFSectionHeader*) (pefptr + kPEFFirstSectionHeaderOffset); + + PEFSectionHeader *loaderHeader = NULL; + UInt16 n = eu16(containerHeader->sectionCount); + for(UInt16 i=0; i < n; i++) + if(sectionHeaders[i].sectionKind == kPEFLoaderSection) + loaderHeader = §ionHeaders[i]; + + PEFLoaderInfoHeader *loaderInfoHeader + = (PEFLoaderInfoHeader*) (pefptr + eu32(loaderHeader->containerOffset)); + + + UInt32 hashTableSize = 1; + UInt32 hashTablePower = eu32(loaderInfoHeader->exportHashTablePower); + while(hashTablePower--) + hashTableSize *= 2; + + UInt32 nSymbols = eu32(loaderInfoHeader->exportedSymbolCount); + + char *symbols /* use char pointer to avoid packing issues */ + = (pefptr + eu32(loaderHeader->containerOffset) + + eu32(loaderInfoHeader->exportHashOffset) + + hashTableSize * sizeof(PEFExportedSymbolHashSlot) + + nSymbols * sizeof(PEFExportedSymbolKey)); + + char *stringTable = pefptr + + eu32(loaderHeader->containerOffset) + + eu32(loaderInfoHeader->loaderStringsOffset); + char *stringTableEnd = pefptr + + eu32(loaderHeader->containerOffset) + + eu32(loaderInfoHeader->exportHashOffset); + vector< pair< const char *, UInt8 > > classesAndNamePtrs; + + for(UInt32 i=0; i < nSymbols; i++) + { + PEFExportedSymbol sym = * (PEFExportedSymbol*) (symbols + 10*i); + + UInt8 symclass = PEFExportedSymbolClass(eu32(sym.classAndName)); + UInt32 nameoffset = PEFExportedSymbolNameOffset(eu32(sym.classAndName)); + + const char *nameptr + = stringTable + nameoffset; + + classesAndNamePtrs.push_back( make_pair(nameptr, symclass) ); + } + sort(classesAndNamePtrs.begin(), classesAndNamePtrs.end()); + + vector< pair > 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); + + //cout << (int) namestart << "-" << (int) nameend << endl; + + //cout << (int)symclass << " " << name << endl; + + exportedSymbols.push_back( make_pair( name, symclass ) ); + } + sort(exportedSymbols.begin(), exportedSymbols.end()); + + { + ofstream expFile("stub.exp"); + //ofstream cFile("stub.c"); + 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; + //cFile << "void " << 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; + //cFile << "int " << sym << " = 42;" << 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; + //system("powerpc-apple-macos-gcc -fno-builtin -c stub.c"); + system("powerpc-apple-macos-as stub.s -o stub.o"); + system(("powerpc-apple-macos-ld -shared --no-check-sections " + "-bexport:stub.exp -o'" + + name + ".o' stub.o").c_str()); + system(("powerpc-apple-macos-ar cq '" + libname + "' '" + name + ".o'").c_str()); + system(("powerpc-apple-macos-ar t '" + libname + "'").c_str()); + + unlink("stub.exp"); + unlink("stub.o"); + unlink("stub.c"); + unlink((name + ".o").c_str()); + } + + /*{ + ofstream expFile((name + ".exp").c_str()); + ofstream cFile((name + ".stub.c").c_str()); + for(UInt32 i=0; i< nSymbols; i++) + { + if(exportedSymbols[i].second == kPEFTVectorSymbol) + { + expFile << exportedSymbols[i].first << endl; + cFile << "void " << exportedSymbols[i].first << "() {}" << endl; + } + else if(exportedSymbols[i].second == kPEFDataSymbol) + { + expFile << exportedSymbols[i].first << endl; + cFile << "int " << exportedSymbols[i].first << " = 42;" << endl; + } + } + + system(("powerpc-apple-macos-gcc -fno-builtin -c '" + name + ".stub.c'").c_str()); + system(("powerpc-apple-macos-ld -shared --no-check-sections '-bexport:" + + name + ".exp' -o '" + + name + ".o' '" + name + ".stub.o'").c_str()); + system(("powerpc-apple-macos-ar cq lib" + libname + ".a '" + name + ".o'").c_str()); + system(("powerpc-apple-macos-ar t lib" + libname + ".a").c_str()); + + unlink((name + ".exp").c_str()); + unlink((name + ".stub.c").c_str()); + unlink((name + ".stub.o").c_str()); + //unlink((name + ".o").c_str()); + }*/ + /* + { + ofstream expFile("shared.exp",ios_base::app | ios_base::out); + ofstream cFile("shared.stub.c",ios_base::app | ios_base::out); + for(UInt32 i=0; i< nSymbols; i++) + { + if(exportedSymbols[i].second == kPEFTVectorSymbol) + { + expFile << exportedSymbols[i].first << endl; + cFile << "void " << exportedSymbols[i].first << "() {}" << endl; + } + else if(exportedSymbols[i].second == kPEFDataSymbol) + { + expFile << exportedSymbols[i].first << endl; + cFile << "int " << exportedSymbols[i].first << " = 42;" << endl; + } + } + + }*/ + + /*{ + PEFSectionHeader *lastInstantiated = + §ionHeaders[eu16(containerHeader->instSectionCount)-1]; + + UInt32 containerSize = eu32(lastInstantiated->containerOffset) + + eu32(lastInstantiated->containerLength); + pefptr += containerSize; + pefsize -= containerSize; + }*/ +} + +bool FindPEFContainer(const char *path, const char *libname, + UInt32& offset, UInt32& length) +{ + bool found = false; + FSRef ref; + FSPathMakeRef((const UInt8*) path, &ref, NULL); + + short refnum = FSOpenResFile(&ref, fsRdPerm); + + Handle h = Get1Resource('cfrg', 0); + HLock(h); + + CFragResource *cfrg = (CFragResource*) *h; + CFragResourceMember *member = &(cfrg -> firstMember); + + for(UInt16 i = 0; i < cfrg->memberCount; i++) + { + cout << i << ": " << string(member->name+1, member->name+1+member->name[0]) + << endl; + if((member->architecture == kPowerPCCFragArch + || member->architecture == kAnyCFragArch) + && (string(member->name+1, member->name+1+member->name[0]) + == libname)) + { + offset = member->offset; + length = member->length; + found = true; + break; + } + + member = (CFragResourceMember*) (((char*)member) + member->memberSize); + } + + CloseResFile(refnum); + + return found; +} + +void MakeImportLibraryMulti(char *file, const char *path, string libname) +{ + FSRef ref; + FSPathMakeRef((const UInt8*) path, &ref, NULL); + + short refnum = FSOpenResFile(&ref, fsRdPerm); + + Handle h = Get1Resource('cfrg', 0); + HLock(h); + + unlink(("lib" + libname + ".a").c_str()); + + CFragResource *cfrg = (CFragResource*) *h; + CFragResourceMember *member = &(cfrg -> firstMember); + + for(UInt16 i = 0; i < cfrg->memberCount; i++) + { + string membername = + string(member->name+1, member->name+1+member->name[0]); + cout << i << ": " << membername << endl; + if(member->architecture == kPowerPCCFragArch + || member->architecture == kAnyCFragArch) + { + if(member->usage == kStubLibraryCFrag + || member->usage == kImportLibraryCFrag) + MakeImportLibrary(file + member->offset, member->length, + libname, membername); + else if(member->usage == kWeakStubLibraryCFrag) + MakeImportLibrary(file + member->offset, member->length, + libname, membername + "__weak"); + else + std::cerr << "Inappropriate usage flag: " + << (int)member->usage << endl; + //offset = member->offset; + //length = member->length; + //found = true; + //break; + } + else + std::cerr << "Inappropriate arch: " + << string((char*) &member->architecture, + ((char*) &member->architecture) + 4) << endl; + + member = (CFragResourceMember*) (((char*)member) + member->memberSize); + } + + CloseResFile(refnum); + /* + system("powerpc-apple-macos-gcc -fno-builtin -c shared.stub.c"); + system("powerpc-apple-macos-ld -shared --no-check-sections -bexport:shared.exp " + "-o shared.o shared.stub.o"); + system(("powerpc-apple-macos-ar cq lib" + libname + ".a shared.o").c_str()); + */ + /*unlink("shared.exp"); + unlink("shared.stub.c"); + unlink("shared.stub.o"); + unlink("shared.o");*/ +} + +int main (int argc, char * const argv[]) +{ + //printf("%d\n",argc); + if(argc != 3) + { + cerr << "Usage: makeimport []" << endl; + return 1; + } + + int fd = open(argv[1], O_RDONLY, 0); + if(fd < 0) + { + perror(argv[1]); + return 1; + } + struct stat sb; + fstat(fd, &sb); + off_t filesize = sb.st_size; + char *p = (char*) mmap(NULL, filesize, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0); + + /*UInt32 offset, length; + if(FindPEFContainer(argv[1], argv[2], offset, length)) + { + MakeImportLibrary(p+offset, length, argv[2]); + } + else + { + cerr << "No cfrg resource found or specified library not found." << endl + << "Using first container." << endl; + MakeImportLibrary(p, filesize, argv[2]); + }*/ + MakeImportLibraryMulti(p,argv[1], argv[2]); + + close(fd); + return 0; +} diff --git a/MakePEF/MakePEF.cc b/PEFTools/MakePEF.cc similarity index 93% rename from MakePEF/MakePEF.cc rename to PEFTools/MakePEF.cc index 0842f8470e..406b1a8534 100755 --- a/MakePEF/MakePEF.cc +++ b/PEFTools/MakePEF.cc @@ -12,48 +12,7 @@ #include "powerpc.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 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 */ -#include - - /* 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 +#include "PEF.h" typedef unsigned bfd_size_type; typedef unsigned bfd_vma; diff --git a/PEFTools/PEF.h b/PEFTools/PEF.h new file mode 100644 index 0000000000..c876165b1c --- /dev/null +++ b/PEFTools/PEF.h @@ -0,0 +1,46 @@ +#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 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 */ +#include + +/* 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 + +#endif // PEF_H diff --git a/MakePEF/external.h b/PEFTools/external.h similarity index 100% rename from MakePEF/external.h rename to PEFTools/external.h diff --git a/MakePEF/powerpc.h b/PEFTools/powerpc.h similarity index 100% rename from MakePEF/powerpc.h rename to PEFTools/powerpc.h diff --git a/MakePEF/xcoff.h b/PEFTools/xcoff.h similarity index 100% rename from MakePEF/xcoff.h rename to PEFTools/xcoff.h