tidy up flags. don't destroy/recreate the regions every stack change, but clear exist...
[AROS.git] / tools / elf2hunk / elf2hunk.c
blob60727fabd301e1e0d711766408993713357018e9
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #define PROTOTYPES
7 #define HAVE_STDARG_H
9 #include <stdio.h>
10 #include <string.h>
11 #include <stdlib.h>
12 #include <stdint.h>
13 #include <assert.h>
14 #include <ctype.h>
15 #include <errno.h>
16 #include <unistd.h>
17 #include <fcntl.h>
18 #include <limits.h>
19 #include <dirent.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
24 #define F_VERBOSE (1 << 0)
25 #define F_NOCONVERT (1 << 1)
27 #if defined(__GNUC__)&&defined(WIN32)
28 #include <winsock2.h>
29 #define mkdir(path, mode) mkdir(path)
30 #else
31 #include <arpa/inet.h>
32 typedef uint32_t ULONG;
33 typedef int BOOL;
34 #endif
35 typedef uint8_t UBYTE;
36 typedef uint16_t UWORD;
37 typedef uint32_t IPTR;
38 typedef int32_t SIPTR;
39 typedef char * STRPTR;
41 #if !defined(FALSE)&&!defined(TRUE)
42 #define FALSE 0
43 #define TRUE (!FALSE)
44 #endif
46 /* Memory allocation flags */
47 #define MEMF_ANY 0L
48 #define MEMF_PUBLIC (1L<<0)
49 #define MEMF_CHIP (1L<<1)
50 #define MEMF_FAST (1L<<2)
51 #define MEMF_EXECUTABLE (1L<<4) /* AmigaOS v4 compatible */
52 #define MEMF_LOCAL (1L<<8)
53 #define MEMF_24BITDMA (1L<<9)
54 #define MEMF_KICK (1L<<10)
55 #define MEMF_31BIT (1L<<12) /* Low address space (<2GB). Effective only on 64 bit machines. */
56 #define MEMF_CLEAR (1L<<16) /* Explicitly clear memory after allocation */
57 #define MEMF_LARGEST (1L<<17)
58 #define MEMF_REVERSE (1L<<18)
59 #define MEMF_TOTAL (1L<<19)
60 #define MEMF_HWALIGNED (1L<<20) /* For AllocMem() - align address and size to physical page boundary */
61 #define MEMF_SEM_PROTECTED (1L<<20) /* For CreatePool() - add semaphore protection to the pool */
62 #define MEMF_NO_EXPUNGE (1L<<31)
64 #define HUNKF_ADVISORY (1L<<29)
65 #define HUNKF_CHIP (1L<<30)
66 #define HUNKF_FAST (1L<<31)
67 #define HUNKF_MEMFLAGS (HUNKF_CHIP | HUNKF_FAST)
70 #define HUNK_CODE 1001
71 #define HUNK_DATA 1002
72 #define HUNK_BSS 1003
73 #define HUNK_RELOC32 1004
74 #define HUNK_SYMBOL 1008
75 #define HUNK_END 1010
76 #define HUNK_HEADER 1011
78 #define SHT_PROGBITS 1
79 #define SHT_SYMTAB 2
80 #define SHT_STRTAB 3
81 #define SHT_RELA 4
82 #define SHT_NOBITS 8
83 #define SHT_REL 9
84 #define SHT_SYMTAB_SHNDX 18
86 #define ET_REL 1
87 #define ET_EXEC 2
89 #define EM_386 3
90 #define EM_68K 4
91 #define EM_PPC 20
92 #define EM_ARM 40
93 #define EM_X86_64 62 /* AMD x86-64 */
95 #define R_386_NONE 0
96 #define R_386_32 1
97 #define R_386_PC32 2
99 /* AMD x86-64 relocations. */
100 #define R_X86_64_NONE 0 /* No reloc */
101 #define R_X86_64_64 1 /* Direct 64 bit */
102 #define R_X86_64_PC32 2 /* PC relative 32 bit signed */
103 #define R_X86_64_32 10
104 #define R_X86_64_32S 11
106 #define R_68k_NONE 0
107 #define R_68K_32 1
108 #define R_68K_PC32 4
109 #define R_68K_PC16 5
111 #define R_PPC_NONE 0
112 #define R_PPC_ADDR32 1
113 #define R_PPC_ADDR16_LO 4
114 #define R_PPC_ADDR16_HA 6
115 #define R_PPC_REL24 10
116 #define R_PPC_REL32 26
117 #define R_PPC_REL16_LO 250
118 #define R_PPC_REL16_HA 252
120 #define R_ARM_NONE 0
121 #define R_ARM_PC24 1
122 #define R_ARM_ABS32 2
123 #define R_ARM_CALL 28
124 #define R_ARM_JUMP24 29
125 #define R_ARM_V4BX 40
126 #define R_ARM_PREL31 42
127 #define R_ARM_MOVW_ABS_NC 43
128 #define R_ARM_MOVT_ABS 44
130 #define STT_NOTYPE 0
131 #define STT_OBJECT 1
132 #define STT_FUNC 2
133 #define STT_SECTION 3
134 #define STT_FILE 4
135 #define STT_LOPROC 13
136 #define STT_HIPROC 15
138 #define SHN_UNDEF 0
139 #define SHN_LORESERVE 0xff00
140 #define SHN_ABS 0xfff1
141 #define SHN_COMMON 0xfff2
142 #define SHN_XINDEX 0xffff
143 #define SHN_HIRESERVE 0xffff
145 #define SHF_WRITE (1 << 0)
146 #define SHF_ALLOC (1 << 1)
147 #define SHF_EXECINSTR (1 << 2)
149 #define ELF_ST_TYPE(i) ((i) & 0x0F)
151 #define EI_VERSION 6
152 #define EV_CURRENT 1
154 #define EI_DATA 5
155 #define ELFDATA2LSB 1
156 #define ELFDATA2MSB 2
158 #define EI_CLASS 4
159 #define ELFCLASS32 1
160 #define ELFCLASS64 2 /* 64-bit objects */
162 #define EI_OSABI 7
163 #define EI_ABIVERSION 8
165 #define ELFOSABI_AROS 15
167 #define PF_X (1 << 0)
169 struct elfheader
171 UBYTE ident[16];
172 UWORD type;
173 UWORD machine;
174 ULONG version;
175 IPTR entry;
176 IPTR phoff;
177 IPTR shoff;
178 ULONG flags;
179 UWORD ehsize;
180 UWORD phentsize;
181 UWORD phnum;
182 UWORD shentsize;
183 UWORD shnum;
184 UWORD shstrndx;
185 } __attribute__((packed));
187 struct sheader
189 ULONG name;
190 ULONG type;
191 IPTR flags;
192 IPTR addr;
193 IPTR offset;
194 IPTR size;
195 ULONG link;
196 ULONG info;
197 IPTR addralign;
198 IPTR entsize;
199 } __attribute__((packed));
201 #define PT_LOAD 1
203 struct pheader
205 ULONG type;
206 ULONG offset;
207 IPTR vaddr;
208 IPTR paddr;
209 ULONG filesz;
210 ULONG memsz;
211 ULONG flags;
212 ULONG align;
213 } __attribute__((packed));
215 struct symbol
217 ULONG name; /* Offset of the name string in the string table */
218 IPTR value; /* Varies; eg. the offset of the symbol in its hunk */
219 IPTR size; /* How much memory does the symbol occupy */
220 UBYTE info; /* What kind of symbol is this ? (global, variable, etc) */
221 UBYTE other; /* undefined */
222 UWORD shindex; /* In which section is the symbol defined ? */
223 } __attribute__((packed));
225 #define ELF_R_SYM(val) ((val) >> 8)
226 #define ELF_R_TYPE(val) ((val) & 0xff)
227 #define ELF_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff))
229 struct relo
231 IPTR offset; /* Address of the relocation relative to the section it refers to */
232 IPTR info; /* Type of the relocation */
233 SIPTR addend; /* Constant addend used to compute value */
236 /* convert section header number to array index */
237 #define SHINDEX(n) \
238 ((n) < SHN_LORESERVE ? (n) : ((n) <= SHN_HIRESERVE ? 0 : (n) - (SHN_HIRESERVE + 1 - SHN_LORESERVE)))
240 /* convert section header array index to section number */
241 #define SHNUM(i) \
242 ((i) < SHN_LORESERVE ? (i) : (i) + (SHN_HIRESERVE + 1 - SHN_LORESERVE))
244 /* m68k Machine's native values */
245 #define AROS_ELF_CLASS ELFCLASS32
246 #define AROS_ELF_DATA ELFDATA2MSB
247 #define AROS_ELF_MACHINE EM_68K
248 #define AROS_ELF_REL SHT_RELA
251 #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
252 # include <stdarg.h>
253 # define VA_START(args, lastarg) va_start(args, lastarg)
254 #else
255 # include <varargs.h>
256 # define VA_START(args, lastarg) va_start(args)
257 #endif
259 #ifdef PROTOTYPES
260 # define PARAMS(x) x
261 #else
262 # define PARAMS(x) ()
263 #endif /* PROTOTYPES */
265 static void set_error(int err)
267 errno = err;
270 #if defined(DEBUG) && DEBUG
271 #define D(x) x
272 #define DB2(x) x
273 #else
274 #define D(x)
275 #define DB2(x)
276 #endif
277 #define bug(fmt,args...) fprintf(stderr, fmt ,##args )
279 static int must_swap = -1;
281 static void eh_fixup(struct elfheader *eh)
283 /* Endian swaps */
284 if (eh->type == 256) {
285 must_swap = 1;
286 eh->type = ntohs(eh->type);
287 eh->machine = ntohs(eh->machine);
288 eh->version = ntohl(eh->version);
289 eh->entry = ntohl(eh->entry);
290 eh->phoff = ntohl(eh->phoff);
291 eh->shoff = ntohl(eh->shoff);
292 eh->flags = ntohl(eh->flags);
293 eh->ehsize = ntohs(eh->ehsize);
294 eh->phentsize = ntohs(eh->phentsize);
295 eh->phnum = ntohs(eh->phnum);
296 eh->shentsize = ntohs(eh->shentsize);
297 eh->shnum = ntohs(eh->shnum);
298 eh->shstrndx = ntohs(eh->shstrndx);
299 } else {
300 must_swap = 0;
304 static void sh_fixup(struct sheader *sh, int n)
306 if (must_swap == 0)
307 return;
309 for (; n > 0; n--, sh++) {
310 sh->name = ntohl(sh->name);
311 sh->type = ntohl(sh->type);
312 sh->flags = ntohl(sh->flags);
313 sh->addr = ntohl(sh->addr);
314 sh->offset = ntohl(sh->offset);
315 sh->size = ntohl(sh->size);
316 sh->link = ntohl(sh->link);
317 sh->info = ntohl(sh->info);
318 sh->addralign = ntohl(sh->addralign);
319 sh->entsize = ntohl(sh->entsize);
323 static void rel_fixup(struct relo *rel)
325 if (must_swap == 0)
326 return;
328 rel->offset = ntohl(rel->offset);
329 rel->info = ntohl(rel->info);
330 rel->addend = ntohl(rel->addend);
333 void sym_fixup(struct symbol *sym)
335 if (must_swap == 0)
336 return;
338 sym->name = ntohl(sym->name);
339 sym->value = ntohl(sym->value);
340 sym->size = ntohl(sym->size);
341 sym->shindex = ntohs(sym->shindex);
344 static void *load_block (int file,ULONG offset,ULONG size)
346 ULONG lsize = (size + sizeof(ULONG) - 1) / sizeof(ULONG);
347 D(bug("[ELF2HUNK] Load Block\n"));
348 D(bug("[ELF2HUNK] (size=%d)\n",(int)size));
349 void *block = malloc(lsize * sizeof(ULONG));
350 if (block) {
351 lseek(file, offset, SEEK_SET);
352 if (read(file, block, size) == size) {
353 return block;
356 free(block);
357 set_error(EIO);
358 } else
359 set_error(ENOMEM);
361 return NULL;
364 static ULONG read_shnum(int file, struct elfheader *eh)
366 ULONG shnum = eh->shnum;
368 /* the ELF header only uses 16 bits to store the count of section headers,
369 * so it can't handle more than 65535 headers. if the count is 0, and an
370 * offset is defined, then the real count can be found in the first
371 * section header (which always exists).
373 * similarly, if the string table index is SHN_XINDEX, then the actual
374 * index is found in the first section header also.
376 * see the System V ABI 2001-04-24 draft for more details.
378 if (eh->shnum == 0)
380 struct sheader sh;
382 if (eh->shoff == 0) {
383 set_error(ENOEXEC);
384 return 0;
387 lseek(file, eh->shoff, SEEK_SET);
388 if (read(file, &sh, sizeof(sh)) != sizeof(sh))
389 return 0;
391 sh_fixup(&sh, 1);
393 /* wider section header count is in the size field */
394 shnum = sh.size;
396 /* sanity, if they're still invalid then this isn't elf */
397 if (shnum == 0)
398 set_error(ENOEXEC);
401 return shnum;
404 static int load_header(int file, struct elfheader *eh)
406 lseek(file, 0, SEEK_SET);
407 if (read(file, eh, sizeof(struct elfheader)) != sizeof(struct elfheader)) {
408 D(bug("[ELF2HUNK] Can't read the %d byte ELF header\n", (int)sizeof(struct elfheader)));
409 return 0;
412 eh_fixup(eh);
414 if (eh->ident[0] != 0x7f || eh->ident[1] != 'E' ||
415 eh->ident[2] != 'L' || eh->ident[3] != 'F') {
416 D(bug("[ELF2HUNK] Not an ELF object\n"));
417 return 0;
419 D(bug("[ELF2HUNK] ELF object\n"));
421 /* WANT_CLASS should be defined for your target */
422 if (eh->ident[EI_CLASS] != AROS_ELF_CLASS ||
423 eh->ident[EI_VERSION] != EV_CURRENT ||
424 eh->type != ET_REL ||
425 eh->ident[EI_DATA] != AROS_ELF_DATA ||
426 eh->machine != AROS_ELF_MACHINE)
428 D(bug("[ELF2HUNK] Object is of wrong type\n"));
429 D(bug("[ELF2HUNK] EI_CLASS is %d - should be %d\n", eh->ident[EI_CLASS] , AROS_ELF_CLASS ));
430 D(bug("[ELF2HUNK] EI_VERSION is %d - should be %d\n", eh->ident[EI_VERSION], EV_CURRENT ));
431 D(bug("[ELF2HUNK] type is %d - should be %d\n", eh->type , ET_REL ));
432 D(bug("[ELF2HUNK] EI_DATA is %d - should be %d\n", eh->ident[EI_DATA] , AROS_ELF_DATA ));
433 D(bug("[ELF2HUNK] machine is %d - should be %d\n", eh->machine , AROS_ELF_MACHINE));
435 set_error(ENOEXEC);
436 return 0;
439 return 1;
442 struct hunkheader {
443 ULONG type;
444 ULONG memflags; /* Memory flags */
445 ULONG size; /* Size in ULONGs */
446 void *data;
447 ULONG relocs;
448 int hunk; /* Allocatable hunk ID */
449 struct hunkreloc {
450 ULONG shid; /* ELF hunk base to add to... */
451 ULONG offset; /* offset in this hunk. */
452 const char *symbol;
453 } *reloc;
456 static int relocate
458 struct elfheader *eh,
459 struct sheader *sh,
460 ULONG shrel_idx,
461 int symtab_shndx,
462 struct relo *rel,
463 struct hunkheader **hh
466 struct sheader *shrel = &sh[shrel_idx];
467 struct sheader *shsymtab = &sh[SHINDEX(shrel->link)];
468 struct sheader *toreloc = &sh[SHINDEX(shrel->info)];
470 struct symbol *symtab = (struct symbol *)hh[SHINDEX(shrel->link)]->data;
471 struct hunkheader *h = hh[SHINDEX(shrel->info)];
474 * Ignore relocs if the target section has no allocation. that can happen
475 * eg. with a .debug PROGBITS and a .rel.debug section
477 D(bug("[ELF2HUNK] sh[%d].flags = 0x%x\n", (int)SHINDEX(shrel->info), (int)toreloc->flags));
478 if (!(toreloc->flags & SHF_ALLOC))
479 return 1;
481 ULONG numrel = shrel->size / shrel->entsize;
482 ULONG i;
483 ULONG hrels;
485 hrels = h->relocs;
486 h->relocs += numrel;
487 h->reloc = realloc(h->reloc, h->relocs * sizeof(struct hunkreloc));
488 struct hunkreloc *hrel = &h->reloc[hrels];
490 for (i=0; i<numrel; i++, rel++)
492 struct symbol sym;
493 ULONG offset;
494 ULONG shindex;
495 ULONG hunk;
496 ULONG value;
497 const char *symname;
499 rel_fixup(rel);
501 #ifdef __arm__
503 * R_ARM_V4BX are actually special marks for the linker.
504 * They even never have a target (shindex == SHN_UNDEF),
505 * so we simply ignore them before doing any checks.
507 if (ELF_R_TYPE(rel->info) == R_ARM_V4BX)
508 continue;
509 #endif
511 sym = symtab[ELF_R_SYM(rel->info)];
512 sym_fixup(&sym);
513 offset = rel->offset;
514 symname = (const char *)(hh[SHINDEX(shsymtab->link)]->data + sym.name);
516 if (sym.shindex != SHN_XINDEX)
517 shindex = sym.shindex;
519 else {
520 if (symtab_shndx < 0) {
521 bug("[ELF2HUNK] got symbol with shndx 0xfff, but there's no symtab shndx table\n");
522 set_error(EINVAL);
523 return 0;
525 shindex = ntohl(((ULONG *)hh[symtab_shndx]->data)[ELF_R_SYM(rel->info)]);
528 D(bug("[ELF2HUNK] Processing %d symbol %s\n", (int)shindex, symname));
530 switch (shindex)
533 case SHN_UNDEF:
534 if (ELF_R_TYPE(rel->info) != 0) {
535 bug("[ELF2HUNK] SHN_UNDEF symbol '%s', type %d unsupported\n", symname, ELF_R_TYPE(rel->info));
536 set_error(EINVAL);
537 return 0;
539 break;
541 case SHN_COMMON:
542 bug("[ELF2HUNK] SHN_COMMON symbol '%s' unsupported\n", symname);
543 set_error(EINVAL);
545 return 0;
547 case SHN_ABS:
548 hunk = ~0; value = sym.value;
549 break;
551 default:
552 hunk = SHINDEX(shindex);
553 value = sym.value;
554 break;
557 switch (ELF_R_TYPE(rel->info))
559 case R_68K_32:
560 value += rel->addend;
561 break;
563 case R_68K_PC32:
564 value += rel->addend - offset;
565 break;
567 case R_68K_PC16:
568 bug("[ELF2HUNK] Unsupported relocation type R_68K_PC16\n");
569 set_error(EINVAL);
570 return 0;
571 break;
573 case R_68k_NONE:
574 break;
576 default:
577 bug("[ELF2HUNK] Unrecognized relocation type %d %d\n", (int)i, (int)ELF_R_TYPE(rel->info));
578 set_error(EINVAL);
579 return 0;
582 D(bug("[ELF2HUNK] Hunk %d, offset 0x%x: base 0x%x\n", (int)hunk, (int)offset, (int)value));
583 *(ULONG *)(h->data + offset) = htonl(value + ntohl(*(ULONG *)(h->data + offset)));
584 if (hunk == ~0) {
585 h->relocs--;
586 continue;
588 hrel->shid = hunk;
589 hrel->offset = offset;
590 hrel->symbol = symname;
591 hrel++;
594 return 1;
597 int reloc_cmp(const void *a, const void *b)
599 const struct hunkreloc *ha = a, *hb = b;
601 if (ha->shid != hb->shid)
602 return hb->shid - ha->shid;
603 return hb->offset - ha->offset;
606 static int wlong(int fd, ULONG val)
608 val = htonl(val);
609 return write(fd, &val, sizeof(val));
612 int sym_dump(int hunk_fd, struct sheader *sh, struct hunkheader **hh, int shid, int symtabndx)
614 int i, err, syms;
615 struct symbol *sym = hh[symtabndx]->data;
616 struct sheader *symtab = &sh[SHINDEX(symtabndx)];
618 syms = symtab->size / sizeof(struct symbol);
620 if (syms == 0)
621 return 1;
623 wlong(hunk_fd, HUNK_SYMBOL);
624 wlong(hunk_fd, syms);
626 /* Dump symbols for this hunk */
627 for (i = 0; i < syms ; i++) {
628 struct symbol s;
629 const char *name;
630 int lsize;
632 s = sym[i];
633 sym_fixup(&s);
635 if (SHINDEX(s.shindex) != shid)
636 continue;
638 name = (const char *)(hh[SHINDEX(symtab->link)]->data + s.name);
639 D(bug("\t0x%08x: %s\n", (int)s.value, name));
640 lsize = (strlen(name) + 4) / 4;
641 wlong(hunk_fd, lsize);
642 err = write(hunk_fd, name, lsize * 4);
643 if (err < 0)
644 return 0;
645 wlong(hunk_fd, s.value);
647 wlong(hunk_fd, 0);
649 return 1;
652 static void reloc_dump(int hunk_fd, struct hunkheader **hh, int h)
654 int i;
656 if (hh[h]->relocs == 0)
657 return;
659 /* Sort the relocations by reference hunk id */
660 qsort(hh[h]->reloc, hh[h]->relocs, sizeof(hh[h]->reloc[0]), reloc_cmp);
662 wlong(hunk_fd, HUNK_RELOC32);
663 D(bug("\tHUNK_RELOC32: %d relocations\n", (int)hh[h]->relocs));
665 for (i = 0; i < hh[h]->relocs; ) {
666 int count;
667 int shid = hh[h]->reloc[i].shid;
668 for (count = i; count < hh[h]->relocs; count++)
669 if (hh[h]->reloc[count].shid != shid)
670 break;
671 count -= i;
672 wlong(hunk_fd, count);
673 D(bug("\t %d relocations relative to Hunk %d\n", count, hh[shid]->hunk));
674 /* Convert from ELF hunk ID to AOS hunk ID */
675 wlong(hunk_fd, hh[shid]->hunk);
676 for (; count > 0; i++, count--) {
677 D(bug("\t\t%d: 0x%08x %s\n", i, (int)hh[h]->reloc[i].offset, hh[h]->reloc[i].symbol));
678 wlong(hunk_fd, hh[h]->reloc[i].offset);
681 wlong(hunk_fd, 0);
684 static int copy_to(int in, int out)
686 static char buff[64*1024];
687 int len, err = 0;
689 do {
690 len = read(in, buff, sizeof(buff));
691 if (len < 0) {
692 perror("Can't read from input file\n");
693 err = len;
695 if (len == 0)
696 break;
697 } while ((err = write(out, buff, len)) == len);
699 if (err < 0) {
700 perror("Can't write to output file\n");
701 return -errno;
704 return 0;
707 int elf2hunk(int file, int hunk_fd, const char *libname, int flags)
709 const __attribute__((unused)) char *names[3]={ "CODE", "DATA", "BSS" };
710 struct hunkheader **hh;
711 struct elfheader eh;
712 struct sheader *sh;
713 char *strtab;
714 int symtab_shndx = -1;
715 int err;
716 ULONG i;
717 BOOL exec_hunk_seen = FALSE;
718 ULONG int_shnum;
719 int hunks = 0;
721 /* load and validate ELF header */
722 D(bug("Load header\n"));
723 if ((flags & F_NOCONVERT) || !load_header(file, &eh)) {
724 /* If it's not an ELF, just copy it.
726 * This simplifies a number of mmakefiles
727 * for the m68k-amiga boot and ISO creation
729 lseek(file, 0, SEEK_SET);
730 return (copy_to(file, hunk_fd) == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
733 D(bug("Read SHNum\n"));
734 int_shnum = read_shnum(file, &eh);
735 if (!int_shnum)
736 return EXIT_FAILURE;
738 /* load section headers */
739 D(bug("Load %d Section Headers @0x%08x\n", int_shnum, (int)eh.shoff));
740 if (!(sh = load_block(file, eh.shoff, int_shnum * eh.shentsize)))
741 return EXIT_FAILURE;
743 sh_fixup(sh, int_shnum);
745 /* Looks like we have a valid executable. Generate a
746 * HUNK header set. Not all may be filled in.
748 hh = calloc(sizeof(*hh), int_shnum);
750 /* Look for the string table */
751 D(bug("Look for string table\n"));
752 for (i = 0; i < int_shnum; i++) {
753 if (sh[i].type == SHT_STRTAB) {
754 strtab = load_block(file, sh[i].offset, sh[i].size);
755 break;
759 /* Iterate over the section headers in order to do some stuff... */
760 D(bug("Look for symbol tables\n"));
761 for (i = 0; i < int_shnum; i++)
764 Load the symbol and string table(s).
766 NOTICE: the ELF standard, at the moment (Nov 2002) explicitely states
767 that only one symbol table per file is allowed. However, it
768 also states that this may change in future... we already handle it.
770 D(bug("sh[%d].type = 0x%08x, .offset = 0x%08x, .size = 0x%08x\n",
771 (int)i, (int)sh[i].type, (int)sh[i].offset, (int)sh[i].size));
772 if (sh[i].type == SHT_SYMTAB || sh[i].type == SHT_STRTAB || sh[i].type == SHT_SYMTAB_SHNDX)
774 hh[i] = calloc(sizeof(struct hunkheader), 1);
775 hh[i]->type = (sh[i].type == SHT_SYMTAB) ? HUNK_SYMBOL : 0;
776 hh[i]->memflags = 0;
777 hh[i]->hunk = -1;
778 hh[i]->data = load_block(file, sh[i].offset, sh[i].size);
779 if (!hh[i]->data)
780 goto error;
782 if (sh[i].type == SHT_SYMTAB_SHNDX) {
783 if (symtab_shndx == -1)
784 symtab_shndx = i;
785 else
786 D(bug("[ELF2HUNK] file contains multiple symtab shndx tables. only using the first one\n"));
789 else
790 /* Load the section in memory if needed, and make an hunk out of it */
791 if (sh[i].flags & SHF_ALLOC && sh[i].size > 0)
793 hh[i] = calloc(sizeof(struct hunkheader), 1);
794 hh[i]->size = sh[i].size;
795 hh[i]->hunk = hunks++;
797 if (sh[i].type == SHT_NOBITS) {
798 /* BSS area */
799 hh[i]->type = HUNK_BSS;
800 hh[i]->memflags = 0;
801 hh[i]->data = NULL;
802 } else {
803 if (sh[i].flags & SHF_EXECINSTR) {
804 hh[i]->type = HUNK_CODE;
805 exec_hunk_seen = TRUE;
806 } else {
807 hh[i]->type = HUNK_DATA;
809 hh[i]->data = load_block(file, sh[i].offset, sh[i].size);
812 if (strtab) {
813 const char *nameext;
815 D(bug("section %s\n", strtab + sh[i].name));
816 nameext = strrchr(strtab + sh[i].name, '.');
817 if (nameext) {
818 if (strcmp(nameext, ".MEMF_CHIP")==0) {
819 hh[i]->memflags |= MEMF_CHIP;
820 } else if (strcmp(nameext, ".MEMF_LOCAL")==0) {
821 hh[i]->memflags |= MEMF_LOCAL;
822 } else if (strcmp(nameext, ".MEMF_KICK")==0) {
823 hh[i]->memflags |= MEMF_KICK;
824 } else if (strcmp(nameext, ".MEMF_FAST")==0) {
825 hh[i]->memflags |= MEMF_FAST;
832 /* Relocate the sections */
833 D(bug("Convert relocation tables\n"));
834 for (i = 0; i < int_shnum; i++)
836 /* Does this relocation section refer to a hunk? If so, addr must be != 0 */
837 if ((sh[i].type == AROS_ELF_REL)
838 && hh[SHINDEX(sh[i].info)]
839 && hh[SHINDEX(sh[i].info)]->data)
841 void *reloc = load_block(file, sh[i].offset, sh[i].size);
843 if (!relocate(&eh, sh, i, symtab_shndx, reloc, hh))
844 return EXIT_FAILURE;
846 free(reloc);
850 D(bug("HUNK_HEADER: \"%s\", hunks=%d, first=%d, last=%d\n", libname, hunks, 0, hunks-1));
852 wlong(hunk_fd, HUNK_HEADER);
853 if (libname == NULL) {
854 wlong(hunk_fd, 0); /* No name */
855 } else {
856 int lsize = (strlen(libname) + 4) / 4;
857 wlong(hunk_fd, lsize);
858 err = write(hunk_fd, libname, lsize * 4);
859 if (err < 0)
860 return EXIT_FAILURE;
862 wlong(hunk_fd, hunks);
863 wlong(hunk_fd, 0); /* First hunk is #0 */
864 wlong(hunk_fd, hunks - 1); /* Last hunk is hunks-1 */
866 /* Write all allocatable hunk sizes */
867 for (i = 0; i < int_shnum; i++) {
868 ULONG count;
870 if (hh[i]==NULL || hh[i]->hunk < 0)
871 continue;
873 count = (hh[i]->size + 4) / 4;
874 switch (hh[i]->memflags) {
875 case MEMF_CHIP:
876 count |= HUNKF_CHIP;
877 break;
878 case MEMF_FAST:
879 count |= HUNKF_FAST;
880 break;
881 case 0:
882 break;
883 default:
884 count |= HUNKF_MEMFLAGS;
885 break;
888 D(bug("\tHunk #%d, %s, lsize=%d\n", hh[i]->hunk, names[hh[i]->type - HUNK_CODE], (int)(hh[i]->size+4)/4));
889 wlong(hunk_fd, count);
891 if ((count & HUNKF_MEMFLAGS) == HUNKF_MEMFLAGS)
892 wlong(hunk_fd, hh[i]->memflags | MEMF_PUBLIC | MEMF_CLEAR);
895 /* Write all hunks */
896 for (i = hunks = 0; i < int_shnum; i++) {
897 int s;
899 if (hh[i]==NULL || hh[i]->hunk < 0)
900 continue;
902 wlong(hunk_fd, hh[i]->type);
903 wlong(hunk_fd, (hh[i]->size + 4) / 4);
905 switch (hh[i]->type) {
906 case HUNK_BSS:
907 D(bug("HUNK_BSS: %d longs\n", (int)((hh[i]->size + 4) / 4)));
908 if (0) {
909 for (s = 0; s < int_shnum; s++) {
910 if (hh[s] && hh[s]->type == HUNK_SYMBOL)
911 sym_dump(hunk_fd, sh, hh, i, s);
914 wlong(hunk_fd, HUNK_END);
915 hunks++;
916 break;
917 case HUNK_CODE:
918 case HUNK_DATA:
919 D(bug("#%d HUNK_%s: %d longs\n", hh[i]->hunk, hh[i]->type == HUNK_CODE ? "CODE" : "DATA", (int)((hh[i]->size + 4) / 4)));
920 err = write(hunk_fd, hh[i]->data, ((hh[i]->size + 4)/4)*4);
921 if (err < 0)
922 return EXIT_FAILURE;
923 if (0) {
924 for (s = 0; s < int_shnum; s++) {
925 if (hh[s] && hh[s]->type == HUNK_SYMBOL)
926 sym_dump(hunk_fd, sh, hh, i, s);
929 reloc_dump(hunk_fd, hh, i);
930 wlong(hunk_fd, HUNK_END);
931 D(bug("\tHUNK_END\n"));
932 break;
933 default:
934 D(bug("Unsupported allocatable hunk type %d\n", (int)hh[i]->type));
935 return EXIT_FAILURE;
939 /* Free all blocks */
940 for (i = 0; i < int_shnum; i++) {
941 if (hh[i]) {
942 if (hh[i]->data)
943 free(hh[i]->data);
944 if (hh[i]->reloc)
945 free(hh[i]->reloc);
946 free(hh[i]);
949 free(hh);
950 free(sh);
952 if (strtab)
953 free(strtab);
955 D(bug("All good, all done.\n"));
956 return EXIT_SUCCESS;
958 error:
959 return EXIT_FAILURE;
962 static int copy(const char *src, const char *dst, int flags);
964 static int copy_dir(const char *src, const char *dst, int flags)
966 DIR *sdir;
967 struct dirent *de;
968 char spath[PATH_MAX], dpath[PATH_MAX];
969 char *sp, *dp;
970 int sleft, dleft;
971 int err = EXIT_SUCCESS;
973 sdir = opendir(src);
974 if (sdir == NULL) {
975 perror(src);
976 return EXIT_FAILURE;
979 snprintf(spath, sizeof(spath), "%s/", src);
980 spath[sizeof(spath)-1] = 0;
981 sp = &spath[strlen(spath)];
982 sleft = &spath[sizeof(spath)-1] - sp;
984 snprintf(dpath, sizeof(dpath), "%s/", dst);
985 dpath[sizeof(dpath)-1] = 0;
986 dp = &dpath[strlen(dpath)];
987 dleft = &dpath[sizeof(dpath)-1] - dp;
989 while ((de = readdir(sdir)) != NULL) {
990 int eflags = 0;
992 if ((strcmp(de->d_name, ".") == 0) ||
993 (strcmp(de->d_name, "..") == 0))
994 continue;
996 /* Don't convert anything in a Development directory */
997 if (strcasecmp(de->d_name, "Development") == 0)
998 eflags |= F_NOCONVERT;
1000 strncpy(sp, de->d_name, sleft);
1001 sp[sleft-1] = 0;
1002 strncpy(dp, de->d_name, dleft);
1003 dp[dleft-1] = 0;
1004 err = copy(spath, dpath, flags | eflags);
1005 if (err != EXIT_SUCCESS)
1006 break;
1009 closedir(sdir);
1011 return err;
1014 static int copy(const char *src, const char *dst, int flags)
1016 int src_fd, hunk_fd;
1017 struct stat st;
1018 int mode, ret;
1020 if (flags & F_VERBOSE)
1021 printf("%s ->\n %s\n", src, dst);
1023 if (stat(src, &st) >= 0) {
1024 mode = st.st_mode;
1025 } else {
1026 mode = 0755;
1029 if (S_ISDIR(mode)) {
1030 unlink(dst);
1031 mkdir(dst, mode);
1032 return copy_dir(src, dst, flags);
1035 src_fd = open(src, O_RDONLY);
1036 if (src_fd < 0) {
1037 perror(src);
1038 return EXIT_FAILURE;
1041 if (strcmp(dst,"-") == 0)
1042 hunk_fd = 1; /* stdout */
1043 else {
1044 unlink(dst);
1045 hunk_fd = open(dst, O_RDWR | O_CREAT | O_TRUNC, mode);
1047 if (hunk_fd < 0) {
1048 perror(dst);
1049 return EXIT_FAILURE;
1052 ret = elf2hunk(src_fd, hunk_fd, NULL, flags);
1053 if (ret != 0)
1054 perror(src);
1056 close(src_fd);
1057 if (hunk_fd != 1)
1058 close(hunk_fd);
1060 return ret;
1063 int main(int argc, char **argv)
1065 int flags = 0;
1067 if (argc == 4 && strcmp(argv[1],"-v") == 0) {
1068 flags |= F_VERBOSE;
1069 argc--;
1070 argv++;
1073 if (argc != 3) {
1074 fprintf(stderr, "Usage:\n%s file.elf file.hunk\n", argv[0]);
1075 fprintf(stderr, "%s src-dir dest-dir\n", argv[0]);
1076 return EXIT_FAILURE;
1079 return copy(argv[1], argv[2], flags);