2c3ee52000-12-22Fredrik Hübinette (Hubbe) #!/usr/local/bin/pike
6ea3382000-12-26Fredrik Hübinette (Hubbe) // Partial linker for COFF files, written by Fredrik Hubinette 2000 // // Things left to do:
f896402000-12-28Fredrik Hübinette (Hubbe) // Support long-format import libaries // Merge sections (if given -O)
6ea3382000-12-26Fredrik Hübinette (Hubbe) // Support line number information
f896402000-12-28Fredrik Hübinette (Hubbe) // Test if resulting files work with cl.exe
6ea3382000-12-26Fredrik Hübinette (Hubbe) // Support 64 bit architechtures
f896402000-12-28Fredrik Hübinette (Hubbe) // Rename sections // Support section symbols (used by pthread.lib) // #define DEBUG
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  class Reloc { Symbol sym; int loc; int type; }; class Section { string name;
5b2b592000-12-27Fredrik Hübinette (Hubbe)  int|string data;
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  array(Reloc) relocs; int virtual_size; int characteristics;
f896402000-12-28Fredrik Hübinette (Hubbe) 
462c412001-01-03Fredrik Hübinette (Hubbe)  /* internal stuff */
f896402000-12-28Fredrik Hübinette (Hubbe)  array(Symbol) symbols_in_this_section=({});
462c412001-01-03Fredrik Hübinette (Hubbe)  string file;
2c3ee52000-12-22Fredrik Hübinette (Hubbe) }; class Symbol { string name; int value; Section section; int type; int cls; array(Symbol) aux;
462c412001-01-03Fredrik Hübinette (Hubbe)  string demangle() { string ret=name; sscanf(ret,"%s@",ret); if( (type >> 4) == 2) ret+="()"; return ret; }
2c3ee52000-12-22Fredrik Hübinette (Hubbe) }; mapping(string:Symbol) global_symbols=([]); array(Section) global_sections=({}); array(string) global_directives=({});
6ea3382000-12-26Fredrik Hübinette (Hubbe) array(string) libpath=({}); array(string) libraries=({});
2c3ee52000-12-22Fredrik Hübinette (Hubbe) 
462c412001-01-03Fredrik Hübinette (Hubbe) int err; #define CHR_LINK_INFO 0x200 #define CHR_LINK_REMOVE 0x800 #define CHR_LINK_ALIGN_1 0x100000 #define CHR_LINK_MEM_DISCARDABLE 0x2000000
2c3ee52000-12-22Fredrik Hübinette (Hubbe) class Linker { string stringtable="";
f896402000-12-28Fredrik Hübinette (Hubbe)  mapping(string:int) num_secnames=([]);
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  mapping(Symbol:int) symbol_to_number=([]);
5b2b592000-12-27Fredrik Hübinette (Hubbe)  mapping(Section:int) section_to_number=([]);
462c412001-01-03Fredrik Hübinette (Hubbe)  mapping(string:int) directive_to_number=([]); array get_ordered(mapping m) { array i=indices(m); array v=values(m); sort(v,i); return i; }
5b2b592000-12-27Fredrik Hübinette (Hubbe) 
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  mapping(string:int) stringtablecache=([]); int add_string(string s) { int pos;
f896402000-12-28Fredrik Hübinette (Hubbe) // werror("Adding string: %O\n",s);
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  s+="\0"; if(pos=stringtablecache[s]) return pos-1; pos=search(stringtable, s); if(pos == -1) { pos=strlen(stringtable); stringtable+=s; } stringtablecache[s]=pos-1; return pos; }
462c412001-01-03Fredrik Hübinette (Hubbe)  int add_directive(string d) { if(directive_to_number[d]) return directive_to_number[d]-1; #ifdef DEBUG werror("Adding directive: %O\n",d); #endif int num=sizeof(directive_to_number); directive_to_number[d]=num+1; return num; }
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  string add_sym_name(string s) { if(strlen(s) <= 8) return s + "\0"*(8-strlen(s)); return sprintf("%-4c%-4c",0,add_string(s)); } int add_symbol(Symbol s) {
f896402000-12-28Fredrik Hübinette (Hubbe)  if(symbol_to_number[s]) {
2c3ee52000-12-22Fredrik Hübinette (Hubbe) #ifdef DEBUG
462c412001-01-03Fredrik Hübinette (Hubbe)  werror("Adding symbol [%d]: %s @ %O:%O again\n", symbol_to_number[s]-1,s->name, s->section ? s->section->name : "", s->section ? s->section->file : "", );
2c3ee52000-12-22Fredrik Hübinette (Hubbe) #endif return symbol_to_number[s]-1;
f896402000-12-28Fredrik Hübinette (Hubbe)  }
2c3ee52000-12-22Fredrik Hübinette (Hubbe) 
f896402000-12-28Fredrik Hübinette (Hubbe)  int num=sizeof(symbol_to_number); #ifdef DEBUG
462c412001-01-03Fredrik Hübinette (Hubbe)  werror("Adding symbol [%d]: %s @ %O:%O\n",num,s->name, s->section ? s->section->name : "external", s->section ? s->section->file : "" );
f896402000-12-28Fredrik Hübinette (Hubbe) #endif symbol_to_number[s]=num+1; if(s->section) add_section(s->section); return num;
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  }
5b2b592000-12-27Fredrik Hübinette (Hubbe)  int add_section(Section s) { if(section_to_number[s]) return section_to_number[s]-1;
462c412001-01-03Fredrik Hübinette (Hubbe)  string name=s->name; sscanf(name,"%s$",name); if(name == ".drectve") { #ifdef DEBUG werror("Adding directives: %O\n",s->data); #endif map(s->data/" ",add_directive); return -1; } #if 0 if(name == ".idata") { string name= ( s->file /"/" )[-1]; add_directive("-LIB:"+name); /* import DLL instead of section */ return -1; /* undefined */ } #endif
f896402000-12-28Fredrik Hübinette (Hubbe)  int num=sizeof(section_to_number); #ifdef DEBUG werror("Adding section [%d]: %s\n",num,s->name); #endif section_to_number[s]=num+1;
462c412001-01-03Fredrik Hübinette (Hubbe) 
f896402000-12-28Fredrik Hübinette (Hubbe)  if(s->relocs) foreach(s->relocs, Reloc r) add_symbol(r->sym); foreach(s->symbols_in_this_section, Symbol sym) add_symbol(sym); return num;
5b2b592000-12-27Fredrik Hübinette (Hubbe)  } int virtual_data_size(int|string s) { return intp(s) ? s : strlen(s); } int file_data_size(int|string s) { return intp(s) ? 0 : strlen(s); }
2c3ee52000-12-22Fredrik Hübinette (Hubbe) 
f896402000-12-28Fredrik Hübinette (Hubbe)  string out()
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  {
462c412001-01-03Fredrik Hübinette (Hubbe)  if(sizeof(directive_to_number)) { Section s=Section(); s->name=".drectve"; s->data=get_ordered(directive_to_number) * " "; s->characteristics = CHR_LINK_INFO | CHR_LINK_REMOVE | CHR_LINK_ALIGN_1; int num=sizeof(section_to_number); section_to_number[s]=num+1; add_section(s); }
f896402000-12-28Fredrik Hübinette (Hubbe)  string symboltable=""; string sectiondata=""; string sectiontable="";
2c3ee52000-12-22Fredrik Hübinette (Hubbe) 
f896402000-12-28Fredrik Hübinette (Hubbe)  int secnum_save=sizeof(section_to_number);
2c3ee52000-12-22Fredrik Hübinette (Hubbe) 
5b2b592000-12-27Fredrik Hübinette (Hubbe)  /* Actually output data */
f896402000-12-28Fredrik Hübinette (Hubbe)  int base=20 /*coff*/ + sizeof(section_to_number) * 40;
462c412001-01-03Fredrik Hübinette (Hubbe)  foreach(get_ordered(section_to_number), Section s)
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  { #ifdef DEBUG
f896402000-12-28Fredrik Hübinette (Hubbe)  werror("Encoding section [%d]: %s\n",add_section(s),s->name);
2c3ee52000-12-22Fredrik Hübinette (Hubbe) #endif sectiontable+= sprintf("%s%-4c%-4c%-4c%-4c%-4c%-4c%-2c%-2c%-4c", add_sym_name(s->name), s->virtual_size, 0, /* virtual address */
5b2b592000-12-27Fredrik Hübinette (Hubbe)  virtual_data_size(s->data), stringp(s->data) ? (base + strlen(sectiondata)) : 0,
9b6bd42000-12-27Fredrik Hübinette (Hubbe)  s->relocs && (base + strlen(sectiondata) + file_data_size(s->data)),
5b2b592000-12-27Fredrik Hübinette (Hubbe)  0, /* no linenums yet */ s->relocs && sizeof(s->relocs),
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  0, s->characteristics);
5b2b592000-12-27Fredrik Hübinette (Hubbe)  if(stringp(s->data)) sectiondata+=s->data; if(s->relocs) foreach(s->relocs, Reloc r) sectiondata+=sprintf("%-4c%-4c%-2c", r->loc, add_symbol(r->sym), r->type); }
2c3ee52000-12-22Fredrik Hübinette (Hubbe) 
462c412001-01-03Fredrik Hübinette (Hubbe)  foreach(get_ordered(symbol_to_number), Symbol s)
f896402000-12-28Fredrik Hübinette (Hubbe)  { symboltable+=sprintf("%s%-4c%-2c%-2c%c%c", add_sym_name(s->name), s->value, s->section ? add_section(s->section) +1 : 0, s->type, s->cls, 0); /* aux symbols not supported */ } if( secnum_save != sizeof(section_to_number)) { werror("Sections appeared too late!\n"); exit(1); } if( strlen(sectiontable) != sizeof(section_to_number) * 40) {
462c412001-01-03Fredrik Hübinette (Hubbe)  werror("Complete failure %d != %d!\n",
f896402000-12-28Fredrik Hübinette (Hubbe)  strlen(sectiontable),
462c412001-01-03Fredrik Hübinette (Hubbe)  sizeof(section_to_number) * 40);
f896402000-12-28Fredrik Hübinette (Hubbe)  exit(1); } string ret=
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  sprintf("%-2c%-2c%-4c%-4c%-4c%-2c%-2c" /* coff */ "%s%s%s%s" /* the rest */ , /* coff */ 0x14c, /* Intel x86 */
5b2b592000-12-27Fredrik Hübinette (Hubbe)  sizeof(section_to_number),
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  time(), base+strlen(sectiondata),
f896402000-12-28Fredrik Hübinette (Hubbe)  sizeof(symbol_to_number),
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  0, /* opt header size */ 0, /* no character */ sectiontable, sectiondata, symboltable, stringtable);
f896402000-12-28Fredrik Hübinette (Hubbe)  if(ret [ base + strlen(sectiondata).. base+strlen(sectiondata)+strlen(symboltable) -1 ] != symboltable) { werror("Symbol table offset is wrong.\n"); exit(1); } return ret;
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  } } mapping machine_table = ([ 0:"Unknown", 0x14c:"Intel x86", ]); class Bitfield { array(string) names; string desc(int num) { int x; array(string) ret=({}); while(num && x<sizeof(names)) { if(1 & num) ret+=({ names[x] }); x++; num>>=1; num&=0x7fffffff; } if(!sizeof(ret) || num) ret+=({ sprintf("%x",num << x) }); return ret*" | "; } void create(string ... n) { names=n; } } Bitfield character_descriptor=Bitfield( "RELOCS_STRIPPED", "EXECUTABLE_IMAGE", "LINE_NUMS_STRIPPED", "LOCAL_SYMS_STRIPPED", "AGGRESSIVE_WS_TRIM", "LARGE_ADDRESS_AWARE", "16BIT_MACHINE", "BYTES_REVERSED_LO", "32BIT_MACHINE", "DEBUG_STRIPPED", "REMOVABLE_RUN_FROM_SWAP", "FILE_SYSTEM", "DLL", "UP_SYSTE_MONLY", "BYTES_REVERSED_HI" ); Bitfield section_character_descriptor=Bitfield( "DSECT", "NOLOAD", "GROUP", "TYPE_NO_PAD", "*COPY", "*CODE", "INITED_DATA", "UNINITED_DATA", "LNK_OTHER", "LNK_INFO", "TYPE_OVER", "LNK_REMOVE", "LNK_COMDAT", "-", "-", "MEM_FARDATA", "*MEM_PURGEABLE", "*MEM_16BIT", "*MEM_LOCKED", "*MEM_PRELOAD", "ALIGN_1", "ALIGN_2", "ALIGN_4", "ALIGN_8", "LNK_NRELOC_OVFL", "MEM_DISCARDABLE", "MEM_NOT_CACHED", "MEM_NOT_PAGED", "MEM_SHARED", "MEM_EXECUTE", "MEM_READ", "MEM_WRITE", ); class dumpfile { string filename; string data; int base; int stringtable; int symboltable, numsymbols; int sections, numsections; array(Symbol) file_symbols; array(Section) file_sections; void hexdump(int pos) { string x=data[pos..pos+128]; foreach(x/8,string line) { write("%06x: %{%02x %} %O\n",pos,values(line),line); pos+=strlen(x); }
462c412001-01-03Fredrik Hübinette (Hubbe)  string line=x%8; write("%06x: %{%02x %} %s %O\n", pos, values(line), " "*(8-strlen(line)), line);
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  } int i4(int pos) { pos+=base; return data[pos] | (data[pos+1]<<8) | (data[pos+2]<<16) | (data[pos+3]<<24); } int i8(int pos) { pos+=base; return data[pos] | (data[pos+1]<<8) | (data[pos+2]<<16) | (data[pos+3]<<24) | (data[pos+4]<<32) | (data[pos+5]<<40) | (data[pos+6]<<48) | (data[pos+7]<<56); } int i1(int pos) { pos+=base; return data[pos]; } int i2(int pos) { pos+=base; return data[pos] | (data[pos+1]<<8); } string nulltermstring(int p) { p+=base; int end=search(data,"\0",p); return data[p..end-1]; } string range(int from, int len) { from+=base; return data[from..from+len-1]; } string getCOFFstring(int pos) { if(!i4(pos)) { return nulltermstring(stringtable + i4(pos+4)); } return ( range(pos,8)/"\0" )[0]; } string decodeRelocType(int t) { switch(t) { case 0: return "absolute"; case 1: return "dir16"; case 2: return "rel16"; case 6: return "dir32"; case 7: return "dir32nb"; case 9: return "seg12"; case 10: return "sect"; case 11: return "secrel"; case 20: return "rel32"; default: return sprintf("<%d>",t); } } array(Reloc) dumpRelocs(int pos, int num_relocs) { array(Reloc) ret=({}); for(int e=0;e<num_relocs;e++) { #ifdef DEBUG write(" [ %08x = symbol(%5d, %8s) = %s]\n", i4(pos), i4(pos+4), decodeRelocType(i2(pos+8)), getsymbolname(i4(pos+4))); #endif Reloc r=Reloc(); r->loc=i4(pos); r->sym=file_symbols[i4(pos+4)]; r->type=i2(pos+8); pos+=10; ret+=({r}); } return ret; } int translatevaddr(int addr) { int pos=sections; for(int e=0;e<numsections;e++) { int start=i4(pos+12); if(addr >= start && addr < start + i4(pos+8)) { // write("--start=%d-%d-sect=%d--\n",start,i4(pos+20),e); return addr - start + i4(pos+20); } pos+=40; } return -1; } void dumpSECTS() { int pos=sections; #ifdef DEBUG write("\n-=SECTIONS=-\n"); #endif for(int e=0;e<numsections;e++) { string caracter; #ifdef DEBUG write("\n"); write("Name : %s\n",getCOFFstring(pos)); write("Virtual Size : %x\n",i4(pos+8)); write("Virtual Addres : %x\n",i4(pos+12)); write("RAW data size : %x\n",i4(pos+16)); write("Ptr2RawData : %x\n",i4(pos+20)); write("Ptr2Relocs : %x\n",i4(pos+24)); write("Ptr2Linenums : %x\n",i4(pos+28)); write("num relocs : %x\n",i2(pos+32)); write("num linenums : %x\n",i2(pos+34)); write("characteristics : %s\n", caracter=section_character_descriptor->desc(i4(pos+36))); #endif file_sections[e]->name=getCOFFstring(pos);
462c412001-01-03Fredrik Hübinette (Hubbe)  file_sections[e]->file=filename;
5b2b592000-12-27Fredrik Hübinette (Hubbe)  if(i4(pos+20)) { file_sections[e]->data=range(i4(pos+20),i4(pos+16)); }else{ file_sections[e]->data=i4(pos+16); }
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  file_sections[e]->virtual_size=i4(pos+8);; file_sections[e]->characteristics=i4(pos+36);
5b2b592000-12-27Fredrik Hübinette (Hubbe)  if(i4(pos+24)) file_sections[e]->relocs=dumpRelocs(i4(pos+24), i2(pos+32));
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  if(file_sections[e]->characteristics & CHR_LINK_INFO) { foreach(file_sections[e]->data/" ", string directive) if(search(global_directives, directive) == -1) global_directives+=({ directive }); } else { global_sections+=({ file_sections[e] }); } #ifdef DEBUG if(search(caracter,"LNK_INFO")!=-1) write("%O\n",range(i4(pos+20),i4(pos+16))); #endif pos+=40; } } string getvirtualname(int vaddr) { int x=translatevaddr(vaddr); if(x==-1) return sprintf("<out of bounds %x>",vaddr); return nulltermstring(x); } /* Symbol table stuff */ string decodeCOFFtypeLSB(int t) { switch(t) { case 0: return "null"; case 1: return "void"; case 2: return "char"; case 3: return "short"; case 4: return "int"; case 5: return "long"; case 6: return "float"; case 7: return "double"; case 8: return "struct"; case 9: return "union"; case 10: return "enum"; case 11: return "MOE"; case 12: return "byte"; case 13: return "word"; case 14: return "uint"; case 15: return "dword"; default: return sprintf("<%x>",t); } } string decodeCOFFtype(int t) { switch(t >> 4) { case 0: return decodeCOFFtypeLSB(t); case 1: return decodeCOFFtypeLSB(t & 15) + "*"; case 2: return decodeCOFFtypeLSB(t & 15) + "()"; case 3: return decodeCOFFtypeLSB(t & 15) + "[]"; default: return sprintf("<%x>",t); } } string decodeCOFFstorageclass(int t) { switch(t) { case -1: case 255: return "End of function"; case 0: return "null"; case 1: return "automatic"; case 2: return "external"; case 3: return "static"; case 4: return "register"; case 5: return "external def"; case 6: return "label"; case 7: return "undef label"; case 8: return "member of struct"; case 9: return "argument"; case 10: return "struct tag"; case 11: return "member of union"; case 12: return "union tag"; case 13: return "type def"; case 14: return "undef static"; case 15: return "enum tag"; case 16: return "member of enum"; case 17: return "register param"; case 18: return "bit field"; case 100: return "block"; case 101: return "function"; case 102: return "end of struct"; case 103: return "file"; case 104: return "section"; case 105: return "weak external"; default: return sprintf("<%x>",t); } } string getsymbolname(int x) { if(x >= numsymbols) return sprintf("Out of bound (%d)",x); return getCOFFstring(symboltable + x * 18); } void dumpSymTable() { array ret=allocate(numsymbols); int pos=symboltable; for(int e=0;e<numsymbols;e++) { int aux; #ifdef DEBUG #if 1 write("[%5d] %08x %4x %-9s %-9s %x %s\n", e, i4(pos+8), i2(pos+12), decodeCOFFtype(i2(pos+14)), decodeCOFFstorageclass(i1(pos+16)), aux=i1(pos+17), getCOFFstring(pos)); #else write("[%5d] name : %s\n",e,getCOFFstring(pos)); write("[%5d] value : %x\n",e,i4(pos+8)); write("[%5d] secnum : %d\n",e,i2(pos+12)); write("[%5d] type : %s\n",e,decodeCOFFtype(i2(pos+14))); write("[%5d] Storage class : %s\n",e,decodeCOFFstorageclass(i1(pos+16))); write("[%5d] Num Aux syms : %x\n",e,aux=i1(pos+17)); #endif #endif
272e912001-01-11Fredrik Hübinette (Hubbe)  switch(i1(pos+16)) { case 103: continue; /* file */ }
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  string name=getCOFFstring(pos); int cls=i1(pos+16); int sect=i2(pos+12); int value=i4(pos+8); int type=i2(pos+14); if(sect > 32768) sect=65536-sect; Symbol s=Symbol(); s->name=name; s->value=value;
272e912001-01-11Fredrik Hübinette (Hubbe) // werror("SECT: %O %O\n",sect,file_sections);
f896402000-12-28Fredrik Hübinette (Hubbe)  if(sect > 0) s->section=file_sections[sect-1];
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  s->type=type; s->cls=cls; s->aux=0; #define COFFSYM_external 2 switch(cls) { case COFFSYM_external:
462c412001-01-03Fredrik Hübinette (Hubbe)  string tmpname=s->demangle(); if(global_symbols[tmpname]) { Symbol newsym=global_symbols[tmpname]; if(newsym->section && sect > 0) { werror("%s: Warning: Symbol %s redefined.\n", filename, name); newsym=s; } if(sect > 0) { if( (newsym->type >> 4) != (type>>4) ) { werror("Warning: same symbol, different levels of indirection!!!!!!\n"); err++; } } s=newsym; } if(sect > 0) { s->section=file_sections[sect-1]; s->value = value; s->type = type; } global_symbols[tmpname]=s;
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  } file_symbols[e]=s; aux=i1(pos+17); pos+=18; for(int a=0;a<aux;a++) { pos+=18; e++; } } } void dumpCOFF(int pos) { #ifdef DEBUG write("-=COFF HEADER=-\n"); #endif sscanf(reverse(range(pos,20)), "%2c%2c%4c%4c%4c%2c%2c", int characteristics, int sizeofoptheader, numsymbols, symboltable, int timestamp, numsections, int machine); #ifdef DEBUG write("Machine : %s\n",machine_table[machine] || sprintf("%x",machine)); write("Sections : %x\n",numsections); write("Timesamp : %s",ctime(timestamp)); write("Symbol Table: %x\n",symboltable); write("Symbols : %d\n",numsymbols); write("Optheadsize : %x\n",sizeofoptheader); write("Character : %s\n",character_descriptor->desc(characteristics)); #endif stringtable = symboltable + numsymbols*18; sections=pos+20+sizeofoptheader; file_symbols=allocate(numsymbols); file_sections=allocate(numsections,Section)(); dumpSymTable(); dumpSECTS(); } int dumpPE(int pos) { #ifdef DEBUG write("Potential PE identifier at 0x%x ... ",pos); #endif
f896402000-12-28Fredrik Hübinette (Hubbe)  if(range(pos,4)!="PE\0\0")
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  { #ifdef DEBUG write("No.\n"); #endif return 0; } else { #ifdef DEBUG write("Yes.\n"); #endif } dumpCOFF(pos+4); return 1; } void dumpArchive(int pos) {
6ea3382000-12-26Fredrik Hübinette (Hubbe)  string name; int num; int longnames;
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  while(pos < strlen(data)) {
6ea3382000-12-26Fredrik Hübinette (Hubbe)  num++;
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  int size = (int) range(pos+48,10);
6ea3382000-12-26Fredrik Hübinette (Hubbe)  name=range(pos,16); if(name[0]=='/') { if(num == 3) { longnames=pos+60; } else if(longnames && sscanf(name,"/%d",int longnamenum)) { name=nulltermstring(longnames + longnamenum); } }else{ if(sscanf(reverse(name),"%*s/%s",name)) name=reverse(name); }
2c3ee52000-12-22Fredrik Hübinette (Hubbe) #ifdef DEBUG write("\n"); write("# name: %s\n",name);
6ea3382000-12-26Fredrik Hübinette (Hubbe)  write("# date: %s",ctime( (int) range(pos+16,12) ) );
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  write("# uid : %s\n",range(pos+28,6)); write("# gid : %s\n",range(pos+34,6)); write("# mode: %s\n",range(pos+40,8)); write("# size: %s\n",range(pos+48,10)); #endif if(name[0]!='/')
6ea3382000-12-26Fredrik Hübinette (Hubbe)  { dumpfile(data, pos+60, 0, name); }
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  pos+=60; pos+=(size+1)&~1; } }
6ea3382000-12-26Fredrik Hübinette (Hubbe)  void dumpImportLib() { string name= ( filename/"/" )[-1]; sscanf(range(0,20), "%-2c%-2c%-2c%-2c%-4c%-4c%-2c%-2c", int sig1, int sig2, int version, int machine, int timestamp, int size_of_data, int ordinal, int type);
462c412001-01-03Fredrik Hübinette (Hubbe) #if 0
6ea3382000-12-26Fredrik Hübinette (Hubbe)  write("Sig1 : %x\n",sig1); write("Sig2 : %x\n",sig2); write("version : %x\n",version); write("Machine : %x\n", machine); write("Time : %s",ctime(timestamp)); write("Ordinal : %x\n",ordinal); write("Type: : %x\n",type); write("Name : %s\n",nulltermstring(20));
462c412001-01-03Fredrik Hübinette (Hubbe)  write("Importing library: %O\n",name);
6ea3382000-12-26Fredrik Hübinette (Hubbe) #endif
462c412001-01-03Fredrik Hübinette (Hubbe)  #if 0
6ea3382000-12-26Fredrik Hübinette (Hubbe)  global_directives|=({ "-LIB:"+name });
462c412001-01-03Fredrik Hübinette (Hubbe) #else Section s=Section(); #if 0 s->name=".idata"; s->file=filename; #else s->name=".drectve"; // werror("Creating Directive -LIB:%s\n",name); s->data = "-LIB:"+name; s->file="autogenerated"; #endif string symname=nulltermstring(20); #ifdef DEBUG werror("Importing symbol: %O\n",symname); #endif string tmpname=symname; sscanf(tmpname,"%s@",tmpname); Symbol sym=global_symbols[tmpname]; if(!sym) global_symbols[tmpname]=sym=Symbol(); sym->name=symname; sym->section=s; sym->type=type; /* correct ???? */ sym->cls = COFFSYM_external; symname="__imp_"+symname; #ifdef DEBUG werror("Importing symbol: %O\n",symname); #endif tmpname="__imp_"+tmpname+"()"; sym=global_symbols[tmpname]; if(!sym) global_symbols[tmpname]=sym=Symbol(); sym->name=symname; sym->section=s; sym->type=type | (2<<4); /* correct ???? */ sym->cls = COFFSYM_external; #endif
6ea3382000-12-26Fredrik Hübinette (Hubbe)  }
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  void create(string d, void|int p, void|int len, void|string f) { base=p; data=d; filename=f; if(!len) len=strlen(d)-base; if(range(0,8) == "!<arch>\n") { #ifdef DEBUG write("Archive!\n"); #endif dumpArchive(8); }else{
6ea3382000-12-26Fredrik Hübinette (Hubbe)  if(i2(0) == 0 && i2(2) == 0xffff)
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  {
462c412001-01-03Fredrik Hübinette (Hubbe)  dumpImportLib();
6ea3382000-12-26Fredrik Hübinette (Hubbe)  }else{
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  dumpCOFF(0);
6ea3382000-12-26Fredrik Hübinette (Hubbe)  }
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  } } } int main(int argc, array(string) argv) {
462c412001-01-03Fredrik Hübinette (Hubbe)  int export_all;
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  int strip=0; string output="a.out"; // werror("%O\n",argv); werror("Pike Win32 partial linker.\n"
272e912001-01-11Fredrik Hübinette (Hubbe)  "$Id: pntld,v 1.7 2001/01/11 23:21:24 hubbe Exp $\n"
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  "Written by Fredrik Hubinette 2000\n"); foreach(Getopt.find_all_options(argv,aggregate( ({"output",Getopt.HAS_ARG,({"-o"})}), ({"R",Getopt.HAS_ARG,({"-R"})}), ({"L",Getopt.HAS_ARG,({"-L"})}), ({"l",Getopt.HAS_ARG,({"-l"})}), ({"S",Getopt.NO_ARG,({"-S"})}),
f896402000-12-28Fredrik Hübinette (Hubbe)  ({"a",Getopt.NO_ARG,({"-a"})}),
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  ({"ignore","Getopt.HAS_ARG",({"-r","-i","-s","-g","-B","-W"})}), )),array opt) { switch(opt[0]) { case "S": strip++; break; case "L":
6ea3382000-12-26Fredrik Hübinette (Hubbe)  libpath|=({opt[1]}); break; case "R":
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  global_directives|=({ "-?rpath:"+opt[1] }); break; case "l": switch(opt[1]) { case "c": case "m": break; default:
6ea3382000-12-26Fredrik Hübinette (Hubbe)  libraries|=({opt[1]});
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  } break;
f896402000-12-28Fredrik Hübinette (Hubbe)  case "a": export_all++; break;
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  case "output": output=opt[1]; break; } }
6ea3382000-12-26Fredrik Hübinette (Hubbe)  if(getenv("NTLD_LIBRARY_PATH")) libpath|=getenv("NTLD_LIBRARY_PATH")/":"; if(getenv("NTLD_RUN_PATH")) foreach(getenv("NTLD_RUN_PATH")/":",string p) global_directives|=({"-?rpath:"+p}); libpath|=({"."}); foreach(libraries, string lib) { int found; foreach(libpath, string path) { string filename=combine_path(path,lib+".lib"); #ifdef DEBUG werror("Looking for %s\n",filename); #endif if(string file=Stdio.read_file(filename)) { dumpfile(file, 0, 0, filename); found=1; break; } filename=combine_path(path,upper_case(lib+".lib")); #ifdef DEBUG werror("Looking for %s\n",filename); #endif if(string file=Stdio.read_file(filename)) { dumpfile(file, 0, 0, filename); found=1; break; } } if(!found) { werror("Failed to find library: %s\n",lib); err++; } }
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  argv=Getopt.get_args(argv); foreach(argv[1..],string file) dumpfile(Stdio.read_file(file),0,0,file+":"+file); if(strip) { global_sections=Array.filter(global_sections, lambda(Section s) { return !(s->characteristics & CHR_LINK_MEM_DISCARDABLE); }); }
462c412001-01-03Fredrik Hübinette (Hubbe)  if(err) exit(err); /* perform fixups */
f896402000-12-28Fredrik Hübinette (Hubbe)  foreach(values(global_symbols), Symbol s) if(s->section)
462c412001-01-03Fredrik Hübinette (Hubbe)  s->section->symbols_in_this_section+=({s});
f896402000-12-28Fredrik Hübinette (Hubbe) 
462c412001-01-03Fredrik Hübinette (Hubbe)  if(!export_all)
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  {
462c412001-01-03Fredrik Hübinette (Hubbe)  foreach(global_sections, Section s) { if(sscanf(s->name,".idata%*s")) { string name= ( s->file /"/" )[-1]; Section s2=Section(); s2->name=".drectve"; s2->data = "-LIB:"+name; foreach(s->symbols_in_this_section, Symbol sym) { // werror("Fixing (%s) %s : %s\n",name,s->name,sym->name); sym->section=s2; sym->value=0; if((sym->type >> 4) == 2) { werror("Warning: Symbol %s is double indirected!\n",sym->name); } sym->type=2<<4; } } }
2c3ee52000-12-22Fredrik Hübinette (Hubbe)  }
462c412001-01-03Fredrik Hübinette (Hubbe) 
6ea3382000-12-26Fredrik Hübinette (Hubbe)  if(err) exit(err);
f896402000-12-28Fredrik Hübinette (Hubbe) 
462c412001-01-03Fredrik Hübinette (Hubbe)  Linker l=Linker(); map(global_directives, l->add_directive);
f896402000-12-28Fredrik Hübinette (Hubbe)  werror("Creating %s\n",output); if(export_all) {
462c412001-01-03Fredrik Hübinette (Hubbe)  map(global_sections, l->add_section); map(values(global_symbols), l->add_symbol);
f896402000-12-28Fredrik Hübinette (Hubbe)  }else{ foreach(global_directives, string dir) { if(sscanf(dir,"-export:%s",string sym)) { // werror("Exporting symbol: %O\n",sym);
462c412001-01-03Fredrik Hübinette (Hubbe)  if(global_symbols[sym]) l->add_symbol(global_symbols[sym]); if(global_symbols[sym+"()"]) l->add_symbol(global_symbols[sym+"()"]);
f896402000-12-28Fredrik Hübinette (Hubbe)  } } }
462c412001-01-03Fredrik Hübinette (Hubbe)  if(err) exit(err); rm(output);
f896402000-12-28Fredrik Hübinette (Hubbe)  Stdio.write_file(output, l->out());
6ea3382000-12-26Fredrik Hübinette (Hubbe)  exit(err);
2c3ee52000-12-22Fredrik Hübinette (Hubbe) }