2c3ee5 | 2000-12-22 | Fredrik Hübinette (Hubbe) | | #!/usr/local/bin/pike
|
6ea338 | 2000-12-26 | Fredrik Hübinette (Hubbe) | | // Partial linker for COFF files, written by Fredrik Hubinette 2000
//
// Things left to do:
// Merge sections
// Test if resulting files work with cl.exe
// Support line number information
// Support 64 bit architechtures
|
2c3ee5 | 2000-12-22 | Fredrik Hübinette (Hubbe) | |
class Reloc
{
Symbol sym;
int loc;
int type;
};
class Section
{
string name;
|
5b2b59 | 2000-12-27 | Fredrik Hübinette (Hubbe) | | int|string data;
|
2c3ee5 | 2000-12-22 | Fredrik Hübinette (Hubbe) | | array(Reloc) relocs;
int virtual_size;
int characteristics;
};
class Symbol
{
string name;
int value;
Section section;
int type;
int cls;
array(Symbol) aux;
};
mapping(string:Symbol) global_symbols=([]);
array(Section) global_sections=({});
array(string) global_directives=({});
|
6ea338 | 2000-12-26 | Fredrik Hübinette (Hubbe) | | array(string) libpath=({});
array(string) libraries=({});
|
2c3ee5 | 2000-12-22 | Fredrik Hübinette (Hubbe) | |
class Linker
{
string ret="";
string stringtable="";
string symboltable="";
string sectiondata="";
string sectiontable="";
int num_symbols;
mapping(Symbol:int) symbol_to_number=([]);
|
5b2b59 | 2000-12-27 | Fredrik Hübinette (Hubbe) | | int base;
int num_sections;
mapping(Section:int) section_to_number=([]);
|
2c3ee5 | 2000-12-22 | Fredrik Hübinette (Hubbe) | | mapping(string:int) stringtablecache=([]);
int add_string(string s)
{
int pos;
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;
}
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)
{
#ifdef DEBUG
werror("Encoding symbol named: %s\n",s->name);
#endif
if(symbol_to_number[s])
return symbol_to_number[s]-1;
num_symbols++;
symboltable+=sprintf("%s%-4c%-2c%-2c%c%c",
add_sym_name(s->name),
s->value,
|
5b2b59 | 2000-12-27 | Fredrik Hübinette (Hubbe) | | s->section ? add_section(s->section) +1 : 0,
|
2c3ee5 | 2000-12-22 | Fredrik Hübinette (Hubbe) | | s->type,
s->cls,
0); /* aux symbols not supported */
symbol_to_number[s]=sizeof(symbol_to_number)+1;
return symbol_to_number[s]-1;
}
|
5b2b59 | 2000-12-27 | Fredrik Hübinette (Hubbe) | | int add_section(Section s)
{
if(section_to_number[s])
return section_to_number[s]-1;
section_to_number[s]=++num_sections;
return section_to_number[s]-1;
}
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);
}
|
2c3ee5 | 2000-12-22 | Fredrik Hübinette (Hubbe) | |
string out(array(Section) sections,
array(Symbol) exports)
{
int secnum;
|
5b2b59 | 2000-12-27 | Fredrik Hübinette (Hubbe) | | foreach(sections, Section s) add_section(s);
foreach(exports, Symbol s) add_symbol(s);
|
2c3ee5 | 2000-12-22 | Fredrik Hübinette (Hubbe) | |
|
5b2b59 | 2000-12-27 | Fredrik Hübinette (Hubbe) | | /* Actually output data */
Section s;
base=20 /*coff*/ + sizeof(section_to_number) * 40;
for(int secnum=1;s=search(section_to_number, secnum);secnum++)
|
2c3ee5 | 2000-12-22 | Fredrik Hübinette (Hubbe) | | {
#ifdef DEBUG
werror("Encoding section named: %s\n",s->name);
#endif
sectiontable+=
sprintf("%s%-4c%-4c%-4c%-4c%-4c%-4c%-2c%-2c%-4c",
add_sym_name(s->name),
s->virtual_size,
0, /* virtual address */
|
5b2b59 | 2000-12-27 | Fredrik Hübinette (Hubbe) | | virtual_data_size(s->data),
stringp(s->data) ? (base + strlen(sectiondata)) : 0,
|
9b6bd4 | 2000-12-27 | Fredrik Hübinette (Hubbe) | | s->relocs && (base + strlen(sectiondata) + file_data_size(s->data)),
|
5b2b59 | 2000-12-27 | Fredrik Hübinette (Hubbe) | | 0, /* no linenums yet */
s->relocs && sizeof(s->relocs),
|
2c3ee5 | 2000-12-22 | Fredrik Hübinette (Hubbe) | | 0,
s->characteristics);
|
5b2b59 | 2000-12-27 | Fredrik 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);
}
|
2c3ee5 | 2000-12-22 | Fredrik Hübinette (Hubbe) | |
return
sprintf("%-2c%-2c%-4c%-4c%-4c%-2c%-2c" /* coff */
"%s%s%s%s" /* the rest */ ,
/* coff */
0x14c, /* Intel x86 */
|
5b2b59 | 2000-12-27 | Fredrik Hübinette (Hubbe) | | sizeof(section_to_number),
|
2c3ee5 | 2000-12-22 | Fredrik Hübinette (Hubbe) | | time(),
base+strlen(sectiondata),
num_symbols,
0, /* opt header size */
0, /* no character */
sectiontable,
sectiondata,
symboltable,
stringtable);
}
}
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",
);
#define CHR_LINK_INFO 0x200
#define CHR_LINK_REMOVE 0x800
#define CHR_LINK_ALIGN_1 0x100000
#define CHR_LINK_MEM_DISCARDABLE 0x2000000
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);
}
}
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);
|
5b2b59 | 2000-12-27 | Fredrik 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);
}
|
2c3ee5 | 2000-12-22 | Fredrik Hübinette (Hubbe) | | file_sections[e]->virtual_size=i4(pos+8);;
file_sections[e]->characteristics=i4(pos+36);
|
5b2b59 | 2000-12-27 | Fredrik Hübinette (Hubbe) | |
if(i4(pos+24))
file_sections[e]->relocs=dumpRelocs(i4(pos+24), i2(pos+32));
|
2c3ee5 | 2000-12-22 | Fredrik 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
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;
s->section=sect>0 ? file_sections[sect-1] : 0;
s->type=type;
s->cls=cls;
s->aux=0;
#define COFFSYM_external 2
switch(cls)
{
case COFFSYM_external:
if(global_symbols[name])
{
s=global_symbols[name];
if(s->section && sect > 0)
|
5b2b59 | 2000-12-27 | Fredrik Hübinette (Hubbe) | | werror("%s: Warning: Symbol %s redefined.\n",
|
2c3ee5 | 2000-12-22 | Fredrik Hübinette (Hubbe) | | filename,
name);
}
if(sect > 0)
{
s->section = file_sections[sect-1];
s->value = value;
s->type = type;
}
global_symbols[name]=s;
}
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
if(data[pos..pos+3]!="PE\0\0")
{
#ifdef DEBUG
write("No.\n");
#endif
return 0;
} else {
#ifdef DEBUG
write("Yes.\n");
#endif
}
dumpCOFF(pos+4);
return 1;
}
void dumpArchive(int pos)
{
|
6ea338 | 2000-12-26 | Fredrik Hübinette (Hubbe) | | string name;
int num;
int longnames;
|
2c3ee5 | 2000-12-22 | Fredrik Hübinette (Hubbe) | | while(pos < strlen(data))
{
|
6ea338 | 2000-12-26 | Fredrik Hübinette (Hubbe) | | num++;
|
2c3ee5 | 2000-12-22 | Fredrik Hübinette (Hubbe) | | int size = (int) range(pos+48,10);
|
6ea338 | 2000-12-26 | Fredrik 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);
}
|
2c3ee5 | 2000-12-22 | Fredrik Hübinette (Hubbe) | | #ifdef DEBUG
write("\n");
write("# name: %s\n",name);
|
6ea338 | 2000-12-26 | Fredrik Hübinette (Hubbe) | | write("# date: %s",ctime( (int) range(pos+16,12) ) );
|
2c3ee5 | 2000-12-22 | Fredrik 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]!='/')
|
6ea338 | 2000-12-26 | Fredrik Hübinette (Hubbe) | | {
dumpfile(data, pos+60, 0, name);
}
|
2c3ee5 | 2000-12-22 | Fredrik Hübinette (Hubbe) | | pos+=60;
pos+=(size+1)&~1;
}
}
|
6ea338 | 2000-12-26 | Fredrik Hübinette (Hubbe) | | void dumpImportLib()
{
string name= ( filename/"/" )[-1];
#if 0
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);
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));
write("Importing library: %O\n",name);
#endif
global_directives|=({ "-LIB:"+name });
}
|
2c3ee5 | 2000-12-22 | Fredrik 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{
|
6ea338 | 2000-12-26 | Fredrik Hübinette (Hubbe) | | if(i2(0) == 0 && i2(2) == 0xffff)
|
2c3ee5 | 2000-12-22 | Fredrik Hübinette (Hubbe) | | {
|
6ea338 | 2000-12-26 | Fredrik Hübinette (Hubbe) | | dumpImportLib();
}else{
|
2c3ee5 | 2000-12-22 | Fredrik Hübinette (Hubbe) | | dumpCOFF(0);
|
6ea338 | 2000-12-26 | Fredrik Hübinette (Hubbe) | | }
|
2c3ee5 | 2000-12-22 | Fredrik Hübinette (Hubbe) | | }
}
}
int main(int argc, array(string) argv)
{
|
6ea338 | 2000-12-26 | Fredrik Hübinette (Hubbe) | | int err;
|
2c3ee5 | 2000-12-22 | Fredrik Hübinette (Hubbe) | | int strip=0;
string output="a.out";
// werror("%O\n",argv);
werror("Pike Win32 partial linker.\n"
|
9b6bd4 | 2000-12-27 | Fredrik Hübinette (Hubbe) | | "$Id: pntld,v 1.4 2000/12/28 01:17:04 hubbe Exp $\n"
|
2c3ee5 | 2000-12-22 | Fredrik 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"})}),
({"ignore","Getopt.HAS_ARG",({"-r","-i","-s","-g","-B","-W"})}),
)),array opt)
{
switch(opt[0])
{
case "S": strip++; break;
case "L":
|
6ea338 | 2000-12-26 | Fredrik Hübinette (Hubbe) | | libpath|=({opt[1]});
break;
case "R":
|
2c3ee5 | 2000-12-22 | Fredrik Hübinette (Hubbe) | | global_directives|=({ "-?rpath:"+opt[1] });
break;
case "l":
switch(opt[1])
{
case "c": case "m": break;
default:
|
6ea338 | 2000-12-26 | Fredrik Hübinette (Hubbe) | | libraries|=({opt[1]});
|
2c3ee5 | 2000-12-22 | Fredrik Hübinette (Hubbe) | | }
break;
case "output":
output=opt[1];
break;
}
}
|
6ea338 | 2000-12-26 | Fredrik 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++;
}
}
|
2c3ee5 | 2000-12-22 | Fredrik 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);
});
}
if(sizeof(global_directives))
{
Section s=Section();
s->name=".drectve";
s->data=global_directives * " ";
s->characteristics = CHR_LINK_INFO | CHR_LINK_REMOVE | CHR_LINK_ALIGN_1;
s->relocs=({});
global_sections= ({s}) + global_sections;
}
|
6ea338 | 2000-12-26 | Fredrik Hübinette (Hubbe) | | if(err) exit(err);
|
2c3ee5 | 2000-12-22 | Fredrik Hübinette (Hubbe) | | rm(output);
Stdio.write_file(output,
Linker()->out(global_sections,
values(global_symbols)));
|
6ea338 | 2000-12-26 | Fredrik Hübinette (Hubbe) | | exit(err);
|
2c3ee5 | 2000-12-22 | Fredrik Hübinette (Hubbe) | | }
|