1bd389b36SDavid du Colombier #include <u.h> 2bd389b36SDavid du Colombier #include <libc.h> 3bd389b36SDavid du Colombier #include <bio.h> 4bd389b36SDavid du Colombier #include <bootexec.h> 5bd389b36SDavid du Colombier #include <mach.h> 67dd7cddfSDavid du Colombier #include "elf.h" 73e12c5d1SDavid du Colombier 83e12c5d1SDavid du Colombier /* 93e12c5d1SDavid du Colombier * All a.out header types. The dummy entry allows canonical 103e12c5d1SDavid du Colombier * processing of the union as a sequence of longs 113e12c5d1SDavid du Colombier */ 123e12c5d1SDavid du Colombier 133e12c5d1SDavid du Colombier typedef struct { 143e12c5d1SDavid du Colombier union{ 15*4de34a7eSDavid du Colombier struct { 16*4de34a7eSDavid du Colombier Exec; /* a.out.h */ 17*4de34a7eSDavid du Colombier uvlong hdr[1]; 18*4de34a7eSDavid du Colombier }; 19*4de34a7eSDavid du Colombier Ehdr; /* elf.h */ 20*4de34a7eSDavid du Colombier struct mipsexec; /* bootexec.h */ 21*4de34a7eSDavid du Colombier struct mips4kexec; /* bootexec.h */ 22*4de34a7eSDavid du Colombier struct sparcexec; /* bootexec.h */ 23*4de34a7eSDavid du Colombier struct nextexec; /* bootexec.h */ 243e12c5d1SDavid du Colombier } e; 253e12c5d1SDavid du Colombier long dummy; /* padding to ensure extra long */ 263e12c5d1SDavid du Colombier } ExecHdr; 273e12c5d1SDavid du Colombier 287dd7cddfSDavid du Colombier static int nextboot(int, Fhdr*, ExecHdr*); 297dd7cddfSDavid du Colombier static int sparcboot(int, Fhdr*, ExecHdr*); 307dd7cddfSDavid du Colombier static int mipsboot(int, Fhdr*, ExecHdr*); 317dd7cddfSDavid du Colombier static int mips4kboot(int, Fhdr*, ExecHdr*); 327dd7cddfSDavid du Colombier static int common(int, Fhdr*, ExecHdr*); 33*4de34a7eSDavid du Colombier static int commonllp64(int, Fhdr*, ExecHdr*); 347dd7cddfSDavid du Colombier static int adotout(int, Fhdr*, ExecHdr*); 357dd7cddfSDavid du Colombier static int elfdotout(int, Fhdr*, ExecHdr*); 367dd7cddfSDavid du Colombier static int armdotout(int, Fhdr*, ExecHdr*); 377dd7cddfSDavid du Colombier static int alphadotout(int, Fhdr*, ExecHdr*); 38*4de34a7eSDavid du Colombier static void setsym(Fhdr*, long, long, long, vlong); 39*4de34a7eSDavid du Colombier static void setdata(Fhdr*, uvlong, long, vlong, long); 40*4de34a7eSDavid du Colombier static void settext(Fhdr*, uvlong, uvlong, long, vlong); 41*4de34a7eSDavid du Colombier static void hswal(void*, int, ulong(*)(ulong)); 42*4de34a7eSDavid du Colombier static uvlong _round(uvlong, ulong); 433e12c5d1SDavid du Colombier 443e12c5d1SDavid du Colombier /* 453e12c5d1SDavid du Colombier * definition of per-executable file type structures 463e12c5d1SDavid du Colombier */ 473e12c5d1SDavid du Colombier 483e12c5d1SDavid du Colombier typedef struct Exectable{ 493e12c5d1SDavid du Colombier long magic; /* big-endian magic number of file */ 503e12c5d1SDavid du Colombier char *name; /* executable identifier */ 5112fd1c83SDavid du Colombier char *dlmname; /* dynamically loadable module identifier */ 523e12c5d1SDavid du Colombier int type; /* Internal code */ 533e12c5d1SDavid du Colombier Mach *mach; /* Per-machine data */ 54*4de34a7eSDavid du Colombier long hsize; /* header size */ 55*4de34a7eSDavid du Colombier ulong (*swal)(ulong); /* beswal or leswal */ 567dd7cddfSDavid du Colombier int (*hparse)(int, Fhdr*, ExecHdr*); 573e12c5d1SDavid du Colombier } ExecTable; 583e12c5d1SDavid du Colombier 593e12c5d1SDavid du Colombier extern Mach mmips; 607dd7cddfSDavid du Colombier extern Mach mmips2le; 617dd7cddfSDavid du Colombier extern Mach mmips2be; 623e12c5d1SDavid du Colombier extern Mach msparc; 63b0dcc5a8SDavid du Colombier extern Mach msparc64; 643e12c5d1SDavid du Colombier extern Mach m68020; 653e12c5d1SDavid du Colombier extern Mach mi386; 66b0dcc5a8SDavid du Colombier extern Mach mamd64; 677dd7cddfSDavid du Colombier extern Mach marm; 687dd7cddfSDavid du Colombier extern Mach mpower; 697dd7cddfSDavid du Colombier extern Mach malpha; 703e12c5d1SDavid du Colombier 713e12c5d1SDavid du Colombier ExecTable exectab[] = 723e12c5d1SDavid du Colombier { 733e12c5d1SDavid du Colombier { V_MAGIC, /* Mips v.out */ 743e12c5d1SDavid du Colombier "mips plan 9 executable", 7512fd1c83SDavid du Colombier "mips plan 9 dlm", 763e12c5d1SDavid du Colombier FMIPS, 773e12c5d1SDavid du Colombier &mmips, 783e12c5d1SDavid du Colombier sizeof(Exec), 793e12c5d1SDavid du Colombier beswal, 803e12c5d1SDavid du Colombier adotout }, 817dd7cddfSDavid du Colombier { M_MAGIC, /* Mips 4.out */ 827dd7cddfSDavid du Colombier "mips 4k plan 9 executable BE", 8312fd1c83SDavid du Colombier "mips 4k plan 9 dlm BE", 847dd7cddfSDavid du Colombier FMIPS2BE, 857dd7cddfSDavid du Colombier &mmips2be, 867dd7cddfSDavid du Colombier sizeof(Exec), 877dd7cddfSDavid du Colombier beswal, 887dd7cddfSDavid du Colombier adotout }, 897dd7cddfSDavid du Colombier { N_MAGIC, /* Mips 0.out */ 907dd7cddfSDavid du Colombier "mips 4k plan 9 executable LE", 9112fd1c83SDavid du Colombier "mips 4k plan 9 dlm LE", 927dd7cddfSDavid du Colombier FMIPS2LE, 937dd7cddfSDavid du Colombier &mmips2le, 947dd7cddfSDavid du Colombier sizeof(Exec), 957dd7cddfSDavid du Colombier beswal, 967dd7cddfSDavid du Colombier adotout }, 973e12c5d1SDavid du Colombier { 0x160<<16, /* Mips boot image */ 983e12c5d1SDavid du Colombier "mips plan 9 boot image", 9912fd1c83SDavid du Colombier nil, 1003e12c5d1SDavid du Colombier FMIPSB, 1013e12c5d1SDavid du Colombier &mmips, 1023e12c5d1SDavid du Colombier sizeof(struct mipsexec), 1033e12c5d1SDavid du Colombier beswal, 1043e12c5d1SDavid du Colombier mipsboot }, 105219b2ee8SDavid du Colombier { (0x160<<16)|3, /* Mips boot image */ 106219b2ee8SDavid du Colombier "mips 4k plan 9 boot image", 10712fd1c83SDavid du Colombier nil, 108219b2ee8SDavid du Colombier FMIPSB, 10980ee5cbfSDavid du Colombier &mmips2be, 110219b2ee8SDavid du Colombier sizeof(struct mips4kexec), 1113e12c5d1SDavid du Colombier beswal, 112219b2ee8SDavid du Colombier mips4kboot }, 1133e12c5d1SDavid du Colombier { K_MAGIC, /* Sparc k.out */ 1143e12c5d1SDavid du Colombier "sparc plan 9 executable", 11512fd1c83SDavid du Colombier "sparc plan 9 dlm", 1163e12c5d1SDavid du Colombier FSPARC, 1173e12c5d1SDavid du Colombier &msparc, 1183e12c5d1SDavid du Colombier sizeof(Exec), 1193e12c5d1SDavid du Colombier beswal, 1203e12c5d1SDavid du Colombier adotout }, 1213e12c5d1SDavid du Colombier { 0x01030107, /* Sparc boot image */ 1223e12c5d1SDavid du Colombier "sparc plan 9 boot image", 12312fd1c83SDavid du Colombier nil, 1243e12c5d1SDavid du Colombier FSPARCB, 1253e12c5d1SDavid du Colombier &msparc, 1263e12c5d1SDavid du Colombier sizeof(struct sparcexec), 1273e12c5d1SDavid du Colombier beswal, 1283e12c5d1SDavid du Colombier sparcboot }, 129b0dcc5a8SDavid du Colombier { U_MAGIC, /* Sparc64 u.out */ 130b0dcc5a8SDavid du Colombier "sparc64 plan 9 executable", 131b0dcc5a8SDavid du Colombier "sparc64 plan 9 dlm", 132b0dcc5a8SDavid du Colombier FSPARC64, 133b0dcc5a8SDavid du Colombier &msparc64, 134b0dcc5a8SDavid du Colombier sizeof(Exec), 135b0dcc5a8SDavid du Colombier beswal, 136b0dcc5a8SDavid du Colombier adotout }, 1373e12c5d1SDavid du Colombier { A_MAGIC, /* 68020 2.out & boot image */ 1383e12c5d1SDavid du Colombier "68020 plan 9 executable", 13912fd1c83SDavid du Colombier "68020 plan 9 dlm", 1403e12c5d1SDavid du Colombier F68020, 1413e12c5d1SDavid du Colombier &m68020, 1423e12c5d1SDavid du Colombier sizeof(Exec), 1433e12c5d1SDavid du Colombier beswal, 1443e12c5d1SDavid du Colombier common }, 1453e12c5d1SDavid du Colombier { 0xFEEDFACE, /* Next boot image */ 1463e12c5d1SDavid du Colombier "next plan 9 boot image", 14712fd1c83SDavid du Colombier nil, 1483e12c5d1SDavid du Colombier FNEXTB, 1493e12c5d1SDavid du Colombier &m68020, 1503e12c5d1SDavid du Colombier sizeof(struct nextexec), 1513e12c5d1SDavid du Colombier beswal, 1523e12c5d1SDavid du Colombier nextboot }, 1533e12c5d1SDavid du Colombier { I_MAGIC, /* I386 8.out & boot image */ 1543e12c5d1SDavid du Colombier "386 plan 9 executable", 15512fd1c83SDavid du Colombier "386 plan 9 dlm", 1563e12c5d1SDavid du Colombier FI386, 1573e12c5d1SDavid du Colombier &mi386, 1583e12c5d1SDavid du Colombier sizeof(Exec), 1593e12c5d1SDavid du Colombier beswal, 1603e12c5d1SDavid du Colombier common }, 161b0dcc5a8SDavid du Colombier { S_MAGIC, /* amd64 6.out & boot image */ 162b0dcc5a8SDavid du Colombier "amd64 plan 9 executable", 163b0dcc5a8SDavid du Colombier "amd64 plan 9 dlm", 164b0dcc5a8SDavid du Colombier FAMD64, 165b0dcc5a8SDavid du Colombier &mamd64, 166*4de34a7eSDavid du Colombier sizeof(Exec)+8, 167*4de34a7eSDavid du Colombier nil, 168*4de34a7eSDavid du Colombier commonllp64 }, 1699a747e4fSDavid du Colombier { Q_MAGIC, /* PowerPC q.out & boot image */ 1707dd7cddfSDavid du Colombier "power plan 9 executable", 17112fd1c83SDavid du Colombier "power plan 9 dlm", 1727dd7cddfSDavid du Colombier FPOWER, 1737dd7cddfSDavid du Colombier &mpower, 1747dd7cddfSDavid du Colombier sizeof(Exec), 1757dd7cddfSDavid du Colombier beswal, 1767dd7cddfSDavid du Colombier common }, 17770b8e010SDavid du Colombier { ELF_MAG, /* any elf32 */ 178b0dcc5a8SDavid du Colombier "elf executable", 17912fd1c83SDavid du Colombier nil, 18070b8e010SDavid du Colombier FNONE, 18170b8e010SDavid du Colombier &mi386, 1827dd7cddfSDavid du Colombier sizeof(Ehdr), 183*4de34a7eSDavid du Colombier nil, 1847dd7cddfSDavid du Colombier elfdotout }, 1857dd7cddfSDavid du Colombier { E_MAGIC, /* Arm 5.out */ 186b0dcc5a8SDavid du Colombier "arm plan 9 executable", 187b0dcc5a8SDavid du Colombier "arm plan 9 dlm", 1887dd7cddfSDavid du Colombier FARM, 1897dd7cddfSDavid du Colombier &marm, 1907dd7cddfSDavid du Colombier sizeof(Exec), 1917dd7cddfSDavid du Colombier beswal, 1927dd7cddfSDavid du Colombier common }, 1937dd7cddfSDavid du Colombier { (143<<16)|0413, /* (Free|Net)BSD Arm */ 194b0dcc5a8SDavid du Colombier "arm *bsd executable", 19512fd1c83SDavid du Colombier nil, 1967dd7cddfSDavid du Colombier FARM, 1977dd7cddfSDavid du Colombier &marm, 1987dd7cddfSDavid du Colombier sizeof(Exec), 1997dd7cddfSDavid du Colombier leswal, 2007dd7cddfSDavid du Colombier armdotout }, 2017dd7cddfSDavid du Colombier { L_MAGIC, /* alpha 7.out */ 2027dd7cddfSDavid du Colombier "alpha plan 9 executable", 20312fd1c83SDavid du Colombier "alpha plan 9 dlm", 2047dd7cddfSDavid du Colombier FALPHA, 2057dd7cddfSDavid du Colombier &malpha, 2067dd7cddfSDavid du Colombier sizeof(Exec), 2077dd7cddfSDavid du Colombier beswal, 2087dd7cddfSDavid du Colombier common }, 2097dd7cddfSDavid du Colombier { 0x0700e0c3, /* alpha boot image */ 2107dd7cddfSDavid du Colombier "alpha plan 9 boot image", 21112fd1c83SDavid du Colombier nil, 2127dd7cddfSDavid du Colombier FALPHAB, 2137dd7cddfSDavid du Colombier &malpha, 2147dd7cddfSDavid du Colombier sizeof(Exec), 2157dd7cddfSDavid du Colombier beswal, 2167dd7cddfSDavid du Colombier alphadotout }, 2173e12c5d1SDavid du Colombier { 0 }, 2183e12c5d1SDavid du Colombier }; 2193e12c5d1SDavid du Colombier 2207dd7cddfSDavid du Colombier Mach *mach = &mi386; /* Global current machine table */ 2217dd7cddfSDavid du Colombier 2227dd7cddfSDavid du Colombier static ExecTable* 2237dd7cddfSDavid du Colombier couldbe4k(ExecTable *mp) 2247dd7cddfSDavid du Colombier { 2259a747e4fSDavid du Colombier Dir *d; 2267dd7cddfSDavid du Colombier ExecTable *f; 2277dd7cddfSDavid du Colombier 2289a747e4fSDavid du Colombier if((d=dirstat("/proc/1/regs")) == nil) 2297dd7cddfSDavid du Colombier return mp; 2309a747e4fSDavid du Colombier if(d->length < 32*8){ /* R3000 */ 2319a747e4fSDavid du Colombier free(d); 2327dd7cddfSDavid du Colombier return mp; 2339a747e4fSDavid du Colombier } 2349a747e4fSDavid du Colombier free(d); 2357dd7cddfSDavid du Colombier for (f = exectab; f->magic; f++) 2367dd7cddfSDavid du Colombier if(f->magic == M_MAGIC) { 2377dd7cddfSDavid du Colombier f->name = "mips plan 9 executable on mips2 kernel"; 2387dd7cddfSDavid du Colombier return f; 2397dd7cddfSDavid du Colombier } 2407dd7cddfSDavid du Colombier return mp; 2417dd7cddfSDavid du Colombier } 2427dd7cddfSDavid du Colombier 2433e12c5d1SDavid du Colombier int 2443e12c5d1SDavid du Colombier crackhdr(int fd, Fhdr *fp) 2453e12c5d1SDavid du Colombier { 2463e12c5d1SDavid du Colombier ExecTable *mp; 2473e12c5d1SDavid du Colombier ExecHdr d; 248*4de34a7eSDavid du Colombier int nb, ret; 249*4de34a7eSDavid du Colombier ulong magic; 2503e12c5d1SDavid du Colombier 2513e12c5d1SDavid du Colombier fp->type = FNONE; 2527dd7cddfSDavid du Colombier nb = read(fd, (char *)&d.e, sizeof(d.e)); 2537dd7cddfSDavid du Colombier if (nb <= 0) 2543e12c5d1SDavid du Colombier return 0; 2557dd7cddfSDavid du Colombier 2567dd7cddfSDavid du Colombier ret = 0; 2573e12c5d1SDavid du Colombier fp->magic = magic = beswal(d.e.magic); /* big-endian */ 2583e12c5d1SDavid du Colombier for (mp = exectab; mp->magic; mp++) { 25912fd1c83SDavid du Colombier if (nb < mp->hsize) 26012fd1c83SDavid du Colombier continue; 26112fd1c83SDavid du Colombier if (mp->magic == (magic & ~DYN_MAGIC)) { 2627dd7cddfSDavid du Colombier if(mp->magic == V_MAGIC) 2637dd7cddfSDavid du Colombier mp = couldbe4k(mp); 2647dd7cddfSDavid du Colombier 2653e12c5d1SDavid du Colombier fp->type = mp->type; 26612fd1c83SDavid du Colombier if ((magic & DYN_MAGIC) && mp->dlmname != nil) 26712fd1c83SDavid du Colombier fp->name = mp->dlmname; 26812fd1c83SDavid du Colombier else 2693e12c5d1SDavid du Colombier fp->name = mp->name; 270219b2ee8SDavid du Colombier fp->hdrsz = mp->hsize; /* zero on bootables */ 2713e12c5d1SDavid du Colombier mach = mp->mach; 272*4de34a7eSDavid du Colombier if(mp->swal != nil) 273*4de34a7eSDavid du Colombier hswal(&d, sizeof(d.e)/sizeof(ulong), mp->swal); 2747dd7cddfSDavid du Colombier ret = mp->hparse(fd, fp, &d); 2753e12c5d1SDavid du Colombier seek(fd, mp->hsize, 0); /* seek to end of header */ 2767dd7cddfSDavid du Colombier break; 2773e12c5d1SDavid du Colombier } 2783e12c5d1SDavid du Colombier } 2797dd7cddfSDavid du Colombier if(mp->magic == 0) 2807dd7cddfSDavid du Colombier werrstr("unknown header type"); 2817dd7cddfSDavid du Colombier return ret; 2823e12c5d1SDavid du Colombier } 283*4de34a7eSDavid du Colombier 2843e12c5d1SDavid du Colombier /* 2853e12c5d1SDavid du Colombier * Convert header to canonical form 2863e12c5d1SDavid du Colombier */ 2873e12c5d1SDavid du Colombier static void 288*4de34a7eSDavid du Colombier hswal(void *v, int n, ulong (*swap)(ulong)) 2893e12c5d1SDavid du Colombier { 290*4de34a7eSDavid du Colombier ulong *ulp; 291*4de34a7eSDavid du Colombier 292*4de34a7eSDavid du Colombier for(ulp = v; n--; ulp++) 293*4de34a7eSDavid du Colombier *ulp = (*swap)(*ulp); 2943e12c5d1SDavid du Colombier } 295*4de34a7eSDavid du Colombier 29670b8e010SDavid du Colombier /* 2973e12c5d1SDavid du Colombier * Crack a normal a.out-type header 2983e12c5d1SDavid du Colombier */ 2997dd7cddfSDavid du Colombier static int 3007dd7cddfSDavid du Colombier adotout(int fd, Fhdr *fp, ExecHdr *hp) 3013e12c5d1SDavid du Colombier { 3027dd7cddfSDavid du Colombier long pgsize; 3033e12c5d1SDavid du Colombier 3047dd7cddfSDavid du Colombier USED(fd); 3057dd7cddfSDavid du Colombier pgsize = mach->pgsize; 306219b2ee8SDavid du Colombier settext(fp, hp->e.entry, pgsize+sizeof(Exec), 307219b2ee8SDavid du Colombier hp->e.text, sizeof(Exec)); 308219b2ee8SDavid du Colombier setdata(fp, _round(pgsize+fp->txtsz+sizeof(Exec), pgsize), 309219b2ee8SDavid du Colombier hp->e.data, fp->txtsz+sizeof(Exec), hp->e.bss); 3103e12c5d1SDavid du Colombier setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz); 3117dd7cddfSDavid du Colombier return 1; 3123e12c5d1SDavid du Colombier } 3133e12c5d1SDavid du Colombier 314*4de34a7eSDavid du Colombier static void 315*4de34a7eSDavid du Colombier commonboot(Fhdr *fp) 316*4de34a7eSDavid du Colombier { 317*4de34a7eSDavid du Colombier uvlong kbase; 318*4de34a7eSDavid du Colombier 319*4de34a7eSDavid du Colombier kbase = mach->kbase; 320*4de34a7eSDavid du Colombier if ((fp->entry & kbase) != kbase) 321*4de34a7eSDavid du Colombier return; 322*4de34a7eSDavid du Colombier 323*4de34a7eSDavid du Colombier switch(fp->type) { /* boot image */ 324*4de34a7eSDavid du Colombier case F68020: 325*4de34a7eSDavid du Colombier fp->type = F68020B; 326*4de34a7eSDavid du Colombier fp->name = "68020 plan 9 boot image"; 327*4de34a7eSDavid du Colombier break; 328*4de34a7eSDavid du Colombier case FI386: 329*4de34a7eSDavid du Colombier fp->type = FI386B; 330*4de34a7eSDavid du Colombier fp->txtaddr = (u32int)fp->entry; 331*4de34a7eSDavid du Colombier fp->name = "386 plan 9 boot image"; 332*4de34a7eSDavid du Colombier fp->dataddr = _round(fp->txtaddr+fp->txtsz, mach->pgsize); 333*4de34a7eSDavid du Colombier break; 334*4de34a7eSDavid du Colombier case FARM: 335*4de34a7eSDavid du Colombier fp->txtaddr = kbase+0x8010; 336*4de34a7eSDavid du Colombier fp->name = "ARM plan 9 boot image"; 337*4de34a7eSDavid du Colombier fp->dataddr = fp->txtaddr+fp->txtsz; 338*4de34a7eSDavid du Colombier return; 339*4de34a7eSDavid du Colombier case FALPHA: 340*4de34a7eSDavid du Colombier fp->type = FALPHAB; 341*4de34a7eSDavid du Colombier fp->txtaddr = (u32int)fp->entry; 342*4de34a7eSDavid du Colombier fp->name = "alpha plan 9 boot image?"; 343*4de34a7eSDavid du Colombier fp->dataddr = fp->txtaddr+fp->txtsz; 344*4de34a7eSDavid du Colombier break; 345*4de34a7eSDavid du Colombier case FPOWER: 346*4de34a7eSDavid du Colombier fp->type = FPOWERB; 347*4de34a7eSDavid du Colombier fp->txtaddr = (u32int)fp->entry; 348*4de34a7eSDavid du Colombier fp->name = "power plan 9 boot image"; 349*4de34a7eSDavid du Colombier fp->dataddr = fp->txtaddr+fp->txtsz; 350*4de34a7eSDavid du Colombier break; 351*4de34a7eSDavid du Colombier case FAMD64: 352*4de34a7eSDavid du Colombier fp->type = FAMD64B; 353*4de34a7eSDavid du Colombier fp->txtaddr = fp->entry; 354*4de34a7eSDavid du Colombier fp->name = "amd64 plan 9 boot image"; 355*4de34a7eSDavid du Colombier fp->dataddr = _round(fp->txtaddr+fp->txtsz, mach->pgsize); 356*4de34a7eSDavid du Colombier break; 357*4de34a7eSDavid du Colombier default: 358*4de34a7eSDavid du Colombier return; 359*4de34a7eSDavid du Colombier } 360*4de34a7eSDavid du Colombier fp->hdrsz = 0; /* header stripped */ 361*4de34a7eSDavid du Colombier } 362*4de34a7eSDavid du Colombier 3633e12c5d1SDavid du Colombier /* 3643e12c5d1SDavid du Colombier * 68020 2.out and 68020 bootable images 3653e12c5d1SDavid du Colombier * 386I 8.out and 386I bootable images 3667dd7cddfSDavid du Colombier * alpha plan9-style bootable images for axp "headerless" boot 3673e12c5d1SDavid du Colombier * 3683e12c5d1SDavid du Colombier */ 3697dd7cddfSDavid du Colombier static int 3707dd7cddfSDavid du Colombier common(int fd, Fhdr *fp, ExecHdr *hp) 3713e12c5d1SDavid du Colombier { 3727dd7cddfSDavid du Colombier adotout(fd, fp, hp); 3739a747e4fSDavid du Colombier if(hp->e.magic & DYN_MAGIC) { 3749a747e4fSDavid du Colombier fp->txtaddr = 0; 3759a747e4fSDavid du Colombier fp->dataddr = fp->txtsz; 3769a747e4fSDavid du Colombier return 1; 3779a747e4fSDavid du Colombier } 378*4de34a7eSDavid du Colombier commonboot(fp); 3797dd7cddfSDavid du Colombier return 1; 3803e12c5d1SDavid du Colombier } 381*4de34a7eSDavid du Colombier 382*4de34a7eSDavid du Colombier static int 383*4de34a7eSDavid du Colombier commonllp64(int, Fhdr *fp, ExecHdr *hp) 384*4de34a7eSDavid du Colombier { 385*4de34a7eSDavid du Colombier long pgsize; 386*4de34a7eSDavid du Colombier uvlong entry; 387*4de34a7eSDavid du Colombier 388*4de34a7eSDavid du Colombier hswal(&hp->e, sizeof(Exec)/sizeof(long), beswal); 389*4de34a7eSDavid du Colombier if(!(hp->e.magic & HDR_MAGIC)) 390*4de34a7eSDavid du Colombier return 0; 391*4de34a7eSDavid du Colombier 392*4de34a7eSDavid du Colombier /* 393*4de34a7eSDavid du Colombier * There can be more magic here if the 394*4de34a7eSDavid du Colombier * header ever needs more expansion. 395*4de34a7eSDavid du Colombier * For now just catch use of any of the 396*4de34a7eSDavid du Colombier * unused bits. 397*4de34a7eSDavid du Colombier */ 398*4de34a7eSDavid du Colombier if((hp->e.magic & ~DYN_MAGIC)>>16) 399*4de34a7eSDavid du Colombier return 0; 400*4de34a7eSDavid du Colombier entry = beswav(hp->e.hdr[0]); 401*4de34a7eSDavid du Colombier 402*4de34a7eSDavid du Colombier pgsize = mach->pgsize; 403*4de34a7eSDavid du Colombier settext(fp, entry, pgsize+fp->hdrsz, hp->e.text, fp->hdrsz); 404*4de34a7eSDavid du Colombier setdata(fp, _round(pgsize+fp->txtsz+fp->hdrsz, pgsize), 405*4de34a7eSDavid du Colombier hp->e.data, fp->txtsz+fp->hdrsz, hp->e.bss); 406*4de34a7eSDavid du Colombier setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz); 407*4de34a7eSDavid du Colombier 408*4de34a7eSDavid du Colombier if(hp->e.magic & DYN_MAGIC) { 409*4de34a7eSDavid du Colombier fp->txtaddr = 0; 410*4de34a7eSDavid du Colombier fp->dataddr = fp->txtsz; 411*4de34a7eSDavid du Colombier return 1; 4123e12c5d1SDavid du Colombier } 413*4de34a7eSDavid du Colombier commonboot(fp); 4147dd7cddfSDavid du Colombier return 1; 4153e12c5d1SDavid du Colombier } 4163e12c5d1SDavid du Colombier 4173e12c5d1SDavid du Colombier /* 4183e12c5d1SDavid du Colombier * mips bootable image. 4193e12c5d1SDavid du Colombier */ 4207dd7cddfSDavid du Colombier static int 4217dd7cddfSDavid du Colombier mipsboot(int fd, Fhdr *fp, ExecHdr *hp) 4223e12c5d1SDavid du Colombier { 4237dd7cddfSDavid du Colombier USED(fd); 4243e12c5d1SDavid du Colombier switch(hp->e.amagic) { 4253e12c5d1SDavid du Colombier default: 4263e12c5d1SDavid du Colombier case 0407: /* some kind of mips */ 4273e12c5d1SDavid du Colombier fp->type = FMIPSB; 4283e12c5d1SDavid du Colombier settext(fp, hp->e.mentry, hp->e.text_start, hp->e.tsize, 4293e12c5d1SDavid du Colombier sizeof(struct mipsexec)+4); 4303e12c5d1SDavid du Colombier setdata(fp, hp->e.data_start, hp->e.dsize, 4313e12c5d1SDavid du Colombier fp->txtoff+hp->e.tsize, hp->e.bsize); 4323e12c5d1SDavid du Colombier break; 4333e12c5d1SDavid du Colombier case 0413: /* some kind of mips */ 4343e12c5d1SDavid du Colombier fp->type = FMIPSB; 4353e12c5d1SDavid du Colombier settext(fp, hp->e.mentry, hp->e.text_start, hp->e.tsize, 0); 4363e12c5d1SDavid du Colombier setdata(fp, hp->e.data_start, hp->e.dsize, hp->e.tsize, 4373e12c5d1SDavid du Colombier hp->e.bsize); 4383e12c5d1SDavid du Colombier break; 4393e12c5d1SDavid du Colombier } 4403e12c5d1SDavid du Colombier setsym(fp, hp->e.nsyms, 0, hp->e.pcsize, hp->e.symptr); 441219b2ee8SDavid du Colombier fp->hdrsz = 0; /* header stripped */ 4427dd7cddfSDavid du Colombier return 1; 4433e12c5d1SDavid du Colombier } 444219b2ee8SDavid du Colombier 4453e12c5d1SDavid du Colombier /* 446219b2ee8SDavid du Colombier * mips4k bootable image. 4473e12c5d1SDavid du Colombier */ 4487dd7cddfSDavid du Colombier static int 4497dd7cddfSDavid du Colombier mips4kboot(int fd, Fhdr *fp, ExecHdr *hp) 4503e12c5d1SDavid du Colombier { 4517dd7cddfSDavid du Colombier USED(fd); 452219b2ee8SDavid du Colombier switch(hp->e.h.amagic) { 453219b2ee8SDavid du Colombier default: 454219b2ee8SDavid du Colombier case 0407: /* some kind of mips */ 455219b2ee8SDavid du Colombier fp->type = FMIPSB; 456219b2ee8SDavid du Colombier settext(fp, hp->e.h.mentry, hp->e.h.text_start, hp->e.h.tsize, 457219b2ee8SDavid du Colombier sizeof(struct mips4kexec)); 458219b2ee8SDavid du Colombier setdata(fp, hp->e.h.data_start, hp->e.h.dsize, 459219b2ee8SDavid du Colombier fp->txtoff+hp->e.h.tsize, hp->e.h.bsize); 460219b2ee8SDavid du Colombier break; 461219b2ee8SDavid du Colombier case 0413: /* some kind of mips */ 462219b2ee8SDavid du Colombier fp->type = FMIPSB; 463219b2ee8SDavid du Colombier settext(fp, hp->e.h.mentry, hp->e.h.text_start, hp->e.h.tsize, 0); 464219b2ee8SDavid du Colombier setdata(fp, hp->e.h.data_start, hp->e.h.dsize, hp->e.h.tsize, 465219b2ee8SDavid du Colombier hp->e.h.bsize); 466219b2ee8SDavid du Colombier break; 4673e12c5d1SDavid du Colombier } 468219b2ee8SDavid du Colombier setsym(fp, hp->e.h.nsyms, 0, hp->e.h.pcsize, hp->e.h.symptr); 469219b2ee8SDavid du Colombier fp->hdrsz = 0; /* header stripped */ 4707dd7cddfSDavid du Colombier return 1; 471219b2ee8SDavid du Colombier } 472219b2ee8SDavid du Colombier 4733e12c5d1SDavid du Colombier /* 4743e12c5d1SDavid du Colombier * sparc bootable image 4753e12c5d1SDavid du Colombier */ 4767dd7cddfSDavid du Colombier static int 4777dd7cddfSDavid du Colombier sparcboot(int fd, Fhdr *fp, ExecHdr *hp) 4783e12c5d1SDavid du Colombier { 4797dd7cddfSDavid du Colombier USED(fd); 4803e12c5d1SDavid du Colombier fp->type = FSPARCB; 4813e12c5d1SDavid du Colombier settext(fp, hp->e.sentry, hp->e.sentry, hp->e.stext, 4823e12c5d1SDavid du Colombier sizeof(struct sparcexec)); 4833e12c5d1SDavid du Colombier setdata(fp, hp->e.sentry+hp->e.stext, hp->e.sdata, 4843e12c5d1SDavid du Colombier fp->txtoff+hp->e.stext, hp->e.sbss); 4853e12c5d1SDavid du Colombier setsym(fp, hp->e.ssyms, 0, hp->e.sdrsize, fp->datoff+hp->e.sdata); 486219b2ee8SDavid du Colombier fp->hdrsz = 0; /* header stripped */ 4877dd7cddfSDavid du Colombier return 1; 4883e12c5d1SDavid du Colombier } 4893e12c5d1SDavid du Colombier 4903e12c5d1SDavid du Colombier /* 4913e12c5d1SDavid du Colombier * next bootable image 4923e12c5d1SDavid du Colombier */ 4937dd7cddfSDavid du Colombier static int 4947dd7cddfSDavid du Colombier nextboot(int fd, Fhdr *fp, ExecHdr *hp) 4953e12c5d1SDavid du Colombier { 4967dd7cddfSDavid du Colombier USED(fd); 4973e12c5d1SDavid du Colombier fp->type = FNEXTB; 4983e12c5d1SDavid du Colombier settext(fp, hp->e.textc.vmaddr, hp->e.textc.vmaddr, 4993e12c5d1SDavid du Colombier hp->e.texts.size, hp->e.texts.offset); 5003e12c5d1SDavid du Colombier setdata(fp, hp->e.datac.vmaddr, hp->e.datas.size, 5013e12c5d1SDavid du Colombier hp->e.datas.offset, hp->e.bsss.size); 5023e12c5d1SDavid du Colombier setsym(fp, hp->e.symc.nsyms, hp->e.symc.spoff, hp->e.symc.pcoff, 5033e12c5d1SDavid du Colombier hp->e.symc.symoff); 504219b2ee8SDavid du Colombier fp->hdrsz = 0; /* header stripped */ 5057dd7cddfSDavid du Colombier return 1; 5063e12c5d1SDavid du Colombier } 5073e12c5d1SDavid du Colombier 5087dd7cddfSDavid du Colombier /* 50970b8e010SDavid du Colombier * Elf32 binaries. 5107dd7cddfSDavid du Colombier */ 5117dd7cddfSDavid du Colombier static int 5127dd7cddfSDavid du Colombier elfdotout(int fd, Fhdr *fp, ExecHdr *hp) 5137dd7cddfSDavid du Colombier { 5147dd7cddfSDavid du Colombier 515*4de34a7eSDavid du Colombier ulong (*swal)(ulong); 51670b8e010SDavid du Colombier ushort (*swab)(ushort); 5177dd7cddfSDavid du Colombier Ehdr *ep; 51870b8e010SDavid du Colombier Phdr *ph; 51970b8e010SDavid du Colombier int i, it, id, is, phsz; 5207dd7cddfSDavid du Colombier 52170b8e010SDavid du Colombier /* bitswap the header according to the DATA format */ 5227dd7cddfSDavid du Colombier ep = &hp->e; 52370b8e010SDavid du Colombier if(ep->ident[CLASS] != ELFCLASS32) { 52470b8e010SDavid du Colombier werrstr("bad ELF class - not 32 bit"); 52570b8e010SDavid du Colombier return 0; 52670b8e010SDavid du Colombier } 52770b8e010SDavid du Colombier if(ep->ident[DATA] == ELFDATA2LSB) { 52870b8e010SDavid du Colombier swab = leswab; 52970b8e010SDavid du Colombier swal = leswal; 53070b8e010SDavid du Colombier } else if(ep->ident[DATA] == ELFDATA2MSB) { 53170b8e010SDavid du Colombier swab = beswab; 53270b8e010SDavid du Colombier swal = beswal; 53370b8e010SDavid du Colombier } else { 53470b8e010SDavid du Colombier werrstr("bad ELF encoding - not big or little endian"); 53570b8e010SDavid du Colombier return 0; 53670b8e010SDavid du Colombier } 53770b8e010SDavid du Colombier 53870b8e010SDavid du Colombier ep->type = swab(ep->type); 53970b8e010SDavid du Colombier ep->machine = swab(ep->machine); 54070b8e010SDavid du Colombier ep->version = swal(ep->version); 54170b8e010SDavid du Colombier ep->elfentry = swal(ep->elfentry); 54270b8e010SDavid du Colombier ep->phoff = swal(ep->phoff); 54370b8e010SDavid du Colombier ep->shoff = swal(ep->shoff); 54470b8e010SDavid du Colombier ep->flags = swal(ep->flags); 54570b8e010SDavid du Colombier ep->ehsize = swab(ep->ehsize); 54670b8e010SDavid du Colombier ep->phentsize = swab(ep->phentsize); 54770b8e010SDavid du Colombier ep->phnum = swab(ep->phnum); 54870b8e010SDavid du Colombier ep->shentsize = swab(ep->shentsize); 54970b8e010SDavid du Colombier ep->shnum = swab(ep->shnum); 55070b8e010SDavid du Colombier ep->shstrndx = swab(ep->shstrndx); 55170b8e010SDavid du Colombier if(ep->type != EXEC || ep->version != CURRENT) 5527dd7cddfSDavid du Colombier return 0; 5537dd7cddfSDavid du Colombier 55470b8e010SDavid du Colombier /* we could definitely support a lot more machines here */ 5557dd7cddfSDavid du Colombier fp->magic = ELF_MAG; 5567dd7cddfSDavid du Colombier fp->hdrsz = (ep->ehsize+ep->phnum*ep->phentsize+16)&~15; 55770b8e010SDavid du Colombier switch(ep->machine) { 55870b8e010SDavid du Colombier case I386: 55970b8e010SDavid du Colombier mach = &mi386; 56070b8e010SDavid du Colombier fp->type = FI386; 56170b8e010SDavid du Colombier break; 56270b8e010SDavid du Colombier case MIPS: 56370b8e010SDavid du Colombier mach = &mmips; 56470b8e010SDavid du Colombier fp->type = FMIPS; 56570b8e010SDavid du Colombier break; 566b0dcc5a8SDavid du Colombier case SPARC64: 567b0dcc5a8SDavid du Colombier mach = &msparc64; 568b0dcc5a8SDavid du Colombier fp->type = FSPARC64; 569b0dcc5a8SDavid du Colombier break; 57070b8e010SDavid du Colombier case POWER: 57170b8e010SDavid du Colombier mach = &mpower; 57270b8e010SDavid du Colombier fp->type = FPOWER; 57370b8e010SDavid du Colombier break; 574b0dcc5a8SDavid du Colombier case AMD64: 575b0dcc5a8SDavid du Colombier mach = &mamd64; 576b0dcc5a8SDavid du Colombier fp->type = FAMD64; 577b0dcc5a8SDavid du Colombier break; 57870b8e010SDavid du Colombier default: 5797dd7cddfSDavid du Colombier return 0; 5807dd7cddfSDavid du Colombier } 5817dd7cddfSDavid du Colombier 58270b8e010SDavid du Colombier if(ep->phentsize != sizeof(Phdr)) { 58370b8e010SDavid du Colombier werrstr("bad ELF header size"); 58470b8e010SDavid du Colombier return 0; 58570b8e010SDavid du Colombier } 58670b8e010SDavid du Colombier phsz = sizeof(Phdr)*ep->phnum; 58770b8e010SDavid du Colombier ph = malloc(phsz); 58870b8e010SDavid du Colombier if(!ph) 58970b8e010SDavid du Colombier return 0; 59070b8e010SDavid du Colombier seek(fd, ep->phoff, 0); 59170b8e010SDavid du Colombier if(read(fd, ph, phsz) < 0) { 59270b8e010SDavid du Colombier free(ph); 59370b8e010SDavid du Colombier return 0; 59470b8e010SDavid du Colombier } 595*4de34a7eSDavid du Colombier hswal(ph, phsz/sizeof(ulong), swal); 5967dd7cddfSDavid du Colombier 59770b8e010SDavid du Colombier /* find text, data and symbols and install them */ 59870b8e010SDavid du Colombier it = id = is = -1; 59970b8e010SDavid du Colombier for(i = 0; i < ep->phnum; i++) { 60070b8e010SDavid du Colombier if(ph[i].type == LOAD 60170b8e010SDavid du Colombier && (ph[i].flags & (R|X)) == (R|X) && it == -1) 60270b8e010SDavid du Colombier it = i; 60370b8e010SDavid du Colombier else if(ph[i].type == LOAD 60470b8e010SDavid du Colombier && (ph[i].flags & (R|W)) == (R|W) && id == -1) 60570b8e010SDavid du Colombier id = i; 60670b8e010SDavid du Colombier else if(ph[i].type == NOPTYPE && is == -1) 60770b8e010SDavid du Colombier is = i; 60870b8e010SDavid du Colombier } 60970b8e010SDavid du Colombier if(it == -1 || id == -1) { 610b0dcc5a8SDavid du Colombier /* 611b0dcc5a8SDavid du Colombier * The SPARC64 boot image is something of an ELF hack. 612b0dcc5a8SDavid du Colombier * Text+Data+BSS are represented by ph[0]. Symbols 613b0dcc5a8SDavid du Colombier * are represented by ph[1]: 614b0dcc5a8SDavid du Colombier * 615b0dcc5a8SDavid du Colombier * filesz, memsz, vaddr, paddr, off 616b0dcc5a8SDavid du Colombier * ph[0] : txtsz+datsz, txtsz+datsz+bsssz, txtaddr-KZERO, datasize, txtoff 617b0dcc5a8SDavid du Colombier * ph[1] : symsz, lcsz, 0, 0, symoff 618b0dcc5a8SDavid du Colombier */ 619b0dcc5a8SDavid du Colombier if(ep->machine == SPARC64 && ep->phnum == 2) { 620b0dcc5a8SDavid du Colombier ulong txtaddr, txtsz, dataddr, bsssz; 621b0dcc5a8SDavid du Colombier 622b0dcc5a8SDavid du Colombier txtaddr = ph[0].vaddr | 0x80000000; 623b0dcc5a8SDavid du Colombier txtsz = ph[0].filesz - ph[0].paddr; 624b0dcc5a8SDavid du Colombier dataddr = txtaddr + txtsz; 625b0dcc5a8SDavid du Colombier bsssz = ph[0].memsz - ph[0].filesz; 626b0dcc5a8SDavid du Colombier settext(fp, ep->elfentry | 0x80000000, txtaddr, txtsz, ph[0].offset); 627b0dcc5a8SDavid du Colombier setdata(fp, dataddr, ph[0].paddr, ph[0].offset + txtsz, bsssz); 628b0dcc5a8SDavid du Colombier setsym(fp, ph[1].filesz, 0, ph[1].memsz, ph[1].offset); 629b0dcc5a8SDavid du Colombier free(ph); 630b0dcc5a8SDavid du Colombier return 1; 631b0dcc5a8SDavid du Colombier } 632b0dcc5a8SDavid du Colombier 63370b8e010SDavid du Colombier werrstr("No TEXT or DATA sections"); 63470b8e010SDavid du Colombier free(ph); 63570b8e010SDavid du Colombier return 0; 6367dd7cddfSDavid du Colombier } 6377dd7cddfSDavid du Colombier 63870b8e010SDavid du Colombier settext(fp, ep->elfentry, ph[it].vaddr, ph[it].memsz, ph[it].offset); 639603dff34SDavid du Colombier setdata(fp, ph[id].vaddr, ph[id].filesz, ph[id].offset, ph[id].memsz - ph[id].filesz); 64070b8e010SDavid du Colombier if(is != -1) 64170b8e010SDavid du Colombier setsym(fp, ph[is].filesz, 0, ph[is].memsz, ph[is].offset); 64270b8e010SDavid du Colombier free(ph); 6437dd7cddfSDavid du Colombier return 1; 6447dd7cddfSDavid du Colombier } 6457dd7cddfSDavid du Colombier 6467dd7cddfSDavid du Colombier /* 6477dd7cddfSDavid du Colombier * alpha bootable 6487dd7cddfSDavid du Colombier */ 6497dd7cddfSDavid du Colombier static int 6507dd7cddfSDavid du Colombier alphadotout(int fd, Fhdr *fp, ExecHdr *hp) 6517dd7cddfSDavid du Colombier { 652*4de34a7eSDavid du Colombier uvlong kbase; 6537dd7cddfSDavid du Colombier 6547dd7cddfSDavid du Colombier USED(fd); 6557dd7cddfSDavid du Colombier settext(fp, hp->e.entry, sizeof(Exec), hp->e.text, sizeof(Exec)); 6567dd7cddfSDavid du Colombier setdata(fp, fp->txtsz+sizeof(Exec), hp->e.data, fp->txtsz+sizeof(Exec), hp->e.bss); 6577dd7cddfSDavid du Colombier setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz); 6587dd7cddfSDavid du Colombier 6597dd7cddfSDavid du Colombier /* 6607dd7cddfSDavid du Colombier * Boot images have some of bits <31:28> set: 6617dd7cddfSDavid du Colombier * 0x80400000 kernel 6627dd7cddfSDavid du Colombier * 0x20000000 secondary bootstrap 6637dd7cddfSDavid du Colombier */ 6647dd7cddfSDavid du Colombier kbase = 0xF0000000; 6657dd7cddfSDavid du Colombier if (fp->entry & kbase) { 6667dd7cddfSDavid du Colombier fp->txtaddr = fp->entry; 6677dd7cddfSDavid du Colombier fp->name = "alpha plan 9 boot image"; 6687dd7cddfSDavid du Colombier fp->hdrsz = 0; /* header stripped */ 6697dd7cddfSDavid du Colombier fp->dataddr = fp->entry+fp->txtsz; 6707dd7cddfSDavid du Colombier } 6717dd7cddfSDavid du Colombier return 1; 6727dd7cddfSDavid du Colombier } 6737dd7cddfSDavid du Colombier 6747dd7cddfSDavid du Colombier /* 6757dd7cddfSDavid du Colombier * (Free|Net)BSD ARM header. 6767dd7cddfSDavid du Colombier */ 6777dd7cddfSDavid du Colombier static int 6787dd7cddfSDavid du Colombier armdotout(int fd, Fhdr *fp, ExecHdr *hp) 6797dd7cddfSDavid du Colombier { 680*4de34a7eSDavid du Colombier uvlong kbase; 6817dd7cddfSDavid du Colombier 6827dd7cddfSDavid du Colombier USED(fd); 6837dd7cddfSDavid du Colombier settext(fp, hp->e.entry, sizeof(Exec), hp->e.text, sizeof(Exec)); 6847dd7cddfSDavid du Colombier setdata(fp, fp->txtsz, hp->e.data, fp->txtsz, hp->e.bss); 6857dd7cddfSDavid du Colombier setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz); 6867dd7cddfSDavid du Colombier 6877dd7cddfSDavid du Colombier kbase = 0xF0000000; 6887dd7cddfSDavid du Colombier if ((fp->entry & kbase) == kbase) { /* Boot image */ 6897dd7cddfSDavid du Colombier fp->txtaddr = kbase+sizeof(Exec); 6907dd7cddfSDavid du Colombier fp->name = "ARM *BSD boot image"; 6917dd7cddfSDavid du Colombier fp->hdrsz = 0; /* header stripped */ 6927dd7cddfSDavid du Colombier fp->dataddr = kbase+fp->txtsz; 6937dd7cddfSDavid du Colombier } 6947dd7cddfSDavid du Colombier return 1; 6957dd7cddfSDavid du Colombier } 6963e12c5d1SDavid du Colombier 6973e12c5d1SDavid du Colombier static void 698*4de34a7eSDavid du Colombier settext(Fhdr *fp, uvlong e, uvlong a, long s, vlong off) 6993e12c5d1SDavid du Colombier { 7003e12c5d1SDavid du Colombier fp->txtaddr = a; 7013e12c5d1SDavid du Colombier fp->entry = e; 7023e12c5d1SDavid du Colombier fp->txtsz = s; 7033e12c5d1SDavid du Colombier fp->txtoff = off; 7043e12c5d1SDavid du Colombier } 705*4de34a7eSDavid du Colombier 7063e12c5d1SDavid du Colombier static void 707*4de34a7eSDavid du Colombier setdata(Fhdr *fp, uvlong a, long s, vlong off, long bss) 7083e12c5d1SDavid du Colombier { 7093e12c5d1SDavid du Colombier fp->dataddr = a; 7103e12c5d1SDavid du Colombier fp->datsz = s; 7113e12c5d1SDavid du Colombier fp->datoff = off; 7123e12c5d1SDavid du Colombier fp->bsssz = bss; 7133e12c5d1SDavid du Colombier } 714*4de34a7eSDavid du Colombier 7153e12c5d1SDavid du Colombier static void 716*4de34a7eSDavid du Colombier setsym(Fhdr *fp, long symsz, long sppcsz, long lnpcsz, vlong symoff) 7173e12c5d1SDavid du Colombier { 718*4de34a7eSDavid du Colombier fp->symsz = symsz; 7193e12c5d1SDavid du Colombier fp->symoff = symoff; 720*4de34a7eSDavid du Colombier fp->sppcsz = sppcsz; 7213e12c5d1SDavid du Colombier fp->sppcoff = fp->symoff+fp->symsz; 722*4de34a7eSDavid du Colombier fp->lnpcsz = lnpcsz; 7233e12c5d1SDavid du Colombier fp->lnpcoff = fp->sppcoff+fp->sppcsz; 7243e12c5d1SDavid du Colombier } 7253e12c5d1SDavid du Colombier 726219b2ee8SDavid du Colombier 727*4de34a7eSDavid du Colombier static uvlong 728*4de34a7eSDavid du Colombier _round(uvlong a, ulong b) 729219b2ee8SDavid du Colombier { 730*4de34a7eSDavid du Colombier uvlong w; 731219b2ee8SDavid du Colombier 732219b2ee8SDavid du Colombier w = (a/b)*b; 733219b2ee8SDavid du Colombier if (a!=w) 734219b2ee8SDavid du Colombier w += b; 735219b2ee8SDavid du Colombier return(w); 736219b2ee8SDavid du Colombier } 737