]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libmach/executable.c
Import sources from 2011-03-30 iso image - lib
[plan9front.git] / sys / src / libmach / executable.c
1 #include        <u.h>
2 #include        <libc.h>
3 #include        <bio.h>
4 #include        <bootexec.h>
5 #include        <mach.h>
6 #include        "elf.h"
7
8 /*
9  *      All a.out header types.  The dummy entry allows canonical
10  *      processing of the union as a sequence of longs
11  */
12
13 typedef struct {
14         union{
15                 struct {
16                         Exec;           /* a.out.h */
17                         uvlong hdr[1];
18                 };
19                 Ehdr;                   /* elf.h */
20                 struct mipsexec;        /* bootexec.h */
21                 struct mips4kexec;      /* bootexec.h */
22                 struct sparcexec;       /* bootexec.h */
23                 struct nextexec;        /* bootexec.h */
24         } e;
25         long dummy;                     /* padding to ensure extra long */
26 } ExecHdr;
27
28 static  int     nextboot(int, Fhdr*, ExecHdr*);
29 static  int     sparcboot(int, Fhdr*, ExecHdr*);
30 static  int     mipsboot(int, Fhdr*, ExecHdr*);
31 static  int     mips4kboot(int, Fhdr*, ExecHdr*);
32 static  int     common(int, Fhdr*, ExecHdr*);
33 static  int     commonllp64(int, Fhdr*, ExecHdr*);
34 static  int     adotout(int, Fhdr*, ExecHdr*);
35 static  int     elfdotout(int, Fhdr*, ExecHdr*);
36 static  int     armdotout(int, Fhdr*, ExecHdr*);
37 static  void    setsym(Fhdr*, long, long, long, vlong);
38 static  void    setdata(Fhdr*, uvlong, long, vlong, long);
39 static  void    settext(Fhdr*, uvlong, uvlong, long, vlong);
40 static  void    hswal(void*, int, ulong(*)(ulong));
41 static  uvlong  _round(uvlong, ulong);
42
43 /*
44  *      definition of per-executable file type structures
45  */
46
47 typedef struct Exectable{
48         long    magic;                  /* big-endian magic number of file */
49         char    *name;                  /* executable identifier */
50         char    *dlmname;               /* dynamically loadable module identifier */
51         uchar   type;                   /* Internal code */
52         uchar   _magic;                 /* _MAGIC() magic */
53         Mach    *mach;                  /* Per-machine data */
54         long    hsize;                  /* header size */
55         ulong   (*swal)(ulong);         /* header swap, beswal or leswal */
56         int     (*hparse)(int, Fhdr*, ExecHdr*);
57 } ExecTable;
58
59 extern  Mach    mmips;
60 extern  Mach    mmips2le;
61 extern  Mach    mmips2be;
62 extern  Mach    msparc;
63 extern  Mach    msparc64;
64 extern  Mach    m68020;
65 extern  Mach    mi386;
66 extern  Mach    mamd64;
67 extern  Mach    marm;
68 extern  Mach    mpower;
69 extern  Mach    mpower64;
70 extern  Mach    malpha;
71
72 ExecTable exectab[] =
73 {
74         { V_MAGIC,                      /* Mips v.out */
75                 "mips plan 9 executable BE",
76                 "mips plan 9 dlm BE",
77                 FMIPS,
78                 1,
79                 &mmips,
80                 sizeof(Exec),
81                 beswal,
82                 adotout },
83         { P_MAGIC,                      /* Mips 0.out (r3k le) */
84                 "mips plan 9 executable LE",
85                 "mips plan 9 dlm LE",
86                 FMIPSLE,
87                 1,
88                 &mmips,
89                 sizeof(Exec),
90                 beswal,
91                 adotout },
92         { M_MAGIC,                      /* Mips 4.out */
93                 "mips 4k plan 9 executable BE",
94                 "mips 4k plan 9 dlm BE",
95                 FMIPS2BE,
96                 1,
97                 &mmips2be,
98                 sizeof(Exec),
99                 beswal,
100                 adotout },
101         { N_MAGIC,                      /* Mips 0.out */
102                 "mips 4k plan 9 executable LE",
103                 "mips 4k plan 9 dlm LE",
104                 FMIPS2LE,
105                 1,
106                 &mmips2le,
107                 sizeof(Exec),
108                 beswal,
109                 adotout },
110         { 0x160<<16,                    /* Mips boot image */
111                 "mips plan 9 boot image",
112                 nil,
113                 FMIPSB,
114                 0,
115                 &mmips,
116                 sizeof(struct mipsexec),
117                 beswal,
118                 mipsboot },
119         { (0x160<<16)|3,                /* Mips boot image */
120                 "mips 4k plan 9 boot image",
121                 nil,
122                 FMIPSB,
123                 0,
124                 &mmips2be,
125                 sizeof(struct mips4kexec),
126                 beswal,
127                 mips4kboot },
128         { K_MAGIC,                      /* Sparc k.out */
129                 "sparc plan 9 executable",
130                 "sparc plan 9 dlm",
131                 FSPARC,
132                 1,
133                 &msparc,
134                 sizeof(Exec),
135                 beswal,
136                 adotout },
137         { 0x01030107,                   /* Sparc boot image */
138                 "sparc plan 9 boot image",
139                 nil,
140                 FSPARCB,
141                 0,
142                 &msparc,
143                 sizeof(struct sparcexec),
144                 beswal,
145                 sparcboot },
146         { U_MAGIC,                      /* Sparc64 u.out */
147                 "sparc64 plan 9 executable",
148                 "sparc64 plan 9 dlm",
149                 FSPARC64,
150                 1,
151                 &msparc64,
152                 sizeof(Exec),
153                 beswal,
154                 adotout },
155         { A_MAGIC,                      /* 68020 2.out & boot image */
156                 "68020 plan 9 executable",
157                 "68020 plan 9 dlm",
158                 F68020,
159                 1,
160                 &m68020,
161                 sizeof(Exec),
162                 beswal,
163                 common },
164         { 0xFEEDFACE,                   /* Next boot image */
165                 "next plan 9 boot image",
166                 nil,
167                 FNEXTB,
168                 0,
169                 &m68020,
170                 sizeof(struct nextexec),
171                 beswal,
172                 nextboot },
173         { I_MAGIC,                      /* I386 8.out & boot image */
174                 "386 plan 9 executable",
175                 "386 plan 9 dlm",
176                 FI386,
177                 1,
178                 &mi386,
179                 sizeof(Exec),
180                 beswal,
181                 common },
182         { S_MAGIC,                      /* amd64 6.out & boot image */
183                 "amd64 plan 9 executable",
184                 "amd64 plan 9 dlm",
185                 FAMD64,
186                 1,
187                 &mamd64,
188                 sizeof(Exec)+8,
189                 beswal,
190                 commonllp64 },
191         { Q_MAGIC,                      /* PowerPC q.out & boot image */
192                 "power plan 9 executable",
193                 "power plan 9 dlm",
194                 FPOWER,
195                 1,
196                 &mpower,
197                 sizeof(Exec),
198                 beswal,
199                 common },
200         { T_MAGIC,                      /* power64 9.out & boot image */
201                 "power64 plan 9 executable",
202                 "power64 plan 9 dlm",
203                 FPOWER64,
204                 1,
205                 &mpower64,
206                 sizeof(Exec)+8,
207                 beswal,
208                 commonllp64 },
209         { ELF_MAG,                      /* any elf32 */
210                 "elf executable",
211                 nil,
212                 FNONE,
213                 0,
214                 &mi386,
215                 sizeof(Ehdr),
216                 nil,
217                 elfdotout },
218         { E_MAGIC,                      /* Arm 5.out and boot image */
219                 "arm plan 9 executable",
220                 "arm plan 9 dlm",
221                 FARM,
222                 1,
223                 &marm,
224                 sizeof(Exec),
225                 beswal,
226                 common },
227         { (143<<16)|0413,               /* (Free|Net)BSD Arm */
228                 "arm *bsd executable",
229                 nil,
230                 FARM,
231                 0,
232                 &marm,
233                 sizeof(Exec),
234                 leswal,
235                 armdotout },
236         { L_MAGIC,                      /* alpha 7.out */
237                 "alpha plan 9 executable",
238                 "alpha plan 9 dlm",
239                 FALPHA,
240                 1,
241                 &malpha,
242                 sizeof(Exec),
243                 beswal,
244                 common },
245         { 0x0700e0c3,                   /* alpha boot image */
246                 "alpha plan 9 boot image",
247                 nil,
248                 FALPHA,
249                 0,
250                 &malpha,
251                 sizeof(Exec),
252                 beswal,
253                 common },
254         { 0 },
255 };
256
257 Mach    *mach = &mi386;                 /* Global current machine table */
258
259 static ExecTable*
260 couldbe4k(ExecTable *mp)
261 {
262         Dir *d;
263         ExecTable *f;
264
265         if((d=dirstat("/proc/1/regs")) == nil)
266                 return mp;
267         if(d->length < 32*8){           /* R3000 */
268                 free(d);
269                 return mp;
270         }
271         free(d);
272         for (f = exectab; f->magic; f++)
273                 if(f->magic == M_MAGIC) {
274                         f->name = "mips plan 9 executable on mips2 kernel";
275                         return f;
276                 }
277         return mp;
278 }
279
280 int
281 crackhdr(int fd, Fhdr *fp)
282 {
283         ExecTable *mp;
284         ExecHdr d;
285         int nb, ret;
286         ulong magic;
287
288         fp->type = FNONE;
289         nb = read(fd, (char *)&d.e, sizeof(d.e));
290         if (nb <= 0)
291                 return 0;
292
293         ret = 0;
294         magic = beswal(d.e.magic);              /* big-endian */
295         for (mp = exectab; mp->magic; mp++) {
296                 if (nb < mp->hsize)
297                         continue;
298
299                 /*
300                  * The magic number has morphed into something
301                  * with fields (the straw was DYN_MAGIC) so now
302                  * a flag is needed in Fhdr to distinguish _MAGIC()
303                  * magic numbers from foreign magic numbers.
304                  *
305                  * This code is creaking a bit and if it has to
306                  * be modified/extended much more it's probably
307                  * time to step back and redo it all.
308                  */
309                 if(mp->_magic){
310                         if(mp->magic != (magic & ~DYN_MAGIC))
311                                 continue;
312
313                         if(mp->magic == V_MAGIC)
314                                 mp = couldbe4k(mp);
315
316                         if ((magic & DYN_MAGIC) && mp->dlmname != nil)
317                                 fp->name = mp->dlmname;
318                         else
319                                 fp->name = mp->name;
320                 }
321                 else{
322                         if(mp->magic != magic)
323                                 continue;
324                         fp->name = mp->name;
325                 }
326                 fp->type = mp->type;
327                 fp->hdrsz = mp->hsize;          /* will be zero on bootables */
328                 fp->_magic = mp->_magic;
329                 fp->magic = magic;
330
331                 mach = mp->mach;
332                 if(mp->swal != nil)
333                         hswal(&d, sizeof(d.e)/sizeof(ulong), mp->swal);
334                 ret = mp->hparse(fd, fp, &d);
335                 seek(fd, mp->hsize, 0);         /* seek to end of header */
336                 break;
337         }
338         if(mp->magic == 0)
339                 werrstr("unknown header type");
340         return ret;
341 }
342
343 /*
344  * Convert header to canonical form
345  */
346 static void
347 hswal(void *v, int n, ulong (*swap)(ulong))
348 {
349         ulong *ulp;
350
351         for(ulp = v; n--; ulp++)
352                 *ulp = (*swap)(*ulp);
353 }
354
355 /*
356  *      Crack a normal a.out-type header
357  */
358 static int
359 adotout(int fd, Fhdr *fp, ExecHdr *hp)
360 {
361         long pgsize;
362
363         USED(fd);
364         pgsize = mach->pgsize;
365         settext(fp, hp->e.entry, pgsize+sizeof(Exec),
366                         hp->e.text, sizeof(Exec));
367         setdata(fp, _round(pgsize+fp->txtsz+sizeof(Exec), pgsize),
368                 hp->e.data, fp->txtsz+sizeof(Exec), hp->e.bss);
369         setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz);
370         return 1;
371 }
372
373 static void
374 commonboot(Fhdr *fp)
375 {
376         if (!(fp->entry & mach->ktmask))
377                 return;
378
379         switch(fp->type) {                              /* boot image */
380         case F68020:
381                 fp->type = F68020B;
382                 fp->name = "68020 plan 9 boot image";
383                 break;
384         case FI386:
385                 fp->type = FI386B;
386                 fp->txtaddr = (u32int)fp->entry;
387                 fp->name = "386 plan 9 boot image";
388                 fp->dataddr = _round(fp->txtaddr+fp->txtsz, mach->pgsize);
389                 break;
390         case FARM:
391                 fp->type = FARMB;
392                 fp->txtaddr = (u32int)fp->entry;
393                 fp->name = "ARM plan 9 boot image";
394                 fp->dataddr = _round(fp->txtaddr+fp->txtsz, mach->pgsize);
395                 return;
396         case FALPHA:
397                 fp->type = FALPHAB;
398                 fp->txtaddr = (u32int)fp->entry;
399                 fp->name = "alpha plan 9 boot image";
400                 fp->dataddr = fp->txtaddr+fp->txtsz;
401                 break;
402         case FPOWER:
403                 fp->type = FPOWERB;
404                 fp->txtaddr = (u32int)fp->entry;
405                 fp->name = "power plan 9 boot image";
406                 fp->dataddr = fp->txtaddr+fp->txtsz;
407                 break;
408         case FAMD64:
409                 fp->type = FAMD64B;
410                 fp->txtaddr = fp->entry;
411                 fp->name = "amd64 plan 9 boot image";
412                 fp->dataddr = _round(fp->txtaddr+fp->txtsz, mach->pgsize);
413                 break;
414         default:
415                 return;
416         }
417         fp->hdrsz = 0;                  /* header stripped */
418 }
419
420 /*
421  *      _MAGIC() style headers and
422  *      alpha plan9-style bootable images for axp "headerless" boot
423  *
424  */
425 static int
426 common(int fd, Fhdr *fp, ExecHdr *hp)
427 {
428         adotout(fd, fp, hp);
429         if(hp->e.magic & DYN_MAGIC) {
430                 fp->txtaddr = 0;
431                 fp->dataddr = fp->txtsz;
432                 return 1;
433         }
434         commonboot(fp);
435         return 1;
436 }
437
438 static int
439 commonllp64(int, Fhdr *fp, ExecHdr *hp)
440 {
441         long pgsize;
442         uvlong entry;
443
444         if(!(hp->e.magic & HDR_MAGIC))
445                 return 0;
446
447         /*
448          * There can be more magic here if the
449          * header ever needs more expansion.
450          * For now just catch use of any of the
451          * unused bits.
452          */
453         if((hp->e.magic & ~DYN_MAGIC)>>16)
454                 return 0;
455         entry = beswav(hp->e.hdr[0]);
456
457         pgsize = mach->pgsize;
458         settext(fp, entry, pgsize+fp->hdrsz, hp->e.text, fp->hdrsz);
459         setdata(fp, _round(pgsize+fp->txtsz+fp->hdrsz, pgsize),
460                 hp->e.data, fp->txtsz+fp->hdrsz, hp->e.bss);
461         setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz);
462
463         if(hp->e.magic & DYN_MAGIC) {
464                 fp->txtaddr = 0;
465                 fp->dataddr = fp->txtsz;
466                 return 1;
467         }
468         commonboot(fp);
469         return 1;
470 }
471
472 /*
473  *      mips bootable image.
474  */
475 static int
476 mipsboot(int fd, Fhdr *fp, ExecHdr *hp)
477 {
478         USED(fd);
479         fp->type = FMIPSB;
480         switch(hp->e.amagic) {
481         default:
482         case 0407:      /* some kind of mips */
483                 settext(fp, (u32int)hp->e.mentry, (u32int)hp->e.text_start,
484                         hp->e.tsize, sizeof(struct mipsexec)+4);
485                 setdata(fp, (u32int)hp->e.data_start, hp->e.dsize,
486                         fp->txtoff+hp->e.tsize, hp->e.bsize);
487                 break;
488         case 0413:      /* some kind of mips */
489                 settext(fp, (u32int)hp->e.mentry, (u32int)hp->e.text_start,
490                         hp->e.tsize, 0);
491                 setdata(fp, (u32int)hp->e.data_start, hp->e.dsize,
492                         hp->e.tsize, hp->e.bsize);
493                 break;
494         }
495         setsym(fp, hp->e.nsyms, 0, hp->e.pcsize, hp->e.symptr);
496         fp->hdrsz = 0;                  /* header stripped */
497         return 1;
498 }
499
500 /*
501  *      mips4k bootable image.
502  */
503 static int
504 mips4kboot(int fd, Fhdr *fp, ExecHdr *hp)
505 {
506         USED(fd);
507         fp->type = FMIPSB;
508         switch(hp->e.h.amagic) {
509         default:
510         case 0407:      /* some kind of mips */
511                 settext(fp, (u32int)hp->e.h.mentry, (u32int)hp->e.h.text_start,
512                         hp->e.h.tsize, sizeof(struct mips4kexec));
513                 setdata(fp, (u32int)hp->e.h.data_start, hp->e.h.dsize,
514                         fp->txtoff+hp->e.h.tsize, hp->e.h.bsize);
515                 break;
516         case 0413:      /* some kind of mips */
517                 settext(fp, (u32int)hp->e.h.mentry, (u32int)hp->e.h.text_start,
518                         hp->e.h.tsize, 0);
519                 setdata(fp, (u32int)hp->e.h.data_start, hp->e.h.dsize,
520                         hp->e.h.tsize, hp->e.h.bsize);
521                 break;
522         }
523         setsym(fp, hp->e.h.nsyms, 0, hp->e.h.pcsize, hp->e.h.symptr);
524         fp->hdrsz = 0;                  /* header stripped */
525         return 1;
526 }
527
528 /*
529  *      sparc bootable image
530  */
531 static int
532 sparcboot(int fd, Fhdr *fp, ExecHdr *hp)
533 {
534         USED(fd);
535         fp->type = FSPARCB;
536         settext(fp, hp->e.sentry, hp->e.sentry, hp->e.stext,
537                 sizeof(struct sparcexec));
538         setdata(fp, hp->e.sentry+hp->e.stext, hp->e.sdata,
539                 fp->txtoff+hp->e.stext, hp->e.sbss);
540         setsym(fp, hp->e.ssyms, 0, hp->e.sdrsize, fp->datoff+hp->e.sdata);
541         fp->hdrsz = 0;                  /* header stripped */
542         return 1;
543 }
544
545 /*
546  *      next bootable image
547  */
548 static int
549 nextboot(int fd, Fhdr *fp, ExecHdr *hp)
550 {
551         USED(fd);
552         fp->type = FNEXTB;
553         settext(fp, hp->e.textc.vmaddr, hp->e.textc.vmaddr,
554                 hp->e.texts.size, hp->e.texts.offset);
555         setdata(fp, hp->e.datac.vmaddr, hp->e.datas.size,
556                 hp->e.datas.offset, hp->e.bsss.size);
557         setsym(fp, hp->e.symc.nsyms, hp->e.symc.spoff, hp->e.symc.pcoff,
558                 hp->e.symc.symoff);
559         fp->hdrsz = 0;                  /* header stripped */
560         return 1;
561 }
562
563 /*
564  * Elf32 binaries.
565  */
566 static int
567 elfdotout(int fd, Fhdr *fp, ExecHdr *hp)
568 {
569
570         ulong (*swal)(ulong);
571         ushort (*swab)(ushort);
572         Ehdr *ep;
573         Phdr *ph;
574         int i, it, id, is, phsz;
575
576         /* bitswap the header according to the DATA format */
577         ep = &hp->e;
578         if(ep->ident[CLASS] != ELFCLASS32) {
579                 werrstr("bad ELF class - not 32 bit");
580                 return 0;
581         }
582         if(ep->ident[DATA] == ELFDATA2LSB) {
583                 swab = leswab;
584                 swal = leswal;
585         } else if(ep->ident[DATA] == ELFDATA2MSB) {
586                 swab = beswab;
587                 swal = beswal;
588         } else {
589                 werrstr("bad ELF encoding - not big or little endian");
590                 return 0;
591         }
592
593         ep->type = swab(ep->type);
594         ep->machine = swab(ep->machine);
595         ep->version = swal(ep->version);
596         ep->elfentry = swal(ep->elfentry);
597         ep->phoff = swal(ep->phoff);
598         ep->shoff = swal(ep->shoff);
599         ep->flags = swal(ep->flags);
600         ep->ehsize = swab(ep->ehsize);
601         ep->phentsize = swab(ep->phentsize);
602         ep->phnum = swab(ep->phnum);
603         ep->shentsize = swab(ep->shentsize);
604         ep->shnum = swab(ep->shnum);
605         ep->shstrndx = swab(ep->shstrndx);
606         if(ep->type != EXEC || ep->version != CURRENT)
607                 return 0;
608
609         /* we could definitely support a lot more machines here */
610         fp->magic = ELF_MAG;
611         fp->hdrsz = (ep->ehsize+ep->phnum*ep->phentsize+16)&~15;
612         switch(ep->machine) {
613         case I386:
614                 mach = &mi386;
615                 fp->type = FI386;
616                 break;
617         case MIPS:
618                 mach = &mmips;
619                 fp->type = FMIPS;
620                 break;
621         case SPARC64:
622                 mach = &msparc64;
623                 fp->type = FSPARC64;
624                 break;
625         case POWER:
626                 mach = &mpower;
627                 fp->type = FPOWER;
628                 break;
629         case AMD64:
630                 mach = &mamd64;
631                 fp->type = FAMD64;
632                 break;
633         case ARM:
634                 mach = &marm;
635                 fp->type = FARM;
636                 break;
637         default:
638                 return 0;
639         }
640
641         if(ep->phentsize != sizeof(Phdr)) {
642                 werrstr("bad ELF header size");
643                 return 0;
644         }
645         phsz = sizeof(Phdr)*ep->phnum;
646         ph = malloc(phsz);
647         if(!ph)
648                 return 0;
649         seek(fd, ep->phoff, 0);
650         if(read(fd, ph, phsz) < 0) {
651                 free(ph);
652                 return 0;
653         }
654         hswal(ph, phsz/sizeof(ulong), swal);
655
656         /* find text, data and symbols and install them */
657         it = id = is = -1;
658         for(i = 0; i < ep->phnum; i++) {
659                 if(ph[i].type == LOAD
660                 && (ph[i].flags & (R|X)) == (R|X) && it == -1)
661                         it = i;
662                 else if(ph[i].type == LOAD
663                 && (ph[i].flags & (R|W)) == (R|W) && id == -1)
664                         id = i;
665                 else if(ph[i].type == NOPTYPE && is == -1)
666                         is = i;
667         }
668         if(it == -1 || id == -1) {
669                 /*
670                  * The SPARC64 boot image is something of an ELF hack.
671                  * Text+Data+BSS are represented by ph[0].  Symbols
672                  * are represented by ph[1]:
673                  *
674                  *              filesz, memsz, vaddr, paddr, off
675                  * ph[0] : txtsz+datsz, txtsz+datsz+bsssz, txtaddr-KZERO, datasize, txtoff
676                  * ph[1] : symsz, lcsz, 0, 0, symoff
677                  */
678                 if(ep->machine == SPARC64 && ep->phnum == 2) {
679                         ulong txtaddr, txtsz, dataddr, bsssz;
680
681                         txtaddr = ph[0].vaddr | 0x80000000;
682                         txtsz = ph[0].filesz - ph[0].paddr;
683                         dataddr = txtaddr + txtsz;
684                         bsssz = ph[0].memsz - ph[0].filesz;
685                         settext(fp, ep->elfentry | 0x80000000, txtaddr, txtsz, ph[0].offset);
686                         setdata(fp, dataddr, ph[0].paddr, ph[0].offset + txtsz, bsssz);
687                         setsym(fp, ph[1].filesz, 0, ph[1].memsz, ph[1].offset);
688                         free(ph);
689                         return 1;
690                 }
691
692                 werrstr("No TEXT or DATA sections");
693                 free(ph);
694                 return 0;
695         }
696
697         settext(fp, ep->elfentry, ph[it].vaddr, ph[it].memsz, ph[it].offset);
698         setdata(fp, ph[id].vaddr, ph[id].filesz, ph[id].offset, ph[id].memsz - ph[id].filesz);
699         if(is != -1)
700                 setsym(fp, ph[is].filesz, 0, ph[is].memsz, ph[is].offset);
701         free(ph);
702         return 1;
703 }
704
705 /*
706  * (Free|Net)BSD ARM header.
707  */
708 static int
709 armdotout(int fd, Fhdr *fp, ExecHdr *hp)
710 {
711         uvlong kbase;
712
713         USED(fd);
714         settext(fp, hp->e.entry, sizeof(Exec), hp->e.text, sizeof(Exec));
715         setdata(fp, fp->txtsz, hp->e.data, fp->txtsz, hp->e.bss);
716         setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz);
717
718         kbase = 0xF0000000;
719         if ((fp->entry & kbase) == kbase) {             /* Boot image */
720                 fp->txtaddr = kbase+sizeof(Exec);
721                 fp->name = "ARM *BSD boot image";
722                 fp->hdrsz = 0;          /* header stripped */
723                 fp->dataddr = kbase+fp->txtsz;
724         }
725         return 1;
726 }
727
728 static void
729 settext(Fhdr *fp, uvlong e, uvlong a, long s, vlong off)
730 {
731         fp->txtaddr = a;
732         fp->entry = e;
733         fp->txtsz = s;
734         fp->txtoff = off;
735 }
736
737 static void
738 setdata(Fhdr *fp, uvlong a, long s, vlong off, long bss)
739 {
740         fp->dataddr = a;
741         fp->datsz = s;
742         fp->datoff = off;
743         fp->bsssz = bss;
744 }
745
746 static void
747 setsym(Fhdr *fp, long symsz, long sppcsz, long lnpcsz, vlong symoff)
748 {
749         fp->symsz = symsz;
750         fp->symoff = symoff;
751         fp->sppcsz = sppcsz;
752         fp->sppcoff = fp->symoff+fp->symsz;
753         fp->lnpcsz = lnpcsz;
754         fp->lnpcoff = fp->sppcoff+fp->sppcsz;
755 }
756
757
758 static uvlong
759 _round(uvlong a, ulong b)
760 {
761         uvlong w;
762
763         w = (a/b)*b;
764         if (a!=w)
765                 w += b;
766         return(w);
767 }