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{ 154de34a7eSDavid du Colombier struct { 164de34a7eSDavid du Colombier Exec; /* a.out.h */ 174de34a7eSDavid du Colombier uvlong hdr[1]; 184de34a7eSDavid du Colombier }; 194de34a7eSDavid du Colombier Ehdr; /* elf.h */ 204de34a7eSDavid du Colombier struct mipsexec; /* bootexec.h */ 214de34a7eSDavid du Colombier struct mips4kexec; /* bootexec.h */ 224de34a7eSDavid du Colombier struct sparcexec; /* bootexec.h */ 234de34a7eSDavid 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*); 334de34a7eSDavid 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*); 374de34a7eSDavid du Colombier static void setsym(Fhdr*, long, long, long, vlong); 384de34a7eSDavid du Colombier static void setdata(Fhdr*, uvlong, long, vlong, long); 394de34a7eSDavid du Colombier static void settext(Fhdr*, uvlong, uvlong, long, vlong); 404de34a7eSDavid du Colombier static void hswal(void*, int, ulong(*)(ulong)); 414de34a7eSDavid du Colombier static uvlong _round(uvlong, ulong); 423e12c5d1SDavid du Colombier 433e12c5d1SDavid du Colombier /* 443e12c5d1SDavid du Colombier * definition of per-executable file type structures 453e12c5d1SDavid du Colombier */ 463e12c5d1SDavid du Colombier 473e12c5d1SDavid du Colombier typedef struct Exectable{ 483e12c5d1SDavid du Colombier long magic; /* big-endian magic number of file */ 493e12c5d1SDavid du Colombier char *name; /* executable identifier */ 5012fd1c83SDavid du Colombier char *dlmname; /* dynamically loadable module identifier */ 512cca75a1SDavid du Colombier uchar type; /* Internal code */ 522cca75a1SDavid du Colombier uchar _magic; /* _MAGIC() magic */ 533e12c5d1SDavid du Colombier Mach *mach; /* Per-machine data */ 544de34a7eSDavid du Colombier long hsize; /* header size */ 554de34a7eSDavid 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 */ 749cd23d14SDavid du Colombier "mips plan 9 executable BE", 759cd23d14SDavid du Colombier "mips plan 9 dlm BE", 763e12c5d1SDavid du Colombier FMIPS, 772cca75a1SDavid du Colombier 1, 783e12c5d1SDavid du Colombier &mmips, 793e12c5d1SDavid du Colombier sizeof(Exec), 803e12c5d1SDavid du Colombier beswal, 813e12c5d1SDavid du Colombier adotout }, 829cd23d14SDavid du Colombier { P_MAGIC, /* Mips 0.out (r3k le) */ 839cd23d14SDavid du Colombier "mips plan 9 executable LE", 849cd23d14SDavid du Colombier "mips plan 9 dlm LE", 859cd23d14SDavid du Colombier FMIPSLE, 869cd23d14SDavid du Colombier 1, 879cd23d14SDavid du Colombier &mmips, 889cd23d14SDavid du Colombier sizeof(Exec), 899cd23d14SDavid du Colombier beswal, 909cd23d14SDavid du Colombier adotout }, 917dd7cddfSDavid du Colombier { M_MAGIC, /* Mips 4.out */ 927dd7cddfSDavid du Colombier "mips 4k plan 9 executable BE", 9312fd1c83SDavid du Colombier "mips 4k plan 9 dlm BE", 947dd7cddfSDavid du Colombier FMIPS2BE, 952cca75a1SDavid du Colombier 1, 967dd7cddfSDavid du Colombier &mmips2be, 977dd7cddfSDavid du Colombier sizeof(Exec), 987dd7cddfSDavid du Colombier beswal, 997dd7cddfSDavid du Colombier adotout }, 1007dd7cddfSDavid du Colombier { N_MAGIC, /* Mips 0.out */ 1017dd7cddfSDavid du Colombier "mips 4k plan 9 executable LE", 10212fd1c83SDavid du Colombier "mips 4k plan 9 dlm LE", 1037dd7cddfSDavid du Colombier FMIPS2LE, 1042cca75a1SDavid du Colombier 1, 1057dd7cddfSDavid du Colombier &mmips2le, 1067dd7cddfSDavid du Colombier sizeof(Exec), 1077dd7cddfSDavid du Colombier beswal, 1087dd7cddfSDavid du Colombier adotout }, 1093e12c5d1SDavid du Colombier { 0x160<<16, /* Mips boot image */ 1103e12c5d1SDavid du Colombier "mips plan 9 boot image", 11112fd1c83SDavid du Colombier nil, 1123e12c5d1SDavid du Colombier FMIPSB, 1132cca75a1SDavid du Colombier 0, 1143e12c5d1SDavid du Colombier &mmips, 1153e12c5d1SDavid du Colombier sizeof(struct mipsexec), 1163e12c5d1SDavid du Colombier beswal, 1173e12c5d1SDavid du Colombier mipsboot }, 118219b2ee8SDavid du Colombier { (0x160<<16)|3, /* Mips boot image */ 119219b2ee8SDavid du Colombier "mips 4k plan 9 boot image", 12012fd1c83SDavid du Colombier nil, 121219b2ee8SDavid du Colombier FMIPSB, 1222cca75a1SDavid du Colombier 0, 12380ee5cbfSDavid du Colombier &mmips2be, 124219b2ee8SDavid du Colombier sizeof(struct mips4kexec), 1253e12c5d1SDavid du Colombier beswal, 126219b2ee8SDavid du Colombier mips4kboot }, 1273e12c5d1SDavid du Colombier { K_MAGIC, /* Sparc k.out */ 1283e12c5d1SDavid du Colombier "sparc plan 9 executable", 12912fd1c83SDavid du Colombier "sparc plan 9 dlm", 1303e12c5d1SDavid du Colombier FSPARC, 1312cca75a1SDavid du Colombier 1, 1323e12c5d1SDavid du Colombier &msparc, 1333e12c5d1SDavid du Colombier sizeof(Exec), 1343e12c5d1SDavid du Colombier beswal, 1353e12c5d1SDavid du Colombier adotout }, 1363e12c5d1SDavid du Colombier { 0x01030107, /* Sparc boot image */ 1373e12c5d1SDavid du Colombier "sparc plan 9 boot image", 13812fd1c83SDavid du Colombier nil, 1393e12c5d1SDavid du Colombier FSPARCB, 1402cca75a1SDavid du Colombier 0, 1413e12c5d1SDavid du Colombier &msparc, 1423e12c5d1SDavid du Colombier sizeof(struct sparcexec), 1433e12c5d1SDavid du Colombier beswal, 1443e12c5d1SDavid du Colombier sparcboot }, 145b0dcc5a8SDavid du Colombier { U_MAGIC, /* Sparc64 u.out */ 146b0dcc5a8SDavid du Colombier "sparc64 plan 9 executable", 147b0dcc5a8SDavid du Colombier "sparc64 plan 9 dlm", 148b0dcc5a8SDavid du Colombier FSPARC64, 1492cca75a1SDavid du Colombier 1, 150b0dcc5a8SDavid du Colombier &msparc64, 151b0dcc5a8SDavid du Colombier sizeof(Exec), 152b0dcc5a8SDavid du Colombier beswal, 153b0dcc5a8SDavid du Colombier adotout }, 1543e12c5d1SDavid du Colombier { A_MAGIC, /* 68020 2.out & boot image */ 1553e12c5d1SDavid du Colombier "68020 plan 9 executable", 15612fd1c83SDavid du Colombier "68020 plan 9 dlm", 1573e12c5d1SDavid du Colombier F68020, 1582cca75a1SDavid du Colombier 1, 1593e12c5d1SDavid du Colombier &m68020, 1603e12c5d1SDavid du Colombier sizeof(Exec), 1613e12c5d1SDavid du Colombier beswal, 1623e12c5d1SDavid du Colombier common }, 1633e12c5d1SDavid du Colombier { 0xFEEDFACE, /* Next boot image */ 1643e12c5d1SDavid du Colombier "next plan 9 boot image", 16512fd1c83SDavid du Colombier nil, 1663e12c5d1SDavid du Colombier FNEXTB, 1672cca75a1SDavid du Colombier 0, 1683e12c5d1SDavid du Colombier &m68020, 1693e12c5d1SDavid du Colombier sizeof(struct nextexec), 1703e12c5d1SDavid du Colombier beswal, 1713e12c5d1SDavid du Colombier nextboot }, 1723e12c5d1SDavid du Colombier { I_MAGIC, /* I386 8.out & boot image */ 1733e12c5d1SDavid du Colombier "386 plan 9 executable", 17412fd1c83SDavid du Colombier "386 plan 9 dlm", 1753e12c5d1SDavid du Colombier FI386, 1762cca75a1SDavid du Colombier 1, 1773e12c5d1SDavid du Colombier &mi386, 1783e12c5d1SDavid du Colombier sizeof(Exec), 1793e12c5d1SDavid du Colombier beswal, 1803e12c5d1SDavid du Colombier common }, 181b0dcc5a8SDavid du Colombier { S_MAGIC, /* amd64 6.out & boot image */ 182b0dcc5a8SDavid du Colombier "amd64 plan 9 executable", 183b0dcc5a8SDavid du Colombier "amd64 plan 9 dlm", 184b0dcc5a8SDavid du Colombier FAMD64, 1852cca75a1SDavid du Colombier 1, 186b0dcc5a8SDavid du Colombier &mamd64, 1874de34a7eSDavid du Colombier sizeof(Exec)+8, 1884de34a7eSDavid du Colombier nil, 1894de34a7eSDavid du Colombier commonllp64 }, 1909a747e4fSDavid du Colombier { Q_MAGIC, /* PowerPC q.out & boot image */ 1917dd7cddfSDavid du Colombier "power plan 9 executable", 19212fd1c83SDavid du Colombier "power plan 9 dlm", 1937dd7cddfSDavid du Colombier FPOWER, 1942cca75a1SDavid du Colombier 1, 1957dd7cddfSDavid du Colombier &mpower, 1967dd7cddfSDavid du Colombier sizeof(Exec), 1977dd7cddfSDavid du Colombier beswal, 1987dd7cddfSDavid du Colombier common }, 19970b8e010SDavid du Colombier { ELF_MAG, /* any elf32 */ 200b0dcc5a8SDavid du Colombier "elf executable", 20112fd1c83SDavid du Colombier nil, 20270b8e010SDavid du Colombier FNONE, 2032cca75a1SDavid du Colombier 0, 20470b8e010SDavid du Colombier &mi386, 2057dd7cddfSDavid du Colombier sizeof(Ehdr), 2064de34a7eSDavid du Colombier nil, 2077dd7cddfSDavid du Colombier elfdotout }, 208*41fb754aSDavid du Colombier { E_MAGIC, /* Arm 5.out and boot image */ 209b0dcc5a8SDavid du Colombier "arm plan 9 executable", 210b0dcc5a8SDavid du Colombier "arm plan 9 dlm", 2117dd7cddfSDavid du Colombier FARM, 2122cca75a1SDavid du Colombier 1, 2137dd7cddfSDavid du Colombier &marm, 2147dd7cddfSDavid du Colombier sizeof(Exec), 2157dd7cddfSDavid du Colombier beswal, 2167dd7cddfSDavid du Colombier common }, 2177dd7cddfSDavid du Colombier { (143<<16)|0413, /* (Free|Net)BSD Arm */ 218b0dcc5a8SDavid du Colombier "arm *bsd executable", 21912fd1c83SDavid du Colombier nil, 2207dd7cddfSDavid du Colombier FARM, 2212cca75a1SDavid du Colombier 0, 2227dd7cddfSDavid du Colombier &marm, 2237dd7cddfSDavid du Colombier sizeof(Exec), 2247dd7cddfSDavid du Colombier leswal, 2257dd7cddfSDavid du Colombier armdotout }, 2267dd7cddfSDavid du Colombier { L_MAGIC, /* alpha 7.out */ 2277dd7cddfSDavid du Colombier "alpha plan 9 executable", 22812fd1c83SDavid du Colombier "alpha plan 9 dlm", 2297dd7cddfSDavid du Colombier FALPHA, 2302cca75a1SDavid du Colombier 1, 2317dd7cddfSDavid du Colombier &malpha, 2327dd7cddfSDavid du Colombier sizeof(Exec), 2337dd7cddfSDavid du Colombier beswal, 2347dd7cddfSDavid du Colombier common }, 2357dd7cddfSDavid du Colombier { 0x0700e0c3, /* alpha boot image */ 2367dd7cddfSDavid du Colombier "alpha plan 9 boot image", 23712fd1c83SDavid du Colombier nil, 2382cca75a1SDavid du Colombier FALPHA, 2392cca75a1SDavid du Colombier 0, 2407dd7cddfSDavid du Colombier &malpha, 2417dd7cddfSDavid du Colombier sizeof(Exec), 2427dd7cddfSDavid du Colombier beswal, 2432cca75a1SDavid du Colombier common }, 2443e12c5d1SDavid du Colombier { 0 }, 2453e12c5d1SDavid du Colombier }; 2463e12c5d1SDavid du Colombier 2477dd7cddfSDavid du Colombier Mach *mach = &mi386; /* Global current machine table */ 2487dd7cddfSDavid du Colombier 2497dd7cddfSDavid du Colombier static ExecTable* 2507dd7cddfSDavid du Colombier couldbe4k(ExecTable *mp) 2517dd7cddfSDavid du Colombier { 2529a747e4fSDavid du Colombier Dir *d; 2537dd7cddfSDavid du Colombier ExecTable *f; 2547dd7cddfSDavid du Colombier 2559a747e4fSDavid du Colombier if((d=dirstat("/proc/1/regs")) == nil) 2567dd7cddfSDavid du Colombier return mp; 2579a747e4fSDavid du Colombier if(d->length < 32*8){ /* R3000 */ 2589a747e4fSDavid du Colombier free(d); 2597dd7cddfSDavid du Colombier return mp; 2609a747e4fSDavid du Colombier } 2619a747e4fSDavid du Colombier free(d); 2627dd7cddfSDavid du Colombier for (f = exectab; f->magic; f++) 2637dd7cddfSDavid du Colombier if(f->magic == M_MAGIC) { 2647dd7cddfSDavid du Colombier f->name = "mips plan 9 executable on mips2 kernel"; 2657dd7cddfSDavid du Colombier return f; 2667dd7cddfSDavid du Colombier } 2677dd7cddfSDavid du Colombier return mp; 2687dd7cddfSDavid du Colombier } 2697dd7cddfSDavid du Colombier 2703e12c5d1SDavid du Colombier int 2713e12c5d1SDavid du Colombier crackhdr(int fd, Fhdr *fp) 2723e12c5d1SDavid du Colombier { 2733e12c5d1SDavid du Colombier ExecTable *mp; 2743e12c5d1SDavid du Colombier ExecHdr d; 2754de34a7eSDavid du Colombier int nb, ret; 2764de34a7eSDavid du Colombier ulong magic; 2773e12c5d1SDavid du Colombier 2783e12c5d1SDavid du Colombier fp->type = FNONE; 2797dd7cddfSDavid du Colombier nb = read(fd, (char *)&d.e, sizeof(d.e)); 2807dd7cddfSDavid du Colombier if (nb <= 0) 2813e12c5d1SDavid du Colombier return 0; 2827dd7cddfSDavid du Colombier 2837dd7cddfSDavid du Colombier ret = 0; 2842cca75a1SDavid du Colombier magic = beswal(d.e.magic); /* big-endian */ 2853e12c5d1SDavid du Colombier for (mp = exectab; mp->magic; mp++) { 28612fd1c83SDavid du Colombier if (nb < mp->hsize) 28712fd1c83SDavid du Colombier continue; 2882cca75a1SDavid du Colombier 2892cca75a1SDavid du Colombier /* 2902cca75a1SDavid du Colombier * The magic number has morphed into something 2912cca75a1SDavid du Colombier * with fields (the straw was DYN_MAGIC) so now 2922cca75a1SDavid du Colombier * a flag is needed in Fhdr to distinguish _MAGIC() 2932cca75a1SDavid du Colombier * magic numbers from foreign magic numbers. 2942cca75a1SDavid du Colombier * 2952cca75a1SDavid du Colombier * This code is creaking a bit and if it has to 2962cca75a1SDavid du Colombier * be modified/extended much more it's probably 2972cca75a1SDavid du Colombier * time to step back and redo it all. 2982cca75a1SDavid du Colombier */ 2992cca75a1SDavid du Colombier if(mp->_magic){ 3002cca75a1SDavid du Colombier if(mp->magic != (magic & ~DYN_MAGIC)) 3012cca75a1SDavid du Colombier continue; 3022cca75a1SDavid du Colombier 3037dd7cddfSDavid du Colombier if(mp->magic == V_MAGIC) 3047dd7cddfSDavid du Colombier mp = couldbe4k(mp); 3057dd7cddfSDavid du Colombier 30612fd1c83SDavid du Colombier if ((magic & DYN_MAGIC) && mp->dlmname != nil) 30712fd1c83SDavid du Colombier fp->name = mp->dlmname; 30812fd1c83SDavid du Colombier else 3093e12c5d1SDavid du Colombier fp->name = mp->name; 3102cca75a1SDavid du Colombier } 3112cca75a1SDavid du Colombier else{ 3122cca75a1SDavid du Colombier if(mp->magic != magic) 3132cca75a1SDavid du Colombier continue; 3142cca75a1SDavid du Colombier fp->name = mp->name; 3152cca75a1SDavid du Colombier } 3162cca75a1SDavid du Colombier fp->type = mp->type; 3172cca75a1SDavid du Colombier fp->hdrsz = mp->hsize; /* will be zero on bootables */ 3182cca75a1SDavid du Colombier fp->_magic = mp->_magic; 3192cca75a1SDavid du Colombier fp->magic = magic; 3202cca75a1SDavid du Colombier 3213e12c5d1SDavid du Colombier mach = mp->mach; 3224de34a7eSDavid du Colombier if(mp->swal != nil) 3234de34a7eSDavid du Colombier hswal(&d, sizeof(d.e)/sizeof(ulong), mp->swal); 3247dd7cddfSDavid du Colombier ret = mp->hparse(fd, fp, &d); 3253e12c5d1SDavid du Colombier seek(fd, mp->hsize, 0); /* seek to end of header */ 3267dd7cddfSDavid du Colombier break; 3273e12c5d1SDavid du Colombier } 3287dd7cddfSDavid du Colombier if(mp->magic == 0) 3297dd7cddfSDavid du Colombier werrstr("unknown header type"); 3307dd7cddfSDavid du Colombier return ret; 3313e12c5d1SDavid du Colombier } 3324de34a7eSDavid du Colombier 3333e12c5d1SDavid du Colombier /* 3343e12c5d1SDavid du Colombier * Convert header to canonical form 3353e12c5d1SDavid du Colombier */ 3363e12c5d1SDavid du Colombier static void 3374de34a7eSDavid du Colombier hswal(void *v, int n, ulong (*swap)(ulong)) 3383e12c5d1SDavid du Colombier { 3394de34a7eSDavid du Colombier ulong *ulp; 3404de34a7eSDavid du Colombier 3414de34a7eSDavid du Colombier for(ulp = v; n--; ulp++) 3424de34a7eSDavid du Colombier *ulp = (*swap)(*ulp); 3433e12c5d1SDavid du Colombier } 3444de34a7eSDavid du Colombier 34570b8e010SDavid du Colombier /* 3463e12c5d1SDavid du Colombier * Crack a normal a.out-type header 3473e12c5d1SDavid du Colombier */ 3487dd7cddfSDavid du Colombier static int 3497dd7cddfSDavid du Colombier adotout(int fd, Fhdr *fp, ExecHdr *hp) 3503e12c5d1SDavid du Colombier { 3517dd7cddfSDavid du Colombier long pgsize; 3523e12c5d1SDavid du Colombier 3537dd7cddfSDavid du Colombier USED(fd); 3547dd7cddfSDavid du Colombier pgsize = mach->pgsize; 355219b2ee8SDavid du Colombier settext(fp, hp->e.entry, pgsize+sizeof(Exec), 356219b2ee8SDavid du Colombier hp->e.text, sizeof(Exec)); 357219b2ee8SDavid du Colombier setdata(fp, _round(pgsize+fp->txtsz+sizeof(Exec), pgsize), 358219b2ee8SDavid du Colombier hp->e.data, fp->txtsz+sizeof(Exec), hp->e.bss); 3593e12c5d1SDavid du Colombier setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz); 3607dd7cddfSDavid du Colombier return 1; 3613e12c5d1SDavid du Colombier } 3623e12c5d1SDavid du Colombier 3634de34a7eSDavid du Colombier static void 3644de34a7eSDavid du Colombier commonboot(Fhdr *fp) 3654de34a7eSDavid du Colombier { 3662cca75a1SDavid du Colombier if (!(fp->entry & mach->ktmask)) 3674de34a7eSDavid du Colombier return; 3684de34a7eSDavid du Colombier 3694de34a7eSDavid du Colombier switch(fp->type) { /* boot image */ 3704de34a7eSDavid du Colombier case F68020: 3714de34a7eSDavid du Colombier fp->type = F68020B; 3724de34a7eSDavid du Colombier fp->name = "68020 plan 9 boot image"; 3734de34a7eSDavid du Colombier break; 3744de34a7eSDavid du Colombier case FI386: 3754de34a7eSDavid du Colombier fp->type = FI386B; 3764de34a7eSDavid du Colombier fp->txtaddr = (u32int)fp->entry; 3774de34a7eSDavid du Colombier fp->name = "386 plan 9 boot image"; 3784de34a7eSDavid du Colombier fp->dataddr = _round(fp->txtaddr+fp->txtsz, mach->pgsize); 3794de34a7eSDavid du Colombier break; 3804de34a7eSDavid du Colombier case FARM: 381*41fb754aSDavid du Colombier fp->type = FARMB; 382*41fb754aSDavid du Colombier fp->txtaddr = (u32int)fp->entry; 3834de34a7eSDavid du Colombier fp->name = "ARM plan 9 boot image"; 384*41fb754aSDavid du Colombier fp->dataddr = _round(fp->txtaddr+fp->txtsz, mach->pgsize); 3854de34a7eSDavid du Colombier return; 3864de34a7eSDavid du Colombier case FALPHA: 3874de34a7eSDavid du Colombier fp->type = FALPHAB; 3884de34a7eSDavid du Colombier fp->txtaddr = (u32int)fp->entry; 3892cca75a1SDavid du Colombier fp->name = "alpha plan 9 boot image"; 3904de34a7eSDavid du Colombier fp->dataddr = fp->txtaddr+fp->txtsz; 3914de34a7eSDavid du Colombier break; 3924de34a7eSDavid du Colombier case FPOWER: 3934de34a7eSDavid du Colombier fp->type = FPOWERB; 3944de34a7eSDavid du Colombier fp->txtaddr = (u32int)fp->entry; 3954de34a7eSDavid du Colombier fp->name = "power plan 9 boot image"; 3964de34a7eSDavid du Colombier fp->dataddr = fp->txtaddr+fp->txtsz; 3974de34a7eSDavid du Colombier break; 3984de34a7eSDavid du Colombier case FAMD64: 3994de34a7eSDavid du Colombier fp->type = FAMD64B; 4004de34a7eSDavid du Colombier fp->txtaddr = fp->entry; 4014de34a7eSDavid du Colombier fp->name = "amd64 plan 9 boot image"; 4024de34a7eSDavid du Colombier fp->dataddr = _round(fp->txtaddr+fp->txtsz, mach->pgsize); 4034de34a7eSDavid du Colombier break; 4044de34a7eSDavid du Colombier default: 4054de34a7eSDavid du Colombier return; 4064de34a7eSDavid du Colombier } 4074de34a7eSDavid du Colombier fp->hdrsz = 0; /* header stripped */ 4084de34a7eSDavid du Colombier } 4094de34a7eSDavid du Colombier 4103e12c5d1SDavid du Colombier /* 4112cca75a1SDavid du Colombier * _MAGIC() style headers and 4127dd7cddfSDavid du Colombier * alpha plan9-style bootable images for axp "headerless" boot 4133e12c5d1SDavid du Colombier * 4143e12c5d1SDavid du Colombier */ 4157dd7cddfSDavid du Colombier static int 4167dd7cddfSDavid du Colombier common(int fd, Fhdr *fp, ExecHdr *hp) 4173e12c5d1SDavid du Colombier { 4187dd7cddfSDavid du Colombier adotout(fd, fp, hp); 4199a747e4fSDavid du Colombier if(hp->e.magic & DYN_MAGIC) { 4209a747e4fSDavid du Colombier fp->txtaddr = 0; 4219a747e4fSDavid du Colombier fp->dataddr = fp->txtsz; 4229a747e4fSDavid du Colombier return 1; 4239a747e4fSDavid du Colombier } 4244de34a7eSDavid du Colombier commonboot(fp); 4257dd7cddfSDavid du Colombier return 1; 4263e12c5d1SDavid du Colombier } 4274de34a7eSDavid du Colombier 4284de34a7eSDavid du Colombier static int 4294de34a7eSDavid du Colombier commonllp64(int, Fhdr *fp, ExecHdr *hp) 4304de34a7eSDavid du Colombier { 4314de34a7eSDavid du Colombier long pgsize; 4324de34a7eSDavid du Colombier uvlong entry; 4334de34a7eSDavid du Colombier 4344de34a7eSDavid du Colombier hswal(&hp->e, sizeof(Exec)/sizeof(long), beswal); 4354de34a7eSDavid du Colombier if(!(hp->e.magic & HDR_MAGIC)) 4364de34a7eSDavid du Colombier return 0; 4374de34a7eSDavid du Colombier 4384de34a7eSDavid du Colombier /* 4394de34a7eSDavid du Colombier * There can be more magic here if the 4404de34a7eSDavid du Colombier * header ever needs more expansion. 4414de34a7eSDavid du Colombier * For now just catch use of any of the 4424de34a7eSDavid du Colombier * unused bits. 4434de34a7eSDavid du Colombier */ 4444de34a7eSDavid du Colombier if((hp->e.magic & ~DYN_MAGIC)>>16) 4454de34a7eSDavid du Colombier return 0; 4464de34a7eSDavid du Colombier entry = beswav(hp->e.hdr[0]); 4474de34a7eSDavid du Colombier 4484de34a7eSDavid du Colombier pgsize = mach->pgsize; 4494de34a7eSDavid du Colombier settext(fp, entry, pgsize+fp->hdrsz, hp->e.text, fp->hdrsz); 4504de34a7eSDavid du Colombier setdata(fp, _round(pgsize+fp->txtsz+fp->hdrsz, pgsize), 4514de34a7eSDavid du Colombier hp->e.data, fp->txtsz+fp->hdrsz, hp->e.bss); 4524de34a7eSDavid du Colombier setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz); 4534de34a7eSDavid du Colombier 4544de34a7eSDavid du Colombier if(hp->e.magic & DYN_MAGIC) { 4554de34a7eSDavid du Colombier fp->txtaddr = 0; 4564de34a7eSDavid du Colombier fp->dataddr = fp->txtsz; 4574de34a7eSDavid du Colombier return 1; 4583e12c5d1SDavid du Colombier } 4594de34a7eSDavid du Colombier commonboot(fp); 4607dd7cddfSDavid du Colombier return 1; 4613e12c5d1SDavid du Colombier } 4623e12c5d1SDavid du Colombier 4633e12c5d1SDavid du Colombier /* 4643e12c5d1SDavid du Colombier * mips bootable image. 4653e12c5d1SDavid du Colombier */ 4667dd7cddfSDavid du Colombier static int 4677dd7cddfSDavid du Colombier mipsboot(int fd, Fhdr *fp, ExecHdr *hp) 4683e12c5d1SDavid du Colombier { 4697dd7cddfSDavid du Colombier USED(fd); 4702cca75a1SDavid du Colombier fp->type = FMIPSB; 4713e12c5d1SDavid du Colombier switch(hp->e.amagic) { 4723e12c5d1SDavid du Colombier default: 4733e12c5d1SDavid du Colombier case 0407: /* some kind of mips */ 4742cca75a1SDavid du Colombier settext(fp, (u32int)hp->e.mentry, (u32int)hp->e.text_start, 4752cca75a1SDavid du Colombier hp->e.tsize, sizeof(struct mipsexec)+4); 4762cca75a1SDavid du Colombier setdata(fp, (u32int)hp->e.data_start, hp->e.dsize, 4773e12c5d1SDavid du Colombier fp->txtoff+hp->e.tsize, hp->e.bsize); 4783e12c5d1SDavid du Colombier break; 4793e12c5d1SDavid du Colombier case 0413: /* some kind of mips */ 4802cca75a1SDavid du Colombier settext(fp, (u32int)hp->e.mentry, (u32int)hp->e.text_start, 4812cca75a1SDavid du Colombier hp->e.tsize, 0); 4822cca75a1SDavid du Colombier setdata(fp, (u32int)hp->e.data_start, hp->e.dsize, 4832cca75a1SDavid du Colombier hp->e.tsize, hp->e.bsize); 4843e12c5d1SDavid du Colombier break; 4853e12c5d1SDavid du Colombier } 4863e12c5d1SDavid du Colombier setsym(fp, hp->e.nsyms, 0, hp->e.pcsize, hp->e.symptr); 487219b2ee8SDavid du Colombier fp->hdrsz = 0; /* header stripped */ 4887dd7cddfSDavid du Colombier return 1; 4893e12c5d1SDavid du Colombier } 490219b2ee8SDavid du Colombier 4913e12c5d1SDavid du Colombier /* 492219b2ee8SDavid du Colombier * mips4k bootable image. 4933e12c5d1SDavid du Colombier */ 4947dd7cddfSDavid du Colombier static int 4957dd7cddfSDavid du Colombier mips4kboot(int fd, Fhdr *fp, ExecHdr *hp) 4963e12c5d1SDavid du Colombier { 4977dd7cddfSDavid du Colombier USED(fd); 4982cca75a1SDavid du Colombier fp->type = FMIPSB; 499219b2ee8SDavid du Colombier switch(hp->e.h.amagic) { 500219b2ee8SDavid du Colombier default: 501219b2ee8SDavid du Colombier case 0407: /* some kind of mips */ 5022cca75a1SDavid du Colombier settext(fp, (u32int)hp->e.h.mentry, (u32int)hp->e.h.text_start, 5032cca75a1SDavid du Colombier hp->e.h.tsize, sizeof(struct mips4kexec)); 5042cca75a1SDavid du Colombier setdata(fp, (u32int)hp->e.h.data_start, hp->e.h.dsize, 505219b2ee8SDavid du Colombier fp->txtoff+hp->e.h.tsize, hp->e.h.bsize); 506219b2ee8SDavid du Colombier break; 507219b2ee8SDavid du Colombier case 0413: /* some kind of mips */ 5082cca75a1SDavid du Colombier settext(fp, (u32int)hp->e.h.mentry, (u32int)hp->e.h.text_start, 5092cca75a1SDavid du Colombier hp->e.h.tsize, 0); 5102cca75a1SDavid du Colombier setdata(fp, (u32int)hp->e.h.data_start, hp->e.h.dsize, 5112cca75a1SDavid du Colombier hp->e.h.tsize, hp->e.h.bsize); 512219b2ee8SDavid du Colombier break; 5133e12c5d1SDavid du Colombier } 514219b2ee8SDavid du Colombier setsym(fp, hp->e.h.nsyms, 0, hp->e.h.pcsize, hp->e.h.symptr); 515219b2ee8SDavid du Colombier fp->hdrsz = 0; /* header stripped */ 5167dd7cddfSDavid du Colombier return 1; 517219b2ee8SDavid du Colombier } 518219b2ee8SDavid du Colombier 5193e12c5d1SDavid du Colombier /* 5203e12c5d1SDavid du Colombier * sparc bootable image 5213e12c5d1SDavid du Colombier */ 5227dd7cddfSDavid du Colombier static int 5237dd7cddfSDavid du Colombier sparcboot(int fd, Fhdr *fp, ExecHdr *hp) 5243e12c5d1SDavid du Colombier { 5257dd7cddfSDavid du Colombier USED(fd); 5263e12c5d1SDavid du Colombier fp->type = FSPARCB; 5273e12c5d1SDavid du Colombier settext(fp, hp->e.sentry, hp->e.sentry, hp->e.stext, 5283e12c5d1SDavid du Colombier sizeof(struct sparcexec)); 5293e12c5d1SDavid du Colombier setdata(fp, hp->e.sentry+hp->e.stext, hp->e.sdata, 5303e12c5d1SDavid du Colombier fp->txtoff+hp->e.stext, hp->e.sbss); 5313e12c5d1SDavid du Colombier setsym(fp, hp->e.ssyms, 0, hp->e.sdrsize, fp->datoff+hp->e.sdata); 532219b2ee8SDavid du Colombier fp->hdrsz = 0; /* header stripped */ 5337dd7cddfSDavid du Colombier return 1; 5343e12c5d1SDavid du Colombier } 5353e12c5d1SDavid du Colombier 5363e12c5d1SDavid du Colombier /* 5373e12c5d1SDavid du Colombier * next bootable image 5383e12c5d1SDavid du Colombier */ 5397dd7cddfSDavid du Colombier static int 5407dd7cddfSDavid du Colombier nextboot(int fd, Fhdr *fp, ExecHdr *hp) 5413e12c5d1SDavid du Colombier { 5427dd7cddfSDavid du Colombier USED(fd); 5433e12c5d1SDavid du Colombier fp->type = FNEXTB; 5443e12c5d1SDavid du Colombier settext(fp, hp->e.textc.vmaddr, hp->e.textc.vmaddr, 5453e12c5d1SDavid du Colombier hp->e.texts.size, hp->e.texts.offset); 5463e12c5d1SDavid du Colombier setdata(fp, hp->e.datac.vmaddr, hp->e.datas.size, 5473e12c5d1SDavid du Colombier hp->e.datas.offset, hp->e.bsss.size); 5483e12c5d1SDavid du Colombier setsym(fp, hp->e.symc.nsyms, hp->e.symc.spoff, hp->e.symc.pcoff, 5493e12c5d1SDavid du Colombier hp->e.symc.symoff); 550219b2ee8SDavid du Colombier fp->hdrsz = 0; /* header stripped */ 5517dd7cddfSDavid du Colombier return 1; 5523e12c5d1SDavid du Colombier } 5533e12c5d1SDavid du Colombier 5547dd7cddfSDavid du Colombier /* 55570b8e010SDavid du Colombier * Elf32 binaries. 5567dd7cddfSDavid du Colombier */ 5577dd7cddfSDavid du Colombier static int 5587dd7cddfSDavid du Colombier elfdotout(int fd, Fhdr *fp, ExecHdr *hp) 5597dd7cddfSDavid du Colombier { 5607dd7cddfSDavid du Colombier 5614de34a7eSDavid du Colombier ulong (*swal)(ulong); 56270b8e010SDavid du Colombier ushort (*swab)(ushort); 5637dd7cddfSDavid du Colombier Ehdr *ep; 56470b8e010SDavid du Colombier Phdr *ph; 56570b8e010SDavid du Colombier int i, it, id, is, phsz; 5667dd7cddfSDavid du Colombier 56770b8e010SDavid du Colombier /* bitswap the header according to the DATA format */ 5687dd7cddfSDavid du Colombier ep = &hp->e; 56970b8e010SDavid du Colombier if(ep->ident[CLASS] != ELFCLASS32) { 57070b8e010SDavid du Colombier werrstr("bad ELF class - not 32 bit"); 57170b8e010SDavid du Colombier return 0; 57270b8e010SDavid du Colombier } 57370b8e010SDavid du Colombier if(ep->ident[DATA] == ELFDATA2LSB) { 57470b8e010SDavid du Colombier swab = leswab; 57570b8e010SDavid du Colombier swal = leswal; 57670b8e010SDavid du Colombier } else if(ep->ident[DATA] == ELFDATA2MSB) { 57770b8e010SDavid du Colombier swab = beswab; 57870b8e010SDavid du Colombier swal = beswal; 57970b8e010SDavid du Colombier } else { 58070b8e010SDavid du Colombier werrstr("bad ELF encoding - not big or little endian"); 58170b8e010SDavid du Colombier return 0; 58270b8e010SDavid du Colombier } 58370b8e010SDavid du Colombier 58470b8e010SDavid du Colombier ep->type = swab(ep->type); 58570b8e010SDavid du Colombier ep->machine = swab(ep->machine); 58670b8e010SDavid du Colombier ep->version = swal(ep->version); 58770b8e010SDavid du Colombier ep->elfentry = swal(ep->elfentry); 58870b8e010SDavid du Colombier ep->phoff = swal(ep->phoff); 58970b8e010SDavid du Colombier ep->shoff = swal(ep->shoff); 59070b8e010SDavid du Colombier ep->flags = swal(ep->flags); 59170b8e010SDavid du Colombier ep->ehsize = swab(ep->ehsize); 59270b8e010SDavid du Colombier ep->phentsize = swab(ep->phentsize); 59370b8e010SDavid du Colombier ep->phnum = swab(ep->phnum); 59470b8e010SDavid du Colombier ep->shentsize = swab(ep->shentsize); 59570b8e010SDavid du Colombier ep->shnum = swab(ep->shnum); 59670b8e010SDavid du Colombier ep->shstrndx = swab(ep->shstrndx); 59770b8e010SDavid du Colombier if(ep->type != EXEC || ep->version != CURRENT) 5987dd7cddfSDavid du Colombier return 0; 5997dd7cddfSDavid du Colombier 60070b8e010SDavid du Colombier /* we could definitely support a lot more machines here */ 6017dd7cddfSDavid du Colombier fp->magic = ELF_MAG; 6027dd7cddfSDavid du Colombier fp->hdrsz = (ep->ehsize+ep->phnum*ep->phentsize+16)&~15; 60370b8e010SDavid du Colombier switch(ep->machine) { 60470b8e010SDavid du Colombier case I386: 60570b8e010SDavid du Colombier mach = &mi386; 60670b8e010SDavid du Colombier fp->type = FI386; 60770b8e010SDavid du Colombier break; 60870b8e010SDavid du Colombier case MIPS: 60970b8e010SDavid du Colombier mach = &mmips; 61070b8e010SDavid du Colombier fp->type = FMIPS; 61170b8e010SDavid du Colombier break; 612b0dcc5a8SDavid du Colombier case SPARC64: 613b0dcc5a8SDavid du Colombier mach = &msparc64; 614b0dcc5a8SDavid du Colombier fp->type = FSPARC64; 615b0dcc5a8SDavid du Colombier break; 61670b8e010SDavid du Colombier case POWER: 61770b8e010SDavid du Colombier mach = &mpower; 61870b8e010SDavid du Colombier fp->type = FPOWER; 61970b8e010SDavid du Colombier break; 620b0dcc5a8SDavid du Colombier case AMD64: 621b0dcc5a8SDavid du Colombier mach = &mamd64; 622b0dcc5a8SDavid du Colombier fp->type = FAMD64; 623b0dcc5a8SDavid du Colombier break; 62470b8e010SDavid du Colombier default: 6257dd7cddfSDavid du Colombier return 0; 6267dd7cddfSDavid du Colombier } 6277dd7cddfSDavid du Colombier 62870b8e010SDavid du Colombier if(ep->phentsize != sizeof(Phdr)) { 62970b8e010SDavid du Colombier werrstr("bad ELF header size"); 63070b8e010SDavid du Colombier return 0; 63170b8e010SDavid du Colombier } 63270b8e010SDavid du Colombier phsz = sizeof(Phdr)*ep->phnum; 63370b8e010SDavid du Colombier ph = malloc(phsz); 63470b8e010SDavid du Colombier if(!ph) 63570b8e010SDavid du Colombier return 0; 63670b8e010SDavid du Colombier seek(fd, ep->phoff, 0); 63770b8e010SDavid du Colombier if(read(fd, ph, phsz) < 0) { 63870b8e010SDavid du Colombier free(ph); 63970b8e010SDavid du Colombier return 0; 64070b8e010SDavid du Colombier } 6414de34a7eSDavid du Colombier hswal(ph, phsz/sizeof(ulong), swal); 6427dd7cddfSDavid du Colombier 64370b8e010SDavid du Colombier /* find text, data and symbols and install them */ 64470b8e010SDavid du Colombier it = id = is = -1; 64570b8e010SDavid du Colombier for(i = 0; i < ep->phnum; i++) { 64670b8e010SDavid du Colombier if(ph[i].type == LOAD 64770b8e010SDavid du Colombier && (ph[i].flags & (R|X)) == (R|X) && it == -1) 64870b8e010SDavid du Colombier it = i; 64970b8e010SDavid du Colombier else if(ph[i].type == LOAD 65070b8e010SDavid du Colombier && (ph[i].flags & (R|W)) == (R|W) && id == -1) 65170b8e010SDavid du Colombier id = i; 65270b8e010SDavid du Colombier else if(ph[i].type == NOPTYPE && is == -1) 65370b8e010SDavid du Colombier is = i; 65470b8e010SDavid du Colombier } 65570b8e010SDavid du Colombier if(it == -1 || id == -1) { 656b0dcc5a8SDavid du Colombier /* 657b0dcc5a8SDavid du Colombier * The SPARC64 boot image is something of an ELF hack. 658b0dcc5a8SDavid du Colombier * Text+Data+BSS are represented by ph[0]. Symbols 659b0dcc5a8SDavid du Colombier * are represented by ph[1]: 660b0dcc5a8SDavid du Colombier * 661b0dcc5a8SDavid du Colombier * filesz, memsz, vaddr, paddr, off 662b0dcc5a8SDavid du Colombier * ph[0] : txtsz+datsz, txtsz+datsz+bsssz, txtaddr-KZERO, datasize, txtoff 663b0dcc5a8SDavid du Colombier * ph[1] : symsz, lcsz, 0, 0, symoff 664b0dcc5a8SDavid du Colombier */ 665b0dcc5a8SDavid du Colombier if(ep->machine == SPARC64 && ep->phnum == 2) { 666b0dcc5a8SDavid du Colombier ulong txtaddr, txtsz, dataddr, bsssz; 667b0dcc5a8SDavid du Colombier 668b0dcc5a8SDavid du Colombier txtaddr = ph[0].vaddr | 0x80000000; 669b0dcc5a8SDavid du Colombier txtsz = ph[0].filesz - ph[0].paddr; 670b0dcc5a8SDavid du Colombier dataddr = txtaddr + txtsz; 671b0dcc5a8SDavid du Colombier bsssz = ph[0].memsz - ph[0].filesz; 672b0dcc5a8SDavid du Colombier settext(fp, ep->elfentry | 0x80000000, txtaddr, txtsz, ph[0].offset); 673b0dcc5a8SDavid du Colombier setdata(fp, dataddr, ph[0].paddr, ph[0].offset + txtsz, bsssz); 674b0dcc5a8SDavid du Colombier setsym(fp, ph[1].filesz, 0, ph[1].memsz, ph[1].offset); 675b0dcc5a8SDavid du Colombier free(ph); 676b0dcc5a8SDavid du Colombier return 1; 677b0dcc5a8SDavid du Colombier } 678b0dcc5a8SDavid du Colombier 67970b8e010SDavid du Colombier werrstr("No TEXT or DATA sections"); 68070b8e010SDavid du Colombier free(ph); 68170b8e010SDavid du Colombier return 0; 6827dd7cddfSDavid du Colombier } 6837dd7cddfSDavid du Colombier 68470b8e010SDavid du Colombier settext(fp, ep->elfentry, ph[it].vaddr, ph[it].memsz, ph[it].offset); 685603dff34SDavid du Colombier setdata(fp, ph[id].vaddr, ph[id].filesz, ph[id].offset, ph[id].memsz - ph[id].filesz); 68670b8e010SDavid du Colombier if(is != -1) 68770b8e010SDavid du Colombier setsym(fp, ph[is].filesz, 0, ph[is].memsz, ph[is].offset); 68870b8e010SDavid du Colombier free(ph); 6897dd7cddfSDavid du Colombier return 1; 6907dd7cddfSDavid du Colombier } 6917dd7cddfSDavid du Colombier 6927dd7cddfSDavid du Colombier /* 6937dd7cddfSDavid du Colombier * (Free|Net)BSD ARM header. 6947dd7cddfSDavid du Colombier */ 6957dd7cddfSDavid du Colombier static int 6967dd7cddfSDavid du Colombier armdotout(int fd, Fhdr *fp, ExecHdr *hp) 6977dd7cddfSDavid du Colombier { 6984de34a7eSDavid du Colombier uvlong kbase; 6997dd7cddfSDavid du Colombier 7007dd7cddfSDavid du Colombier USED(fd); 7017dd7cddfSDavid du Colombier settext(fp, hp->e.entry, sizeof(Exec), hp->e.text, sizeof(Exec)); 7027dd7cddfSDavid du Colombier setdata(fp, fp->txtsz, hp->e.data, fp->txtsz, hp->e.bss); 7037dd7cddfSDavid du Colombier setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz); 7047dd7cddfSDavid du Colombier 7057dd7cddfSDavid du Colombier kbase = 0xF0000000; 7067dd7cddfSDavid du Colombier if ((fp->entry & kbase) == kbase) { /* Boot image */ 7077dd7cddfSDavid du Colombier fp->txtaddr = kbase+sizeof(Exec); 7087dd7cddfSDavid du Colombier fp->name = "ARM *BSD boot image"; 7097dd7cddfSDavid du Colombier fp->hdrsz = 0; /* header stripped */ 7107dd7cddfSDavid du Colombier fp->dataddr = kbase+fp->txtsz; 7117dd7cddfSDavid du Colombier } 7127dd7cddfSDavid du Colombier return 1; 7137dd7cddfSDavid du Colombier } 7143e12c5d1SDavid du Colombier 7153e12c5d1SDavid du Colombier static void 7164de34a7eSDavid du Colombier settext(Fhdr *fp, uvlong e, uvlong a, long s, vlong off) 7173e12c5d1SDavid du Colombier { 7183e12c5d1SDavid du Colombier fp->txtaddr = a; 7193e12c5d1SDavid du Colombier fp->entry = e; 7203e12c5d1SDavid du Colombier fp->txtsz = s; 7213e12c5d1SDavid du Colombier fp->txtoff = off; 7223e12c5d1SDavid du Colombier } 7234de34a7eSDavid du Colombier 7243e12c5d1SDavid du Colombier static void 7254de34a7eSDavid du Colombier setdata(Fhdr *fp, uvlong a, long s, vlong off, long bss) 7263e12c5d1SDavid du Colombier { 7273e12c5d1SDavid du Colombier fp->dataddr = a; 7283e12c5d1SDavid du Colombier fp->datsz = s; 7293e12c5d1SDavid du Colombier fp->datoff = off; 7303e12c5d1SDavid du Colombier fp->bsssz = bss; 7313e12c5d1SDavid du Colombier } 7324de34a7eSDavid du Colombier 7333e12c5d1SDavid du Colombier static void 7344de34a7eSDavid du Colombier setsym(Fhdr *fp, long symsz, long sppcsz, long lnpcsz, vlong symoff) 7353e12c5d1SDavid du Colombier { 7364de34a7eSDavid du Colombier fp->symsz = symsz; 7373e12c5d1SDavid du Colombier fp->symoff = symoff; 7384de34a7eSDavid du Colombier fp->sppcsz = sppcsz; 7393e12c5d1SDavid du Colombier fp->sppcoff = fp->symoff+fp->symsz; 7404de34a7eSDavid du Colombier fp->lnpcsz = lnpcsz; 7413e12c5d1SDavid du Colombier fp->lnpcoff = fp->sppcoff+fp->sppcsz; 7423e12c5d1SDavid du Colombier } 7433e12c5d1SDavid du Colombier 744219b2ee8SDavid du Colombier 7454de34a7eSDavid du Colombier static uvlong 7464de34a7eSDavid du Colombier _round(uvlong a, ulong b) 747219b2ee8SDavid du Colombier { 7484de34a7eSDavid du Colombier uvlong w; 749219b2ee8SDavid du Colombier 750219b2ee8SDavid du Colombier w = (a/b)*b; 751219b2ee8SDavid du Colombier if (a!=w) 752219b2ee8SDavid du Colombier w += b; 753219b2ee8SDavid du Colombier return(w); 754219b2ee8SDavid du Colombier } 755