changelog shortlog tags branches changeset files revisions annotate raw help

Mercurial > hg > plan9front / sys/src/libmach/executable.c

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