diff --git a/reactos/tools/ppc-build/alink/Alinksrc.txt b/reactos/tools/ppc-build/alink/Alinksrc.txt new file mode 100644 index 00000000000..6fa3d16dd94 --- /dev/null +++ b/reactos/tools/ppc-build/alink/Alinksrc.txt @@ -0,0 +1,23 @@ +ALINK Source Code, V1.6, Copyright 1998-9 Anthony A.J. Williams. +All Rights Reserved. + +This source code is free for all to use, compile and distribute for any +purpose, provided it remains unmodified, and I am credited. You may not +charge for this source code, or any executables compiled from it, but you +may charge a small distribution fee to cover costs, and you may charge +for any warranty or support you may wish to give your customers. + +As this source is free, it comes with no warranty whatsoever - use it +entirely at your own risk. + +makefile contains the makefile for use with GCC (RSXNT) + +alink.mak contains the makefile for use with GCC (RSXNT), linking with the +ALINK libaries. Set C_INCLUDE_PATH to point to the ALINK library headers. + +alink2.mak contains the makefile for use with MSVC, linking with the ALINK +libraries. Set INCLUDE to point to the ALINK library headers. + +Any comments or bug reports, please email me at + +anthony_w@geocities.com diff --git a/reactos/tools/ppc-build/alink/Makefile b/reactos/tools/ppc-build/alink/Makefile new file mode 100644 index 00000000000..69b9223e6a6 --- /dev/null +++ b/reactos/tools/ppc-build/alink/Makefile @@ -0,0 +1,12 @@ +%.o: %.cpp + g++ -g -c -o $@ $< + +all: alink.exe + +clean: + rm -rf alink.exe *.o + +alink.o combine.o util.o output.o objload.o coff.o cofflib.o elf.o: alink.h + +alink.exe: alink.o combine.o util.o output.o objload.o coff.o cofflib.o elf.o + g++ -g -o $@ $^ diff --git a/reactos/tools/ppc-build/alink/alink.cpp b/reactos/tools/ppc-build/alink/alink.cpp new file mode 100644 index 00000000000..7fcddb33616 --- /dev/null +++ b/reactos/tools/ppc-build/alink/alink.cpp @@ -0,0 +1,1843 @@ +#include "alink.h" + +#define strupr(x) + +char case_sensitive=1; +char padsegments=0; +char mapfile=0; +std::string mapname; +unsigned short maxalloc=0xffff; +int output_type=OUTPUT_EXE; +std::string outname; + +FILE *afile=0; +UINT filepos=0; +long reclength=0; +unsigned char rectype=0; +char li_le=0; +UINT prevofs=0; +long prevseg=0; +long gotstart=0; +RELOC startaddr; +UINT imageBase=0; +UINT fileAlign=1; +UINT objectAlign=1; +UINT stackSize; +UINT stackCommitSize; +UINT heapSize; +UINT heapCommitSize; +unsigned char osMajor,osMinor; +unsigned char subsysMajor,subsysMinor; +unsigned int subSystem; +int buildDll=FALSE; +std::string stubName; + +long errcount=0; + +std::vector buf; +PDATABLOCK lidata; + +std::vector namelist; +std::vector seglist; +std::vector outlist; +std::vector grplist; +SORTLIST publics; +std::vector externs; +std::vector comdefs; +std::vector relocs; +std::vector impdefs; +std::vector expdefs; +std::vector libfiles; +std::vector resource; +SORTLIST comdats; +std::vector modname; +std::vector filename; +UINT namemin=0, +pubmin=0, + segmin=0, + grpmin=0, + extmin=0, + commin=0, + fixmin=0, + impmin=0,impsreq=0, + expmin=0; +UINT libPathCount=0; +std::vector libPath; +std::string entryPoint; +int cpuIdent = 0; + +void processArgs(int argc,char **argv) +{ + long i,j; + int helpRequested=FALSE; + UINT setbase,setfalign,setoalign; + UINT setstack,setstackcommit,setheap,setheapcommit; + int setsubsysmajor,setsubsysminor,setosmajor,setosminor; + unsigned char setsubsys; + int gotbase=FALSE,gotfalign=FALSE,gotoalign=FALSE,gotsubsys=FALSE; + int gotstack=FALSE,gotstackcommit=FALSE,gotheap=FALSE,gotheapcommit=FALSE; + int gotsubsysver=FALSE,gotosver=FALSE; + char *p,*q; + int c; + std::vector newargs; + FILE *argFile; + + for(i=1;i(256*1048576)) + || (getBitCount(setoalign)>1)) + { + printf("Bad object alignment\n"); + exit(1); + } + gotoalign=TRUE; + } + else + { + printf("Invalid switch %s\n",newargs[i].c_str()); + exit(1); + } + } + else if(!strcmp(&newargs[i][1],"osver")) + { + if(i<(newargs.size()-1)) + { + i++; + if(sscanf(&newargs[i][0],"%d.%d%n",&setosmajor,&setosminor,&j)!=2) + { + printf("Invalid version number %s\n",newargs[i].c_str()); + exit(1); + } + if((j!=newargs[i].size()) || (setosmajor<0) || (setosminor<0) + || (setosmajor>65535) || (setosminor>65535)) + { + printf("Invalid version number %s\n",newargs[i].c_str()); + exit(1); + } + gotosver=TRUE; + } + else + { + printf("Invalid switch %s\n",newargs[i].c_str()); + exit(1); + } + break; + } + else + { + printf("Invalid switch %s\n",newargs[i].c_str()); + exit(1); + } + break; + } + break; + case 'L': + if(newargs[i].size()==2) + { + if(i<(newargs.size()-1)) + { + i++; + j=newargs[i].size(); + if(newargs[i][j-1]!=PATH_CHAR) + { + /* append a path separator if not present */ + std::string lp = newargs[i]; + lp += PATH_CHAR; + libPath.push_back(lp); + } + else + { + libPath.push_back(newargs[i]); + } + } + else + { + printf("Invalid switch %s\n",newargs[i].c_str()); + exit(1); + } + break; + } + printf("Invalid switch %s\n",newargs[i].c_str()); + exit(1); + break; + case 'h': + case 'H': + case '?': + if(newargs[i].size()==2) + { + helpRequested=TRUE; + } + else if(!strcmp(&newargs[i][1],"heapsize")) + { + if(i<(newargs.size()-1)) + { + i++; + setheap=strtoul(newargs[i].c_str(),&p,0); + if(p[0]) /* if not at end of arg */ + { + printf("Bad heap size\n"); + exit(1); + } + gotheap=TRUE; + } + else + { + printf("Invalid switch %s\n",newargs[i].c_str()); + exit(1); + } + break; + } + else if(!strcmp(&newargs[i][1],"heapcommitsize")) + { + if(i<(newargs.size()-1)) + { + i++; + setheapcommit=strtoul(newargs[i].c_str(),&p,0); + if(p[0]) /* if not at end of arg */ + { + printf("Bad heap commit size\n"); + exit(1); + } + gotheapcommit=TRUE; + } + else + { + printf("Invalid switch %s\n",newargs[i].c_str()); + exit(1); + } + break; + } + break; + case 'b': + if(!strcmp(&newargs[i][1],"base")) + { + if(i<(newargs.size()-1)) + { + i++; + setbase=strtoul(newargs[i].c_str(),&p,0); + if(p[0]) /* if not at end of arg */ + { + printf("Bad image base\n"); + exit(1); + } + if(setbase&0xffff) + { + printf("Bad image base\n"); + exit(1); + } + gotbase=TRUE; + } + else + { + printf("Invalid switch %s\n",newargs[i].c_str()); + exit(1); + } + break; + } + else + { + printf("Invalid switch %s\n",newargs[i].c_str()); + exit(1); + } + break; + case 's': + if(!strcmp(&newargs[i][1],"subsys")) + { + if(i<(newargs.size()-1)) + { + i++; + if(!strcmp(newargs[i].c_str(),"gui") + || !strcmp(newargs[i].c_str(),"windows") + || !strcmp(newargs[i].c_str(),"win")) + { + setsubsys=PE_SUBSYS_WINDOWS; + gotsubsys=TRUE; + } + else if(!strcmp(newargs[i].c_str(),"char") + || !strcmp(newargs[i].c_str(),"console") + || !strcmp(newargs[i].c_str(),"con")) + { + setsubsys=PE_SUBSYS_CONSOLE; + gotsubsys=TRUE; + } + else if(!strcmp(newargs[i].c_str(),"native")) + { + setsubsys=PE_SUBSYS_NATIVE; + gotsubsys=TRUE; + } + else if(!strcmp(newargs[i].c_str(),"posix")) + { + setsubsys=PE_SUBSYS_POSIX; + gotsubsys=TRUE; + } + else + { + printf("Invalid subsystem id %s\n",newargs[i].c_str()); + exit(1); + } + } + else + { + printf("Invalid switch %s\n",newargs[i].c_str()); + exit(1); + } + break; + } + else if(!strcmp(&newargs[i][1],"subsysver")) + { + if(i<(newargs.size()-1)) + { + i++; + if(sscanf(newargs[i].c_str(),"%d.%d%n",&setsubsysmajor,&setsubsysminor,&j)!=2) + { + printf("Invalid version number %s\n",newargs[i].c_str()); + exit(1); + } + if((j!=newargs[i].size()) || (setsubsysmajor<0) || (setsubsysminor<0) + || (setsubsysmajor>65535) || (setsubsysminor>65535)) + { + printf("Invalid version number %s\n",newargs[i].c_str()); + exit(1); + } + gotsubsysver=TRUE; + } + else + { + printf("Invalid switch %s\n",newargs[i].c_str()); + exit(1); + } + break; + } + else if(!strcmp(&newargs[i][1],"stacksize")) + { + if(i<(newargs.size()-1)) + { + i++; + setstack=strtoul(newargs[i].c_str(),&p,0); + if(p[0]) /* if not at end of arg */ + { + printf("Bad stack size\n"); + exit(1); + } + gotstack=TRUE; + } + else + { + printf("Invalid switch %s\n",newargs[i].c_str()); + exit(1); + } + break; + } + else if(!strcmp(&newargs[i][1],"stackcommitsize")) + { + if(i<(newargs.size()-1)) + { + i++; + setstackcommit=strtoul(newargs[i].c_str(),&p,0); + if(p[0]) /* if not at end of arg */ + { + printf("Bad stack commit size\n"); + exit(1); + } + gotstackcommit=TRUE; + } + else + { + printf("Invalid switch %s\n",newargs[i].c_str()); + exit(1); + } + break; + } + else if(!strcmp(&newargs[i][1],"stub")) + { + if(i<(newargs.size()-1)) + { + i++; + stubName=newargs[i]; + } + else + { + printf("Invalid switch %s\n",newargs[i].c_str()); + exit(1); + } + break; + } + else + { + printf("Invalid switch %s\n",newargs[i].c_str()); + exit(1); + } + break; + case 'f': + if(!strcmp(&newargs[i][1],"filealign")) + { + if(i<(newargs.size()-1)) + { + i++; + setfalign=strtoul(newargs[i].c_str(),&p,0); + if(p[0]) /* if not at end of arg */ + { + printf("Bad file alignment\n"); + exit(1); + } + if((setfalign<512)|| (setfalign>65536) + || (getBitCount(setfalign)>1)) + { + printf("Bad file alignment\n"); + exit(1); + } + gotfalign=TRUE; + } + else + { + printf("Invalid switch %s\n",newargs[i].c_str()); + exit(1); + } + } + else + { + printf("Invalid switch %s\n",newargs[i].c_str()); + exit(1); + } + break; + case 'd': + if(!strcmp(&newargs[i][1],"dll")) + { + buildDll=TRUE; + } + else + { + printf("Invalid switch %s\n",newargs[i].c_str()); + exit(1); + } + break; + case 'e': + if(!strcmp(&newargs[i][1],"entry")) + { + if(i<(newargs.size()-1)) + { + i++; + entryPoint=newargs[i]; + } + else + { + printf("Invalid switch %s\n",newargs[i].c_str()); + exit(1); + } + } + else + { + printf("Invalid switch %s\n",newargs[i].c_str()); + exit(1); + } + break; + + default: + printf("Invalid switch %s\n",newargs[i].c_str()); + exit(1); + } + } + else + { + std::string newfilename = newargs[i]; + if(newfilename.find('.') == std::string::npos) + newfilename += DEFAULT_EXTENSION; + filename.push_back(newfilename); + } + } + if(helpRequested || !filename.size()) + { + printf("Usage: ALINK [file [file [...]]] [options]\n"); + printf("\n"); + printf(" Each file may be an object file, a library, or a Win32 resource\n"); + printf(" file. If no extension is specified, .obj is assumed. Modules are\n"); + printf(" only loaded from library files if they are required to match an\n"); + printf(" external reference.\n"); + printf(" Options and files may be listed in any order, all mixed together.\n"); + printf("\n"); + printf("The following options are permitted:\n"); + printf("\n"); + printf(" @name Load additional options from response file name\n"); + printf(" -c Enable Case sensitivity\n"); + printf(" -c+ Enable Case sensitivity\n"); + printf(" -c- Disable Case sensitivity\n"); + printf(" -p Enable segment padding\n"); + printf(" -p+ Enable segment padding\n"); + printf(" -p- Disable segment padding\n"); + printf(" -m Enable map file\n"); + printf(" -m+ Enable map file\n"); + printf(" -m- Disable map file\n"); + printf("----Press Enter to continue---"); + while(((c=getchar())!='\n') && (c!=EOF)); + printf("\n"); + printf(" -h Display this help list\n"); + printf(" -H \"\n"); + printf(" -? \"\n"); + printf(" -L ddd Add directory ddd to search list\n"); + printf(" -o name Choose output file name\n"); + printf(" -oXXX Choose output format XXX\n"); + printf(" Available options are:\n"); + printf(" COM - MSDOS COM file\n"); + printf(" EXE - MSDOS EXE file\n"); + printf(" PE - Win32 PE Executable\n"); + printf(" -entry name Use public symbol name as the entry point\n"); + printf("\nOptions for PE files:\n"); + printf(" -base addr Set base address of image\n"); + printf(" -filealign addr Set section alignment in file\n"); + printf(" -objectalign addr Set section alignment in memory\n"); + printf(" -subsys xxx Set subsystem used\n"); + printf(" Available options are:\n"); + printf(" console Select character mode\n"); + printf(" con \"\n"); + printf(" char \"\n"); + printf(" windows Select windowing mode\n"); + printf(" win \"\n"); + printf(" gui \"\n"); + printf(" native Select native mode\n"); + printf(" posix Select POSIX mode\n"); + printf(" -subsysver x.y Select subsystem version x.y\n"); + printf(" -osver x.y Select OS version x.y\n"); + printf(" -stub xxx Use xxx as the MSDOS stub\n"); + printf(" -dll Build DLL instead of EXE\n"); + printf(" -stacksize xxx Set stack size to xxx\n"); + printf(" -stackcommitsize xxx Set stack commit size to xxx\n"); + printf(" -heapsize xxx Set heap size to xxx\n"); + printf(" -heapcommitsize xxx Set heap commit size to xxx\n"); + exit(0); + } + if((output_type!=OUTPUT_PE) && + (gotoalign || gotfalign || gotbase || gotsubsys || gotstack || + gotstackcommit || gotheap || gotheapcommit || buildDll || stubName.size() || + gotsubsysver || gotosver)) + { + printf("Option not supported for non-PE output formats\n"); + exit(1); + } + if(gotstack) + { + stackSize=setstack; + } + if(gotstackcommit) + { + stackCommitSize=setstackcommit; + } + if(stackCommitSize>stackSize) + { + printf("Stack commit size is greater than stack size, committing whole stack\n"); + stackCommitSize=stackSize; + } + if(gotheap) + { + heapSize=setheap; + } + if(gotheapcommit) + { + heapCommitSize=setheapcommit; + } + if(heapCommitSize>heapSize) + { + printf("Heap commit size is greater than heap size, committing whole heap\n"); + heapCommitSize=heapSize; + } + if(gotoalign) + { + objectAlign=setoalign; + } + if(gotfalign) + { + fileAlign=setfalign; + } + if(gotbase) + { + imageBase=setbase; + } + if(gotsubsys) + { + subSystem=setsubsys; + } + if(gotsubsysver) + { + subsysMajor=setsubsysmajor; + subsysMinor=setsubsysminor; + } + if(gotosver) + { + osMajor=setosmajor; + osMinor=setosminor; + } +} + +void matchExterns() +{ + long i,j,old_nummods,k; + int n; + std::string name; + SORTLIST::iterator listnode, l; + PPUBLIC pubdef; + + do + { + for(i=0;isecond.size();k++) + { + /* exports can only match global publics */ + if(((PPUBLIC)listnode->second[k])->modnum==0) + { + expdefs[i].pubdef=(PPUBLIC)listnode->second[k]; + break; + } + } + } + } + for(i=0;isecond.size();k++) + { + /* local publics can only match externs in same module */ + /* and global publics can only match global externs */ + if(((PPUBLIC)listnode->second[k])->modnum==externs[i].modnum) + { + externs[i].pubdef=(PPUBLIC)listnode->second[k]; + externs[i].flags=EXT_MATCHEDPUBLIC; + break; + } + } + } + if(externs[i].flags==EXT_NOMATCH) + { + for(j=0;jsecond.size()); + break; + } + } + } + } + for(i=0;(isecond.size()); + break; + } + } + } + } + for(l=publics.begin(); + (l!=publics.end())&&(modname.size()==old_nummods); + ++l) + { + for(k=0;ksecond.size();k++) + { + pubdef=(PPUBLIC)l->second[k]; + if(pubdef->aliasName == "") continue; + if((listnode=publics.find(pubdef->aliasName)) != publics.end()) + { + for(j=0;jsecond.size();j++) + { + if((((PPUBLIC)listnode->second[j])->modnum==pubdef->modnum) + && ((PPUBLIC)listnode->second[j])->aliasName == "") + { + /* if we've found a match for the alias, then kill the alias */ + (*pubdef)=(*((PPUBLIC)listnode->second[j])); + break; + } + } + } + if(pubdef->aliasName == "") continue; + for(k=0;kaliasName; + if(!(libfiles[k].flags&LIBF_CASESENSITIVE)) + { + strupr(name); + } + + if((listnode=libfiles[k].symbols.find(name)) != libfiles[k].symbols.end()) + { + loadlibmod(k,listnode->second.size()); + break; + } + } + + } + } + + } while (old_nummods!=modname.size()); +} + +void matchComDefs() +{ + int i,j,k; + int comseg; + int comfarseg; + SORTLIST::iterator listnode; + PPUBLIC pubdef; + + if(!comdefs.size()) return; + + for(i=0;imodnum!=comdefs[j]->modnum) continue; + if(comdefs[i]->name == comdefs[j]->name) + { + if(comdefs[i]->isFar!=comdefs[j]->isFar) + { + printf("Mismatched near/far type for COMDEF %s\n",comdefs[i]->name.c_str()); + exit(1); + } + if(comdefs[i]->length>comdefs[j]->length) + comdefs[j]->length=comdefs[i]->length; + free(comdefs[i]); + comdefs[i]=0; + break; + } + } + } + + for(i=0;iname)) != publics.end()) + { + for(j=0;jsecond.size();j++) + { + /* local publics can only match externs in same module */ + /* and global publics can only match global externs */ + if((((PPUBLIC)listnode->second[j])->modnum==comdefs[i]->modnum) + && ((PPUBLIC)listnode->second[j])->aliasName == "") + { + free(comdefs[i]); + comdefs[i]=0; + break; + } + } + } + } + + PSEG seg = new SEG(); + seg->name = "COMDEFS"; + comseg=seglist.size(); + seglist.push_back(seg); + + for(i=0;iname == "") continue; + if(grplist[i]->name != "DGROUP") + { + if(grplist[i]->numsegs==0) continue; /* don't add to an emtpy group */ + /* because empty groups are special */ + /* else add to group */ + grplist[i]->segindex[grplist[i]->numsegs]=seglist[comseg]; + grplist[i]->numsegs++; + break; + } + } + + seg = new SEG(); + seg->name = "FARCOMDEFS"; + comfarseg=seglist.size(); + seglist.push_back(seg); + + for(i=0;iisFar) + { + if(comdefs[i]->length>65536) + { + seg = new SEG(); + seg->name = "FARCOMDEFS"; + seg->length=comdefs[i]->length; + seg->datmask.resize((comdefs[i]->length+7)/8); + for(j=0;j<(comdefs[i]->length+7)/8;j++) + seglist[seglist.size()-1]->datmask[j]=0; + pubdef->seg=seglist[seglist.size()-1]; + seglist.push_back(seg); + pubdef->ofs=0; + } + else if((comdefs[i]->length+seglist[comfarseg]->length)>65536) + { + seglist[comfarseg]->datmask.resize((seglist[comfarseg]->length+7)/8); + for(j=0;j<(seglist[comfarseg]->length+7)/8;j++) + seglist[comfarseg]->datmask[j]=0; + + seg = new SEG(); + seg->name = "FARCOMDEFS"; + seg->length=comdefs[i]->length; + comfarseg=seglist.size(); + seglist.push_back(seg); + pubdef->seg=seglist[comfarseg]; + pubdef->ofs=0; + } + else + { + pubdef->seg=seglist[comfarseg]; + pubdef->ofs=seglist[comfarseg]->length; + seglist[comfarseg]->length+=comdefs[i]->length; + } + } + else + { + pubdef->seg=seglist[comseg]; + pubdef->ofs=seglist[comseg]->length; + seglist[comseg]->length+=comdefs[i]->length; + } + pubdef->modnum=comdefs[i]->modnum; + pubdef->grpnum=-1; + pubdef->typenum=0; + if((listnode=publics.find(comdefs[i]->name)) != publics.end()) + { + for(j=0;jsecond.size();++j) + { + if(((PPUBLIC)listnode->second[j])->modnum==pubdef->modnum) + { + if(((PPUBLIC)listnode->second[j])->aliasName == "") + { + printf("Duplicate public symbol %s\n",comdefs[i]->name.c_str()); + exit(1); + } + (*((PPUBLIC)listnode->second[j]))=(*pubdef); + pubdef=NULL; + break; + } + } + } + if(pubdef) + { + SORTLIST::iterator it = publics.find(comdefs[i]->name); + if(it == publics.end()) + { + std::vector vv; + vv.push_back((void *)pubdef); + publics.insert(std::make_pair(comdefs[i]->name, vv)); + } else { + it->second.push_back((void *)pubdef); + } + } + } + seglist[comfarseg]->datmask.reserve((seglist[comfarseg]->length+7)/8); + for(j=0;j<(seglist[comfarseg]->length+7)/8;j++) + seglist[comfarseg]->datmask[j]=0; + + + seglist[comseg]->datmask.reserve((seglist[comseg]->length+7)/8); + for(j=0;j<(seglist[comseg]->length+7)/8;j++) + seglist[comseg]->datmask[j]=0; + + + for(i=0;isecond.size();j++) + { + /* global publics only can match exports */ + if(((PPUBLIC)listnode->second[j])->modnum==0) + { + expdefs[i].pubdef=(PPUBLIC)listnode->second[j]; + break; + } + } + } + } + for(i=0;isecond.size();j++) + { + /* global publics only can match exports */ + if(((PPUBLIC)(listnode->second[j]))->modnum==externs[i].modnum) + { + externs[i].pubdef=(PPUBLIC)(listnode->second[j]); + externs[i].flags=EXT_MATCHEDPUBLIC; + break; + } + } + } + } +} + +void sortSegments() +{ + long i,j; + PSEG k, baseSeg; + UINT base=0,align; + + for(i=0;iattr&SEG_ALIGN)!=SEG_ABS) + { + seglist[i]->absframe=0; + } + } + } + + for(i=0;iseg=NULL; + for(j=0;jnumsegs;j++) + { + k=grplist[i]->segindex[j]; + if(!k) + { + printf("Error - group %s contains non-existent segment\n",grplist[i]->name.c_str()); + exit(1); + } + /* don't add removed sections */ + if(k->winFlags & WINF_REMOVE) + { + continue; + } + /* add non-absolute segment */ + if((k->attr&SEG_ALIGN)!=SEG_ABS) + { + switch(k->attr&SEG_ALIGN) + { + case SEG_WORD: + align=2; + break; + case SEG_DWORD: + align=4; + break; + case SEG_8BYTE: + align=0x8; + break; + case SEG_PARA: + align=0x10; + break; + case SEG_32BYTE: + align=0x20; + break; + case SEG_64BYTE: + align=0x40; + break; + case SEG_PAGE: + align=0x100; + break; + case SEG_MEMPAGE: + align=0x1000; + break; + case SEG_BYTE: + default: + align=1; + break; + } + if(alignsetbase(base); + if(k->length>0) + { + base+=k->length; + if(k->absframe!=0) + { + printf("Error - Segment %s part of more than one group\n",k->name.c_str()); + exit(1); + } + k->absframe=1; + k->absofs=i+1; + if(!grplist[i]->seg) + { + grplist[i]->seg=k; + } + if(outlist.size()==0) + { + baseSeg=k; + } + else + { + outlist[outlist.size()-1]->virtualSize=k->getbase()- + outlist[outlist.size()-1]->getbase(); + } + outlist.push_back(k); + } + } + } + } + } + for(i=0;iwinFlags & WINF_REMOVE) + { + continue; + } + /* add non-absolute segment, not already dealt with */ + if(((seglist[i]->attr&SEG_ALIGN)!=SEG_ABS) && + !seglist[i]->absframe) + { + switch(seglist[i]->attr&SEG_ALIGN) + { + case SEG_WORD: + case SEG_BYTE: + case SEG_DWORD: + case SEG_PARA: + align=0x10; + break; + case SEG_PAGE: + align=0x100; + break; + case SEG_MEMPAGE: + align=0x1000; + break; + default: + align=1; + break; + } + if(alignsetbase(base); + if(seglist[i]->length>0) + { + base+=seglist[i]->length; + seglist[i]->absframe=1; + seglist[i]->absofs=0; + if(outlist.size()==0) + { + baseSeg=seglist[i]; + } + else + { + outlist[outlist.size()-1]->virtualSize=seglist[i]->getbase()- + outlist[outlist.size()-1]->getbase(); + } + outlist.push_back(seglist[i]); + } + } + else if((seglist[i]->attr&SEG_ALIGN)==SEG_ABS) + { + seglist[i]->setbase((seglist[i]->absframe<<4)+seglist[i]->absofs); + } + } + } + /* build size of last segment in output list */ + if(outlist.size()) + { + outlist[outlist.size()-1]->virtualSize= + (outlist[outlist.size()-1]->length+objectAlign-1)& + (0xffffffff-(objectAlign-1)); + } + for(i=0;iseg)) grplist[i]->seg=baseSeg; + } +} + +void printRelocs(FILE *afile) +{ + int i; + + if(relocs.size()) + { + INT_TO_NAME disptypes[] = { + { REL_SEGDISP, "REL_SEGDISP" }, + { REL_GRPDISP, "REL_GRPDISP" }, + { REL_EXTDISP, "REL_EXTDISP" }, + { REL_EXPFRAME, "REL_EXPFRAME" }, + { REL_SEGONLY, "REL_SEGONLY" }, + { REL_GRPONLY, "REL_GRPONLY" }, + { REL_EXTONLY, "REL_EXTONLY" }, + { 0 } + }; + + INT_TO_NAME frametypes[] = { + { REL_SEGFRAME, "REL_SEGFRAME" }, + { REL_GRPFRAME, "REL_GRPFRAME" }, + { REL_EXTFRAME, "REL_EXTFRAME" }, + { REL_LILEFRAME,"REL_LILEFRAME"}, + { REL_TARGETFRAME,"REL_TARGETFRAME"}, + { 0 } + }; + + INT_TO_NAME reloctype[] = { + { FIX_LBYTE, "FIX_LBYTE" }, + { FIX_OFS16, "FIX_OFS16" }, + { FIX_BASE, "FIX_BASE" }, + { FIX_PTR1616, "FIX_PTR1616" }, + { FIX_HBYTE, "FIX_HBYTE" }, + { FIX_OFS16_2, "FIX_OFS16_2" }, + { FIX_OFS32, "FIX_OFS32" }, + { FIX_PTR1632, "FIX_PTR1632" }, + { FIX_RVA32, "FIX_RVA32" }, + { FIX_REL32, "FIX_REL32" }, + { FIX_PPC_ADDR24, "FIX_PPC_ADDR24" }, + { FIX_PPC_REL24, "FIX_PPC_REL24" }, + { FIX_PPC_RVA16LO, "FIX_PPC_RVA16LO" }, + { FIX_PPC_RVA16HA, "FIX_PPC_RVA16HA" }, + { FIX_PPC_SECTOFF, "FIX_PPC_SECTOFF" }, + { 0 } + }; + + fprintf(afile,"\n %li relocs:\n",relocs.size()); + for(i=0;i %-10s(%d) type %-16s(%d) ofs %08x disp %08x" + " | frame (%-10s) target (%-10s)" + " | addr %08x off %08x info %08x\n", + findName(frametypes, relocs[i]->ftype), + relocs[i]->ftype, + findName(disptypes, relocs[i]->ttype), + relocs[i]->ttype, + findName(reloctype, relocs[i]->rtype), + relocs[i]->rtype, + relocs[i]->ofs, + relocs[i]->disp, + (relocs[i]->seg ? + relocs[i]->seg->name.c_str() : + externs[relocs[i]->frame].name.c_str()), + (relocs[i]->targseg ? + relocs[i]->targseg->name.c_str() : + externs[relocs[i]->target].name.c_str()), + relocs[i]->orig.r_address, + relocs[i]->orig.r_offset, + relocs[i]->orig.r_info); + } + } +} + +void loadFiles() +{ + long i,j,k; + std::string name; + + for(i=0;iname.c_str()); + switch(seglist[i]->attr&SEG_COMBINE) + { + case SEG_PRIVATE: + fprintf(afile,"PRIVATE "); + break; + case SEG_PUBLIC: + fprintf(afile,"PUBLIC "); + break; + case SEG_PUBLIC2: + fprintf(afile,"PUBLIC(2) "); + break; + case SEG_STACK: + fprintf(afile,"STACK "); + break; + case SEG_COMMON: + fprintf(afile,"COMMON "); + break; + case SEG_PUBLIC3: + fprintf(afile,"PUBLIC(3) "); + break; + default: + fprintf(afile,"unknown "); + break; + } + if(seglist[i]->attr&SEG_USE32) + { + fprintf(afile,"USE32 "); + } + else + { + fprintf(afile,"USE16 "); + } + switch(seglist[i]->attr&SEG_ALIGN) + { + case SEG_ABS: + fprintf(afile,"AT 0%04lXh ",seglist[i]->absframe); + break; + case SEG_BYTE: + fprintf(afile,"BYTE "); + break; + case SEG_WORD: + fprintf(afile,"WORD "); + break; + case SEG_PARA: + fprintf(afile,"PARA "); + break; + case SEG_PAGE: + fprintf(afile,"PAGE "); + break; + case SEG_DWORD: + fprintf(afile,"DWORD "); + break; + case SEG_MEMPAGE: + fprintf(afile,"MEMPAGE "); + break; + default: + fprintf(afile,"unknown "); + } + if(seglist[i]->classindex>=0) + fprintf(afile,"'%s'\n",namelist[seglist[i]->classindex].c_str()); + else + fprintf(afile,"\n"); + fprintf(afile," at %08lX, length %08lX\n", + (output_type == OUTPUT_PE) ? + seglist[i]->getbase() + objectAlign + imageBase : + seglist[i]->getbase(), + seglist[i]->length); + } + } + for(i=0;iname.c_str()); + for(j=0;jnumsegs;j++) + { + fprintf(afile," %s\n",grplist[i]->segindex[j]->name.c_str()); + } + } + + if(publics.size()) + { + fprintf(afile,"\npublics:\n"); + } + for(l=publics.begin();l!=publics.end();++l) + { + for(j=0;jsecond.size();++j) + { + q=(PPUBLIC)l->second[j]; + if(q->modnum) continue; + fprintf(afile,"%s at %s:%08lX\n", + l->first.c_str(), + (q->seg) ? q->seg->name.c_str() : "Absolute", + q->ofs); + } + } + + printRelocs(afile); + + if(expdefs.size()) + { + fprintf(afile,"\n %li exports:\n",expdefs.size()); + for(i=0;i=0)&&(outname[i]!='.')&&(outname[i]!=PATH_CHAR)&&(outname[i]!=':')) + { + i--; + } + if(outname[i]=='.') + { + outname[i]=0; + } + } + i=outname.size(); + while((i>=0)&&(outname[i]!='.')&&(outname[i]!=PATH_CHAR)&&(outname[i]!=':')) + { + i--; + } + if(outname[i]!='.') + { + switch(output_type) + { + case OUTPUT_EXE: + case OUTPUT_PE: + if(!buildDll) + { + outname += ".exe"; + } + else + { + outname += ".dll"; + } + break; + case OUTPUT_COM: + outname += ".com"; + break; + default: + break; + } + } + + if(mapfile) + { + if(!mapname.size()) + { + mapname = outname; + while((i>=0)&&(mapname[i]!='.')&&(mapname[i]!=PATH_CHAR)&&(mapname[i]!=':')) + { + i--; + } + if(mapname[i]!='.') + { + i=mapname.size(); + } + mapname += ".map"; + } + } + else + { + if(mapname.size()) + { + mapname=""; + } + } + + loadFiles(); + + if(!modname.size()) + { + printf("No required modules specified\n"); + exit(1); + } + + if(resource.size() && (output_type!=OUTPUT_PE)) + { + printf("Cannot link resources into a non-PE application\n"); + exit(1); + } + + if(entryPoint.size()) + { + if(!case_sensitive) + { + strupr(entryPoint); + } + + if(gotstart) + { + printf("Warning, overriding entry point from Command Line\n"); + } + /* define an external reference for entry point */ + externs.push_back(EXTREC(entryPoint)); + + /* point start address to this external */ + startaddr.ftype=REL_EXTFRAME; /* REL_EXTDISP ? */ + startaddr.frame=externs.size()-1; + startaddr.ttype=REL_EXTONLY; + startaddr.target=externs.size()-1; + + gotstart=TRUE; + } + + matchExterns(); + printf("matched Externs\n"); + + matchComDefs(); + printf("matched ComDefs\n"); + + for(i=0;ialiasName.c_str() != "") + { + printf("Unresolved export %s=%s, with alias %s\n",expdefs[i].exp_name.c_str(),expdefs[i].int_name.c_str(),(char *)expdefs[i].pubdef->aliasName.c_str()); + errcount++; + } + + } + + for(i=0;ialiasName != "") + { + printf("Unresolved external %s with alias %s\n",externs[i].name.c_str(),externs[i].pubdef->aliasName.c_str()); + errcount++; + } + } + } + + if(errcount!=0) + { + exit(1); + } + + combineBlocks(); + sortSegments(); + + if(mapfile) generateMap(); + switch(output_type) + { + case OUTPUT_COM: + OutputCOMfile(outname); + break; + case OUTPUT_EXE: + OutputEXEfile(outname); + break; + case OUTPUT_PE: + OutputWin32file(outname); + break; + default: + printf("Invalid output type\n"); + exit(1); + break; + } + return 0; +} diff --git a/reactos/tools/ppc-build/alink/alink.h b/reactos/tools/ppc-build/alink/alink.h new file mode 100644 index 00000000000..86f032ab8da --- /dev/null +++ b/reactos/tools/ppc-build/alink/alink.h @@ -0,0 +1,956 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef unsigned char UCHAR; +typedef unsigned short USHORT; +typedef unsigned long ULONG; + +#define typeid x_typeid +#define class x_class +#define stricmp strcasecmp + +#define TRUE (1==1) +#define FALSE (1==0) + +#define SWITCHCHAR '-' +#define PATH_CHAR '\\' +#define DEFAULT_EXTENSION ".obj" + +#define ERR_EXTRA_DATA 1 +#define ERR_NO_HEADER 2 +#define ERR_NO_RECDATA 3 +#define ERR_NO_MEM 4 +#define ERR_INV_DATA 5 +#define ERR_INV_SEG 6 +#define ERR_BAD_FIXUP 7 +#define ERR_BAD_SEGDEF 8 +#define ERR_ABS_SEG 9 +#define ERR_DUP_PUBLIC 10 +#define ERR_NO_MODEND 11 +#define ERR_EXTRA_HEADER 12 +#define ERR_UNKNOWN_RECTYPE 13 +#define ERR_SEG_TOO_LARGE 14 +#define ERR_MULTIPLE_STARTS 15 +#define ERR_BAD_GRPDEF 16 +#define ERR_OVERWRITE 17 +#define ERR_INVALID_COMENT 18 +#define ERR_ILLEGAL_IMPORTS 19 + +#define PREV_LE 1 +#define PREV_LI 2 +#define PREV_LI32 3 + +#define THEADR 0x80 +#define LHEADR 0x82 +#define COMENT 0x88 +#define MODEND 0x8a +#define MODEND32 0x8b +#define EXTDEF 0x8c +#define TYPDEF 0x8e +#define PUBDEF 0x90 +#define PUBDEF32 0x91 +#define LINNUM 0x94 +#define LINNUM32 0x95 +#define LNAMES 0x96 +#define SEGDEF 0x98 +#define SEGDEF32 0x99 +#define GRPDEF 0x9a +#define FIXUPP 0x9c +#define FIXUPP32 0x9d +#define LEDATA 0xa0 +#define LEDATA32 0xa1 +#define LIDATA 0xa2 +#define LIDATA32 0xa3 +#define COMDEF 0xb0 +#define BAKPAT 0xb2 +#define BAKPAT32 0xb3 +#define LEXTDEF 0xb4 +#define LEXTDEF32 0xb5 +#define LPUBDEF 0xb6 +#define LPUBDEF32 0xb7 +#define LCOMDEF 0xb8 +#define CEXTDEF 0xbc +#define COMDAT 0xc2 +#define COMDAT32 0xc3 +#define LINSYM 0xc4 +#define LINSYM32 0xc5 +#define ALIAS 0xc6 +#define NBKPAT 0xc8 +#define NBKPAT32 0xc9 +#define LLNAMES 0xca +#define LIBHDR 0xf0 +#define LIBEND 0xf1 + +#define COMENT_TRANSLATOR 0x00 +#define COMENT_INTEL_COPYRIGHT 0x01 +#define COMENT_LIB_SPEC 0x81 +#define COMENT_MSDOS_VER 0x9c +#define COMENT_MEMMODEL 0x9d +#define COMENT_DOSSEG 0x9e +#define COMENT_DEFLIB 0x9f +#define COMENT_OMFEXT 0xa0 +#define COMENT_NEWOMF 0xa1 +#define COMENT_LINKPASS 0xa2 +#define COMENT_LIBMOD 0xa3 +#define COMENT_EXESTR 0xa4 +#define COMENT_INCERR 0xa6 +#define COMENT_NOPAD 0xa7 +#define COMENT_WKEXT 0xa8 +#define COMENT_LZEXT 0xa9 +#define COMENT_PHARLAP 0xaa +#define COMENT_IBM386 0xb0 +#define COMENT_RECORDER 0xb1 +#define COMENT_COMMENT 0xda +#define COMENT_COMPILER 0xdb +#define COMENT_DATE 0xdc +#define COMENT_TIME 0xdd +#define COMENT_USER 0xdf +#define COMENT_DEPFILE 0xe9 +#define COMENT_COMMANDLINE 0xff +#define COMENT_PUBTYPE 0xe1 +#define COMENT_COMPARAM 0xea +#define COMENT_TYPDEF 0xe3 +#define COMENT_STRUCTMEM 0xe2 +#define COMENT_OPENSCOPE 0xe5 +#define COMENT_LOCAL 0xe6 +#define COMENT_ENDSCOPE 0xe7 +#define COMENT_SOURCEFILE 0xe8 + +#define EXT_IMPDEF 0x01 +#define EXT_EXPDEF 0x02 + +#define SEG_ALIGN 0x3e0 +#define SEG_COMBINE 0x1c +#define SEG_BIG 0x02 +#define SEG_USE32 0x01 + +#define SEG_ABS 0x00 +#define SEG_BYTE 0x20 +#define SEG_WORD 0x40 +#define SEG_PARA 0x60 +#define SEG_PAGE 0x80 +#define SEG_DWORD 0xa0 +#define SEG_MEMPAGE 0xc0 +#define SEG_BADALIGN 0xe0 +#define SEG_8BYTE 0x100 +#define SEG_32BYTE 0x200 +#define SEG_64BYTE 0x300 + +#define SEG_PRIVATE 0x00 +#define SEG_PUBLIC 0x08 +#define SEG_PUBLIC2 0x10 +#define SEG_STACK 0x14 +#define SEG_COMMON 0x18 +#define SEG_PUBLIC3 0x1c + +typedef enum segdisp_t { +//#define REL_SEGDISP 0x80 + REL_SEGDISP = 0x80, +//#define REL_GRPDISP 0x81 + REL_GRPDISP = 0x81, +//#define REL_EXTDISP 0x82 + REL_EXTDISP = 0x82, +//#define REL_EXPFRAME 0x83 + REL_EXPFRAME = 0x83, +//#define REL_SEGONLY 0x84 + REL_SEGONLY = 0x84, +//#define REL_GRPONLY 0x85 + REL_GRPONLY = 0x85, +//#define REL_EXTONLY 0x86 + REL_EXTONLY = 0x86 +} segdisp_t; + +typedef enum segframe_t { +//#define REL_SEGFRAME 0 + REL_SEGFRAME, +//#define REL_GRPFRAME 1 + REL_GRPFRAME, +//#define REL_EXTFRAME 2 + REL_EXTFRAME, +//#define REL_EXPFFRAME 3 + REL_EXPFFRAME, +//#define REL_LILEFRAME 4 + REL_LILEFRAME, +//#define REL_TARGETFRAME 5 + REL_TARGETFRAME +}; + +#define FIX_SELFREL 0x10 +#define FIX_MASK (0x0f+FIX_SELFREL) + +#define FIX_THRED 0x08 +#define THRED_MASK 0x07 + +#define FIX_LBYTE 0 +#define FIX_OFS16 1 +#define FIX_BASE 2 +#define FIX_PTR1616 3 +#define FIX_HBYTE 4 +#define FIX_OFS16_2 5 +#define FIX_OFS32 9 +#define FIX_PTR1632 11 +#define FIX_OFS32_2 13 + +#define FIX_PPC_ADDR24 259 +#define FIX_PPC_REL24 260 +#define FIX_PPC_RVA16LO 261 +#define FIX_PPC_RVA16HA 262 +#define FIX_PPC_SECTOFF 263 + +/* RVA32 fixups are not supported by OMF, so has an out-of-range number */ +#define FIX_RVA32 256 +#define FIX_REL32 264 +#define FIX_ADDR32 265 + +#define FIX_SELF_LBYTE (FIX_LBYTE+FIX_SELFREL) +#define FIX_SELF_OFS16 (FIX_OFS16+FIX_SELFREL) +#define FIX_SELF_OFS16_2 (FIX_OFS16_2+FIX_SELFREL) +#define FIX_SELF_OFS32 (FIX_OFS32+FIX_SELFREL) +#define FIX_SELF_OFS32_2 (FIX_OFS32_2+FIX_SELFREL) + +#define LIBF_CASESENSITIVE 1 + +#define EXT_NOMATCH 0 +#define EXT_MATCHEDPUBLIC 1 +#define EXT_MATCHEDIMPORT 2 + +#define PE_SIGNATURE 0x00 +#define PE_MACHINEID 0x04 +#define PE_NUMOBJECTS 0x06 +#define PE_DATESTAMP 0x08 +#define PE_SYMBOLPTR 0x0c +#define PE_NUMSYMBOLS 0x10 +#define PE_HDRSIZE 0x14 +#define PE_FLAGS 0x16 +#define PE_MAGIC 0x18 +#define PE_LMAJOR 0x1a +#define PE_LMINOR 0x1b +#define PE_CODESIZE 0x1c +#define PE_INITDATASIZE 0x20 +#define PE_UNINITDATASIZE 0x24 +#define PE_ENTRYPOINT 0x28 +#define PE_CODEBASE 0x2c +#define PE_DATABASE 0x30 +#define PE_IMAGEBASE 0x34 +#define PE_OBJECTALIGN 0x38 +#define PE_FILEALIGN 0x3c +#define PE_OSMAJOR 0x40 +#define PE_OSMINOR 0x42 +#define PE_USERMAJOR 0x44 +#define PE_USERMINOR 0x46 +#define PE_SUBSYSMAJOR 0x48 +#define PE_SUBSYSMINOR 0x4a +#define PE_IMAGESIZE 0x50 +#define PE_HEADERSIZE 0x54 +#define PE_CHECKSUM 0x58 +#define PE_SUBSYSTEM 0x5c +#define PE_DLLFLAGS 0x5e +#define PE_STACKSIZE 0x60 +#define PE_STACKCOMMSIZE 0x64 +#define PE_HEAPSIZE 0x68 +#define PE_HEAPCOMMSIZE 0x6c +#define PE_LOADERFLAGS 0x70 +#define PE_NUMRVAS 0x74 +#define PE_EXPORTRVA 0x78 +#define PE_EXPORTSIZE 0x7c +#define PE_IMPORTRVA 0x80 +#define PE_IMPORTSIZE 0x84 +#define PE_RESOURCERVA 0x88 +#define PE_RESOURCESIZE 0x8c +#define PE_EXCEPTIONRVA 0x90 +#define PE_EXCEPTIONSIZE 0x94 +#define PE_SECURITYRVA 0x98 +#define PE_SECURITYSIZE 0x9c +#define PE_FIXUPRVA 0xa0 +#define PE_FIXUPSIZE 0xa4 +#define PE_DEBUGRVA 0xa8 +#define PE_DEBUGSIZE 0xac +#define PE_DESCRVA 0xb0 +#define PE_DESCSIZE 0xb4 +#define PE_MSPECRVA 0xb8 +#define PE_MSPECSIZE 0xbc +#define PE_TLSRVA 0xc0 +#define PE_TLSSIZE 0xc4 +#define PE_LOADCONFIGRVA 0xc8 +#define PE_LOADCONFIGSIZE 0xcc +#define PE_BOUNDIMPRVA 0xd0 +#define PE_BOUNDIMPSIZE 0xd4 +#define PE_IATRVA 0xd8 +#define PE_IATSIZE 0xdc + +#define PE_OBJECT_NAME 0x00 +#define PE_OBJECT_VIRTSIZE 0x08 +#define PE_OBJECT_VIRTADDR 0x0c +#define PE_OBJECT_RAWSIZE 0x10 +#define PE_OBJECT_RAWPTR 0x14 +#define PE_OBJECT_RELPTR 0x18 +#define PE_OBJECT_LINEPTR 0x1c +#define PE_OBJECT_NUMREL 0x20 +#define PE_OBJECT_NUMLINE 0x22 +#define PE_OBJECT_FLAGS 0x24 + +#define PE_BASE_HEADER_SIZE 0x18 +#define PE_OPTIONAL_HEADER_SIZE 0xe0 +#define PE_OBJECTENTRY_SIZE 0x28 +#define PE_HEADBUF_SIZE (PE_BASE_HEADER_SIZE+PE_OPTIONAL_HEADER_SIZE) +#define PE_IMPORTDIRENTRY_SIZE 0x14 +#define PE_NUM_VAS 0x10 +#define PE_EXPORTHEADER_SIZE 0x28 +#define PE_RESENTRY_SIZE 0x08 +#define PE_RESDIR_SIZE 0x10 +#define PE_RESDATAENTRY_SIZE 0x10 +#define PE_SYMBOL_SIZE 0x12 +#define PE_RELOC_SIZE 0x0a + +#define PE_ORDINAL_FLAG 0x80000000 +#define PE_INTEL386 0x014c +#define PE_POWERPC 0x01f0 +#define PE_MAGICNUM 0x010b +#define PE_FILE_EXECUTABLE 0x0002 +#define PE_FILE_32BIT 0x0100 +#define PE_FILE_LIBRARY 0x2000 + +#define PE_REL_LOW16 0x2000 +#define PE_REL_OFS32 0x3000 + +#define PE_SUBSYS_NATIVE 1 +#define PE_SUBSYS_WINDOWS 2 +#define PE_SUBSYS_CONSOLE 3 +#define PE_SUBSYS_POSIX 7 + +//seglist[0]->nameindex=0 o=-1 l=38 a=140 f=00100a00 +//seglist[1]->nameindex=1 o=-1 l=8 a=178 f=60400020 +//seglist[2]->nameindex=2 o=-1 l=20 a=186 f=40300040 + +#define WINF_UNDEFINED 0x00000000 +#define WINF_CODE 0x00000020 +#define WINF_INITDATA 0x00000040 +#define WINF_UNINITDATA 0x00000080 +#define WINF_DISCARDABLE 0x02000000 +#define WINF_NOPAGE 0x08000000 +#define WINF_SHARED 0x10000000 +#define WINF_EXECUTE 0x20000000 +#define WINF_READABLE 0x40000000 +#define WINF_WRITEABLE 0x80000000 +#define WINF_ALIGN_NOPAD 0x00000008 +#define WINF_ALIGN_BYTE 0x00100000 +#define WINF_ALIGN_WORD 0x00200000 +#define WINF_ALIGN_DWORD 0x00300000 +#define WINF_ALIGN_8 0x00400000 +#define WINF_ALIGN_PARA 0x00500000 +#define WINF_ALIGN_32 0x00600000 +#define WINF_ALIGN_64 0x00700000 +#define WINF_ALIGN (WINF_ALIGN_64) +#define WINF_COMMENT 0x00000200 +#define WINF_REMOVE 0x00000800 +#define WINF_COMDAT 0x00001000 +#define WINF_NEG_FLAGS (WINF_DISCARDABLE | WINF_NOPAGE) +#define WINF_IMAGE_FLAGS 0xfa0008e0 + +#define COFF_SYM_EXTERNAL 2 +#define COFF_SYM_STATIC 3 +#define COFF_SYM_LABEL 6 +#define COFF_SYM_FUNCTION 101 +#define COFF_SYM_FILE 103 +#define COFF_SYM_SECTION 104 + +#define COFF_FIX_DIR32 6 +#define COFF_FIX_RVA32 7 +#define COFF_FIX_REL32 0x14 + +#define R_PPC_ADDR32 1 +#define R_PPC_ADDR24 2 +#define R_PPC_ADDR16 3 +#define R_PPC_ADDR16_LO 4 +#define R_PPC_ADDR16_HI 5 +#define R_PPC_ADDR16_HA 6 +#define R_PPC_REL24 10 +#define R_PPC_UADDR32 24 +#define R_PPC_REL32 26 +#define R_PPC_SECTOFF 33 + +#define IMAGE_REL_PPC_ABSOLUTE 0x00 +#define IMAGE_REL_PPC_ADDR64 0x01 +#define IMAGE_REL_PPC_ADDR32 0x02 +#define IMAGE_REL_PPC_ADDR24 0x03 +#define IMAGE_REL_PPC_ADDR16 0x04 +#define IMAGE_REL_PPC_ADDR14 0x05 +#define IMAGE_REL_PPC_REL24 0x06 +#define IMAGE_REL_PPC_REL14 0x07 +#define IMAGE_REL_PPC_ADDR32NB 0x0a +#define IMAGE_REL_PPC_SECREL 0x0b +#define IMAGE_REL_PPC_SECTION 0x0c +#define IMAGE_REL_PPC_SECREL16 0x0f +#define IMAGE_REL_PPC_REFHI 0x10 +#define IMAGE_REL_PPC_REFLO 0x11 +#define IMAGE_REL_PPC_PAIR 0x12 +#define IMAGE_REL_PPC_SECRELLO 0x13 +#define IMAGE_REL_PPC_SECRELHI 0x14 +#define IMAGE_REL_PPC_GPREL 0x15 + +#define OUTPUT_COM 1 +#define OUTPUT_EXE 2 +#define OUTPUT_PE 3 + +#define WIN32_DEFAULT_BASE 0x00400000 +#define WIN32_DEFAULT_FILEALIGN 0x00000200 +#define WIN32_DEFAULT_OBJECTALIGN 0x00001000 +#define WIN32_DEFAULT_STACKSIZE 0x00100000 +#define WIN32_DEFAULT_STACKCOMMITSIZE 0x00001000 +#define WIN32_DEFAULT_HEAPSIZE 0x00100000 +#define WIN32_DEFAULT_HEAPCOMMITSIZE 0x00001000 +#define WIN32_DEFAULT_SUBSYS PE_SUBSYS_WINDOWS +#define WIN32_DEFAULT_SUBSYSMAJOR 4 +#define WIN32_DEFAULT_SUBSYSMINOR 0 +#define WIN32_DEFAULT_OSMAJOR 1 +#define WIN32_DEFAULT_OSMINOR 0 + +#define EXP_ORD 0x80 + +typedef char *PCHAR,**PPCHAR; +typedef unsigned char *PUCHAR; +typedef unsigned long UINT; + +extern UINT imageBase; +extern UINT fileAlign; +extern UINT objectAlign; +extern UINT stackSize; +extern UINT stackCommitSize; +extern UINT heapSize; +extern UINT heapCommitSize; + +template +int get32(T &vect, int offset) +{ + return vect[offset] | + (vect[offset+1] << 8) | + (vect[offset+2] << 16) | + (vect[offset+3] << 24); +} + +template +void put32(T &vect, int offset, int val) +{ + vect[offset] = val; + vect[offset+1] = val >> 8; + vect[offset+2] = val >> 16; + vect[offset+3] = val >> 24; +} + +template +int get16(T &vect, int offset) +{ + return vect[offset] | (vect[offset+1] << 8); +} + +template +void put16(T &vect, int offset, int val) +{ + vect[offset] = val; vect[offset+1] = val >> 8; +} + +template +void ClearNbit(T &mask,long i) +{ + mask[i/8]&=0xff-(1<<(i%8)); +} + +template +void SetNbit(T &mask,long i) +{ + mask[i/8]|=(1<<(i%8)); +} + +template +char GetNbit(T &mask,long i) +{ + return (mask[i/8]>>(i%8))&1; +} + +template +long GetIndex(T &buf,long *index) +{ + long i; + if(buf[*index]&0x80) + { + i=((buf[*index]&0x7f)*256)+buf[(*index)+1]; + (*index)+=2; + return i; + } + else + { + return buf[(*index)++]; + } +} + +static int roundup(int x, int align) +{ + x += align-1; + return x & ~(align-1); +} + +typedef struct __int_to_name { + int id; + const char *name; +} INT_TO_NAME, *PINT_TO_NAME; + +static const char *findName(const INT_TO_NAME *names, int id) +{ + for( int i = 0; names[i].name; i++ ) { + if(names[i].id == id) return names[i].name; + } + return ""; +} + +typedef struct __seg { +private: + UINT base; +public: + std::string name; + long classindex; + long overlayindex; + long orderindex; + UINT length; + UINT virtualSize; + UINT absframe; + UINT absofs; + UINT winFlags; + UINT fileBase; + unsigned short attr; + std::vector data; + std::vector datmask; + + __seg() { + classindex = overlayindex = orderindex = -1; + length = virtualSize = absframe = absofs = base = 0; + winFlags = WINF_READABLE | WINF_WRITEABLE | WINF_NEG_FLAGS; + attr = SEG_PRIVATE | SEG_PARA; + } + + UINT getbase() { return base; } + void setbase(UINT base) { + this->base = base; + } +} SEG, *PSEG, **PPSEG; + +typedef struct __datablock { + long count; + long blocks; + long dataofs; + std::vector data; + __datablock() { count = blocks = dataofs = 0; } +} DATABLOCK, *PDATABLOCK, **PPDATABLOCK; + +typedef struct __pubdef { + PSEG seg; + long grpnum; + long typenum; + UINT ofs; + UINT modnum; + std::string name; + std::string aliasName; + __pubdef() { + seg = 0; grpnum = typenum = ofs = modnum = 0; + } +} PUBLIC, *PPUBLIC,**PPPUBLIC; + +typedef struct __extdef { + std::string name; + long typenum; + PPUBLIC pubdef; + long impnum; + long flags; + UINT modnum; + __extdef(std::string name = "") : name(name), typenum(-1), pubdef(0), impnum(0), flags(EXT_NOMATCH), modnum(0) { } +} EXTREC, *PEXTREC,**PPEXTREC; + +typedef struct __imprec { + std::string int_name, mod_name, imp_name; + unsigned short ordinal; + char flags; + PSEG seg; + UINT abs, ofs; + __imprec() { + abs = ordinal = flags = 0; seg = 0; ofs = 0; + } +} IMPREC, *PIMPREC, **PPIMPREC; + +typedef struct __exprec { + std::string int_name, exp_name; + UINT ordinal; + char flags; + PPUBLIC pubdef; + UINT modnum; + __exprec() { + ordinal = flags = modnum = 0; + pubdef = 0; + } +} EXPREC, *PEXPREC, **PPEXPREC; + +typedef struct __comdef { + std::string name; + UINT length; + int isFar; + UINT modnum; + __comdef() { length = isFar = modnum; } +} COMREC, *PCOMREC, **PPCOMREC; + +typedef struct __elf32sym +{ + ULONG st_name; + ULONG st_value; + ULONG st_size; + UCHAR st_info; + UCHAR st_other; + USHORT st_shndx; +} ELF32SYM, *PELF32SYM; + +typedef struct __elf32rela +{ + ULONG r_offset; + ULONG r_info; + ULONG r_address; +} ELF32RELA, *PELF32RELA; + +typedef struct __elf32relx +{ + ULONG r_offset; + ULONG r_info; + ULONG r_address; + ULONG r_seg; /* Implied by section order */ +} ELF32RELX, *PELF32RELX; + +typedef struct __reloc { + UINT ofs; + segframe_t ftype; + segdisp_t ttype; + unsigned short rtype; + long target; + UINT disp; + UINT outputPos; + PSEG seg, targseg; + UINT frame; + ELF32RELX orig; + __reloc() { + frame = 0; seg = 0; targseg = 0; + ftype = REL_SEGFRAME; + ttype = REL_SEGDISP; + rtype = target = disp = outputPos = 0; + } +} RELOC, *PRELOC,**PPRELOC; + +typedef struct __grp { + std::string name; + long numsegs; + PSEG segindex[256]; + PSEG seg; + __grp() { numsegs = 0; seg = 0; memset(segindex, 0, sizeof(segindex)); } +} GRP, *PGRP, **PPGRP; + +typedef std::map > SORTLIST; +typedef struct __libfile { + std::string filename; + unsigned short blocksize; + unsigned short numdicpages; + UINT dicstart; + char flags; + char libtype; + int modsloaded; + std::vector modlist; + std::vector longnames; + SORTLIST symbols; +} LIBFILE, *PLIBFILE, **PPLIBFILE; + +typedef struct __libentry { + UINT libfile; + UINT modpage; +} LIBENTRY, *PLIBENTRY, **PPLIBENTRY; + +typedef struct __resource { + std::vector xtypename; + std::vector name; + std::vector data; + UINT length; + unsigned short typeid; + unsigned short id; + unsigned short languageid; +} RESOURCE, *PRESOURCE; + +typedef struct __coffsym { + std::string name; + UINT value; + short section; + unsigned short type; + unsigned char coff_class; + long extnum; + UINT numAuxRecs; + std::vector auxRecs; + int isComDat; + int originalSym; + PSEG segptr; + + __coffsym() { + value = numAuxRecs = extnum = isComDat = originalSym = 0; + section = 0; type = 0; + coff_class = 0; segptr = 0; + } +} COFFSYM, *PCOFFSYM; + +typedef struct __comdatrec +{ + UINT segnum; + UINT combineType; + UINT linkwith; +} COMDATREC, *PCOMDAT; + +#define EI_NIDENT 16 + +typedef struct __elf32hdr +{ + UCHAR e_ident[EI_NIDENT]; + USHORT e_type, e_machine; + ULONG e_version; + ULONG e_entry; + ULONG e_phoff; + ULONG e_shoff; + ULONG e_flags; + USHORT e_ehsize, e_phentsize; + USHORT e_phnum, e_shentsize; + USHORT e_shnum, e_shtrndx; +} ELF32HDR, *PELF32HDR; + +typedef struct __elf32shdr +{ + ULONG sh_name; + ULONG sh_type; + ULONG sh_flags; + ULONG sh_addr; + ULONG sh_offset; + ULONG sh_size; + ULONG sh_link; + ULONG sh_info; + ULONG sh_addralign; + ULONG sh_entsize; +} ELF32SHDR, *PELF32SHDR; + +#define ET_NONE 0 +#define ET_REL 1 +#define ET_EXEC 2 +#define ET_DYN 3 +#define ET_CORE 4 +#define ET_LOOS 0xfe00 +#define ET_HIOS 0xfeff +#define ET_LOPROC 0xff00 +#define ET_HIPROC 0xffff + +#define EM_NONE 0 +#define EM_M32 1 +#define EM_SPARC 2 +#define EM_386 3 +#define EM_68K 4 +#define EM_88K 5 +/* #define EM_RESERVED 6 */ +#define EM_860 7 +#define EM_MIPS 8 +/* #define EM_RESERVED 9 */ +#define EM_MIPS_RS3_LE 10 +/* #define EM_RESERVED 11-14 */ +#define EM_PARISC 15 +/* #define EM_RESERVED 16 */ +#define EM_VPP500 17 +#define EM_SPARC32PLUS 18 +#define EM_960 19 +#define EM_PPC 20 +/* #define EM_RESERVED 21-35 */ +#define EM_V800 36 +#define EM_FR20 37 +#define EM_RH32 38 +#define EM_RCE 39 +#define EM_ARM 40 +#define EM_ALPHA 41 +#define EM_SH 42 +#define EM_SPARCV9 43 +#define EM_TRICORE 44 +#define EM_ARC 45 +#define EM_H8_300 46 +#define EM_H8_300H 47 +#define EM_H8S 48 +#define EM_H8_500 49 +#define EM_IA_64 50 +#define EM_MIPPS_X 51 +#define EM_COLDFIRE 52 +#define EM_68HC12 53 + +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' + +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_UNKNOWN12 12 +#define SHT_UNKNOWN13 13 +#define SHT_INIT_ARRAY 14 +#define SHT_FINI_ARRAY 15 +#define SHT_PREINIT_ARRAY 16 +#define SHT_GROUP 17 +#define SHT_SYMTAB_SHNDX 18 +#define SHT_NUM 19 + +#define SHF_WRITE 1 +#define SHF_ALLOC 2 +#define SHF_EXECINSTR 4 + +#define STB_LOCAL 0 +#define STB_GLOBAL 1 +#define STB_WEAK 2 +#define STB_LOOS 10 +#define STB_HIOS 11 +#define STB_LOPROC 13 +#define STB_HIPROC 15 + +#define STT_FILE 4 +#define STT_COMMON 5 +#define SHN_COMMON 0xfff2 + +#define ELF32SYMSIZE 16 + +#define ELF32_ST_BIND(info) ((info) >> 4) +#define ELF32_ST_TYPE(info) ((info) & 0xf) +#define ELF32_ST_INFO(bind,type) (((bind)<<4) | ((type)&0xf)) + +#define ELF32_R_SYM(info) ((info) >> 8) +#define ELF32_R_TYPE(info) ((unsigned char)(info)) +#define ELF32_R_INFO(sym, type) (((sym)<<8)+(unsigned char)(type)) + +#define T_NULL 0 +#define T_VOID 1 +#define T_CHAR 2 +#define T_SHORT 3 +#define T_INT 4 +#define T_LONG 5 +#define T_FLOAT 6 +#define T_DOUBLE 7 +#define T_STRUCT 8 +#define T_UNION 9 +#define T_ENUM 10 +#define T_MOE 11 +#define T_UCHAR 12 +#define T_USHORT 13 +#define T_UINT 14 +#define T_ULONG 15 +#define T_LNGDBL 16 +#define DT_NON 0 +#define DT_PTR 1 +#define DT_FCN 2 +#define DT_ARY 3 + +#define COFFTYPE(dt,t) (((dt)<<4)|t) + +int sortCompare(const void *x1,const void *x2); +void processArgs(int argc,char *argv[]); +void combine_groups(long i,long j); +void combine_common(long i,long j); +void combine_segments(PSEG i,PSEG j); +void combineBlocks(); +void OutputWin32file(const std::string &outname); +void OutputEXEfile(const std::string &outname); +void OutputCOMfile(const std::string &outname); +void GetFixupTarget(PRELOC r,PSEG *tseg,UINT *tofs,int isFlat); +void loadlibmod(UINT libnum,UINT modpage); +void loadlib(FILE *libfile,std::string libname); +void loadelf(FILE *libfile); +void loadCoffLib(FILE *libfile,std::string libname); +void loadcofflibmod(PLIBFILE p,FILE *libfile); +long loadmod(FILE *objfile); +void loadres(FILE *resfile); +void loadcoff(FILE *objfile); +void loadCoffImport(FILE *objfile); +void LoadFIXUP(PRELOC r,PUCHAR buf,long *p); +void RelocLIDATA(PDATABLOCK p,long *ofs,PRELOC r); +void EmitLiData(PDATABLOCK p,long segnum,long *ofs); +PDATABLOCK BuildLiData(long *bufofs); +void DestroyLIDATA(PDATABLOCK p); +void ReportError(long errnum); +int wstricmp(const char *s1,const char*s2); +int wstrlen(const char *s); +unsigned short wtoupper(unsigned short a); +int getBitCount(UINT a); +int _wstricmp(unsigned char *a, unsigned char *b); +int _wstrlen(unsigned char *a); +#define strdup _strdup + +extern char case_sensitive; +extern char padsegments; +extern char mapfile; +extern std::string mapname; +extern unsigned short maxalloc; +extern int output_type; +extern std::string outname; + +extern FILE *afile; +extern UINT filepos; +extern long reclength; +extern unsigned char rectype; +extern char li_le; +extern UINT prevofs; +extern long prevseg; +extern long gotstart; +extern RELOC startaddr; +extern unsigned char osMajor,osMinor; +extern unsigned char subsysMajor,subsysMinor; +extern unsigned int subSystem; + +extern long errcount; + +extern std::vector buf; +extern PDATABLOCK lidata; + +//extern std::vector namelist; +extern std::vector seglist; +extern std::vector outlist; +extern std::vector grplist; +extern SORTLIST publics; +extern std::vector externs; +extern std::vector comdefs; +extern std::vector relocs; +extern std::vector impdefs; +extern std::vector expdefs; +extern std::vector libfiles; +extern std::vector resource; +extern std::vector modname; +extern std::vector filename; +extern SORTLIST comdats; +extern UINT namemin, + pubmin, + segmin, + grpmin, + extmin, + commin, + fixmin, + impmin,impsreq, + expmin; + +extern int buildDll; +extern std::string stubName, entryPoint; +extern int cpuIdent; diff --git a/reactos/tools/ppc-build/alink/alink.mak b/reactos/tools/ppc-build/alink/alink.mak new file mode 100644 index 00000000000..929758cee6c --- /dev/null +++ b/reactos/tools/ppc-build/alink/alink.mak @@ -0,0 +1,11 @@ +CC = gcc -Zomf -c -s -O5 + +%.obj: %.c + $(CC) -o $@ $< + +all: blink.exe + +alink.obj coff.obj cofflib.obj combine.obj output.obj objload.obj util.obj: alink.h + +blink.exe: alink.obj coff.obj cofflib.obj combine.obj output.obj objload.obj util.obj + alink -subsys con @lib/def.rsp -o $@ $^ diff --git a/reactos/tools/ppc-build/alink/alink2.mak b/reactos/tools/ppc-build/alink/alink2.mak new file mode 100644 index 00000000000..ae6b8023bb9 --- /dev/null +++ b/reactos/tools/ppc-build/alink/alink2.mak @@ -0,0 +1,11 @@ +CC = cl /Zl /c /Ox + +%.obj: %.c + $(CC) /Fo$@ $< + +all: blink.exe + +alink.obj coff.obj cofflib.obj combine.obj output.obj objload.obj util.obj: alink.h + +blink.exe: alink.obj coff.obj cofflib.obj combine.obj output.obj objload.obj util.obj + alink -subsys con @lib/def.rsp -o $@ $^ diff --git a/reactos/tools/ppc-build/alink/coff.cpp b/reactos/tools/ppc-build/alink/coff.cpp new file mode 100644 index 00000000000..a2d5be19c76 --- /dev/null +++ b/reactos/tools/ppc-build/alink/coff.cpp @@ -0,0 +1,723 @@ +#include "alink.h" + +#define strupr(x) + +void loadcoff(FILE *objfile) +{ + unsigned char headbuf[20]; + unsigned char buf[100]; + PUCHAR bigbuf; + std::vector stringList; + UINT thiscpu; + UINT numSect; + UINT headerSize; + UINT symbolPtr; + UINT numSymbols; + UINT stringPtr; + UINT stringSize; + UINT stringOfs; + UINT i,j,k,l; + UINT fileStart; + UINT minseg; + UINT numrel; + UINT relofs; + UINT relshift; + UINT sectname; + long sectorder; + std::vector sym; + UINT combineType; + PPUBLIC pubdef; + PCOMDAT comdat; + PCHAR comdatsym; + std::vector nlist; + SORTLIST::iterator listnode; + + minseg=seglist.size(); + fileStart=ftell(objfile); + + if(fread(headbuf,1,20,objfile)!=20) + { + printf("Unable to read from file\n"); + exit(1); + } + thiscpu=headbuf[0]+256*headbuf[1]; + if(!thiscpu) + { + /* if we've got an import module, start at the beginning */ + fseek(objfile,fileStart,SEEK_SET); + /* and load it */ + loadCoffImport(objfile); + return; + } + + if(thiscpu==0x14c) + cpuIdent = PE_INTEL386; + if(thiscpu==0x1f0) + cpuIdent = PE_POWERPC; + + if(!cpuIdent) + { + printf("Unsupported CPU type for module (type %x)\n", thiscpu); + exit(1); + } + + numSect=get16(headbuf, PE_NUMOBJECTS-PE_MACHINEID); + symbolPtr=get32(headbuf, PE_SYMBOLPTR-PE_MACHINEID); + numSymbols=get32(headbuf, PE_NUMSYMBOLS-PE_MACHINEID); + + if(headbuf[PE_HDRSIZE-PE_MACHINEID]|headbuf[PE_HDRSIZE-PE_MACHINEID+1]) + { + printf("warning, optional header discarded\n"); + headerSize=headbuf[PE_HDRSIZE-PE_MACHINEID]+256*headbuf[PE_HDRSIZE-PE_MACHINEID+1]; + } + else + headerSize=0; + headerSize+=PE_BASE_HEADER_SIZE-PE_MACHINEID; + + stringPtr=symbolPtr+numSymbols*PE_SYMBOL_SIZE; + if(stringPtr) + { + fseek(objfile,fileStart+stringPtr,SEEK_SET); + if(fread(buf,1,4,objfile)!=4) + { + printf("Invalid COFF object file, unable to read string table size\n"); + exit(1); + } + stringSize=buf[0]+(buf[1]<<8)+(buf[2]<<16)+(buf[3]<<24); + if(!stringSize) stringSize=4; + if(stringSize<4) + { + printf("Invalid COFF object file, bad string table size %i\n",stringSize); + exit(1); + } + stringPtr+=4; + stringSize-=4; + } + else + { + stringSize=0; + } + if(stringSize) + { + stringList.resize(stringSize); + if(fread(&stringList[0],1,stringSize,objfile)!=stringSize) + { + printf("Invalid COFF object file, unable to read string table\n"); + exit(1); + } + if(stringList[stringSize-1]) + { + printf("Invalid COFF object file, last string unterminated\n"); + exit(1); + } + } + else + { + stringList.resize(0); + } + + if(symbolPtr && numSymbols) + { + fseek(objfile,fileStart+symbolPtr,SEEK_SET); + sym.resize(numSymbols); + for(i=0;i=stringSize) + { + printf("Invalid COFF object file bad symbol location\n"); + exit(1); + } + sym[i].name=(char *)&stringList[0]+stringOfs; + } + if(!case_sensitive) + { + strupr(sym[i].name); + } + + sym[i].value=get32(buf, 8); + sym[i].section=get16(buf, 12); + sym[i].type=get16(buf, 14); + sym[i].coff_class=buf[16]; + sym[i].extnum=-1; + sym[i].numAuxRecs=buf[17]; + sym[i].isComDat=FALSE; + + switch(sym[i].coff_class) + { + case COFF_SYM_SECTION: { /* section symbol */ + if(sym[i].section<-1) + { + break; + } + /* section symbols declare an extern always, so can use in relocs */ + /* they may also include a PUBDEF */ + EXTREC ext; + ext.name=sym[i].name; + ext.pubdef=NULL; + ext.modnum=0; + ext.flags=EXT_NOMATCH; + sym[i].extnum=externs.size(); + externs.push_back(ext); + if(sym[i].section!=0) /* if the section is defined here, make public */ + { + pubdef=new PUBLIC(); + pubdef->grpnum=-1; + pubdef->typenum=0; + pubdef->modnum=0; + pubdef->aliasName=""; + pubdef->ofs=sym[i].value; + + if(sym[i].section==-1) + { + pubdef->seg=0; + } + else + { + pubdef->seg=seglist[minseg+sym[i].section-1]; + } + if((listnode=publics.find(sym[i].name)) != publics.end()) + { + for(j=0;jsecond.size();++j) + { + if(((PPUBLIC)listnode->second[j])->modnum==pubdef->modnum) + { + if(((PPUBLIC)listnode->second[j])->aliasName == "") + { + printf("Duplicate public symbol %s\n",sym[i].name.c_str()); + exit(1); + } + (*((PPUBLIC)listnode->second[j]))=(*pubdef); + pubdef=NULL; + break; + } + } + } + if(pubdef) + { + SORTLIST::iterator it = publics.find(sym[i].name); + if(it == publics.end()) { + std::vector vv; + vv.push_back((void *)pubdef); + publics.insert(std::make_pair(sym[i].name,vv)); + } else { + it->second.push_back((void *)pubdef); + } + } + } + } + case COFF_SYM_STATIC: /* allowed, but ignored for now as we only want to process if required */ + case COFF_SYM_LABEL: + case COFF_SYM_FILE: + case COFF_SYM_FUNCTION: + case COFF_SYM_EXTERNAL: + break; + default: + printf("unsupported symbol class %02X for symbol %s\n",sym[i].coff_class,sym[i].name.c_str()); + exit(1); + } + if(sym[i].numAuxRecs) + { + sym[i].auxRecs.resize(sym[i].numAuxRecs*PE_SYMBOL_SIZE); + } + else + { + sym[i].auxRecs.resize(0); + } + + /* read in the auxillary records for this symbol */ + for(j=0;j=stringSize) + { + printf("Invalid COFF object file\n"); + exit(1); + } + nlist.push_back((char *)&stringList[0]+sectname); + sectname=nlist.size()-1; + } + else + { + nlist.push_back((char *)buf); + sectname=nlist.size()-1; + } + size_t dollar = nlist[sectname].find('$'); + if(dollar != std::string::npos) + { + /* if we have a grouped segment, sort by original name */ + sectorder=sectname; + /* and get real name, without $ sort section */ + sectname=nlist.size(); + std::string no_dollar = nlist[sectname].substr(dollar); + nlist.push_back(no_dollar); + } + else + { + sectorder=-1; + } + + numrel=get16(buf, PE_OBJECT_NUMREL); + relofs=get32(buf, PE_OBJECT_RELPTR); + + PSEG seg = new SEG(); + seg->name=nlist[sectname]; + seg->orderindex=sectorder; + seg->classindex=-1; + seg->overlayindex=-1; + seg->length=get32(buf, PE_OBJECT_RAWSIZE); + + seg->attr=SEG_PUBLIC|SEG_USE32; + seg->winFlags=get32(buf, PE_OBJECT_FLAGS); + seg->setbase(get32(buf, PE_OBJECT_RAWPTR)); + + if(seg->winFlags & WINF_ALIGN_NOPAD) + { + seg->winFlags &= (0xffffffff-WINF_ALIGN); + seg->winFlags |= WINF_ALIGN_BYTE; + } + + switch(seg->winFlags & WINF_ALIGN) + { + case WINF_ALIGN_BYTE: + seg->attr |= SEG_BYTE; + break; + case WINF_ALIGN_WORD: + seg->attr |= SEG_WORD; + break; + case WINF_ALIGN_DWORD: + seg->attr |= SEG_DWORD; + break; + case WINF_ALIGN_8: + seg->attr |= SEG_8BYTE; + break; + case WINF_ALIGN_PARA: + seg->attr |= SEG_PARA; + break; + case WINF_ALIGN_32: + seg->attr |= SEG_32BYTE; + break; + case WINF_ALIGN_64: + seg->attr |= SEG_64BYTE; + break; + case 0: + seg->attr |= SEG_PARA; /* default */ + break; + default: + printf("Invalid COFF object file, bad section alignment %08X\n",seg->winFlags); + exit(1); + } + + /* invert all negative-logic flags */ + seg->winFlags ^= WINF_NEG_FLAGS; + /* remove .debug sections */ + if(nlist[sectname] == ".debug") + { + seg->winFlags |= WINF_REMOVE; + seg->length=0; + numrel=0; + } + + if(seg->winFlags & WINF_COMDAT) + { + printf("COMDAT section %s\n",nlist[sectname].c_str()); + comdat=new COMDATREC(); + combineType=0; + comdat->linkwith=0; + for(j=0;jlinkwith=sym[j].auxRecs[12]+(sym[j].auxRecs[13]<<8)+minseg-1; + printf("Combine type %i ",sym[j].auxRecs[14]); + printf("Link alongside section %i",comdat->linkwith); + + break; + } + } + if(j==numSymbols) + { + printf("Invalid COMDAT section\n"); + exit(1); + } + for(j++;jsegnum=seglist.size(); + comdat->combineType=combineType; + + printf("COMDATs not yet supported\n"); + exit(1); + + printf("Combine types for duplicate COMDAT symbol %s do not match\n",comdatsym); + exit(1); + } + + if(seg->length) + { + seg->data.resize(seg->length); + + seg->datmask.resize((seg->length+7)/8); + + if(seg->getbase()) + { + fseek(objfile,fileStart+seg->getbase(),SEEK_SET); + if(fread(&seg->data[0],1,seg->length,objfile) + !=seg->length) + { + printf("Invalid COFF object file\n"); + exit(1); + } + for(j=0;j<(seg->length+7)/8;j++) + seg->datmask[j]=0xff; + } + else + { + for(j=0;j<(seg->length+7)/8;j++) + seg->datmask[j]=0; + } + + } + else + { + seg->data.resize(0); + seg->datmask.resize(0); + } + + if(numrel) fseek(objfile,fileStart+relofs,SEEK_SET); + for(j=0;jofs=buf[0]+(buf[1]<<8)+(buf[2]<<16)+(buf[3]<<24); + reloc->ofs-=relshift; + /* get segment */ + reloc->seg=seglist[i+minseg]; + reloc->disp=0; + /* get relocation target external index */ + reloc->target=get32(buf, 4); + if(reloc->target>=numSymbols) + { + printf("Invalid COFF object file, undefined symbol\n"); + exit(1); + } + k=reloc->target; + reloc->ttype=REL_EXTONLY; /* assume external reloc */ + if(sym[k].extnum<0) + { + switch(sym[k].coff_class) + { + case COFF_SYM_EXTERNAL: { + /* global symbols declare an extern when used in relocs */ + EXTREC ext; + ext.name=(char *)sym[k].name.c_str(); + ext.pubdef=NULL; + ext.modnum=0; + ext.flags=EXT_NOMATCH; + sym[k].extnum=externs.size(); + externs.push_back(ext); + /* they may also include a COMDEF or a PUBDEF */ + /* this is dealt with after all sections loaded, to cater for COMDAT symbols */ + } break; + case COFF_SYM_STATIC: /* static symbol */ + case COFF_SYM_LABEL: /* code label symbol */ + if(sym[k].section<-1) + { + printf("cannot relocate against a debug info symbol\n"); + exit(1); + break; + } + if(sym[k].section==0) + { + if(sym[k].value) + { + EXTREC ext; + ext.name=(char *)sym[k].name.c_str(); + ext.pubdef=NULL; + ext.modnum=modname.size()-1; + ext.flags=EXT_NOMATCH; + sym[k].extnum=externs.size(); + externs.push_back(ext); + + PCOMREC com = new COMREC(); + com->length=sym[k].value; + com->isFar=FALSE; + com->name=(char *)sym[k].name.c_str(); + com->modnum=modname.size()-1; + comdefs.push_back(com); + } + else + { + printf("Undefined symbol %s\n",sym[k].name.c_str()); + exit(1); + } + } + else + { + /* update relocation information to reflect symbol */ + reloc->ttype=REL_SEGDISP; + reloc->disp=sym[k].value; + if(sym[k].section==-1) + { + /* absolute symbols have section=-1 */ + reloc->target=-1; + } + else + { + /* else get real number of section */ + reloc->target=sym[k].section+minseg-1; + } + } + break; + default: + printf("undefined symbol class 0x%02X for symbol %s\n",sym[k].coff_class,sym[k].name.c_str()); + exit(1); + } + } + if(reloc->ttype==REL_EXTONLY) + { + /* set relocation target to external if sym is external */ + reloc->target=sym[k].extnum; + } + + /* frame is current segment (only relevant for non-FLAT output) */ + reloc->ftype=REL_SEGFRAME; + reloc->frame=i+minseg; + /* set relocation type */ + switch(get16(buf,8)) + { + case COFF_FIX_DIR32: + reloc->rtype=FIX_OFS32; + break; + + case COFF_FIX_RVA32: + reloc->rtype=FIX_RVA32; + break; +/* + case 0x0a: - + break; + case 0x0b: + break; +*/ + case COFF_FIX_REL32: + reloc->rtype=FIX_SELF_OFS32; + break; + default: + printf("unsupported COFF relocation type %04X\n",buf[8]+(buf[9]<<8)); + exit(1); + } + relocs.push_back(reloc); + } + + seglist.push_back(seg); + } + /* build PUBDEFs or COMDEFs for external symbols defined here that aren't COMDAT symbols. */ + for(i=0;ilength=sym[i].value; + com->isFar=FALSE; + com->name=sym[i].name; + com->modnum=0; + comdefs.push_back(com); + } + } + else + { + pubdef=new PUBLIC(); + pubdef->grpnum=-1; + pubdef->typenum=0; + pubdef->modnum=0; + pubdef->aliasName=""; + pubdef->ofs=sym[i].value; + + if(sym[i].section==-1) + { + pubdef->seg=0; + } + else + { + pubdef->seg=seglist[minseg+sym[i].section-1]; + } + if((listnode=publics.find(sym[i].name)) != publics.end()) + { + for(j=0;jsecond.size();++j) + { + if(((PPUBLIC)listnode->second[j])->modnum==pubdef->modnum) + { + if(((PPUBLIC)listnode->second[j])->aliasName == "") + { + printf("Duplicate public symbol %s\n",sym[i].name.c_str()); + exit(1); + } + (*((PPUBLIC)listnode->second[j]))=(*pubdef); + pubdef=NULL; + break; + } + } + } + if(pubdef) + { + SORTLIST::iterator it = publics.find(sym[i].name); + if( it == publics.end() ) { + std::vector vv; + vv.push_back((void *)pubdef); + publics.insert(std::make_pair(sym[i].name, vv)); + } else { + it->second.push_back((void *)pubdef); + } + } + } + } +} + +void loadCoffImport(FILE *objfile) +{ + UINT fileStart; + UINT thiscpu; + + fileStart=ftell(objfile); + + if(fread(&buf[0],1,20,objfile)!=20) + { + printf("Unable to read from file\n"); + exit(1); + } + + if(get32(buf,0) != 0xffff0000) + { + printf("Invalid Import entry\n"); + exit(1); + } + /* get CPU type */ + thiscpu=get16(buf,6); + printf("Import CPU=%04X\n",thiscpu); + + if(thiscpu!=0x14c && thiscpu!=0x1f0) + { + printf("Unsupported CPU type for module (type %x)\n", thiscpu); + exit(1); + } + +} diff --git a/reactos/tools/ppc-build/alink/cofflib.cpp b/reactos/tools/ppc-build/alink/cofflib.cpp new file mode 100644 index 00000000000..4f5b1757bb7 --- /dev/null +++ b/reactos/tools/ppc-build/alink/cofflib.cpp @@ -0,0 +1,310 @@ +#include "alink.h" + +#define strupr(x) + +void loadCoffLib(FILE *libfile,std::string libname) +{ + UINT i,j; + UINT numsyms; + UINT modpage; + UINT memberSize; + UINT startPoint; + PUCHAR endptr; + PLIBFILE p; + std::string name; + std::vector modbuf; + SORTLIST symlist; + int x; + + libfiles.push_back(LIBFILE()); + p=&libfiles[libfiles.size()-1]; + p->filename=libname; + startPoint=ftell(libfile); + + if(fread(&buf[0],1,8,libfile)!=8) + { + printf("Error reading from file\n"); + exit(1); + } + buf[8]=0; + /* complain if file header is wrong */ + if(strcmp((char *)&buf[0],"!\n")) + { + printf("Invalid library file format - bad file header\n"); + printf("\"%s\"\n",&buf[0]); + + exit(1); + } + /* read archive member header */ + if(fread(&buf[0],1,60,libfile)!=60) + { + printf("Error reading from file\n"); + exit(1); + } + if((buf[58]!=0x60) || (buf[59]!='\n')) + { + printf("Invalid library file format - bad member signature\n"); + exit(1); + } + buf[16]=0; + /* check name of first linker member */ + if(strcmp((char *)&buf[0],"/ ")) /* 15 spaces */ + { + printf("Invalid library file format - bad member name\n"); + exit(1); + } + buf[58]=0; + + /* strip trailing spaces from size */ + endptr=&buf[57]; + while((endptr>(&buf[48])) && isspace(*endptr)) + { + *endptr=0; + endptr--; + } + + /* get size */ + errno=0; + memberSize=strtoul((char *)&buf[48],(PPCHAR)&endptr,10); + if(errno || (*endptr)) + { + printf("Invalid library file format - bad member size\n"); + exit(1); + } + if((memberSize<4) && memberSize) + { + printf("Invalid library file format - bad member size\n"); + exit(1); + } + if(!memberSize) + { + numsyms=0; + } + else + { + if(fread(&buf[0],1,4,libfile)!=4) + { + printf("Error reading from file\n"); + exit(1); + } + numsyms=buf[3]+(buf[2]<<8)+(buf[1]<<16)+(buf[0]<<24); + } + printf("%u symbols\n",numsyms); + + if(numsyms) + { + if(fread(&modbuf[0],1,4*numsyms,libfile)!=4*numsyms) + { + printf("Error reading from file\n"); + exit(1); + } + } + + for(i=0;i vv; + vv.resize(modpage); + symlist.insert(std::make_pair(name, vv)); + } + + if(numsyms) + { + p->symbols=symlist; + } + + /* move to an even byte boundary in the file */ + if(ftell(libfile)&1) + { + fseek(libfile,1,SEEK_CUR); + } + + if(ftell(libfile)!=(startPoint+68+memberSize)) + { + printf("Invalid first linker member\n"); + printf("Pos=%08X, should be %08X\n",ftell(libfile),startPoint+68+memberSize); + + exit(1); + } + + printf("Loaded first linker member\n"); + + startPoint=ftell(libfile); + + /* read archive member header */ + if(fread(&buf[0],1,60,libfile)!=60) + { + printf("Error reading from file\n"); + exit(1); + } + if((buf[58]!=0x60) || (buf[59]!='\n')) + { + printf("Invalid library file format - bad member signature\n"); + exit(1); + } + buf[16]=0; + /* check name of second linker member */ + if(!strcmp((char *)&buf[0],"/ ")) /* 15 spaces */ + { + /* OK, so we've found it, now skip over */ + buf[58]=0; + + /* strip trailing spaces from size */ + endptr=&buf[57]; + while((endptr>(&buf[48])) && isspace(*endptr)) + { + *endptr=0; + endptr--; + } + + /* get size */ + errno=0; + memberSize=strtoul((char *)&buf[48],(PPCHAR)&endptr,10); + if(errno || (*endptr)) + { + printf("Invalid library file format - bad member size\n"); + exit(1); + } + if((memberSize<8) && memberSize) + { + printf("Invalid library file format - bad member size\n"); + exit(1); + } + + /* move over second linker member */ + fseek(libfile,startPoint+60+memberSize,SEEK_SET); + + /* move to an even byte boundary in the file */ + if(ftell(libfile)&1) + { + fseek(libfile,1,SEEK_CUR); + } + } + else + { + fseek(libfile,startPoint,SEEK_SET); + } + + + startPoint=ftell(libfile); + p->longnames.resize(0); + + /* read archive member header */ + if(fread(&buf[0],1,60,libfile)!=60) + { + printf("Error reading from file\n"); + exit(1); + } + if((buf[58]!=0x60) || (buf[59]!='\n')) + { + printf("Invalid library file format - bad 3rd member signature\n"); + exit(1); + } + buf[16]=0; + /* check name of long names linker member */ + if(!strcmp((char *)&buf[0],"// ")) /* 14 spaces */ + { + buf[58]=0; + + /* strip trailing spaces from size */ + endptr=&buf[57]; + while((endptr>(&buf[48])) && isspace(*endptr)) + { + *endptr=0; + endptr--; + } + + /* get size */ + errno=0; + memberSize=strtoul((char *)&buf[48],(PPCHAR)&endptr,10); + if(errno || (*endptr)) + { + printf("Invalid library file format - bad member size\n"); + exit(1); + } + if(memberSize) + { + p->longnames.resize(memberSize); + if(fread(&p->longnames[0],1,memberSize,libfile)!=memberSize) + { + printf("Error reading from file\n"); + exit(1); + } + } + } + else + { + /* if no long names member, move back to member header */ + fseek(libfile,startPoint,SEEK_SET); + } + + + p->modsloaded=0; + p->modlist.resize(numsyms); + p->libtype='C'; + p->blocksize=1; + p->flags=LIBF_CASESENSITIVE; +} + +void loadcofflibmod(PLIBFILE p,FILE *libfile) +{ + char *name; + UINT ofs; + + if(fread(&buf[0],1,60,libfile)!=60) + { + printf("Error reading from file\n"); + exit(1); + } + if((buf[58]!=0x60) || (buf[59]!='\n')) + { + printf("Invalid library member header\n"); + exit(1); + } + buf[16]=0; + if(buf[0]=='/') + { + ofs=15; + while(isspace(buf[ofs])) + { + buf[ofs]=0; + ofs--; + } + + ofs=strtoul((char *)&buf[1],&name,10); + if(!buf[1] || *name) + { + printf("Invalid string number \n"); + exit(1); + } + name=(char *)&p->longnames[0]+ofs; + } + else + { + name=(char *)&buf[0]; + } + + printf("Loading module %s\n",name); + loadcoff(libfile); +} diff --git a/reactos/tools/ppc-build/alink/combine.cpp b/reactos/tools/ppc-build/alink/combine.cpp new file mode 100755 index 00000000000..cd82543751b --- /dev/null +++ b/reactos/tools/ppc-build/alink/combine.cpp @@ -0,0 +1,519 @@ +#include "alink.h" + +void fixpubsegs(PSEG src,PSEG dest,UINT shift) +{ + UINT i,j; + PPUBLIC q; + SORTLIST::iterator it; + + for(it=publics.begin();it!=publics.end();++it) + { + for(j=0;jsecond.size();++it) + { + q=(PPUBLIC)it->second[j]; + if(q->seg==src) + { + q->seg=dest; + q->ofs+=shift; + } + } + } +} + +void fixpubgrps(int src,int dest) +{ + UINT i,j; + PPUBLIC q; + SORTLIST::iterator it; + + for(it=publics.begin();it!=publics.end();++it) + { + for(j=0;jsecond.size();++j) + { + q=(PPUBLIC)it->second[j]; + if(q->grpnum==src) + { + q->grpnum=dest; + } + } + } +} + +void combine_segments(PSEG destseg,PSEG srcseg) +{ + UINT k,n; + std::vector p,q; + long a1,a2; + + assert(destseg != srcseg); + + k=destseg->length; + switch(srcseg->attr&SEG_ALIGN) + { + case SEG_WORD: + a2=2; + k=(k+1)&0xfffffffe; + break; + case SEG_PARA: + a2=16; + k=(k+0xf)&0xfffffff0; + break; + case SEG_PAGE: + a2=0x100; + k=(k+0xff)&0xffffff00; + break; + case SEG_DWORD: + a2=4; + k=(k+3)&0xfffffffc; + break; + case SEG_MEMPAGE: + a2=0x1000; + k=(k+0xfff)&0xfffff000; + break; + case SEG_8BYTE: + a2=8; + k=(k+7)&0xfffffff8; + break; + case SEG_32BYTE: + a2=32; + k=(k+31)&0xffffffe0; + break; + case SEG_64BYTE: + a2=64; + k=(k+63)&0xffffffc0; + break; + default: + a2=1; + break; + } + switch(destseg->attr&SEG_ALIGN) + { + case SEG_WORD: + a1=2; + break; + case SEG_DWORD: + a1=4; + break; + case SEG_8BYTE: + a1=8; + break; + case SEG_PARA: + a1=16; + break; + case SEG_32BYTE: + a1=32; + break; + case SEG_64BYTE: + a1=64; + break; + case SEG_PAGE: + a1=0x100; + break; + case SEG_MEMPAGE: + a1=0x1000; + break; + default: + a1=1; + break; + } + + srcseg->setbase(k); + p.resize(k+srcseg->length); + q.resize((k+srcseg->length+7)/8); + for(k=0;klength;k++) + { + if(GetNbit(destseg->datmask,k)) + { + SetNbit(q,k); + p[k]=destseg->data[k]; + } + else + { + ClearNbit(q,k); + } + } + for(;kgetbase();k++) + { + ClearNbit(q,k); + } + for(;k<(srcseg->getbase()+srcseg->length);k++) + { + if(GetNbit(srcseg->datmask,k-srcseg->getbase())) + { + p[k]=srcseg->data[k-srcseg->getbase()]; + SetNbit(q,k); + } + else + { + ClearNbit(q,k); + } + } + destseg->length=k; + if(a2>a1) destseg->attr=srcseg->attr; + destseg->winFlags |= srcseg->winFlags; + destseg->data=p; + destseg->datmask=q; + + fixpubsegs(srcseg,destseg,srcseg->getbase()); + + for(k=0;kseg==srcseg) + { + relocs[k]->seg=destseg; + relocs[k]->ofs+=srcseg->getbase(); + } + if(relocs[k]->ttype==REL_SEGDISP) + { + if(relocs[k]->targseg==srcseg) + { + relocs[k]->targseg=destseg; + relocs[k]->disp=srcseg->getbase(); + } + } + else if(relocs[k]->ttype==REL_SEGONLY) + { + if(relocs[k]->targseg==srcseg) + { + relocs[k]->targseg=destseg; + relocs[k]->ttype=REL_SEGDISP; + relocs[k]->disp=srcseg->getbase(); + } + } + if((relocs[k]->ftype==REL_SEGFRAME) || + (relocs[k]->ftype==REL_LILEFRAME)) + { + if(relocs[k]->seg==srcseg) + { + relocs[k]->seg=destseg; + } + } + } + + if(gotstart) + { + if(startaddr.ttype==REL_SEGDISP) + { + if(startaddr.targseg==srcseg) + { + startaddr.targseg=destseg; + startaddr.disp+=srcseg->getbase(); + } + } + else if(startaddr.ttype==REL_SEGONLY) + { + if(startaddr.targseg==srcseg) + { + startaddr.targseg=destseg; + startaddr.disp=srcseg->getbase(); + startaddr.ttype=REL_SEGDISP; + } + } + if((startaddr.ftype==REL_SEGFRAME) || + (startaddr.ftype==REL_LILEFRAME)) + { + if(startaddr.seg==srcseg) + { + startaddr.seg=destseg; + } + } + } + + for(k=0;knumsegs;n++) + { + if(grplist[k]->segindex[n]==srcseg) + { + grplist[k]->segindex[n]=destseg; + } + } + } + } + + srcseg=0; +} + +void combine_common(long i,long j) +{ + UINT k,n; + std::vector p,q; + + if(seglist[j]->length>seglist[i]->length) + { + k=seglist[i]->length; + seglist[i]->length=seglist[j]->length; + seglist[j]->length=k; + p=seglist[i]->data; + q=seglist[i]->datmask; + seglist[i]->data=seglist[j]->data; + seglist[i]->datmask=seglist[j]->datmask; + } + else + { + p=seglist[j]->data; + q=seglist[j]->datmask; + } + for(k=0;klength;k++) + { + if(GetNbit(q,k)) + { + if(GetNbit(seglist[i]->datmask,k)) + { + if(seglist[i]->data[k]!=p[k]) + { + ReportError(ERR_OVERWRITE); + } + } + else + { + SetNbit(seglist[i]->datmask,k); + seglist[i]->data[k]=p[k]; + } + } + } + + fixpubsegs(seglist[j],seglist[i],0); + + for(k=0;kseg==seglist[j]) + { + relocs[k]->seg=seglist[i]; + } + if(relocs[k]->ttype==REL_SEGDISP) + { + if(relocs[k]->target==j) + { + relocs[k]->target=i; + } + } + else if(relocs[k]->ttype==REL_SEGONLY) + { + if(relocs[k]->target==j) + { + relocs[k]->target=i; + } + } + if((relocs[k]->ftype==REL_SEGFRAME) || + (relocs[k]->ftype==REL_LILEFRAME)) + { + if(relocs[k]->frame==j) + { + relocs[k]->frame=i; + } + } + } + + if(gotstart) + { + if(startaddr.ttype==REL_SEGDISP) + { + if(startaddr.target==j) + { + startaddr.target=i; + } + } + else if(startaddr.ttype==REL_SEGONLY) + { + if(startaddr.target==j) + { + startaddr.target=i; + } + } + if((startaddr.ftype==REL_SEGFRAME) || + (startaddr.ftype==REL_LILEFRAME)) + { + if(startaddr.frame==j) + { + startaddr.frame=i; + } + } + } + + for(k=0;knumsegs;n++) + { + if(grplist[k]->segindex[n]==seglist[j]) + { + grplist[k]->segindex[n]=seglist[i]; + } + } + } + } + + free(seglist[j]); + seglist[j]=0; +} + +void combine_groups(long i,long j) +{ + long n,m; + char match; + + for(n=0;nnumsegs;n++) + { + match=0; + for(m=0;mnumsegs;m++) + { + if(grplist[j]->segindex[n]==grplist[i]->segindex[m]) + { + match=1; + } + } + if(!match) + { + grplist[i]->numsegs++; + grplist[i]->segindex[grplist[i]->numsegs]=grplist[j]->segindex[n]; + } + } + free(grplist[j]); + grplist[j]=0; + + fixpubgrps(j,i); + + for(n=0;nftype==REL_GRPFRAME) + { + if(relocs[n]->frame==j) + { + relocs[n]->frame=i; + } + } + if((relocs[n]->ttype==REL_GRPONLY) || (relocs[n]->ttype==REL_GRPDISP)) + { + if(relocs[n]->target==j) + { + relocs[n]->target=i; + } + } + } + + if(gotstart) + { + if((startaddr.ttype==REL_GRPDISP) || (startaddr.ttype==REL_GRPONLY)) + { + if(startaddr.target==j) + { + startaddr.target=i; + } + } + if(startaddr.ftype==REL_GRPFRAME) + { + if(startaddr.frame==j) + { + startaddr.frame=i; + } + } + } +} + +void combineBlocks() +{ + long i,j,k; + std::string name; + long attr; + UINT count; + std::vector slist; + UINT curseg; + + for(i=0;iattr&SEG_ALIGN)!=SEG_ABS)) + { + if(seglist[i]->winFlags & WINF_COMDAT) continue; /* don't combine COMDAT segments */ + name=seglist[i]->name; + attr=seglist[i]->attr&(SEG_COMBINE|SEG_USE32); + + switch(attr&SEG_COMBINE) + { + case SEG_STACK: + for(j=i+1;jwinFlags & WINF_COMDAT) continue; + if((seglist[j]->attr&SEG_ALIGN)==SEG_ABS) continue; + if((seglist[j]->attr&SEG_COMBINE)!=SEG_STACK) continue; + combine_segments(seglist[i],seglist[j]); + } + break; + case SEG_PUBLIC: + case SEG_PUBLIC2: + case SEG_PUBLIC3: + slist.resize(1); + slist[0] = i; + /* get list of segments to combine */ + for(j=i+1,count=1;jwinFlags & WINF_COMDAT) continue; + if((seglist[j]->attr&SEG_ALIGN)==SEG_ABS) continue; + if(attr!=(seglist[j]->attr&(SEG_COMBINE|SEG_USE32))) continue; + if(name != seglist[j]->name) continue; + slist.push_back(j); + } + /* sort them by sortorder */ + for(j=0;jorderindex<0 || + seglist[slist[j]]->orderindex<0) continue; + + if(seglist[slist[j]]->name > + seglist[slist[k]]->name) { + int x = slist[k]; + slist[k] = slist[j]; + slist[j] = x; + } + } + } + /* then combine in that order */ + for(j=1;jattr&SEG_ALIGN)!=SEG_ABS)) && + ((seglist[i]->attr&(SEG_ALIGN|SEG_COMBINE|SEG_USE32))==(seglist[j]->attr&(SEG_ALIGN|SEG_COMBINE|SEG_USE32))) + && + (name == seglist[j]->name) + && !(seglist[j]->winFlags & WINF_COMDAT) + ) + { + combine_common(i,j); + } + } + break; + default: + break; + } + } + } + + for(i=0;iname == grplist[j]->name) + { + combine_groups(i,j); + } + } + } + } +} + + diff --git a/reactos/tools/ppc-build/alink/elf.cpp b/reactos/tools/ppc-build/alink/elf.cpp new file mode 100755 index 00000000000..cf50d2a14a6 --- /dev/null +++ b/reactos/tools/ppc-build/alink/elf.cpp @@ -0,0 +1,693 @@ +#include "alink.h" +#include + +#define strupr(x) + +unsigned short get16(unsigned char **src) +{ + unsigned short out = ((*src)[0] & 0xff) | (((*src)[1] & 0xff) << 8); + *src += 2; + return out; +} + +unsigned long get32(unsigned char **src) +{ + unsigned long out = + ((*src)[0] & 0xff) | + (((*src)[1] & 0xff) << 8) | + (((*src)[2] & 0xff) << 16) | + (((*src)[3] & 0xff) << 24); + *src += 4; + return out; +} + +int wantSeg(PSEG seg) +{ + return + !((seg->name.find(".debug") != std::string::npos) || + (seg->name.find(".rela") != std::string::npos) || + (seg->name.find("symtab") != std::string::npos) || + (seg->name.find("strtab") != std::string::npos)); +} + +int readElf32Hdr(FILE *objfile, PELF32HDR elf32hdr) +{ + unsigned char headbuf[52]; + PUCHAR hptr = headbuf; + + if(fread(headbuf,1,52,objfile)!=52) + { + return 0; + } + + memcpy(elf32hdr->e_ident, headbuf, EI_NIDENT); + hptr += EI_NIDENT; + elf32hdr->e_type = get16(&hptr); + elf32hdr->e_machine = get16(&hptr); + elf32hdr->e_version = get32(&hptr); + elf32hdr->e_entry = get32(&hptr); + elf32hdr->e_phoff = get32(&hptr); + elf32hdr->e_shoff = get32(&hptr); + elf32hdr->e_flags = get32(&hptr); + elf32hdr->e_ehsize = get16(&hptr); + elf32hdr->e_phentsize=get16(&hptr); + elf32hdr->e_phnum = get16(&hptr); + elf32hdr->e_shentsize=get16(&hptr); + elf32hdr->e_shnum = get16(&hptr); + elf32hdr->e_shtrndx = get16(&hptr); + + return 1; +} + +int readElf32SHdr(FILE *objfile, PELF32SHDR elf32shdr) +{ + unsigned char buf[40]; + PUCHAR bptr = buf; + + if(fread(buf,1,40,objfile)!=40) + { + return 0; + } + + elf32shdr->sh_name = get32(&bptr); + elf32shdr->sh_type = get32(&bptr); + elf32shdr->sh_flags = get32(&bptr); + elf32shdr->sh_addr = get32(&bptr); + elf32shdr->sh_offset = get32(&bptr); + elf32shdr->sh_size = get32(&bptr); + elf32shdr->sh_link = get32(&bptr); + elf32shdr->sh_info = get32(&bptr); + elf32shdr->sh_addralign =get32(&bptr); + elf32shdr->sh_entsize = get32(&bptr); + + return 1; +} + +int readElf32Sym(FILE *objfile, PELF32SYM elf32sym) +{ + unsigned char buf[16]; + unsigned char *bptr = buf; + + if(fread(buf,1,16,objfile)!=16) + { + return 0; + } + + elf32sym->st_name = get32(&bptr); + elf32sym->st_value = get32(&bptr); + elf32sym->st_size = get32(&bptr); + elf32sym->st_info = *bptr; bptr++; + elf32sym->st_other = *bptr; bptr++; + elf32sym->st_shndx = get16(&bptr); + + return 1; +} + +int readElf32Rel(FILE *objfile, PELF32RELX elf32rel) +{ + unsigned char buf[8]; + unsigned char *bptr = buf; + + if(fread(buf,1,8,objfile)!=8) + { + return 0; + } + + elf32rel->r_offset = get32(&bptr); + elf32rel->r_info = get32(&bptr); + elf32rel->r_address= 0; + + return 1; +} + +int readElf32Rela(FILE *objfile, PELF32RELX elf32rel) +{ + unsigned char buf[12]; + unsigned char *bptr = buf; + + if(fread(buf,1,12,objfile)!=12) + { + return 0; + } + + elf32rel->r_offset = get32(&bptr); + elf32rel->r_info = get32(&bptr); + elf32rel->r_address= get32(&bptr); + + return 1; +} + +void swapscn( PELF32SHDR seca, PELF32SHDR secb ) { + ELF32SHDR scn; + memcpy(&scn, seca, sizeof(scn)); + memcpy(seca, secb, sizeof(scn)); + memcpy(secb, &scn, sizeof(scn)); +} + +void loadelf(FILE *objfile) +{ + unsigned char buf[100]; + PUCHAR bigbuf; + std::vector stringList; + UINT thiscpu; + UINT symbolPtr = 0; + UINT numSymbols; + UINT stringPtr = 0; + UINT stringSize; + UINT stringOfs; + UINT curBase = 0; + UINT i,j,k,l; + UINT fileStart; + UINT relcount = 0; + UINT bss, bsscur = 0; + std::vector sym; + PPUBLIC pubdef; + PCOMDAT comdat; + PCHAR comdatsym; + SORTLIST::iterator listnode; + ELF32HDR elf32hdr; + std::vector elf32shdr; + int elf32sn = 0; + ELF32SYM elf32sym; + std::vector stringListOffsets; + int stringOffset = 0, secNum; + std::vector rel; + + fileStart=ftell(objfile); + + if(!readElf32Hdr(objfile, &elf32hdr)) + { + printf("Unable to read from file\n"); + exit(1); + } + + if( elf32hdr.e_machine == EM_386 ) + cpuIdent = PE_INTEL386; + else if( elf32hdr.e_machine == EM_PPC ) + cpuIdent = PE_POWERPC; + + if( !cpuIdent ) { + printf("Unsupported CPU type for module (type %x)\n", elf32hdr.e_machine); + exit(1); + } + + elf32shdr.resize((elf32hdr.e_shnum * 2) + 1); + memset(&elf32shdr[0], 0, (sizeof(elf32shdr[0]) * elf32hdr.e_shnum * 2) + 1); + stringListOffsets.resize(elf32hdr.e_shnum); + + /* Find a symbol section */ + for( i = 0; i < elf32hdr.e_shnum; i++ ) + { + int seekto = fileStart + elf32hdr.e_shoff + elf32hdr.e_shentsize * i; + if(fseek(objfile, seekto, 0)==-1) + { + printf("Short elf file (wanted to seek to %d)\n", seekto); + exit(1); + } + + if(!readElf32SHdr(objfile, &(elf32shdr[i]))) + { + printf("Could not read elf section header %d\n", i); + exit(1); + } + } + + /* Find string tables */ + for( i = 0; i < elf32hdr.e_shnum; i++ ) + { + if( elf32shdr[i].sh_type != SHT_STRTAB ) continue; + + stringPtr = elf32shdr[i].sh_offset; + stringSize = elf32shdr[i].sh_size + 1; + + if(fseek(objfile,fileStart+stringPtr,SEEK_SET)==-1) + { + printf("Short elf file, unable to seek to (%d)\n", stringPtr); + exit(1); + } + + if(stringSize) + { + stringList.resize(stringSize + stringOffset); + if(fread(&stringList[0]+stringOffset,1,stringSize - 1,objfile)!=stringSize - 1) + { + printf("Invalid elf object file, unable to read string table\n"); + exit(1); + } + stringList[stringSize-1] = 0; + + stringListOffsets[i] = stringOffset; + stringOffset += stringSize; + } + } + + /* Find segment order */ + for( i = 0; i < elf32hdr.e_shnum; i++ ) + { + const char *segname = (char *) + &stringList[0] + stringListOffsets[elf32hdr.e_shtrndx] + + elf32shdr[i].sh_name; + + if(elf32shdr[i].sh_type == SHT_REL || + elf32shdr[i].sh_type == SHT_RELA || + elf32shdr[i].sh_type == SHT_SYMTAB || + elf32shdr[i].sh_type == SHT_STRTAB) + continue; + + if(!strcmp(segname,".bss")) + { + bss = i; + bsscur = elf32shdr[i].sh_size; + } + } + + for( i = 0; i < elf32hdr.e_shnum; i++ ) + { + if(elf32shdr[i].sh_type == SHT_REL || + elf32shdr[i].sh_type == SHT_RELA || + elf32shdr[i].sh_type == SHT_SYMTAB || + elf32shdr[i].sh_type == SHT_STRTAB) + continue; + } + + memcpy(&elf32shdr[elf32hdr.e_shnum], &elf32shdr[0], sizeof(elf32shdr[0])); + + memcpy(&elf32shdr[0], &elf32shdr[elf32sn], sizeof(elf32shdr[0]) * elf32sn); + + elf32sn = elf32hdr.e_shnum; + + for( i = 0; i < elf32sn; i++ ) + { + if(stringPtr && !symbolPtr && elf32shdr[i].sh_type == SHT_SYMTAB) + { + int actualNum = 0; + + symbolPtr = elf32shdr[i].sh_offset; + numSymbols = elf32shdr[i].sh_size / ELF32SYMSIZE; + + if(fseek(objfile,fileStart+symbolPtr,SEEK_SET)==-1) + { + printf("Short elf file, unable to seek to (%d)\n", symbolPtr); + exit(1); + } + + sym.resize(numSymbols); + + for( j = 0; j < numSymbols; j++ ) + { + if(!readElf32Sym(objfile, &elf32sym)) + { + printf("Could not read elf symbol %d\n", i); + exit(1); + } + + sym[j].name = (char *) + (&stringList[stringListOffsets[elf32shdr[i].sh_link]] + + elf32sym.st_name); + +#if 0 + fprintf(stderr, + "S[%05x] value %08x size %08x info %08x " + "other %08x shndx %08x %s\n", + j, + elf32sym.st_value, elf32sym.st_size, elf32sym.st_info, + elf32sym.st_other, elf32sym.st_shndx, sym[j].name.c_str()); +#endif + + if(!case_sensitive) + { + strupr(sym[j].name); + } + + if(elf32sym.st_shndx == SHN_COMMON) + { + UINT thisbss = roundup(bsscur, elf32sym.st_value); + /* Round up bss objects */ + bsscur = thisbss + elf32sym.st_size; + sym[j].section = bss; + sym[j].value = thisbss; + sym[j].coff_class = COFF_SYM_EXTERNAL; + //fprintf( stderr, "BSS: @%08x(%04x) %s\n", sym[j].value, elf32sym.st_size, sym[j].name.c_str() ); + } + else + { + if(sym[j].name == entryPoint) + sym[j].coff_class = COFF_SYM_EXTERNAL; + else + sym[j].coff_class = COFF_SYM_STATIC; + sym[j].section = elf32sym.st_shndx; + sym[j].value = elf32sym.st_value; + } + + sym[j].extnum = -1; + sym[j].type = COFFTYPE(DT_FCN,T_NULL); + } + } + else if(elf32shdr[i].sh_type == SHT_REL || + elf32shdr[i].sh_type == SHT_RELA) + { + int rela = elf32shdr[i].sh_type == SHT_RELA; + int size = rela ? sizeof(ELF32RELA) : 8; + int oldrel = relcount; + + relcount+=elf32shdr[i].sh_size/size; + + rel.resize(relcount); + fseek(objfile,fileStart+elf32shdr[i].sh_offset,SEEK_SET); + + for( j = oldrel; j < relcount; j++ ) + { + if( rela ) + readElf32Rela(objfile, &rel[j]); + else + readElf32Rel(objfile, &rel[j]); + + rel[j].r_seg = elf32shdr[i].sh_info; + } + } + } + + for(i=0;iname= + (char *)&stringList[0] + stringListOffsets[elf32hdr.e_shtrndx] + + elf32shdr[i].sh_name; + seg->orderindex=0; + seg->classindex=-1; + seg->overlayindex=-1; + if(seg->name == ".bss") + { + seg->length = bsscur; + } + else + { + seg->length=elf32shdr[i].sh_size; + } + + seg->attr=SEG_PUBLIC|SEG_USE32|SEG_DWORD; + seg->winFlags=WINF_ALIGN_DWORD | WINF_READABLE; + seg->fileBase = elf32shdr[i].sh_offset; + seg->setbase(curBase); + if( wantSeg(seg) ) { + curBase += roundup(curBase + seg->length, objectAlign); + } else { + seg->winFlags |= WINF_REMOVE; + } + + if( elf32shdr[i].sh_flags & SHF_WRITE ) + seg->winFlags |= WINF_WRITEABLE; + + if( elf32shdr[i].sh_flags == 0 ) + seg->winFlags |= WINF_COMMENT; + + switch( elf32shdr[i].sh_type ) + { + case SHT_PROGBITS: + if( elf32shdr[i].sh_flags & SHF_EXECINSTR ) + seg->winFlags |= WINF_CODE | WINF_EXECUTE; + else + seg->winFlags |= WINF_INITDATA; + break; + + case SHT_NOBITS: + if( elf32shdr[i].sh_flags & SHF_WRITE ) + seg->winFlags |= WINF_UNINITDATA; + break; + + default: + break; + } + + if(seg->winFlags & WINF_ALIGN_NOPAD) + { + seg->winFlags &= ~WINF_ALIGN; + seg->winFlags |= WINF_ALIGN_BYTE; + } + + /* invert all negative-logic flags */ + seg->winFlags ^= WINF_NEG_FLAGS; + seg->datmask.resize(roundup(seg->length,8)/8); + seg->data.resize(roundup(seg->length,8)); + if(seg->name == ".bss") + { + memset(&seg->datmask[0], 0, seg->datmask.size()); + memset(&seg->data[0], 0, seg->data.size()); + } + else + { + memset(&seg->datmask[0], 0xff, seg->datmask.size()); + fseek(objfile, seg->fileBase, 0); + fread(&seg->data[0], 1, seg->length, objfile); + } + seglist.push_back(seg); + } + + for( i = 0; i < numSymbols; i++ ) { + sym[i].segptr = seglist[sym[i].section]; + + switch(sym[i].coff_class) + { + case COFF_SYM_SECTION: { /* section symbol */ + /* section symbols declare an extern always, so can use in relocs */ + /* they may also include a PUBDEF */ + EXTREC ext; + ext.name=(char *)sym[i].name.c_str(); + ext.pubdef=NULL; + ext.modnum=0; + ext.flags=EXT_NOMATCH; + sym[i].extnum=externs.size(); + externs.push_back(ext); + if(sym[i].section) /* if the section is defined here, make public */ + { + pubdef=new PUBLIC(); + pubdef->grpnum=-1; + pubdef->typenum=0; + pubdef->modnum=0; + pubdef->aliasName=""; + pubdef->name = sym[i].name; + pubdef->ofs=sym[i].value; + //fprintf(stderr, "sym[%05d] public %s\n", i, sym[i].name.c_str()); + + if(sym[i].section==-1) + { + pubdef->seg=NULL; + } + else + { + pubdef->seg=seglist[sym[i].section]; + } + if((listnode=publics.find(sym[i].name)) != publics.end()) + { + for(j=0;jsecond.size();++j) + { + if(((PPUBLIC)listnode->second[j])->modnum==pubdef->modnum) + { + if(((PPUBLIC)listnode->second[j])->aliasName=="") + { + printf("Duplicate public symbol %s\n",sym[i].name.c_str()); + exit(1); + } + (*((PPUBLIC)listnode->second[j]))=(*pubdef); + pubdef=NULL; + break; + } + } + } + if(pubdef) + { + SORTLIST::iterator it = publics.find(sym[i].name); + if( it == publics.end() ) { + std::vector vv; + vv.push_back((void *)pubdef); + publics.insert(std::make_pair(sym[i].name, vv)); + } else { + it->second.push_back((void *)pubdef); + } + } + } + } break; + + case COFF_SYM_EXTERNAL: + case COFF_SYM_STATIC: /* allowed, but ignored for now as we only want to process if required */ + case COFF_SYM_LABEL: + case COFF_SYM_FILE: + case COFF_SYM_FUNCTION: + break; + + default: + printf("unsupported symbol class %02X for symbol %s\n",sym[i].coff_class,sym[i].name.c_str()); + exit(1); + } + } + + for(i=0;iwinFlags & WINF_REMOVE) ) continue; + + PRELOC reloc = new RELOC(); + /* get address to relocate */ + reloc->ofs=rel[j].r_offset; + reloc->orig = rel[j]; + reloc->ftype = REL_SEGFRAME; + + /* get segment */ + reloc->seg = seglist[rel[j].r_seg]; + + if( cpuIdent == PE_INTEL386 ) + reloc->disp=4; + else + reloc->disp=rel[j].r_address; + + /* get relocation target external index */ + reloc->target=rel[j].r_info >> 8; + + if(reloc->target>=numSymbols) + { + printf("Invalid ELF object file, undefined symbol\n"); + exit(1); + } + k=reloc->target; + reloc->ttype=REL_EXTDISP; /* assume external reloc */ + + if(sym[k].extnum<0) + { + switch(sym[k].coff_class) + { + case COFF_SYM_EXTERNAL: { + /* global symbols declare an extern when used in relocs */ + EXTREC ext; + ext.name=sym[k].name; + ext.pubdef=NULL; + ext.modnum=0; + ext.flags=EXT_NOMATCH; + sym[k].extnum=externs.size(); + externs.push_back(ext); + /* they may also include a COMDEF or a PUBDEF */ + /* this is dealt with after all sections loaded, to cater + for COMDAT symbols */ + } break; + case COFF_SYM_STATIC: /* static symbol */ + case COFF_SYM_LABEL: /* code label symbol */ + /* update relocation information to reflect symbol */ + reloc->ttype=REL_SEGDISP; + reloc->disp=rel[j].r_address + sym[k].value; + reloc->targseg = seglist[sym[k].section]; + break; + default: + printf("undefined symbol class 0x%02X for symbol %s\n",sym[k].coff_class,sym[k].name.c_str()); + exit(1); + } + } + if(reloc->ttype==REL_EXTONLY || + reloc->ttype==REL_EXTDISP) + { + /* set relocation target to external if sym is external */ + reloc->target=sym[k].extnum; + } + + /* set relocation type */ + switch (rel[j].r_info & 0xff) + { + case R_PPC_ADDR32: + reloc->rtype = FIX_ADDR32; + break; + + case R_PPC_UADDR32: + reloc->rtype = FIX_RVA32; + break; + + case R_PPC_REL32: + reloc->rtype = FIX_REL32; + break; + + case R_PPC_ADDR24: + reloc->rtype = FIX_PPC_ADDR24; + break; + + case R_PPC_REL24: + reloc->rtype = FIX_PPC_REL24; + break; + + case R_PPC_ADDR16_LO: + reloc->rtype = FIX_PPC_RVA16LO; + break; + + case R_PPC_ADDR16_HA: + reloc->rtype = FIX_PPC_RVA16HA; + break; + + default: + printf("unsupported ELF relocation type %04X\n",rel[j].r_info & 0xff); + exit(1); + } + + relocs.push_back(reloc); + } + } + /* build PUBDEFs or COMDEFs for external symbols defined here that aren't COMDAT symbols. */ + for(i=0;igrpnum=-1; + pubdef->typenum=0; + pubdef->modnum=0; + pubdef->name = sym[i].name; + pubdef->aliasName=""; + pubdef->ofs=sym[i].value; + + if(sym[i].section==-1) + { + pubdef->seg=0; + } + else + { + pubdef->seg=seglist[sym[i].section]; + } + if((listnode=publics.find(sym[i].name)) != publics.end()) + { + for(j=0;jsecond.size();++j) + { + if(((PPUBLIC)listnode->second[j])->modnum==pubdef->modnum) + { + if(((PPUBLIC)listnode->second[j])->aliasName=="") + { + printf("Duplicate public symbol %s\n",sym[i].name.c_str()); + exit(1); + } + (*((PPUBLIC)listnode->second[j]))=(*pubdef); + pubdef=NULL; + break; + } + } + } + if(pubdef) + { + SORTLIST::iterator it = publics.find(sym[i].name); + if( it == publics.end() ) { + std::vector vv; + vv.push_back((void *)pubdef); + publics.insert(std::make_pair(sym[i].name,vv)); + } else { + it->second.push_back((void *)pubdef); + } + } + } + + for(i = 0; i < seglist.size(); i++) { + if(seglist[i]->winFlags & WINF_REMOVE) { + seglist.erase(seglist.begin()+i); + i--; + } + } +} diff --git a/reactos/tools/ppc-build/alink/license-note.txt b/reactos/tools/ppc-build/alink/license-note.txt new file mode 100644 index 00000000000..2bd342e7110 --- /dev/null +++ b/reactos/tools/ppc-build/alink/license-note.txt @@ -0,0 +1,8 @@ +I received permission from Anthony Williams to use alink as the basis for +the elf to coff conversion stage in reactos-powerpc. Thanks to Anthony +for writing alink in a way that made it possible to produce binaries for +reactos-powerpc, and for giving me permission to modify it despite the +license. + +This version of alink has been modified heavily, mostly for the benefit +of producing pe-coff powerpc executables. \ No newline at end of file diff --git a/reactos/tools/ppc-build/alink/objload.cpp b/reactos/tools/ppc-build/alink/objload.cpp new file mode 100644 index 00000000000..cc0cade733b --- /dev/null +++ b/reactos/tools/ppc-build/alink/objload.cpp @@ -0,0 +1,1441 @@ +#include "alink.h" + +#define strupr(x) + +char t_thred[4]; +char f_thred[4]; +int t_thredindex[4]; +int f_thredindex[4]; + +void DestroyLIDATA(PDATABLOCK p) +{ + long i; + if(p->blocks) + { + for(i=0;iblocks;i++) + { + DestroyLIDATA(((PPDATABLOCK)(&p->data[0]))[i]); + } + } + delete p; +} + +PDATABLOCK BuildLiData(long *bufofs) +{ + PDATABLOCK p; + long i,j; + + p=new DATABLOCK(); + i=*bufofs; + p->dataofs=i-lidata->dataofs; + p->count=buf[i]+256*buf[i+1]; + i+=2; + if(rectype==LIDATA32) + { + p->count+=(buf[i]+256*buf[i+1])<<16; + i+=2; + } + p->blocks=buf[i]+256*buf[i+1]; + i+=2; + if(p->blocks) + { + p->data.resize(p->blocks*sizeof(PDATABLOCK)); + for(j=0;jblocks;j++) + { + ((PPDATABLOCK)&p->data[0])[j]=BuildLiData(&i); + } + } + else + { + p->data.resize(buf[i]+1); + p->data[0]=buf[i]; + i++; + for(j=0;jdata[0];j++,i++) + { + p->data[j+1]=buf[i]; + } + } + *bufofs=i; + return p; +} + +void EmitLiData(PDATABLOCK p,long segnum,long *ofs) +{ + long i,j; + + for(i=0;icount;i++) + { + if(p->blocks) + { + for(j=0;jblocks;j++) + { + EmitLiData(((PPDATABLOCK)&p->data[0])[j],segnum,ofs); + } + } + else + { + for(j=0;jdata[0];j++,(*ofs)++) + { + if((*ofs)>=seglist[segnum]->length) + { + ReportError(ERR_INV_DATA); + } + if(GetNbit(seglist[segnum]->datmask,*ofs)) + { + if(seglist[segnum]->data[*ofs]!=p->data[j+1]) + { + ReportError(ERR_OVERWRITE); + } + } + seglist[segnum]->data[*ofs]=p->data[j+1]; + SetNbit(seglist[segnum]->datmask,*ofs); + } + } + } +} + +void RelocLIDATA(PDATABLOCK p,long *ofs,PRELOC r) +{ + long i,j; + + for(i=0;icount;i++) + { + if(p->blocks) + { + for(j=0;jblocks;j++) + { + RelocLIDATA(((PPDATABLOCK)&p->data[0])[j],ofs,r); + } + } + else + { + j=r->ofs-p->dataofs; + if(j>=0) + { + if((j<5) || ((li_le==PREV_LI32) && (j<7))) + { + ReportError(ERR_BAD_FIXUP); + } + PRELOC rel = new RELOC(*r); + rel->ofs = *ofs + j; + relocs.push_back(rel); + *ofs+=p->data[0]; + } + } + } +} + +segframe_t intToFrame(int f) +{ + return (segframe_t)f; +} + +segdisp_t intToDisp(int d) +{ + return (segdisp_t)(d + 0x80); +} + +void LoadFIXUP(PRELOC r,PUCHAR buf,long *p) +{ + long j; + int thrednum; + + j=*p; + + // arty -- come back to this + r->ftype=intToFrame(buf[j]>>4); + r->ttype=intToDisp(buf[j]&0xf); + r->disp=0; + j++; + if(r->ftype&FIX_THRED) + { + thrednum=r->ftype&THRED_MASK; + if(thrednum>3) + { + ReportError(ERR_BAD_FIXUP); + } + r->ftype=intToFrame((f_thred[thrednum]>>2)&7); + switch(r->ftype) + { + case REL_SEGFRAME: + case REL_GRPFRAME: + case REL_EXTFRAME: + r->frame=f_thredindex[thrednum]; + if(!r->frame) + { + ReportError(ERR_BAD_FIXUP); + } + break; + case REL_LILEFRAME: + case REL_TARGETFRAME: + break; + default: + ReportError(ERR_BAD_FIXUP); + } + switch(r->ftype) + { + case REL_SEGFRAME: + r->frame+=segmin-1; + break; + case REL_GRPFRAME: + r->frame+=grpmin-1; + break; + case REL_EXTFRAME: + r->frame+=extmin-1; + break; + case REL_LILEFRAME: + r->frame=prevseg; + break; + default: + break; + } + } + else + { + switch(r->ftype) + { + case REL_SEGFRAME: + case REL_GRPFRAME: + case REL_EXTFRAME: + r->frame=GetIndex(buf,&j); + if(!r->frame) + { + ReportError(ERR_BAD_FIXUP); + } + break; + case REL_LILEFRAME: + case REL_TARGETFRAME: + break; + default: + ReportError(ERR_BAD_FIXUP); + } + switch(r->ftype) + { + case REL_SEGFRAME: + r->frame+=segmin-1; + break; + case REL_GRPFRAME: + r->frame+=grpmin-1; + break; + case REL_EXTFRAME: + r->frame+=extmin-1; + break; + case REL_LILEFRAME: + r->frame=prevseg; + break; + default: + break; + } + } + if(r->ttype&FIX_THRED) + { + thrednum=r->ttype&3; + if((r->ttype&4)==0) /* P bit not set? */ + { + r->ttype=intToDisp((t_thred[thrednum]>>2)&3); /* DISP present */ + } + else + { + r->ttype=intToDisp(((t_thred[thrednum]>>2)&3) | 4); /* no disp */ + } + r->target=t_thredindex[thrednum]; + switch(r->ttype) + { + case REL_SEGDISP: + case REL_GRPDISP: + case REL_EXTDISP: + case REL_SEGONLY: + case REL_GRPONLY: + case REL_EXTONLY: + if(!r->target) + { + ReportError(ERR_BAD_FIXUP); + } + break; + case REL_EXPFRAME: + break; + default: + ReportError(ERR_BAD_FIXUP); + } + switch(r->ttype) + { + case REL_SEGDISP: + r->target+=segmin-1; + break; + case REL_GRPDISP: + r->target+=grpmin-1; + break; + case REL_EXTDISP: + r->target+=extmin-1; + break; + case REL_EXPFRAME: + break; + case REL_SEGONLY: + r->target+=segmin-1; + break; + case REL_GRPONLY: + r->target+=grpmin-1; + break; + case REL_EXTONLY: + r->target+=extmin-1; + break; + } + } + else + { + r->target=GetIndex(buf,&j); + switch(r->ttype) + { + case REL_SEGDISP: + case REL_GRPDISP: + case REL_EXTDISP: + case REL_SEGONLY: + case REL_GRPONLY: + case REL_EXTONLY: + if(!r->target) + { + ReportError(ERR_BAD_FIXUP); + } + break; + case REL_EXPFRAME: + break; + default: + ReportError(ERR_BAD_FIXUP); + } + switch(r->ttype) + { + case REL_SEGDISP: + r->target+=segmin-1; + break; + case REL_GRPDISP: + r->target+=grpmin-1; + break; + case REL_EXTDISP: + r->target+=extmin-1; + break; + case REL_EXPFRAME: + break; + case REL_SEGONLY: + r->target+=segmin-1; + break; + case REL_GRPONLY: + r->target+=grpmin-1; + break; + case REL_EXTONLY: + r->target+=extmin-1; + break; + } + } + switch(r->ttype) + { + case REL_SEGDISP: + case REL_GRPDISP: + case REL_EXTDISP: + case REL_EXPFRAME: + r->disp=get16(buf,j); + j+=2; + if(rectype==FIXUPP32) + { + r->disp+=get16(buf,j)<<16; + j+=2; + } + break; + default: + break; + } + if((r->ftype==REL_TARGETFRAME)&&((r->ttype&FIX_THRED)==0)) + { + switch(r->ttype) + { + case REL_SEGDISP: + r->ftype = REL_SEGFRAME; + break; + case REL_GRPDISP: + r->ftype = REL_GRPFRAME; + break; + case REL_EXTDISP: + r->ftype = REL_EXTFRAME; + break; + case REL_EXPFRAME: + r->ftype = REL_EXPFFRAME; + break; + case REL_SEGONLY: + r->ftype = REL_SEGFRAME; + break; + case REL_GRPONLY: + r->ftype = REL_GRPFRAME; + break; + case REL_EXTONLY: + r->ftype = REL_EXTFRAME; + break; + } + r->frame=r->target; + } + + *p=j; +} + +long loadmod(FILE *objfile) +{ + long modpos; + long done; + long i,j,k; + long segnum,grpnum; + PRELOC r; + PPUBLIC pubdef; + std::string name,aliasName; + SORTLIST::iterator listnode; + std::vector nlist; + + modpos=0; + done=0; + li_le=0; + lidata=0; + + while(!done) + { + if(fread(&buf[0],1,3,objfile)!=3) + { + ReportError(ERR_NO_MODEND); + } + rectype=buf[0]; + reclength=buf[1]+256*buf[2]; + if(fread(&buf[0],1,reclength,afile)!=reclength) + { + ReportError(ERR_NO_RECDATA); + } + reclength--; /* remove checksum */ + if((!modpos)&&(rectype!=THEADR)&&(rectype!=LHEADR)) + { + ReportError(ERR_NO_HEADER); + } + switch(rectype) + { + case THEADR: + case LHEADR: + if(modpos) + { + ReportError(ERR_EXTRA_HEADER); + } + modname.push_back(std::string((char *)&buf[1],buf[0])); + strupr(modname[nummods]); + /* printf("Loading module %s\n",modname[nummods]);*/ + if((buf[0]+1)!=reclength) + { + ReportError(ERR_EXTRA_DATA); + } + segmin=seglist.size(); + extmin=externs.size(); + fixmin=relocs.size(); + grpmin=grplist.size(); + impmin=impdefs.size(); + expmin=expdefs.size(); + commin=comdefs.size(); + break; + case COMENT: + li_le=0; + if(lidata) + { + DestroyLIDATA(lidata); + lidata=0; + } + if(reclength>=2) + { + switch(buf[1]) + { + case COMENT_LIB_SPEC: + case COMENT_DEFLIB: { + std::string newfilename((char *)&buf[2],reclength-2); + if(newfilename.find('.') == std::string::npos) + newfilename += ".lib"; + filename.push_back(newfilename); + } break; + case COMENT_OMFEXT: + if(reclength<4) + { + ReportError(ERR_INVALID_COMENT); + } + switch(buf[2]) + { + case EXT_IMPDEF: { + j=4; + if(reclength<(j+4)) + { + ReportError(ERR_INVALID_COMENT); + } + IMPREC imp; + imp.flags=buf[3]; + imp.int_name=std::string((char *)&buf[j+1]); + if(!case_sensitive) + { + strupr(impdefs[impdefs.size()].int_name); + } + j += buf.size() + 1; + imp.mod_name=std::string((char *)&buf[j+1]); + j += buf.size() + 1; + if(!case_sensitive) + { + strupr(impdefs[impdefs.size()].mod_name); + } + if(imp.flags) + { + imp.ordinal=buf[j]+256*buf[j+1]; + j+=2; + } + else + { + if(buf[j]) + { + imp.imp_name=std::string((char *)&buf[j]); + j += imp.imp_name.size() + 1; + } + else + { + imp.imp_name=imp.int_name; + } + } + impdefs.push_back(imp); + } break; + case EXT_EXPDEF: { + EXPREC exp; + j=4; + exp.flags=buf[3]; + exp.pubdef=NULL; + exp.exp_name = std::string((char *)&buf[j]+1,buf[j]); + j+=buf[j]+1; + if(buf[j]) + { + exp.int_name=std::string((char *)buf[j]+1,buf[j]); + if(!case_sensitive) + { + strupr(exp.int_name); + } + } + else + { + exp.int_name=exp.exp_name; + } + j+=buf[j]+1; + if(exp.flags&EXP_ORD) + { + exp.ordinal=buf[j]+256*buf[j+1]; + } + else + { + exp.ordinal=0; + } + expdefs.push_back(exp); + } break; + default: + ReportError(ERR_INVALID_COMENT); + } + break; + case COMENT_DOSSEG: + break; + case COMENT_TRANSLATOR: + case COMENT_INTEL_COPYRIGHT: + case COMENT_MSDOS_VER: + case COMENT_MEMMODEL: + case COMENT_NEWOMF: + case COMENT_LINKPASS: + case COMENT_LIBMOD: + case COMENT_EXESTR: + case COMENT_INCERR: + case COMENT_NOPAD: + case COMENT_WKEXT: + case COMENT_LZEXT: + case COMENT_PHARLAP: + case COMENT_IBM386: + case COMENT_RECORDER: + case COMENT_COMMENT: + case COMENT_COMPILER: + case COMENT_DATE: + case COMENT_TIME: + case COMENT_USER: + case COMENT_DEPFILE: + case COMENT_COMMANDLINE: + case COMENT_PUBTYPE: + case COMENT_COMPARAM: + case COMENT_TYPDEF: + case COMENT_STRUCTMEM: + case COMENT_OPENSCOPE: + case COMENT_LOCAL: + case COMENT_ENDSCOPE: + case COMENT_SOURCEFILE: + break; + default: + printf("COMENT Record (unknown type %02X)\n",buf[1]); + break; + } + } + break; + case LLNAMES: + case LNAMES: + j=0; + while(jattr=buf[0]; + j=1; + if((seg->attr & SEG_ALIGN)==SEG_ABS) + { + seg->absframe=get16(buf,j); + seg->absofs=buf[j+2]; + j+=3; + } + seg->length=buf[j]+256*buf[j+1]; + j+=2; + if(rectype==SEGDEF32) + { + seg->length+=get16(buf,j)<<16; + j+=2; + } + if(seg->attr&SEG_BIG) + { + if(rectype==SEGDEF) + { + seg->length+=65536; + } + else + { + if((seg->attr&SEG_ALIGN)!=SEG_ABS) + { + ReportError(ERR_SEG_TOO_LARGE); + } + } + } + seg->name=nlist[GetIndex(buf,&j)-1]; + seg->classindex=GetIndex(buf,&j)-1; + seg->overlayindex=GetIndex(buf,&j)-1; + seg->orderindex=-1; + if((seg->attr&SEG_ALIGN)!=SEG_ABS) + { + seg->data.resize(seg->length); + seg->datmask.resize((seg->length+7)/8); + for(i=0;i<(seg->length+7)/8;i++) + { + seg->datmask[i]=0; + } + } + else + { + seg->data.resize(0); + seg->datmask.resize(0); + seg->attr&=(0xffff-SEG_COMBINE); + seg->attr|=SEG_PRIVATE; + } + switch(seg->attr&SEG_COMBINE) + { + case SEG_PRIVATE: + case SEG_PUBLIC: + case SEG_PUBLIC2: + case SEG_COMMON: + case SEG_PUBLIC3: + break; + case SEG_STACK: + /* stack segs are always byte aligned */ + seg->attr&=(0xffff-SEG_ALIGN); + seg->attr|=SEG_BYTE; + break; + default: + ReportError(ERR_BAD_SEGDEF); + break; + } + if((seg->attr&SEG_ALIGN)==SEG_BADALIGN) + { + ReportError(ERR_BAD_SEGDEF); + } + if((seg->classindex>=0) && + (nlist[seg->classindex] == "CODE" || + nlist[seg->classindex] == "TEXT")) + { + /* code segment */ + seg->winFlags=WINF_CODE | WINF_INITDATA | WINF_EXECUTE | WINF_READABLE | WINF_NEG_FLAGS; + } + else /* data segment */ + seg->winFlags=WINF_INITDATA | WINF_READABLE | WINF_WRITEABLE | WINF_NEG_FLAGS; + + if(seg->name == "$$SYMBOLS" || + seg->name == "$$TYPES") + { + seg->winFlags |=WINF_REMOVE; + } + seglist.push_back(seg); + } break; + case LEDATA: + case LEDATA32: + j=0; + prevseg=GetIndex(buf,&j)-1; + if(prevseg<0) + { + ReportError(ERR_INV_SEG); + } + prevseg+=segmin; + if((seglist[prevseg]->attr&SEG_ALIGN)==SEG_ABS) + { + ReportError(ERR_ABS_SEG); + } + prevofs=buf[j]+(buf[j+1]<<8); + j+=2; + if(rectype==LEDATA32) + { + prevofs+=(buf[j]+(buf[j+1]<<8))<<16; + j+=2; + } + for(k=0;j=seglist[prevseg]->length) + { + ReportError(ERR_INV_DATA); + } + if(GetNbit(seglist[prevseg]->datmask,prevofs+k)) + { + if(seglist[prevseg]->data[prevofs+k]!=buf[j]) + { + printf("%08lX: %08lX: %i, %li,%li,%li\n",prevofs+k,j,GetNbit(seglist[prevseg]->datmask,prevofs+k),seglist.size(),segmin,prevseg); + ReportError(ERR_OVERWRITE); + } + } + seglist[prevseg]->data[prevofs+k]=buf[j]; + SetNbit(seglist[prevseg]->datmask,prevofs+k); + } + li_le=PREV_LE; + break; + case LIDATA: + case LIDATA32: + if(lidata) + { + DestroyLIDATA(lidata); + } + j=0; + prevseg=GetIndex(buf,&j)-1; + if(prevseg<0) + { + ReportError(ERR_INV_SEG); + } + prevseg+=segmin; + if((seglist[prevseg]->attr&SEG_ALIGN)==SEG_ABS) + { + ReportError(ERR_ABS_SEG); + } + prevofs=buf[j]+(buf[j+1]<<8); + j+=2; + if(rectype==LIDATA32) + { + prevofs+=(buf[j]+(buf[j+1]<<8))<<16; + j+=2; + } + lidata = new DATABLOCK(); + lidata->data.resize(sizeof(PDATABLOCK)*(1024/sizeof(DATABLOCK)+1)); + lidata->blocks=0; + lidata->dataofs=j; + for(i=0;jdata[0])[i]=BuildLiData(&j); + } + lidata->blocks=i; + lidata->count=1; + + k=prevofs; + EmitLiData(lidata,prevseg,&k); + li_le=(rectype==LIDATA)?PREV_LI:PREV_LI32; + break; + case LPUBDEF: + case LPUBDEF32: + case PUBDEF: + case PUBDEF32: + j=0; + grpnum=GetIndex(buf,&j)-1; + if(grpnum>=0) + { + grpnum+=grpmin; + } + segnum=GetIndex(buf,&j)-1; + if(segnum<0) + { + j+=2; + } + else + { + segnum+=segmin; + } + for(;jaliasName=""; + pubdef->grpnum=grpnum; + pubdef->seg=seglist[segnum]; + name=std::string((char *)&buf[j]+1,buf[j]); + j+=name.size()+1; + if(!case_sensitive) + { + strupr(name); + } + pubdef->ofs=buf[j]+256*buf[j+1]; + j+=2; + if((rectype==PUBDEF32) || (rectype==LPUBDEF32)) + { + pubdef->ofs+=(buf[j]+256*buf[j+1])<<16; + j+=2; + } + pubdef->typenum=GetIndex(buf,&j); + if(rectype==LPUBDEF || rectype==LPUBDEF32) + { + pubdef->modnum=modname.size()-1; + } + else + { + pubdef->modnum=0; + } + if((listnode=publics.find(name)) != publics.end()) + { + for(i=0;isecond.size();i++) + { + if(((PPUBLIC)listnode->second[i])->modnum==pubdef->modnum) + { + if(((PPUBLIC)listnode->second[i])->aliasName == "") + { + printf("Duplicate public symbol %s\n",name.c_str()); + exit(1); + } + (*((PPUBLIC)listnode->second[i]))=(*pubdef); + pubdef=NULL; + break; + } + } + } + if(pubdef) + { + SORTLIST::iterator l = publics.find(name); + if(l == publics.end()) { + std::vector vv; + vv.push_back((void *)pubdef); + publics.insert(std::make_pair(name,vv)); + } else { + l->second.push_back((void *)pubdef); + } + } + } + break; + case LEXTDEF: + case LEXTDEF32: + case EXTDEF: { + for(j=0;jname=nlist[GetIndex(buf,&j)-1]; + grp->numsegs=0; + while(jsegindex[grp->numsegs]=seglist[i]; + grp->numsegs++; + } + else + { + ReportError(ERR_BAD_GRPDEF); + } + } + grplist.push_back(grp); + } break; + case FIXUPP: + case FIXUPP32: + j=0; + while(jrtype=(buf[j]>>2); + r->ofs=buf[j]*256+buf[j+1]; + j+=2; + r->ofs&=0x3ff; + r->rtype^=FIX_SELFREL; + r->rtype&=FIX_MASK; + switch(r->rtype) + { + case FIX_LBYTE: + case FIX_OFS16: + case FIX_BASE: + case FIX_PTR1616: + case FIX_HBYTE: + case FIX_OFS16_2: + case FIX_OFS32: + case FIX_PTR1632: + case FIX_OFS32_2: + case FIX_SELF_LBYTE: + case FIX_SELF_OFS16: + case FIX_SELF_OFS16_2: + case FIX_SELF_OFS32: + case FIX_SELF_OFS32_2: + break; + default: + ReportError(ERR_BAD_FIXUP); + } + LoadFIXUP(r,&buf[0],&j); + + if(li_le==PREV_LE) + { + r->ofs+=prevofs; + r->seg=seglist[prevseg]; + PRELOC rel = new RELOC(*r); + relocs.push_back(rel); + } + else + { + r->seg=seglist[prevseg]; + i=prevofs; + RelocLIDATA(lidata,&i,r); + free(r); + } + } + else + { + /* THRED subrecord */ + i=buf[j]; /* get thred number */ + j++; + if(i&0x40) /* Frame? */ + { + f_thred[i&3]=i; + /* get index if required */ + if((i&0x1c)<0xc) + { + f_thredindex[i&3]=GetIndex(buf,&j); + } + i&=3; + } + else + { + t_thred[i&3]=i; + /* target always has index */ + t_thredindex[i&3]=GetIndex(buf,&j); + } + } + } + break; + case BAKPAT: + case BAKPAT32: + j=0; + if(jrtype=FIX_SELF_LBYTE; break; + case 1: rel->rtype=FIX_SELF_OFS16; break; + case 2: rel->rtype=FIX_SELF_OFS32; break; + default: + printf("Bad BAKPAT record\n"); + exit(1); + } + rel->ofs=buf[j]+256*buf[j+1]; + j+=2; + if(rectype==BAKPAT32) + { + rel->ofs+=(buf[j]+256*buf[j+1])<<16; + j+=2; + } + rel->seg=seglist[i]; + rel->target=i; + rel->frame=i; + rel->ttype=REL_SEGDISP; + rel->ftype=REL_SEGFRAME; + rel->disp=buf[j]+256*buf[j+1]; + j+=2; + if(rectype==BAKPAT32) + { + rel->disp+=(buf[j]+256*buf[j+1])<<16; + j+=2; + } + rel->disp+=rel->ofs; + switch(k) + { + case 0: rel->disp++; break; + case 1: rel->disp+=2; break; + case 2: rel->disp+=4; break; + default: + printf("Bad BAKPAT record\n"); + exit(1); + } + relocs.push_back(rel); + } + break; + case LINNUM: + case LINNUM32: + printf("LINNUM record\n"); + break; + case MODEND: + case MODEND32: + done=1; + if(buf[0]&0x40) + { + if(gotstart) + { + ReportError(ERR_MULTIPLE_STARTS); + } + gotstart=1; + j=1; + LoadFIXUP(&startaddr,&buf[0],&j); + if(startaddr.ftype==REL_LILEFRAME) + { + ReportError(ERR_BAD_FIXUP); + } + } + break; + case COMDEF: + for(j=0;jlength=i; + com->isFar=k; + com->modnum=0; + com->name=ext.name; + externs.push_back(ext); + comdefs.push_back(com); + } + + break; + case COMDAT: + case COMDAT32: + printf("COMDAT section\n"); + exit(1); + + break; + case ALIAS: + printf("ALIAS record\n"); + j=0; + name=std::string((char *)&buf[j]+1,buf[j]); + j+=name.size()+1; + if(!case_sensitive) + { + strupr(name); + } + printf("ALIAS name:%s\n",name.c_str()); + aliasName=std::string((char *)&buf[j]+1,buf[j]); + j+=aliasName.size()+1; + if(!case_sensitive) + { + strupr(aliasName); + } + printf("Substitute name:%s\n",aliasName.c_str()); + if(name.size()) + { + printf("Cannot use alias a blank name\n"); + exit(1); + } + if(!aliasName.size()) + { + printf("No Alias name specified for %s\n",name.c_str()); + exit(1); + } + pubdef=new PUBLIC(); + pubdef->seg=0; + pubdef->grpnum=-1; + pubdef->typenum=-1; + pubdef->ofs=0; + pubdef->modnum=0; + pubdef->aliasName=aliasName; + if((listnode=publics.find(name)) != publics.end()) + { + for(i=0;isecond.size();i++) + { + if(((PPUBLIC)listnode->second[i])->modnum==pubdef->modnum) + { + if(((PPUBLIC)listnode->second[i])->aliasName != "") + { + printf("Warning, two aliases for %s, using %s\n",name.c_str(),((PPUBLIC)listnode->second[i])->aliasName.c_str()); + } + free(pubdef); + pubdef=NULL; + break; + } + } + } + if(pubdef) + { + SORTLIST::iterator l = publics.find(name); + if(l == publics.end()) { + std::vector vv; + vv.push_back((void *)pubdef); + publics.insert(std::make_pair(name,vv)); + } else { + l->second.push_back((void *)pubdef); + } + } + break; + default: + ReportError(ERR_UNKNOWN_RECTYPE); + } + filepos+=4+reclength; + modpos+=4+reclength; + } + if(lidata) + { + DestroyLIDATA(lidata); + } + return 0; +} + +void loadlib(FILE *libfile,std::string libname) +{ + unsigned int i,j,k,n; + std::string name; + unsigned short modpage; + PLIBFILE p; + SORTLIST symlist; + + libfiles.push_back(LIBFILE()); + p=&libfiles[libfiles.size()-1]; + + p->filename=libname; + + if(fread(&buf[0],1,3,libfile)!=3) + { + printf("Error reading from file\n"); + exit(1); + } + p->blocksize=buf[1]+256*buf[2]; + if(fread(&buf[0],1,p->blocksize,libfile)<1) + { + printf("Error reading from file\n"); + exit(1); + } + p->blocksize+=3; + p->dicstart=buf[0]+(buf[1]<<8)+(buf[2]<<16)+(buf[3]<<24); + p->numdicpages=buf[4]+256*buf[5]; + p->flags=buf[6]; + p->libtype='O'; + + fseek(libfile,p->dicstart,SEEK_SET); + + for(i=0;inumdicpages;i++) + { + if(fread(&buf[0],1,512,libfile)!=512) + { + printf("Error reading from file\n"); + exit(1); + } + for(j=0;j<37;j++) + { + k=buf[j]*2; + if(k) + { + name=std::string((char *)&buf[k+1],buf[k]); + k+=buf[k]+1; + modpage=buf[k]+256*buf[k+1]; + if(!(p->flags&LIBF_CASESENSITIVE) || !case_sensitive) + { + strupr(name); + } + if(name[name.size()-1]=='!') + { + name = ""; + } + else + { + std::vector items; + items.resize(modpage); + symlist.insert(std::make_pair(name,items)); + } + } + } + } + + p->symbols=symlist; + p->modsloaded=0; +} + +void loadlibmod(UINT libnum,UINT modpage) +{ + PLIBFILE p; + FILE *libfile; + UINT i; + + p=&libfiles[libnum]; + + /* don't open a module we've loaded already */ + for(i=0;imodsloaded;i++) + { + if(p->modlist[i]==modpage) return; + } + + libfile=fopen(p->filename.c_str(),"rb"); + if(!libfile) + { + printf("Error opening file %s\n",p->filename.c_str()); + exit(1); + } + fseek(libfile,modpage*p->blocksize,SEEK_SET); + switch(p->libtype) + { + case 'O': + loadmod(libfile); + break; + case 'C': + loadcofflibmod(p,libfile); + break; + default: + printf("Unknown library file format\n"); + exit(1); + } + + p->modlist[p->modsloaded]=modpage; + p->modsloaded++; + fclose(libfile); +} + +void loadres(FILE *f) +{ + unsigned char buf[32]; + static unsigned char buf2[32]={0,0,0,0,0x20,0,0,0,0xff,0xff,0,0,0xff,0xff,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + UINT i,j; + UINT hdrsize,datsize; + std::vector data; + std::vector hdr; + + if(fread(buf,1,32,f)!=32) + { + printf("Invalid resource file\n"); + exit(1); + } + if(memcmp(buf,buf2,32)) + { + printf("Invalid resource file\n"); + exit(1); + } + printf("Loading Win32 Resource File\n"); + while(!feof(f)) + { + i=ftell(f); + if(i&3) + { + fseek(f,4-(i&3),SEEK_CUR); + } + i=fread(buf,1,8,f); + if(i==0 && feof(f)) return; + if(i!=8) + { + printf("Invalid resource file, no header\n"); + exit(1); + } + datsize=buf[0]+(buf[1]<<8)+(buf[2]<<16)+(buf[3]<<24); + hdrsize=buf[4]+(buf[5]<<8)+(buf[6]<<16)+(buf[7]<<24); + if(hdrsize<16) + { + printf("Invalid resource file, bad header\n"); + exit(1); + } + hdr.resize(hdrsize); + if(fread(&hdr[0],1,hdrsize-8,f)!=(hdrsize-8)) + { + printf("Invalid resource file, missing header\n"); + exit(1); + } + /* if this is a NULL resource, then skip */ + if(!datsize && (hdrsize==32) && !memcmp(buf2+8,&hdr[0],24)) + { + continue; + } + if(datsize) + { + data.resize(datsize); + if(fread(&data[0],1,datsize,f)!=datsize) + { + printf("Invalid resource file, no data\n"); + exit(1); + } + } + else data.resize(0); + RESOURCE res; + res.data=data; + res.length=datsize; + i=0; + hdrsize-=8; + if((hdr[i]==0xff) && (hdr[i+1]==0xff)) + { + res.xtypename.resize(0); + res.typeid=hdr[i+2]+256*hdr[i+3]; + i+=4; + } + else + { + for(j=i;(j<(hdrsize-1))&&(hdr[j]|hdr[j+1]);j+=2); + if(hdr[j]|hdr[j+1]) + { + printf("Invalid resource file, bad name\n"); + exit(1); + } + res.xtypename.resize(j-i+2); + memcpy(&res.xtypename[0],&hdr[i],j-i+2); + i=j+5; + i&=0xfffffffc; + } + if(i>hdrsize) + { + printf("Invalid resource file, overflow\n"); + exit(1); + } + if((hdr[i]==0xff) && (hdr[i+1]==0xff)) + { + res.name.resize(0); + res.id=hdr[i+2]+256*hdr[i+3]; + i+=4; + } + else + { + for(j=i;(j<(hdrsize-1))&&(hdr[j]|hdr[j+1]);j+=2); + if(hdr[j]|hdr[j+1]) + { + printf("Invalid resource file,bad name (2)\n"); + exit(1); + } + res.name.resize(j-i+2); + memcpy(&res.name[0],&hdr[i],j-i+2); + i=j+5; + i&=0xfffffffc; + } + i+=6; /* point to Language ID */ + if(i>hdrsize) + { + printf("Invalid resource file, overflow(2)\n"); + exit(1); + } + res.languageid=hdr[i]+256*hdr[i+1]; + resource.push_back(res); + } +} diff --git a/reactos/tools/ppc-build/alink/output.cpp b/reactos/tools/ppc-build/alink/output.cpp new file mode 100644 index 00000000000..262fbb810ee --- /dev/null +++ b/reactos/tools/ppc-build/alink/output.cpp @@ -0,0 +1,2435 @@ +#include "alink.h" +#include + +static unsigned char defaultStub[]={ + 0x4D,0x5A,0x6C,0x00,0x01,0x00,0x00,0x00, + 0x04,0x00,0x11,0x00,0xFF,0xFF,0x03,0x00, + 0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00, + 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x0E,0x1F,0xBA,0x0E,0x00,0xB4,0x09,0xCD, + 0x21,0xB8,0x00,0x4C,0xCD,0x21,0x54,0x68, + 0x69,0x73,0x20,0x70,0x72,0x6F,0x67,0x72, + 0x61,0x6D,0x20,0x72,0x65,0x71,0x75,0x69, + 0x72,0x65,0x73,0x20,0x57,0x69,0x6E,0x33, + 0x32,0x0D,0x0A,0x24,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +}; + +static UINT defaultStubSize=sizeof(defaultStub); + +void GetFixupTarget(PRELOC r,PSEG *bseg,UINT *tofs,int isFlat) +{ + PSEG baseseg = 0; + PSEG targseg = 0; + UINT targofs = 0; + UINT frameaddr = 0; + + if( r->seg ) + r->outputPos=r->seg->getbase()+r->ofs; + + switch(r->ftype) + { + case REL_SEGFRAME: + case REL_LILEFRAME: + baseseg=r->seg; + frameaddr = r->outputPos; + break; + case REL_GRPFRAME: + baseseg=r->seg; + break; + case REL_EXTFRAME: + switch(externs[r->frame].flags) + { + case EXT_MATCHEDPUBLIC: + if(!externs[r->frame].pubdef) + { + printf("Reloc:Unmatched extern %s\n",externs[r->frame].name.c_str()); + errcount++; + break; + } + + baseseg=externs[r->frame].pubdef->seg; + r->seg = baseseg; + frameaddr = externs[r->frame].pubdef->ofs + r->seg->getbase(); + break; + case EXT_MATCHEDIMPORT: + baseseg=impdefs[externs[r->frame].impnum].seg; + r->seg = baseseg; + break; + default: + errcount++; + exit(1); + break; + } + break; + default: + printf("Reloc:Unsupported FRAME type %i\n",r->ftype); + errcount++; + exit(1); + } + if(!baseseg) + { + printf("Undefined base seg\n"); + exit(1); + } /* this is a fix for TASM FLAT model, where FLAT group has no segments */ + + switch(r->ttype) + { + case REL_EXTDISP: + case REL_EXTONLY: + switch(externs[r->target].flags) + { + case EXT_MATCHEDPUBLIC: + if(!externs[r->target].pubdef) + { + printf("Reloc:Unmatched extern %s\n",externs[r->frame].name.c_str()); + errcount++; + break; + } + + targseg=externs[r->target].pubdef->seg; + targofs=externs[r->target].pubdef->ofs; + r->seg = targseg; + break; + case EXT_MATCHEDIMPORT: + targseg=impdefs[externs[r->target].impnum].seg; + targofs=impdefs[externs[r->target].impnum].ofs; + r->seg = targseg; + break; + default: + printf("Reloc:Unmatched external referenced in frame\n"); + errcount++; + targseg=seglist[0]; + targofs=0; + break; + } + targofs+=r->disp; + break; + case REL_SEGONLY: + targseg=r->targseg; + targofs=0; + break; + case REL_SEGDISP: + targseg=r->targseg; + targofs = r->disp; + break; + case REL_GRPONLY: + targseg=grplist[r->target]->seg; + targofs=0; + break; + case REL_GRPDISP: + targseg=grplist[r->target]->seg; + targofs=r->disp; + break; + default: + printf("Reloc:Unsupported TARGET type %i\n",r->ttype); + errcount++; + } + if(targseg<0) + { + printf("undefined seg\n"); + exit(1); + } + if(!errcount && !targseg) + { + printf("Reloc: no target segment\n"); + + errcount++; + } + if(!errcount && !baseseg) + { + printf("reloc: no base segment\n"); + + errcount++; + } + + if(!errcount) + { +/* + if(((seglist[targseg]->attr&SEG_ALIGN)!=SEG_ABS) && + ((seglist[baseseg]->attr&SEG_ALIGN)!=SEG_ABS)) + { + if(seglist[baseseg]->getbase()>seglist[targseg]->getbase()) + { + printf("Reloc:Negative base address\n"); + errcount++; + } + targofs+=seglist[targseg]->getbase()-seglist[baseseg]->getbase(); + } +*/ + if((baseseg->attr&SEG_ALIGN)==SEG_ABS) + { + //printf("Warning: Reloc frame is absolute segment\n"); + targseg=baseseg; + } + else if((targseg->attr&SEG_ALIGN)==SEG_ABS) + { + //printf("Warning: Reloc target is in absolute segment\n"); + targseg=baseseg; + } + if(!isFlat || ((baseseg->attr&SEG_ALIGN)==SEG_ABS)) + { + if(baseseg->getbase()>(targseg->getbase()+targofs)) + { + printf("Error: target address out of frame\n"); + printf("Base=%08X,target=%08X\n", + baseseg->getbase(),targseg->getbase()+targofs); + errcount++; + } + targofs+=targseg->getbase()-baseseg->getbase(); + *bseg=baseseg; + *tofs=targofs; + } + else + { + *bseg=0; + *tofs=targofs+targseg->getbase(); + if(r->rtype == FIX_REL32 ) + *tofs -= frameaddr; + } + } + else + { + printf("relocation error occurred\n"); + *bseg=0; + *tofs=0; + exit(1); + } +} + + +void OutputCOMfile(const std::string &outname) +{ + long i,j; + UINT started; + UINT lastout; + PSEG targseg; + UINT targofs; + FILE*outfile; + PSEG seg; + unsigned short temps; + unsigned long templ; + + if(impsreq) + { + ReportError(ERR_ILLEGAL_IMPORTS); + } + + errcount=0; + if(gotstart) + { + GetFixupTarget(&startaddr,&seg,&startaddr.ofs,FALSE); + if(errcount) + { + printf("Invalid start address record\n"); + exit(1); + } + + if((startaddr.ofs+startaddr.seg->getbase())!=0x100) + { + printf("Warning, start address not 0100h as required for COM file\n"); + } + } + else + { + printf("Warning, no entry point specified\n"); + } + + for(i=0;iseg; + switch(relocs[i]->rtype) + { + case FIX_BASE: + case FIX_PTR1616: + case FIX_PTR1632: + if((targseg->attr&SEG_ALIGN)!=SEG_ABS) + { + printf("Reloc %li:Segment selector relocations are not supported in COM files\n",i); + errcount++; + } + else + { + j=relocs[i]->ofs; + if(relocs[i]->rtype==FIX_PTR1616) + { + if(targofs>0xffff) + { + printf("Relocs %li:Offset out of range\n",i); + errcount++; + } + temps=get16(seg->data,j); + temps+=targofs; + temps+=targseg->getbase()&0xf; /* non-para seg */ + put16(seg->data,j,temps); + j+=2; + } + else if(relocs[i]->rtype==FIX_PTR1632) + { + templ=get32(seg->data,j); + templ+=targofs; + templ+=targseg->getbase()&0xf; /* non-para seg */ + put32(seg->data,j,templ); + j+=4; + } + temps = get16(seg->data,j); + temps+=targseg->absframe; + put16(seg->data,j,temps); + } + break; + case FIX_OFS32: + case FIX_OFS32_2: + templ=get32(seg->data,relocs[i]->ofs); + templ+=targofs; + templ+=targseg->getbase()&0xf; /* non-para seg */ + put32(seg->data,relocs[i]->ofs,templ); + break; + case FIX_OFS16: + case FIX_OFS16_2: + if(targofs>0xffff) + { + printf("Relocs %li:Offset out of range\n",i); + errcount++; + } + temps=get16(seg->data, relocs[i]->ofs); + temps+=targofs; + temps+=targseg->getbase()&0xf; /* non-para seg */ + put16(seg->data, relocs[i]->ofs, temps); + break; + case FIX_LBYTE: + seg->data[relocs[i]->ofs]+=targofs&0xff; + seg->data[relocs[i]->ofs]+=targseg->getbase()&0xf; /* non-para seg */ + break; + case FIX_HBYTE: + templ=targofs+(targseg->getbase()&0xf); /* non-para seg */ + seg->data[relocs[i]->ofs]+=(templ>>8)&0xff; + break; + case FIX_SELF_LBYTE: + if((targseg->attr&SEG_ALIGN)==SEG_ABS) + { + printf("Error: Absolute Reloc target not supported for self-relative fixups\n"); + errcount++; + } + else + { + j=targseg->getbase()+targofs; + j-=seg->getbase()+relocs[i]->ofs+1; + if((j<-128)||(j>127)) + { + printf("Error: Reloc %li out of range\n",i); + } + else + { + seg->data[relocs[i]->ofs]+=j; + } + } + break; + case FIX_SELF_OFS16: + case FIX_SELF_OFS16_2: + if((targseg->attr&SEG_ALIGN)==SEG_ABS) + { + printf("Error: Absolute Reloc target not supported for self-relative fixups\n"); + errcount++; + } + else + { + j=targseg->getbase()+targofs; + j-=seg->getbase()+relocs[i]->ofs+2; + if((j<-32768)||(j>32767)) + { + printf("Error: Reloc %li out of range\n",i); + } + else + { + temps=get16(seg->data, relocs[i]->ofs); + temps+=j; + put16(seg->data, relocs[i]->ofs, temps); + } + } + break; + case FIX_SELF_OFS32: + case FIX_SELF_OFS32_2: + if((targseg->attr&SEG_ALIGN)==SEG_ABS) + { + printf("Error: Absolute Reloc target not supported for self-relative fixups\n"); + errcount++; + } + else + { + j=targseg->getbase()+targofs; + j-=seg->getbase()+relocs[i]->ofs+4; + templ=get32(seg->data, relocs[i]->ofs); + templ+=j; + put32(seg->data, relocs[i]->ofs, templ); + } + break; + default: + printf("Reloc %li:Relocation type %i not supported\n",i,relocs[i]->rtype); + errcount++; + } + } + + if(errcount!=0) + { + exit(1); + } + outfile=fopen(outname.c_str(),"wb"); + if(!outfile) + { + printf("Error writing to file %s\n",outname.c_str()); + exit(1); + } + + started=lastout=0; + + for(i=0;iattr&SEG_ALIGN) !=SEG_ABS)) + { + if(started>outlist[i]->getbase()) + { + printf("Segment overlap\n"); + fclose(outfile); + exit(1); + } + if(padsegments) + { + while(startedgetbase()) + { + fputc(0,outfile); + started++; + } + } + else + { + started=outlist[i]->getbase(); + } + for(j=0;jlength;j++) + { + if(started>=0x100) + { + if(GetNbit(outlist[i]->datmask,j)) + { + for(;lastoutdata[j],outfile); + lastout=started+1; + } + else if(padsegments) + { + fputc(0,outfile); + lastout=started+1; + } + } + else + { + lastout=started+1; + if(GetNbit(outlist[i]->datmask,j)) + { + printf("Warning - data at offset %08lX (%s:%08lX) discarded\n",started,outlist[i]->name.c_str(),j); + } + } + started++; + } + } + } + + fclose(outfile); +} + +void OutputEXEfile(const std::string &outname) +{ + long i,j; + UINT started,lastout; + PSEG targseg; + UINT targofs; + FILE*outfile; + std::vector headbuf; + long relcount; + int gotstack; + UINT totlength; + PSEG seg; + unsigned short temps; + unsigned long templ; + + if(impsreq) + { + ReportError(ERR_ILLEGAL_IMPORTS); + } + + errcount=0; + gotstack=0; + headbuf.resize(0x40 + (4*relocs.size())); + relcount=0; + + for(i=0;i<0x40;i++) + { + headbuf[i]=0; + } + + headbuf[0x00]='M'; /* sig */ + headbuf[0x01]='Z'; + put16(headbuf, 0x0c, maxalloc); + headbuf[0x18]=0x40; + + if(gotstart) + { + GetFixupTarget(&startaddr,&seg,&startaddr.ofs,FALSE); + if(errcount) + { + printf("Invalid start address record\n"); + exit(1); + } + + i=startaddr.seg->getbase(); + startaddr.ofs+=i&0xf; + i>>=4; + if((startaddr.ofs>65535)||(i>65535)||((startaddr.seg->attr&SEG_ALIGN)==SEG_ABS)) + { + printf("Invalid start address\n"); + errcount++; + } + else + { + put16(headbuf, 0x14, startaddr.ofs); + put16(headbuf, 0x16, i); + } + } + else + { + printf("Warning, no entry point specified\n"); + } + + totlength=0; + + for(i=0;iattr&SEG_ALIGN)!=SEG_ABS) + { + totlength=outlist[i]->getbase()+outlist[i]->length; + if((outlist[i]->attr&SEG_COMBINE)==SEG_STACK) + { + if(gotstack) + { + printf("Internal error - stack segments not combined\n"); + exit(1); + } + gotstack=1; + if((outlist[i]->length>65536)||(outlist[i]->length==0)) + { + printf("SP value out of range\n"); + errcount++; + } + if((outlist[i]->getbase()>0xfffff) || ((outlist[i]->getbase()&0xf)!=0)) + { + printf("SS value out of range\n"); + errcount++; + } + if(!errcount) + { + put16(headbuf, 0x0e, outlist[i]->getbase() >> 4); + put16(headbuf, 0x10, outlist[i]->length); + } + } + } + } + + if(!gotstack) + { + printf("Warning - no stack\n"); + } + + for(i=0;iseg; + GetFixupTarget(relocs[i],&targseg,&targofs,FALSE); + switch(relocs[i]->rtype) + { + case FIX_BASE: + case FIX_PTR1616: + case FIX_PTR1632: + j=relocs[i]->ofs; + if(relocs[i]->rtype==FIX_PTR1616) + { + if(targofs>0xffff) + { + printf("Relocs %li:Offset out of range\n",i); + errcount++; + } + temps=get16(seg->data,j); + temps+=targofs; + temps+=targseg->getbase()&0xf; /* non-para seg */ + put16(seg->data,j,temps); + j+=2; + } + else if(relocs[i]->rtype==FIX_PTR1632) + { + templ=get32(seg->data,j); + templ+=targofs; + templ+=targseg->getbase()&0xf; /* non-para seg */ + put32(seg->data,j,templ); + j+=4; + } + if((targseg->attr&SEG_ALIGN)!=SEG_ABS) + { + if(targseg->getbase()>0xfffff) + { + printf("Relocs %li:Segment base out of range\n",i); + errcount++; + } + temps=get16(seg->data,j); + temps+=(targseg->getbase()>>4); + put16(seg->data,j,temps); + templ=seg->getbase()>>4; + put16(headbuf,0x40+relcount*4+2,templ); + templ=(seg->getbase()&0xf)+j; + put16(headbuf,0x40+relcount+4,templ); + relcount++; + } + else + { + temps=get16(seg->data,j); + temps+=targseg->absframe; + put16(seg->data,j,temps); + } + break; + case FIX_OFS32: + case FIX_OFS32_2: + templ=get32(seg->data,relocs[i]->ofs); + templ+=targofs; + templ+=targseg->getbase()&0xf; /* non-para seg */ + put32(seg->data, relocs[i]->ofs, templ); + break; + case FIX_OFS16: + case FIX_OFS16_2: + if(targofs>0xffff) + { + printf("Relocs %li:Offset out of range\n",i); + errcount++; + } + temps = get32(seg->data, relocs[i]->ofs); + temps+=targofs; + temps+=targseg->getbase()&0xf; /* non-para seg */ + put32(seg->data, relocs[i]->ofs, temps); + break; + case FIX_LBYTE: + seg->data[relocs[i]->ofs]+=targofs&0xff; + seg->data[relocs[i]->ofs]+=targseg->getbase()&0xf; /* non-para seg */ + break; + case FIX_HBYTE: + templ=targofs+(targseg->getbase()&0xf); /* non-para seg */ + seg->data[relocs[i]->ofs]+=(templ>>8)&0xff; + break; + case FIX_SELF_LBYTE: + if((targseg->attr&SEG_ALIGN)==SEG_ABS) + { + printf("Error: Absolute Reloc target not supported for self-relative fixups\n"); + errcount++; + } + else + { + j=targseg->getbase()+targofs; + j-=seg->getbase()+relocs[i]->ofs+1; + if((j<-128)||(j>127)) + { + printf("Error: Reloc %li out of range\n",i); + } + else + { + seg->data[relocs[i]->ofs]+=j; + } + } + break; + case FIX_SELF_OFS16: + case FIX_SELF_OFS16_2: + if((targseg->attr&SEG_ALIGN)==SEG_ABS) + { + printf("Error: Absolute Reloc target not supported for self-relative fixups\n"); + errcount++; + } + else + { + j=targseg->getbase()+targofs; + j-=seg->getbase()+relocs[i]->ofs+2; + if((j<-32768)||(j>32767)) + { + printf("Error: Reloc %li out of range\n",i); + } + else + { + temps = get32(seg->data, relocs[i]->ofs); + temps+=j; + put32(seg->data, relocs[i]->ofs, temps); + } + } + break; + case FIX_SELF_OFS32: + case FIX_SELF_OFS32_2: + if((targseg->attr&SEG_ALIGN)==SEG_ABS) + { + printf("Error: Absolute Reloc target not supported for self-relative fixups\n"); + errcount++; + } + else + { + j=targseg->getbase()+targofs; + j-=seg->getbase()+relocs[i]->ofs+4; + templ=get32(seg->data,relocs[i]->ofs); + templ+=j; + put32(seg->data,relocs[i]->ofs,templ); + } + break; + default: + printf("Reloc %li:Relocation type %i not supported\n",i,relocs[i]->rtype); + errcount++; + } + } + + if(relcount>65535) + { + printf("Too many relocations\n"); + exit(1); + } + + put32(headbuf, 0x06, relcount); + i=relcount*4+0x4f; + i>>=4; + totlength+=i<<4; + put32(headbuf, 0x08, i); + i=totlength%512; + put32(headbuf, 0x02, i); + i=(totlength+0x1ff)>>9; + if(i>65535) + { + printf("File too large\n"); + exit(1); + } + put32(headbuf, 0x04, i); + + if(errcount!=0) + { + exit(1); + } + + outfile=fopen(outname.c_str(),"wb"); + if(!outfile) + { + printf("Error writing to file %s\n",outname.c_str()); + exit(1); + } + + i=get32(headbuf, 8) * 16; + if(fwrite(&headbuf[0],1,i,outfile)!=i) + { + printf("Error writing to file %s\n",outname.c_str()); + exit(1); + } + + started=0; + lastout=0; + + for(i=0;iattr&SEG_ALIGN) !=SEG_ABS)) + { + if(started>outlist[i]->getbase()) + { + printf("Segment overlap\n"); + fclose(outfile); + exit(1); + } + if(padsegments) + { + while(startedgetbase()) + { + fputc(0,outfile); + started++; + } + } + else + { + started=outlist[i]->getbase(); + } + for(j=0;jlength;j++) + { + if(GetNbit(outlist[i]->datmask,j)) + { + for(;lastoutdata[j],outfile); + lastout=started+1; + } + else if(padsegments) + { + fputc(0,outfile); + lastout=started+1; + } + started++; + } + } + } + + if(lastout!=started) + { + fseek(outfile,0,SEEK_SET); + lastout+=(headbuf[8]+256*headbuf[9])<<4; + i=lastout%512; + put32(headbuf, 2, i); + i=(lastout+0x1ff)>>9; + put32(headbuf, 4, i); + i=((totlength-lastout)+0xf)>>4; + if(i>65535) + { + printf("Memory requirements too high\n"); + } + put32(headbuf, 10, i); + if(fwrite(&headbuf[0],1,12,outfile)!=12) + { + printf("Error writing to file\n"); + exit(1); + } + } + fclose(outfile); +} + +long createOutputSection(char *name,UINT winFlags) +{ + UINT j; + PSEG seg = new SEG(); + + outlist.push_back(seg); + seglist.push_back(seg); + seg->name = name; + seg->classindex=-1; + seg->overlayindex=-1; + j=outlist[outlist.size()-1]->getbase()+outlist[outlist.size()-1]->length; + j+=(objectAlign-1); + j&=(0xffffffff-(objectAlign-1)); + seg->setbase(j); + seg->length=0; + seg->data.resize(0); + seg->datmask.resize(0); + seg->absofs=seglist.size()-1; + seg->attr=SEG_BYTE | SEG_PRIVATE; + seg->winFlags=winFlags ^ WINF_NEG_FLAGS; + return outlist.size()-1; +} + +void BuildPEImports(long impsectNum,PUCHAR objectTable) +{ + long i,j,k; + std::vector reqimps; + std::vector dllNames; + UINT reqcount=0; + std::vector dllNumImps, dllImpsDone, dllImpNameSize; + UINT dllCount=0,dllNameSize=0,namePos; + PSEG impsect; + UINT thunkPos,thunk2Pos,impNamePos; + + if(impsectNum<0) return; + for(i=0;isetbase(k+imageBase); /* get base address of section */ + + impsect->length=(dllCount+1)*PE_IMPORTDIRENTRY_SIZE+dllNameSize; + if(impsect->length&3) impsect->length+=4-(impsect->length&3); /* align to 4-byte boundary */ + thunkPos=impsect->getbase()+impsect->length; + for(j=0,i=0;jlength+=i*2*4; /* update length of section too. */ + + for(j=0,i=0;jlength+=i; + + impsect->data.resize(impsect->length); + impsect->datmask.resize((impsect->length+7)/8); + for(i=0;i<(impsect->length+7)/8;i++) + { + impsect->datmask[i]=0xff; + } + + /* end of directory entries=name table */ + namePos=impsect->getbase()+(dllCount+1)*PE_IMPORTDIRENTRY_SIZE; + for(i=0;idata, j, thunkPos-imageBase); /* address of first thunk table */ + put32(impsect->data, j+4, 0); /* zero out time stamp */ + put32(impsect->data, j+8, 0); /* zero out version number */ + put32(impsect->data, j+12, namePos-imageBase); /* address of DLL name */ + thunk2Pos=thunkPos+(dllNumImps[i]+1)*4; /* address of second thunk table */ + put32(impsect->data, j+16, thunk2Pos-imageBase); /* store it */ + + /* add name to table */ + strcpy((char *)(&impsect->data[0])+namePos-impsect->getbase(),(char *)dllNames[i].c_str()); + namePos+=dllNames[i].size()+1; + if(namePos&1) + { + impsect->data[namePos-impsect->getbase()]=0; + namePos++; + } + /* add imported names to table */ + for(k=0;kdata, thunkPos-impsect->getbase(), impNamePos-imageBase); + put32(impsect->data, thunk2Pos-impsect->getbase(), impNamePos-imageBase); + + /* no hint */ + put16(impsect->data, impNamePos-impsect->getbase(), 0); + impNamePos+=2; + /* store name */ + strcpy((char *)(&impsect->data[0])+impNamePos-impsect->getbase(), + (char *)impdefs[reqimps[k]].imp_name.c_str()); + impNamePos+=strlen(impdefs[reqimps[k]].imp_name.c_str())+1; + if(impNamePos&1) + { + impsect->data[impNamePos-impsect->getbase()]=0; + impNamePos++; + } + } + else + { + /* store ordinal number in thunk tables */ + j=impdefs[reqimps[k]].ordinal+PE_ORDINAL_FLAG; + put32(impsect->data, thunkPos-impsect->getbase(), j); + put32(impsect->data, thunk2Pos-impsect->getbase(), j); + } + impdefs[reqimps[k]].abs=impsect->absofs; + impdefs[reqimps[k]].ofs=thunk2Pos-impsect->getbase(); + thunkPos+=4; + thunk2Pos+=4; + } + /* zero out end of thunk tables */ + put32(impsect->data, thunkPos-impsect->getbase(), 0); + put32(impsect->data, thunk2Pos-impsect->getbase(), 0); + thunkPos=thunk2Pos+4; + } + /* zero out the final entry to mark the end of the table */ + j=i*PE_IMPORTDIRENTRY_SIZE; + for(i=0;idata[j]=0; + } + + k=impsect->length; + k+=objectAlign-1; + k&=(0xffffffff-(objectAlign-1)); + impsect->virtualSize=k; + put32(objectTable, 8, k); /* store virtual size (in memory) of segment */ + + k=impsect->length; + put32(objectTable, 16, k); /* store initialised data size */ + + return; +} + +int compar( const void *a, const void *b ) +{ + PRELOC aa = *((PRELOC *)a); + PRELOC bb = *((PRELOC *)b); + + return (aa->outputPos < bb->outputPos) ? -1 : (aa->outputPos > bb->outputPos) ? 1 : 0; +} + +void BuildPERelocs(long relocSectNum,PUCHAR objectTable) +{ + int i,j,r; + PSEG relocSect, seg; + UINT curStartPos; + UINT curBlockPos; + UINT k; + PSEG targseg; + UINT targofs; + unsigned long templ, tinit; + unsigned short temps; + + /* do fixups */ + for(i=0;iseg; + GetFixupTarget(relocs[i],&targseg,&targofs,TRUE); + + assert(seg->length > relocs[i]->ofs+3); + + switch(relocs[i]->rtype) + { + case FIX_BASE: + case FIX_PTR1616: + case FIX_PTR1632: + if(targseg<0) + { + printf("Reloc %li:Segment selector relocations are not supported in PE files\n",i); + printf("rtype=%02X, frame=%04X, target=%04X, ftype=%02X, ttype=%02X\n", + relocs[i]->rtype,relocs[i]->frame,relocs[i]->target,relocs[i]->ftype, + relocs[i]->ttype); + + errcount++; + } + else + { + j=relocs[i]->ofs; + if(relocs[i]->rtype==FIX_PTR1616) + { + if(targofs>0xffff) + { + printf("Relocs %li:Warning 32 bit offset in 16 bit field\n",i); + } + targofs&=0xffff; + temps=get16(seg->data, j); + temps+=targofs; + put16(seg->data, j, temps); + j+=2; + } + else if(relocs[i]->rtype==FIX_PTR1632) + { + templ = get32(seg->data, j); + templ+=targofs; + put32(seg->data, j, templ); + j+=4; + } + temps = get16(seg->data, j); + temps+=targseg->absframe; + put16(seg->data, j, temps); + } + break; + case FIX_OFS32: + case FIX_OFS32_2: + templ = get32(seg->data, relocs[i]->ofs); + templ+=targofs; + put32(seg->data, relocs[i]->ofs, templ); + break; + case FIX_PPC_ADDR24: + templ = get32(seg->data, relocs[i]->ofs); + tinit = templ; templ = targofs; + put32(seg->data, relocs[i]->ofs, templ); + break; + case FIX_PPC_REL24: + templ = get32(seg->data, relocs[i]->ofs); + tinit = templ; + //templ += (targofs - seg->getbase() - relocs[i]->ofs) & 0x3ffffc; + //templ |= tinit & 3; + templ = (templ & 0xfc000003) | + (targofs - seg->getbase() - relocs[i]->ofs) & 0x3fffffc; + put32(seg->data, relocs[i]->ofs, templ); + break; + case FIX_PPC_SECTOFF: + templ = get32(seg->data, relocs[i]->ofs); + tinit = templ; templ =+ targofs - imageBase; + put32(seg->data, relocs[i]->ofs, templ); + break; + case FIX_PPC_RVA16LO: + templ = get16(seg->data, relocs[i]->ofs); + tinit = templ; templ = targofs; + put16(seg->data, relocs[i]->ofs, templ); + break; + case FIX_PPC_RVA16HA: + templ = get16(seg->data, relocs[i]->ofs) << 16; + tinit = templ; templ = targofs; + /* High adjust */ + if( templ & 0x8000 ) templ += 0x8000; + put16(seg->data, relocs[i]->ofs, templ >> 16); + break; + case FIX_ADDR32: + templ = get32(seg->data, relocs[i]->ofs); + tinit = templ; templ = targofs; + put32(seg->data, relocs[i]->ofs, templ); + break; + case FIX_RVA32: + templ = get32(seg->data, relocs[i]->ofs); + tinit = templ; templ =targofs - imageBase; + put32(seg->data, relocs[i]->ofs, templ); + break; + case FIX_REL32: + templ = get32(seg->data, relocs[i]->ofs); + tinit = templ; templ=targofs; + put32(seg->data, relocs[i]->ofs, templ); + break; + case FIX_OFS16: + case FIX_OFS16_2: + if(targofs>0xffff) + { + printf("Relocs %li:Warning 32 bit offset in 16 bit field\n",i); + } + targofs&=0xffff; + temps = get16(seg->data, relocs[i]->ofs); + temps+=targofs; + put16(seg->data, relocs[i]->ofs, temps); + break; + case FIX_LBYTE: + case FIX_HBYTE: + printf("Error: Byte relocations not supported in PE files\n"); + errcount++; + break; + case FIX_SELF_LBYTE: + if(targseg>=0) + { + printf("Error: Absolute Reloc target not supported for self-relative fixups\n"); + errcount++; + } + else + { + j=targofs; + j-=(seg->getbase()+relocs[i]->ofs+1); + if((j<-128)||(j>127)) + { + printf("Error: Reloc %li out of range\n",i); + } + else + { + seg->data[relocs[i]->ofs]+=j; + } + } + break; + case FIX_SELF_OFS16: + case FIX_SELF_OFS16_2: + if(targseg>=0) + { + printf("Error: Absolute Reloc target not supported for self-relative fixups\n"); + errcount++; + } + else + { + j=targofs; + j-=(seg->getbase()+relocs[i]->ofs+2); + if((j<-32768)||(j>32767)) + { + printf("Error: Reloc %li out of range\n",i); + } + else + { + temps = get16(seg->data, relocs[i]->ofs); + temps+=j; + put16(seg->data, relocs[i]->ofs, temps); + } + } + break; + case FIX_SELF_OFS32: + case FIX_SELF_OFS32_2: + if(targseg>=0) + { + printf("Error: Absolute Reloc target not supported for self-relative fixups\n"); + errcount++; + } + else + { + j=targofs; + j-=(seg->getbase()+relocs[i]->ofs+4); + templ = get32(seg->data, relocs[i]->ofs); + templ+=j; + put32(seg->data, relocs[i]->ofs, templ); + } + break; + default: + printf("Reloc %li:Relocation type %i not supported\n",i,relocs[i]->rtype); + errcount++; + } + } + + /* get reloc section */ + relocSect=outlist[relocSectNum]; /* get section structure */ + + /* sort relocations into order of increasing address */ + qsort(&relocs[0], relocs.size(), sizeof(relocs[0]), &compar); + + for(i=0,curStartPos=0,curBlockPos=0;irtype) + { + case FIX_SELF_OFS32: + case FIX_SELF_OFS32_2: + case FIX_SELF_OFS16: + case FIX_SELF_OFS16_2: + case FIX_SELF_LBYTE: + case FIX_RVA32: + continue; /* self-relative fixups and RVA fixups don't relocate */ + default: + break; + } + if(relocs[i]->outputPos>=(curStartPos+0x1000)) /* more than 4K past block start? */ + { + j=relocSect->length&3; + if(j) /* unaligned block position */ + { + relocSect->length+=4-j; /* update length to align block */ + /* and block memory */ + relocSect->data.resize(relocSect->length); + /* update size of current reloc block */ + k = get32(relocSect->data, curBlockPos+4); + k+=4-j; + put32(relocSect->data, curBlockPos+4, k); + for(j=4-j;j>0;j--) + { + relocSect->data[relocSect->length-j]=0; + } + } + curBlockPos=relocSect->length; /* get address in section of current block */ + relocSect->length+=8; /* 8 bytes block header */ + /* increase size of block */ + relocSect->data.resize(relocSect->length); + /* store reloc base address, and block size */ + curStartPos=relocs[i]->outputPos&0xfffff000; /* start of mem page */ + + /* start pos is relative to image base */ + put32(relocSect->data, curBlockPos, curStartPos-imageBase); + put32(relocSect->data, curBlockPos+4, 8); /* start size is 8 bytes */ + } + relocSect->data.resize(relocSect->length+2); + + j=relocs[i]->outputPos-curStartPos; /* low 12 bits of address */ + switch(relocs[i]->rtype) + { + case FIX_PTR1616: + case FIX_OFS16: + case FIX_OFS16_2: + j|= PE_REL_LOW16; + break; + case FIX_PTR1632: + case FIX_OFS32: + case FIX_OFS32_2: + j|= PE_REL_OFS32; + } + /* store relocation */ + put16(relocSect->data, relocSect->length, j); + /* update block length */ + relocSect->length+=2; + /* update size of current reloc block */ + k = get32(relocSect->data, curBlockPos+4); + k+=2; + put32(relocSect->data, curBlockPos+4, k); + } + /* if no fixups, then build NOP fixups, to make Windows NT happy */ + /* when it trys to relocate image */ + if(relocSect->length==0) + { + /* 12 bytes for dummy section */ + relocSect->length=12; + relocSect->data.resize(12); + /* zero it out for now */ + for(i=0;i<12;i++) relocSect->data[i]=0; + relocSect->data[4]=12; /* size of block */ + } + + relocSect->datmask.resize((relocSect->length+7)/8); + for(i=0;i<(relocSect->length+7)/8;i++) + { + relocSect->datmask[i]=0xff; + } + + objectTable+=PE_OBJECTENTRY_SIZE*relocSectNum; /* point to reloc object entry */ + k=relocSect->length; + k+=objectAlign-1; + k&=(0xffffffff-(objectAlign-1)); + relocSect->virtualSize=k; + put32(objectTable, 8, k); /* store virtual size (in memory) of segment */ + put32(objectTable, 16, relocSect->length); /* store initialised data size /*/ + + k = get32(objectTable, -PE_OBJECTENTRY_SIZE+20); + /* add physical length of prev object */ + k += get32(objectTable, -PE_OBJECTENTRY_SIZE+16); + + k+=fileAlign-1; + k&=(0xffffffff-(fileAlign-1)); /* aligned */ + + /* k is now physical location of this object */ + + put32(objectTable, 20, k); /* store physical file offset */ + /* get virtual start of prev object */ + k = get32(objectTable, -PE_OBJECTENTRY_SIZE+12); + k += get32(objectTable, -PE_OBJECTENTRY_SIZE+8); + + /* store base address (RVA) of section */ + put32(objectTable, 12, k); + + relocSect->setbase(k+imageBase); /* relocate section */ + + return; +} + +void BuildPEExports(long SectNum,PUCHAR objectTable,PUCHAR name) +{ + long i,j; + UINT k; + PSEG expSect; + UINT namelen; + UINT numNames=0; + UINT RVAStart; + UINT nameRVAStart; + UINT ordinalStart; + UINT nameSpaceStart; + UINT minOrd; + UINT maxOrd; + UINT numOrds; + std::vector nameList; + PEXPREC curName; + + if(!expdefs.size() || (SectNum<0)) return; /* return if no exports */ + expSect=outlist[SectNum]; + + if(name) + { + namelen=strlen((char *)name); + /* search backwards for path separator */ + for(i=namelen-1;(i>=0) && (name[i]!=PATH_CHAR);i--); + if(i>=0) /* if found path separator */ + { + name+=(i+1); /* update name pointer past path */ + namelen -= (i+1); /* and reduce length */ + } + } + else namelen=0; + + expSect->length=PE_EXPORTHEADER_SIZE+4*expdefs.size()+namelen+1; + /* min section size= header size + num exports * pointer size */ + /* plus space for null-terminated name */ + + minOrd=0xffffffff; /* max ordinal num */ + maxOrd=0; + + for(i=0;ilength+=expdefs[i].exp_name.length()+7; + numNames++; + } + + if(expdefs[i].flags&EXP_ORD) /* ordinal? */ + { + if(expdefs[i].ordinalmaxOrd) maxOrd=expdefs[i].ordinal; + } + } + + numOrds=expdefs.size(); /* by default, number of RVAs=number of exports */ + if(maxOrd>=minOrd) /* actually got some ordinal references? */ + { + i=maxOrd-minOrd+1; /* get number of ordinals */ + if(i>expdefs.size()) /* if bigger range than number of exports */ + { + expSect->length+=4*(i-expdefs.size()); /* up length */ + numOrds=i; /* get new num RVAs */ + } + } + else + { + minOrd=1; /* if none defined, min is set to 1 */ + } + + expSect->data.resize(expSect->length); + + objectTable+=PE_OBJECTENTRY_SIZE*SectNum; /* point to reloc object entry */ + k=expSect->length; + k+=objectAlign-1; + k&=(0xffffffff-(objectAlign-1)); + expSect->virtualSize=k; + put32(objectTable, 8, k); /* store virtual size (in memory) of segment */ + k=expSect->length; + put32(objectTable, 16, k); /* store initialised data size */ + + k =get32(objectTable, -PE_OBJECTENTRY_SIZE+20); /* get physical start of prev object */ + k+=get32(objectTable, -PE_OBJECTENTRY_SIZE+16); /* add physical length of prev object */ + + k+=fileAlign-1; + k&=(0xffffffff-(fileAlign-1)); /* aligned */ + + /* k is now physical location of this object */ + + put32(objectTable, 20, k); /* store physical file offset */ + + k = get32(objectTable, -PE_OBJECTENTRY_SIZE+12); /* get virtual start of prev object */ + k+= get32(objectTable, -PE_OBJECTENTRY_SIZE+8); /* add virtual length of prev object */ + + /* store base address (RVA) of section */ + put32(objectTable, 12, k); + + expSect->setbase(k+imageBase); /* relocate section */ + + /* start with buf=all zero */ + for(i=0;ilength;i++) expSect->data[i]=0; + + /* store creation time of export data */ + k=(UINT)time(NULL); + put32(expSect->data, 4, k); + put32(expSect->data, 16, minOrd); /* store ordinal base */ + + /* store number of RVAs */ + put32(expSect->data, 20, numOrds); + + RVAStart=PE_EXPORTHEADER_SIZE; /* start address of RVA table */ + nameRVAStart=RVAStart+numOrds*4; /* start of name table entries */ + ordinalStart=nameRVAStart+numNames*4; /* start of associated ordinal entries */ + nameSpaceStart=ordinalStart+numNames*2; /* start of actual names */ + + /* store number of named exports */ + put32(expSect->data, 24, numNames); + + /* store address of address table */ + put32(expSect->data, 28, RVAStart+expSect->getbase()-imageBase); + + /* store address of name table */ + put32(expSect->data, 32, nameRVAStart+expSect->getbase()-imageBase); + + /* store address of ordinal table */ + put32(expSect->data, 36, ordinalStart+expSect->getbase()-imageBase); + + /* process numbered exports */ + for(i=0;idata, RVAStart+4*(expdefs[i].ordinal-minOrd)); + if(k) /* error if already used */ + { + printf("Duplicate export ordinal %i\n",expdefs[i].ordinal); + exit(1); + } + /* get RVA of export entry */ + k=expdefs[i].pubdef->ofs+ + expdefs[i].pubdef->seg->getbase()- + imageBase; + /* store it */ + put32(expSect->data, RVAStart+4*(expdefs[i].ordinal-minOrd), k); + } + } + + /* process non-numbered exports */ + for(i=0,j=RVAStart;idata, j); + if(k) j+=4; + } + while(k); /* move through table until we find a free spot */ + /* get RVA of export entry */ + k=expdefs[i].pubdef->ofs; + k+=expdefs[i].pubdef->seg->getbase(); + k-=imageBase; + /* store RVA */ + put32(expSect->data, j, k); + expdefs[i].ordinal=(j-RVAStart)/4+minOrd; /* store ordinal */ + j+=4; + } + } + + if(numNames) /* sort name table if present */ + { + nameList.resize(numNames); + j=0; /* no entries yet */ + for(i=0;i=0;j--) + { + /* break out if we're above previous entry */ + if(curName->exp_name > nameList[j]->exp_name) + { + break; + } + /* else move entry up */ + nameList[j+1]=nameList[j]; + } + j++; /* move to one after better entry */ + nameList[j]=curName; /* insert current entry into position */ + } + /* and store */ + for(i=0;idata, ordinalStart, nameList[i]->ordinal-minOrd); + ordinalStart+=2; + /* store name RVA */ + put32(expSect->data, nameRVAStart, nameSpaceStart+expSect->getbase()-imageBase); + nameRVAStart+=4; + /* store name */ + for(j=0;nameList[i]->exp_name[j];j++,nameSpaceStart++) + { + expSect->data[nameSpaceStart]=nameList[i]->exp_name[j]; + } + /* store NULL */ + expSect->data[nameSpaceStart]=0; + nameSpaceStart++; + } + } + + /* store library name */ + for(j=0;jdata[nameSpaceStart+j]=name[j]; + } + if(namelen) + { + expSect->data[nameSpaceStart+j]=0; + /* store name RVA */ + put32(expSect->data, 12, nameSpaceStart+expSect->getbase()-imageBase); + } + + expSect->datmask.resize((expSect->length+7)/8); + for(i=0;i<(expSect->length+7)/8;i++) + { + expSect->datmask[i]=0xff; + } + + return; +} + +void BuildPEResources(long sectNum,PUCHAR objectTable) +{ + long i,j; + UINT k; + SEG *ressect; + RESOURCE curres; + int numtypes,numnamedtypes; + int numPairs,numnames,numids; + UINT nameSize,dataSize; + UINT tableSize,dataListSize; + UINT namePos,dataPos,tablePos,dataListPos; + UINT curTypePos,curNamePos,curLangPos; + unsigned char *curTypeName,*curName; + int curTypeId,curId; + + if((sectNum<0) || !resource.size()) return; + + objectTable+=PE_OBJECTENTRY_SIZE*sectNum; /* point to import object entry */ + k=get32(objectTable, -PE_OBJECTENTRY_SIZE+20); /* get physical start of prev object */ + k+=get32(objectTable, -PE_OBJECTENTRY_SIZE+16); /* add physical length of prev object */ + + k+=fileAlign-1; + k&=(0xffffffff-(fileAlign-1)); /* aligned */ + + /* k is now physical location of this object */ + + put32(objectTable, 20, k); /* store physical file offset */ + k = get32(objectTable, 12); /* get virtual start of prev object */ + k+= get32(objectTable, 8); /* add virtual length of prev object */ + + /* store base address (RVA) of section */ + put32(objectTable, 12, k); + + ressect=outlist[sectNum]; + ressect->setbase(k); /* get base RVA of section */ + + /* sort into type-id order */ + for(i=1;i=0;j--) + { + if(resource[j].xtypename.size()) + { + if(!curres.xtypename.size()) break; + if(_wstricmp(&curres.xtypename[0],&resource[j].xtypename[0])>0) break; + if(_wstricmp(&curres.xtypename[0],&resource[j].xtypename[0])==0) + { + if(resource[j].name.size()) + { + if(!curres.name.size()) break; + if(_wstricmp(&curres.name[0],&resource[j].name[0])>0) break; + if(_wstricmp(&curres.name[0],&resource[j].name[0])==0) + { + if(resource[j].languageid>curres.languageid) + break; + if(resource[j].languageid==curres.languageid) + { + printf("Error duplicate resource ID\n"); + exit(1); + } + } + } + else + { + if(!curres.name.size()) + { + if(curres.id>resource[j].id) break; + if(curres.id==resource[j].id) + { + if(resource[j].languageid>curres.languageid) + break; + if(resource[j].languageid==curres.languageid) + { + printf("Error duplicate resource ID\n"); + exit(1); + } + } + } + } + } + } + else + { + if(!curres.xtypename.size()) + { + if(curres.typeid>resource[j].typeid) break; + if(curres.typeid==resource[j].typeid) + { + if(resource[j].name.size()) + { + if(!curres.name.size()) break; + if(_wstricmp(&curres.name[0],&resource[j].name[0])>0) break; + if(_wstricmp(&curres.name[0],&resource[j].name[0])==0) + { + if(resource[j].languageid>curres.languageid) + break; + if(resource[j].languageid==curres.languageid) + { + printf("Error duplicate resource ID\n"); + exit(1); + } + } + } + else + { + if(!curres.name.size()) + { + if(curres.id>resource[j].id) break; + if(curres.id==resource[j].id) + { + if(resource[j].languageid>curres.languageid) + break; + if(resource[j].languageid==curres.languageid) + { + printf("Error duplicate resource ID\n"); + exit(1); + } + } + } + } + } + } + } + resource[j+1]=resource[j]; + } + j++; + resource[j]=curres; + } + + nameSize=0; + dataSize=0; + for(i=0;i0) && !_wstricmp(&resource[i].xtypename[0],&resource[i-1].xtypename[0])) + { + if(resource[i].name.size()) + { + if(_wstricmp(&resource[i].name[0],&resource[i-1].name[0])==0) + numPairs--; + } + else + { + if(!resource[i-1].name.size() && (resource[i].id ==resource[i-1].id)) + numPairs--; + } + continue; + } + numnamedtypes++; + } + numtypes=numnamedtypes; + for(;i0) && !resource[i-1].xtypename.size() && (resource[i].typeid==resource[i-1].typeid)) + { + if(resource[i].name.size()) + { + if(_wstricmp(&resource[i].name[0],&resource[i-1].name[0])==0) + numPairs--; + } + else + { + if(!resource[i-1].name.size() && (resource[i].id ==resource[i-1].id)) + numPairs--; + } + continue; + } + numtypes++; + } + + tableSize=(resource.size()+numtypes+numPairs)*PE_RESENTRY_SIZE+ + (numtypes+numPairs+1)*PE_RESDIR_SIZE; + dataListSize=resource.size()*PE_RESDATAENTRY_SIZE; + + tablePos=0; + dataListPos=tableSize; + namePos=tableSize+dataListSize; + dataPos=tableSize+nameSize+dataListSize+3; + dataPos&=0xfffffffc; + + ressect->length=dataPos+dataSize; + + ressect->data.resize(ressect->length); + + ressect->datmask.resize((ressect->length+7)/8); + + /* empty section to start with */ + for(i=0;ilength;i++) + ressect->data[i]=0; + + /* build master directory */ + /* store time/date of creation */ + k=(UINT)time(NULL); + put32(ressect->data, 4, k); + put32(ressect->data, 12, numnamedtypes); + + tablePos=16+numtypes*PE_RESENTRY_SIZE; + curTypePos=16; + curTypeName=NULL; + curTypeId=-1; + for(i=0;idata, curTypePos, namePos); + curTypeName=&resource[i].xtypename[0]; + k=_wstrlen(curTypeName); + put16(ressect->data, namePos, k); + namePos+=2; + memcpy(&ressect->data[0]+namePos,curTypeName,k*2); + namePos+=k*2; + curTypeId=-1; + } + else + { + curTypeName=NULL; + curTypeId=resource[i].typeid; + put32(ressect->data, curTypePos, curTypeId); + } + put32(ressect->data, curTypePos+4, tablePos); + + numnames=numids=0; + for(j=i;ji) && (_wstricmp(&resource[j].name[0],&resource[j-1].name[0])!=0)) + || (j==i)) + numnames++; + } + else + { + if(((j>i) && (resource[j-1].name.size() || (resource[j].id!=resource[j-1].id))) + || (j==i)) + numids++; + } + } + /* store time/date of creation */ + k=(UINT)time(NULL); + put32(ressect->data, tablePos+4, k); + put16(ressect->data, tablePos+12, numnames); + put16(ressect->data, tablePos+14, numids); + + curNamePos=tablePos+PE_RESDIR_SIZE; + curName=NULL; + curId=-1; + tablePos+=PE_RESDIR_SIZE+(numids+numnames)*PE_RESENTRY_SIZE; + curTypePos+=PE_RESENTRY_SIZE; + } + if(!(resource[i].name.size() && curName && + !_wstricmp(&resource[i].name[0],curName)) + && !(!resource[i].name.size() && !curName && curId==resource[i].id)) + { + if(resource[i].name.size()) + { + put32(ressect->data, curNamePos, namePos); + curName=&resource[i].name[0]; + k=_wstrlen(curName); + put16(ressect->data, namePos, k); + namePos+=2; + memcpy(&ressect->data[0]+namePos,curName,k*2); + namePos+=k*2; + curId=-1; + } + else + { + curName=NULL; + curId=resource[i].id; + put32(ressect->data, curNamePos, curId); + } + put32(ressect->data, curNamePos+4, 0x80000000 | tablePos); + + numids=0; + for(j=i;jdata, tablePos+4, k); + put16(ressect->data, tablePos+12, numnames); + put16(ressect->data, tablePos+14, numids); + + curLangPos=tablePos+PE_RESDIR_SIZE; + tablePos+=PE_RESDIR_SIZE+numids*PE_RESENTRY_SIZE; + curNamePos+=PE_RESENTRY_SIZE; + } + put32(ressect->data, curLangPos, resource[i].languageid); + put32(ressect->data, curLangPos+4, dataListPos); + curLangPos+=PE_RESENTRY_SIZE; + + put32(ressect->data, dataListPos, dataPos+ressect->getbase()); + put32(ressect->data, dataListPos+4, resource[i].length); + memcpy(&ressect->data[0]+dataPos,&resource[i].data[0],resource[i].length); + dataPos+=resource[i].length+3; + dataPos&=0xfffffffc; + dataListPos+=PE_RESDATAENTRY_SIZE; + } + + /* mark whole section as required output */ + for(i=0;i<(ressect->length+7)/8;i++) + ressect->datmask[i]=0xff; + + /* update object table */ + ressect->setbase(ressect->getbase()+imageBase); + + k=ressect->length; + k+=objectAlign-1; + k&=(0xffffffff-(objectAlign-1)); + ressect->virtualSize=k; + put32(objectTable, 8, k); /* store virtual size (in memory) of segment */ + k=ressect->length; + put32(objectTable, 16, k); /* store initialised data size */ + return; +} + +void getStub(PUCHAR *pstubData,UINT *pstubSize) +{ + FILE *f; + unsigned char headbuf[0x1c]; + std::vector buf; + UINT imageSize; + UINT headerSize; + UINT relocSize; + UINT relocStart; + int i; + + if(stubName != "") + { + f=fopen((char *)stubName.c_str(),"rb"); + if(!f) + { + printf("Unable to open stub file %s\n",stubName.c_str()); + exit(1); + } + if(fread(headbuf,1,0x1c,f)!=0x1c) /* try and read 0x1c bytes */ + { + printf("Error reading from file %s\n",stubName.c_str()); + exit(1); + } + if((headbuf[0]!=0x4d) || (headbuf[1]!=0x5a)) + { + printf("Stub not valid EXE file\n"); + exit(1); + } + /* get size of image */ + imageSize=headbuf[2]+(headbuf[3]<<8)+((headbuf[4]+(headbuf[5]<<8))<<9); + if(imageSize%512) imageSize-=512; + headerSize=(headbuf[8]+(headbuf[9]<<8))<<4; + relocSize=(headbuf[6]+(headbuf[7]<<8))<<2; + imageSize-=headerSize; + printf("imageSize=%i\n",imageSize); + printf("header=%i\n",headerSize); + printf("reloc=%i\n",relocSize); + + /* allocate buffer for load image */ + buf.resize(imageSize+0x40+((relocSize+0xf)&0xfffffff0)); + /* copy header */ + for(i=0;i<0x1c;i++) buf[i]=headbuf[i]; + + relocStart=headbuf[0x18]+(headbuf[0x19]<<8); + /* load relocs */ + fseek(f,relocStart,SEEK_SET); + if(fread(&buf[0x40],1,relocSize,f)!=relocSize) + { + printf("Error reading from file %s\n",stubName.c_str()); + exit(1); + } + + /* paragraph align reloc size */ + relocSize+=0xf; + relocSize&=0xfffffff0; + + /* move to start of data */ + fseek(f,headerSize,SEEK_SET); + /* new header is 4 paragraphs long + relocSize*/ + relocSize>>=4; + relocSize+=4; + put16(buf, 8, relocSize); + headerSize=relocSize<<4; + /* load data into correct position */ + if(fread(&buf[headerSize],1,imageSize,f)!=imageSize) + { + printf("Error reading from file %s\n",stubName.c_str()); + exit(1); + } + /* relocations start at 0x40 */ + put16(buf, 0x18, 0x40); + imageSize+=headerSize; /* total file size */ + /* store pointer and size */ + (*pstubData)=&buf[0]; + (*pstubSize)=imageSize; + i=imageSize%512; /* size mod 512 */ + imageSize=(imageSize+511)>>9; /* number of 512-byte pages */ + put16(buf, 2, i); + put16(buf, 4, imageSize); + } + else + { + (*pstubData)=defaultStub; + (*pstubSize)=defaultStubSize; + } +} + +void OutputWin32file(const std::string &outname) +{ + long i,j,k; + UINT started; + UINT lastout; + PSEG seg; + std::vector headbuf; + PUCHAR stubData; + FILE*outfile; + UINT headerSize; + UINT headerVirtSize; + UINT stubSize; + long nameIndex; + UINT sectionStart; + UINT headerStart; + long relocSectNum,importSectNum,exportSectNum,resourceSectNum; + long importSectLoc = 0, importSectSize = 0; + long exportSectLoc = 0, exportSectSize = 0; + long resourceSectLoc = 0, resourceSectSize = 0; + long relocSectLoc = 0, relocSectSize = 0; + UINT codeBase=0; + UINT dataBase=0; + UINT codeSize=0; + UINT dataSize=0; + + printf("Generating PE file %s\n",outname.c_str()); + + errcount=0; + + /* allocate section entries for imports, exports and relocs if required */ + if(impsreq) + { + importSectNum=createOutputSection("imports", + WINF_INITDATA | WINF_SHARED | WINF_READABLE); + } + else + { + importSectNum=-1; + } + + if(expdefs.size()) + { + exportSectNum=createOutputSection("exports", + WINF_INITDATA | WINF_SHARED | WINF_READABLE); + } + else + { + exportSectNum=-1; + } + + /* Windows NT requires a reloc section to relocate image files, even */ + /* if it contains no actual fixups */ + relocSectNum=createOutputSection("relocs", + WINF_INITDATA | WINF_SHARED | WINF_DISCARDABLE | WINF_READABLE); + + if(resource.size()) + { + resourceSectNum=createOutputSection("resource", + WINF_INITDATA | WINF_SHARED | WINF_READABLE); + } + else + { + resourceSectNum=-1; + } + + /* build header */ + getStub(&stubData,&stubSize); + + headerStart=stubSize; /* get start of PE header */ + headerStart+=7; + headerStart&=0xfffffff8; /* align PE header to 8 byte boundary */ + + headerSize=PE_HEADBUF_SIZE+outlist.size()*PE_OBJECTENTRY_SIZE+stubSize; + headerVirtSize=headerSize+(objectAlign-1); + headerVirtSize&=(0xffffffff-(objectAlign-1)); + headerSize+=(fileAlign-1); + headerSize&=(0xffffffff-(fileAlign-1)); + + + headbuf.resize(headerSize); + + for(i=0;iname; + if(name.size() > 8) name = name.substr(0,8); + + if(name.size()) + { + strncpy((char *)&headbuf[j],name.c_str(),name.size()); + } + k=outlist[i]->virtualSize; /* get virtual size */ + put32(headbuf, j+8, k); /* store virtual size (in memory) of segment */ + + if(!padsegments) /* if not padding segments, reduce space consumption */ + { + for(k=outlist[i]->length-1;(k>=0)&&!GetNbit(outlist[i]->datmask,k);k--); + k++; /* k=initialised length */ + } + put32(headbuf, j+16, k); /* store initialised data size */ + put32(headbuf, j+20, sectionStart); /* store physical file offset */ + + k+=fileAlign-1; + k&=(0xffffffff-(fileAlign-1)); /* aligned initialised length */ + + sectionStart+=k; /* update section start address for next section */ + + outlist[i]->setbase(outlist[i]->getbase()+headerVirtSize+imageBase); + put32(headbuf, j+12, outlist[i]->getbase()-imageBase); + k=(outlist[i]->winFlags ^ WINF_NEG_FLAGS) & WINF_IMAGE_FLAGS; /* get characteristice for section */ + put32(headbuf, j+36, k); /* store characteristics */ + } + + put16(headbuf, headerStart+PE_NUMOBJECTS, outlist.size()); /* store number of sections */ + + /* build import, export and relocation sections */ + + BuildPEImports(importSectNum,&headbuf[headerStart+PE_HEADBUF_SIZE]); + BuildPEExports(exportSectNum,&headbuf[headerStart+PE_HEADBUF_SIZE],(unsigned char *)outname.c_str()); + BuildPERelocs(relocSectNum,&headbuf[headerStart+PE_HEADBUF_SIZE]); + BuildPEResources(resourceSectNum,&headbuf[headerStart+PE_HEADBUF_SIZE]); + +#if 0 + for(k=headerStart+PE_HEADBUF_SIZE;k=32) && (headbuf[k]<128) ? headbuf[k] : '.'); + } + printf("\n"); + } +#endif + + if(errcount) + { + exit(1); + } + + /* get start address */ + if(gotstart) + { + GetFixupTarget(&startaddr,&seg,&startaddr.ofs,TRUE); + if(errcount) + { + printf("Invalid start address record\n"); + exit(1); + } + i=startaddr.ofs; + i-=imageBase; /* RVA */ + put32(headbuf, headerStart + PE_ENTRYPOINT, i); + if(buildDll) /* if library */ + { + /* flag that entry point should always be called */ + put16(headbuf, headerStart+PE_DLLFLAGS, 15); + } + } + else + { + printf("Warning, no entry point specified\n"); + } + + if(importSectNum>=0) /* if imports, add section entry */ + { + importSectLoc = outlist[importSectNum]->getbase()-imageBase; + importSectSize = outlist[importSectNum]->length; + } + else + { + for(i = 0; i < seglist.size(); i++) + { + if(seglist[i]) + { + if(seglist[i]->name == ".idata") + { + importSectLoc = seglist[i]->getbase() - imageBase; + importSectSize = seglist[i]->length; + } + } + } + } + + printf("importSectLoc %x importSectSize %x\n", + importSectLoc, importSectSize); + + if(importSectLoc) /* if imports, add section entry */ + { + put32(headbuf, headerStart + PE_IMPORTRVA, importSectLoc); + put32(headbuf, headerStart + PE_IMPORTSIZE, importSectSize); + } + + if(exportSectNum>=0) /* if exports, add section entry */ + { + exportSectLoc = outlist[exportSectNum]->getbase()-imageBase; + exportSectSize = outlist[exportSectNum]->length; + } + else + { + for(i = 0; i < seglist.size() && seglist[i]; i++) + { + if(seglist[i]->name == ".edata") + { + exportSectLoc = seglist[i]->getbase() - imageBase; + exportSectSize = seglist[i]->length; + } + } + } + + printf("exportSectLoc %x exportSectSize %x\n", + exportSectLoc, exportSectSize); + + if(exportSectLoc) + { + put32(headbuf, headerStart+PE_EXPORTRVA, exportSectLoc); + put32(headbuf, headerStart+PE_EXPORTSIZE, exportSectSize); + } + + if(relocSectNum>=0) /* if relocs, add section entry */ + { + relocSectLoc = outlist[relocSectNum]->getbase()-imageBase; + relocSectSize = outlist[relocSectNum]->length; + } + else + { + for(i = 0; i < seglist.size() && seglist[i]; i++) + { + if(seglist[i]->name == "relocs") + { + relocSectLoc = seglist[i]->getbase() - imageBase; + relocSectSize = seglist[i]->length; + } + } + } + + printf("relocSectLoc %x relocSectSize %x\n", + relocSectLoc, relocSectSize); + + if(relocSectLoc) /* if relocs, add section entry */ + { + put32(headbuf, headerStart + PE_FIXUPRVA, relocSectLoc); + put32(headbuf, headerStart + PE_FIXUPSIZE, relocSectSize); + } + + if(resourceSectNum>=0) /* if resources, add section entry */ + { + resourceSectLoc = outlist[resourceSectNum]->getbase()-imageBase; + resourceSectSize = outlist[resourceSectNum]->length; + } + else + { + for(i = 0; i < seglist.size() && seglist[i]; i++) + { + if(seglist[i]->name == ".rsrc") + { + resourceSectLoc = seglist[i]->getbase() - imageBase; + resourceSectSize = seglist[i]->length; + } + } + } + + printf("resourceSectLoc %x resourceSectSize %x\n", + resourceSectLoc, resourceSectSize); + + if(resourceSectLoc) /* if relocs, add section entry */ + { + put32(headbuf, headerStart + PE_RESOURCERVA, resourceSectLoc); + put32(headbuf, headerStart + PE_RESOURCESIZE, resourceSectSize); + } + + j=headerStart+PE_HEADBUF_SIZE+(outlist.size()-1)*PE_OBJECTENTRY_SIZE; + + i = get32(headbuf, j+12); + i+= get32(headbuf, j+8); /* add virtual size of section */ + + put32(headbuf, headerStart + PE_IMAGESIZE, i); + put32(headbuf, headerStart + PE_CODEBASE, codeBase); + put32(headbuf, headerStart + PE_DATABASE, dataBase); + put32(headbuf, headerStart + PE_CODESIZE, codeSize); + put32(headbuf, headerStart + PE_INITDATASIZE, dataSize); + + /* zero out section start for all zero-length segments */ + j=headerStart+PE_HEADBUF_SIZE; + for(i=0;iattr&SEG_ALIGN) !=SEG_ABS)) + { + /* ensure section is aligned to file-Align */ + while(ftell(outfile)&(fileAlign-1)) + { + fputc(0,outfile); + } + if(started>outlist[i]->getbase()) + { + printf("Segment overlap\n"); + printf("Next addr=%08X,base=%08X\n",started,outlist[i]->getbase()); + fclose(outfile); + exit(1); + } + if(padsegments) + { + while(startedgetbase()) + { + fputc(0,outfile); + started++; + } + } + else + { + started=outlist[i]->getbase(); + } + for(j=0;jlength;j++) + { + if(GetNbit(outlist[i]->datmask,j)) + { + for(;lastoutdata[j],outfile); + lastout=started+1; + } + else if(padsegments) + { + fputc(0,outfile); + lastout=started+1; + } + started++; + } + started=lastout=outlist[i]->getbase()+outlist[i]->virtualSize; + } + } + + fclose(outfile); +} + diff --git a/reactos/tools/ppc-build/alink/readme.txt b/reactos/tools/ppc-build/alink/readme.txt new file mode 100644 index 00000000000..933ad904996 --- /dev/null +++ b/reactos/tools/ppc-build/alink/readme.txt @@ -0,0 +1,10 @@ +What's here as been modified for use with a PowerPC elf toolchain, but retains +every original feature for x86 as well. + +General modifications: + +- Addition of elf32 input support +- PowerPC and x86 relocation types for elf +- Small bugfixes + +elf.c is based on coff.c, modified to deal with elf sections, symbols etc. diff --git a/reactos/tools/ppc-build/alink/tests/test.c b/reactos/tools/ppc-build/alink/tests/test.c new file mode 100644 index 00000000000..76e8197013a --- /dev/null +++ b/reactos/tools/ppc-build/alink/tests/test.c @@ -0,0 +1 @@ +int main() { return 0; } diff --git a/reactos/tools/ppc-build/alink/tests/test.obj b/reactos/tools/ppc-build/alink/tests/test.obj new file mode 100644 index 00000000000..aeadb144d7b Binary files /dev/null and b/reactos/tools/ppc-build/alink/tests/test.obj differ diff --git a/reactos/tools/ppc-build/alink/tests/test1.c b/reactos/tools/ppc-build/alink/tests/test1.c new file mode 100644 index 00000000000..f774283f6b5 --- /dev/null +++ b/reactos/tools/ppc-build/alink/tests/test1.c @@ -0,0 +1,2 @@ +extern int f( int x ); +int main() { return f(3); } diff --git a/reactos/tools/ppc-build/alink/tests/test2.c b/reactos/tools/ppc-build/alink/tests/test2.c new file mode 100644 index 00000000000..8aabc7df151 --- /dev/null +++ b/reactos/tools/ppc-build/alink/tests/test2.c @@ -0,0 +1 @@ +int f(int x) {return x-3;} diff --git a/reactos/tools/ppc-build/alink/tests/testms.exe b/reactos/tools/ppc-build/alink/tests/testms.exe new file mode 100755 index 00000000000..daf7b9dbee8 Binary files /dev/null and b/reactos/tools/ppc-build/alink/tests/testms.exe differ diff --git a/reactos/tools/ppc-build/alink/util.cpp b/reactos/tools/ppc-build/alink/util.cpp new file mode 100644 index 00000000000..671d7c283ee --- /dev/null +++ b/reactos/tools/ppc-build/alink/util.cpp @@ -0,0 +1,186 @@ +#include "alink.h" + +#define _strdup strdup + +int getBitCount(UINT a) +{ + int count=0; + + while(a) + { + if(a&1) count++; + a>>=1; + } + return count; +} + +void ReportError(long errnum) +{ + UINT tot,i; + + printf("\nError in file at %08lX",filepos); + switch(errnum) + { + case ERR_EXTRA_DATA: + printf(" - extra data in record\n"); + break; + case ERR_NO_HEADER: + printf(" - no header record\n"); + break; + case ERR_NO_RECDATA: + printf(" - record data not present\n"); + break; + case ERR_NO_MEM: + printf(" - insufficient memory\n"); + break; + case ERR_INV_DATA: + printf(" - invalid data address\n"); + break; + case ERR_INV_SEG: + printf(" - invalid segment number\n"); + break; + case ERR_BAD_FIXUP: + printf(" - invalid fixup record\n"); + break; + case ERR_BAD_SEGDEF: + printf(" - invalid segment definition record\n"); + break; + case ERR_ABS_SEG: + printf(" - data emitted to absolute segment\n"); + break; + case ERR_DUP_PUBLIC: + printf(" - duplicate public definition\n"); + break; + case ERR_NO_MODEND: + printf(" - unexpected end of file (no MODEND record)\n"); + break; + case ERR_EXTRA_HEADER: + printf(" - duplicate module header\n"); + break; + case ERR_UNKNOWN_RECTYPE: + printf(" - unknown object module record type %02X\n",rectype); + break; + case ERR_SEG_TOO_LARGE: + printf(" - 4Gb Non-Absolute segments not supported.\n"); + break; + case ERR_MULTIPLE_STARTS: + printf(" - start address defined in more than one module.\n"); + break; + case ERR_BAD_GRPDEF: + printf(" - illegal group definition\n"); + break; + case ERR_OVERWRITE: + printf(" - overlapping data regions\n"); + break; + case ERR_INVALID_COMENT: + printf(" - COMENT record format invalid\n"); + break; + case ERR_ILLEGAL_IMPORTS: + printf(" - Imports required to link, and not supported by output file type\n"); + break; + default: + printf("\n"); + } + printf("seg count = %i\n",seglist.size()); + printf("extcount=%i\n",externs.size()); + printf("grpcount=%i\n",grplist.size()); + printf("comcount=%i\n",comdefs.size()); + printf("fixcount=%i\n",relocs.size()); + printf("impcount=%i\n",impdefs.size()); + printf("expcount=%i\n",expdefs.size()); + printf("modcount=%i\n",modname.size()); + + for(i=0,tot=0;idata.size()) + tot+=seglist[i]->length; + } + printf("total segment size=%08X\n",tot); + + exit(1); +} + +unsigned short wtoupper(unsigned short a) +{ + if(a>=256) return a; + return toupper(a); +} + +int wstricmp(const char *s1,const char *s2) +{ + int i=0; + unsigned short a,b; + + while(TRUE) + { + a=s1[i]+(s1[i+1]<<8); + b=s2[i]+(s2[i+1]<<8); + if(wtoupper(a)wtoupper(b)) return +1; + if(!a) return 0; + i+=2; + } +} + +int wstrlen(const char *s) +{ + int i; + for(i=0;s[i]||s[i+1];i+=2); + return i/2; +} + +void *checkMalloc(size_t x) +{ + void *p; + + p=malloc(x); + if(!p) + { + fprintf(stderr,"Error, Insufficient memory in call to malloc\n"); + exit(1); + } + return p; +} + +void *checkRealloc(void *p,size_t x) +{ + p=realloc(p,x); + if(!p) + { + fprintf(stderr,"Error, Insufficient memory in call to realloc\n"); + exit(1); + } + return p; +} + +char *checkStrdup(const char *s) +{ + char *p; + + if(!s) + { + fprintf(stderr,"Error, Taking duplicate of NULL pointer in call to strdup\n"); + exit(1); + } + p=strdup(s); + if(!p) + { + fprintf(stderr,"Error, Insufficient memory in call to strdup\n"); + exit(1); + } + return p; +} + +int _wstricmp(unsigned char *a, unsigned char *b) +{ + uint16_t *a16 = (uint16_t*)a, *b16 = (uint16_t*)b; + while(*a16 && (*a16 == *b16)) { a16++; b16++; } + return (*a16 < *b16) ? ((*a16 > *b16) ? 1 : 0) : -1; +} + +int _wstrlen(unsigned char *a) +{ + uint16_t *a16 = (uint16_t*)a; + while(*a16++); + return a16 - ((uint16_t *)a); +}