#include #include #include #include #include #include #include #include #include #include #include #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 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 imports; std::vector xcoffImportIndices; int nameOffset; bool weak; std::vector 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 xcoffSections; std::map xcoffSectionNumbers; int nSections = get(xcoffHeader.f_nscns); for(int i=0;i importLibs; std::vector importedSymbolIndices; int totalImportedSyms = 0; std::vector 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 loaderStringTable; int loaderStringTableSize = 0; for(unsigned i=1;i 6) { if(name.substr(name.length()-6,6) == "__weak") { name = name.substr(0,name.length()-6); imp.weak = true; } } if(name.length() > 5) { // the shared library name has been encoded as hex by MakeImport // in order to avoid potential file name issues // classic MacOS shared library names are in MacRoman and // may contain wierd characters; the shared library name is used // as the file name for the archive member, so there can be problems. if(name.substr(0,5) == "imp__") { std::string realName; int i; int n = name.size(); for(i = 5; i < n && name[i] != '_'; i++) ; ++i; for(; i + 1 < n && name[i] != '_'; i+=2) { char c1 = tolower(name[i]); char c2 = tolower(name[i+1]); assert(isdigit(c1) || (c1 >= 'a' && c1 <= 'f')); assert(isdigit(c2) || (c2 >= 'a' && c2 <= 'f')); int c = (c1 >= 'a' ? c1 - 'a' + 10 : c1 - '0') * 16 + (c2 >= 'a' ? c2 - 'a' + 10 : c2 - '0'); realName += (char)c; } name = realName; } } 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= 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; }