2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
21 #include <sys/types.h>
24 #define F_VERBOSE (1 << 0)
25 #define F_NOCONVERT (1 << 1)
27 #if defined(__GNUC__)&&defined(WIN32)
29 #define mkdir(path, mode) mkdir(path)
31 #include <arpa/inet.h>
32 typedef uint32_t ULONG
;
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)
46 /* Memory allocation flags */
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
73 #define HUNK_RELOC32 1004
74 #define HUNK_SYMBOL 1008
76 #define HUNK_HEADER 1011
78 #define SHT_PROGBITS 1
84 #define SHT_SYMTAB_SHNDX 18
93 #define EM_X86_64 62 /* AMD x86-64 */
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
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
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
133 #define STT_SECTION 3
135 #define STT_LOPROC 13
136 #define STT_HIPROC 15
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)
155 #define ELFDATA2LSB 1
156 #define ELFDATA2MSB 2
160 #define ELFCLASS64 2 /* 64-bit objects */
163 #define EI_ABIVERSION 8
165 #define ELFOSABI_AROS 15
167 #define PF_X (1 << 0)
185 } __attribute__((packed
));
199 } __attribute__((packed
));
213 } __attribute__((packed
));
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))
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 /* Note: the conversion below is not in line with ELF specification and is fixed in GNU binutils since 2008
237 * See: https://sourceware.org/bugzilla/show_bug.cgi?id=5900
239 /* convert section header number to array index */
240 /*#define SHINDEX(n) \
241 ((n) < SHN_LORESERVE ? (n) : ((n) <= SHN_HIRESERVE ? 0 : (n) - (SHN_HIRESERVE + 1 - SHN_LORESERVE)))*/
243 /* convert section header array index to section number */
245 ((i) < SHN_LORESERVE ? (i) : (i) + (SHN_HIRESERVE + 1 - SHN_LORESERVE))*/
247 /* m68k Machine's native values */
248 #define AROS_ELF_CLASS ELFCLASS32
249 #define AROS_ELF_DATA ELFDATA2MSB
250 #define AROS_ELF_MACHINE EM_68K
251 #define AROS_ELF_REL SHT_RELA
254 #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
256 # define VA_START(args, lastarg) va_start(args, lastarg)
258 # include <varargs.h>
259 # define VA_START(args, lastarg) va_start(args)
265 # define PARAMS(x) ()
266 #endif /* PROTOTYPES */
268 static void set_error(int err
)
273 #if defined(DEBUG) && DEBUG
280 #define bug(fmt,args...) fprintf(stderr, fmt ,##args )
282 static int must_swap
= -1;
284 static void eh_fixup(struct elfheader
*eh
)
287 if (eh
->type
== 256) {
289 eh
->type
= ntohs(eh
->type
);
290 eh
->machine
= ntohs(eh
->machine
);
291 eh
->version
= ntohl(eh
->version
);
292 eh
->entry
= ntohl(eh
->entry
);
293 eh
->phoff
= ntohl(eh
->phoff
);
294 eh
->shoff
= ntohl(eh
->shoff
);
295 eh
->flags
= ntohl(eh
->flags
);
296 eh
->ehsize
= ntohs(eh
->ehsize
);
297 eh
->phentsize
= ntohs(eh
->phentsize
);
298 eh
->phnum
= ntohs(eh
->phnum
);
299 eh
->shentsize
= ntohs(eh
->shentsize
);
300 eh
->shnum
= ntohs(eh
->shnum
);
301 eh
->shstrndx
= ntohs(eh
->shstrndx
);
307 static void sh_fixup(struct sheader
*sh
, int n
)
312 for (; n
> 0; n
--, sh
++) {
313 sh
->name
= ntohl(sh
->name
);
314 sh
->type
= ntohl(sh
->type
);
315 sh
->flags
= ntohl(sh
->flags
);
316 sh
->addr
= ntohl(sh
->addr
);
317 sh
->offset
= ntohl(sh
->offset
);
318 sh
->size
= ntohl(sh
->size
);
319 sh
->link
= ntohl(sh
->link
);
320 sh
->info
= ntohl(sh
->info
);
321 sh
->addralign
= ntohl(sh
->addralign
);
322 sh
->entsize
= ntohl(sh
->entsize
);
326 static void rel_fixup(struct relo
*rel
)
331 rel
->offset
= ntohl(rel
->offset
);
332 rel
->info
= ntohl(rel
->info
);
333 rel
->addend
= ntohl(rel
->addend
);
336 void sym_fixup(struct symbol
*sym
)
341 sym
->name
= ntohl(sym
->name
);
342 sym
->value
= ntohl(sym
->value
);
343 sym
->size
= ntohl(sym
->size
);
344 sym
->shindex
= ntohs(sym
->shindex
);
347 static void *load_block (int file
,ULONG offset
,ULONG size
)
349 ULONG lsize
= (size
+ sizeof(ULONG
) - 1) / sizeof(ULONG
);
350 D(bug("[ELF2HUNK] Load Block\n"));
351 D(bug("[ELF2HUNK] (size=%d)\n",(int)size
));
352 void *block
= malloc(lsize
* sizeof(ULONG
));
354 lseek(file
, offset
, SEEK_SET
);
355 if (read(file
, block
, size
) == size
) {
367 static ULONG
read_shnum(int file
, struct elfheader
*eh
)
369 ULONG shnum
= eh
->shnum
;
371 /* the ELF header only uses 16 bits to store the count of section headers,
372 * so it can't handle more than 65535 headers. if the count is 0, and an
373 * offset is defined, then the real count can be found in the first
374 * section header (which always exists).
376 * similarly, if the string table index is SHN_XINDEX, then the actual
377 * index is found in the first section header also.
379 * see the System V ABI 2001-04-24 draft for more details.
385 if (eh
->shoff
== 0) {
390 lseek(file
, eh
->shoff
, SEEK_SET
);
391 if (read(file
, &sh
, sizeof(sh
)) != sizeof(sh
))
396 /* wider section header count is in the size field */
399 /* sanity, if they're still invalid then this isn't elf */
407 static int load_header(int file
, struct elfheader
*eh
)
409 lseek(file
, 0, SEEK_SET
);
410 if (read(file
, eh
, sizeof(struct elfheader
)) != sizeof(struct elfheader
)) {
411 D(bug("[ELF2HUNK] Can't read the %d byte ELF header\n", (int)sizeof(struct elfheader
)));
417 if (eh
->ident
[0] != 0x7f || eh
->ident
[1] != 'E' ||
418 eh
->ident
[2] != 'L' || eh
->ident
[3] != 'F') {
419 D(bug("[ELF2HUNK] Not an ELF object\n"));
422 D(bug("[ELF2HUNK] ELF object\n"));
424 /* WANT_CLASS should be defined for your target */
425 if (eh
->ident
[EI_CLASS
] != AROS_ELF_CLASS
||
426 eh
->ident
[EI_VERSION
] != EV_CURRENT
||
427 eh
->type
!= ET_REL
||
428 eh
->ident
[EI_DATA
] != AROS_ELF_DATA
||
429 eh
->machine
!= AROS_ELF_MACHINE
)
431 D(bug("[ELF2HUNK] Object is of wrong type\n"));
432 D(bug("[ELF2HUNK] EI_CLASS is %d - should be %d\n", eh
->ident
[EI_CLASS
] , AROS_ELF_CLASS
));
433 D(bug("[ELF2HUNK] EI_VERSION is %d - should be %d\n", eh
->ident
[EI_VERSION
], EV_CURRENT
));
434 D(bug("[ELF2HUNK] type is %d - should be %d\n", eh
->type
, ET_REL
));
435 D(bug("[ELF2HUNK] EI_DATA is %d - should be %d\n", eh
->ident
[EI_DATA
] , AROS_ELF_DATA
));
436 D(bug("[ELF2HUNK] machine is %d - should be %d\n", eh
->machine
, AROS_ELF_MACHINE
));
447 ULONG memflags
; /* Memory flags */
448 ULONG size
; /* Size in ULONGs */
451 int hunk
; /* Allocatable hunk ID */
453 ULONG shid
; /* ELF hunk base to add to... */
454 ULONG offset
; /* offset in this hunk. */
461 struct elfheader
*eh
,
466 struct hunkheader
**hh
469 struct sheader
*shrel
= &sh
[shrel_idx
];
470 struct sheader
*shsymtab
= &sh
[shrel
->link
];
471 struct sheader
*toreloc
= &sh
[shrel
->info
];
473 struct symbol
*symtab
= (struct symbol
*)hh
[shrel
->link
]->data
;
474 struct hunkheader
*h
= hh
[shrel
->info
];
477 * Ignore relocs if the target section has no allocation. that can happen
478 * eg. with a .debug PROGBITS and a .rel.debug section
480 D(bug("[ELF2HUNK] sh[%d].flags = 0x%x\n", (int)(shrel
->info
), (int)toreloc
->flags
));
481 if (!(toreloc
->flags
& SHF_ALLOC
))
484 ULONG numrel
= shrel
->size
/ shrel
->entsize
;
490 h
->reloc
= realloc(h
->reloc
, h
->relocs
* sizeof(struct hunkreloc
));
491 struct hunkreloc
*hrel
= &h
->reloc
[hrels
];
493 for (i
=0; i
<numrel
; i
++, rel
++)
506 * R_ARM_V4BX are actually special marks for the linker.
507 * They even never have a target (shindex == SHN_UNDEF),
508 * so we simply ignore them before doing any checks.
510 if (ELF_R_TYPE(rel
->info
) == R_ARM_V4BX
)
514 sym
= symtab
[ELF_R_SYM(rel
->info
)];
516 offset
= rel
->offset
;
517 symname
= (const char *)(hh
[shsymtab
->link
]->data
+ sym
.name
);
519 if (sym
.shindex
!= SHN_XINDEX
)
520 shindex
= sym
.shindex
;
523 if (symtab_shndx
< 0) {
524 bug("[ELF2HUNK] got symbol with shndx 0xfff, but there's no symtab shndx table\n");
528 shindex
= ntohl(((ULONG
*)hh
[symtab_shndx
]->data
)[ELF_R_SYM(rel
->info
)]);
531 D(bug("[ELF2HUNK] Processing %d symbol %s\n", (int)shindex
, symname
));
537 if (ELF_R_TYPE(rel
->info
) != 0) {
538 bug("[ELF2HUNK] SHN_UNDEF symbol '%s', type %d unsupported\n", symname
, (int)ELF_R_TYPE(rel
->info
));
545 bug("[ELF2HUNK] SHN_COMMON symbol '%s' unsupported\n", symname
);
551 shid
= ~0; value
= sym
.value
;
560 switch (ELF_R_TYPE(rel
->info
))
563 value
+= rel
->addend
;
567 value
+= rel
->addend
- offset
;
571 bug("[ELF2HUNK] Unsupported relocation type R_68K_PC16,\n");
572 bug("[ELF2HUNK] for symbol '%s'\n", symname
);
582 bug("[ELF2HUNK] Unrecognized relocation type %d %d,\n", (int)i
, (int)ELF_R_TYPE(rel
->info
));
583 bug("[ELF2HUNK] for symbol '%s'\n", symname
);
588 D(bug("[ELF2HUNK] shid %d, offset 0x%x: base 0x%x\n", (int)shid
, (int)offset
, (int)value
));
589 *(ULONG
*)(h
->data
+ offset
) = htonl(value
+ ntohl(*(ULONG
*)(h
->data
+ offset
)));
595 hrel
->offset
= offset
;
596 hrel
->symbol
= symname
;
603 int reloc_cmp(const void *a
, const void *b
)
605 const struct hunkreloc
*ha
= a
, *hb
= b
;
607 if (ha
->shid
!= hb
->shid
)
608 return hb
->shid
- ha
->shid
;
609 return hb
->offset
- ha
->offset
;
612 static int wlong(int fd
, ULONG val
)
615 return write(fd
, &val
, sizeof(val
));
618 int sym_dump(int hunk_fd
, struct sheader
*sh
, struct hunkheader
**hh
, int shid
, int symtabndx
)
621 struct symbol
*sym
= hh
[symtabndx
]->data
;
622 struct sheader
*symtab
= &sh
[symtabndx
];
624 syms
= symtab
->size
/ sizeof(struct symbol
);
629 wlong(hunk_fd
, HUNK_SYMBOL
);
630 wlong(hunk_fd
, syms
);
632 /* Dump symbols for this hunk */
633 for (i
= 0; i
< syms
; i
++) {
641 if (s
.shindex
!= shid
)
644 name
= (const char *)(hh
[symtab
->link
]->data
+ s
.name
);
645 D(bug("\t0x%08x: %s\n", (int)s
.value
, name
));
646 lsize
= (strlen(name
) + 4) / 4;
647 wlong(hunk_fd
, lsize
);
648 err
= write(hunk_fd
, name
, lsize
* 4);
651 wlong(hunk_fd
, s
.value
);
658 static void reloc_dump(int hunk_fd
, struct hunkheader
**hh
, int h
)
662 if (hh
[h
]->relocs
== 0)
665 /* Sort the relocations by reference hunk id */
666 qsort(hh
[h
]->reloc
, hh
[h
]->relocs
, sizeof(hh
[h
]->reloc
[0]), reloc_cmp
);
668 wlong(hunk_fd
, HUNK_RELOC32
);
669 D(bug("\tHUNK_RELOC32: %d relocations\n", (int)hh
[h
]->relocs
));
671 for (i
= 0; i
< hh
[h
]->relocs
; ) {
673 int shid
= hh
[h
]->reloc
[i
].shid
;
674 for (count
= i
; count
< hh
[h
]->relocs
; count
++)
675 if (hh
[h
]->reloc
[count
].shid
!= shid
)
678 wlong(hunk_fd
, count
);
679 D(bug("\t %d relocations relative to Hunk %d\n", count
, hh
[shid
]->hunk
));
680 /* Convert from ELF hunk ID to AOS hunk ID */
681 wlong(hunk_fd
, hh
[shid
]->hunk
);
682 for (; count
> 0; i
++, count
--) {
683 D(bug("\t\t%d: 0x%08x %s\n", i
, (int)hh
[h
]->reloc
[i
].offset
, hh
[h
]->reloc
[i
].symbol
));
684 wlong(hunk_fd
, hh
[h
]->reloc
[i
].offset
);
690 static int copy_to(int in
, int out
)
692 static char buff
[64*1024];
696 len
= read(in
, buff
, sizeof(buff
));
698 perror("Can't read from input file\n");
703 } while ((err
= write(out
, buff
, len
)) == len
);
706 perror("Can't write to output file\n");
713 int elf2hunk(int file
, int hunk_fd
, const char *libname
, int flags
)
715 const __attribute__((unused
)) char *names
[3]={ "CODE", "DATA", "BSS" };
716 struct hunkheader
**hh
;
720 int symtab_shndx
= -1;
723 BOOL exec_hunk_seen
__attribute__ ((unused
)) = FALSE
;
727 /* load and validate ELF header */
728 D(bug("Load header\n"));
729 if ((flags
& F_NOCONVERT
) || !load_header(file
, &eh
)) {
730 /* If it's not an ELF, just copy it.
732 * This simplifies a number of mmakefiles
733 * for the m68k-amiga boot and ISO creation
735 lseek(file
, 0, SEEK_SET
);
736 return (copy_to(file
, hunk_fd
) == 0) ? EXIT_SUCCESS
: EXIT_FAILURE
;
739 D(bug("Read SHNum\n"));
740 int_shnum
= read_shnum(file
, &eh
);
744 /* load section headers */
745 D(bug("Load %d Section Headers @0x%08x\n", int_shnum
, (int)eh
.shoff
));
746 if (!(sh
= load_block(file
, eh
.shoff
, int_shnum
* eh
.shentsize
)))
749 sh_fixup(sh
, int_shnum
);
751 /* Looks like we have a valid executable. Generate a
752 * HUNK header set. Not all may be filled in.
754 hh
= calloc(sizeof(*hh
), int_shnum
);
756 /* Look for the string table */
757 D(bug("Look for string table\n"));
758 for (i
= 0; i
< int_shnum
; i
++) {
759 if (sh
[i
].type
== SHT_STRTAB
&& i
== eh
.shstrndx
) {
760 strtab
= load_block(file
, sh
[i
].offset
, sh
[i
].size
);
765 /* Iterate over the section headers in order to do some stuff... */
766 D(bug("Look for symbol tables\n"));
767 for (i
= 0; i
< int_shnum
; i
++)
770 Load the symbol and string table(s).
772 NOTICE: the ELF standard, at the moment (Nov 2002) explicitely states
773 that only one symbol table per file is allowed. However, it
774 also states that this may change in future... we already handle it.
776 D(bug("sh[%d].type = 0x%08x, .offset = 0x%08x, .size = 0x%08x\n",
777 (int)i
, (int)sh
[i
].type
, (int)sh
[i
].offset
, (int)sh
[i
].size
));
778 if (sh
[i
].type
== SHT_SYMTAB
|| sh
[i
].type
== SHT_STRTAB
|| sh
[i
].type
== SHT_SYMTAB_SHNDX
)
780 hh
[i
] = calloc(sizeof(struct hunkheader
), 1);
781 hh
[i
]->type
= (sh
[i
].type
== SHT_SYMTAB
) ? HUNK_SYMBOL
: 0;
784 hh
[i
]->data
= load_block(file
, sh
[i
].offset
, sh
[i
].size
);
788 if (sh
[i
].type
== SHT_SYMTAB_SHNDX
) {
789 if (symtab_shndx
== -1)
792 D(bug("[ELF2HUNK] file contains multiple symtab shndx tables. only using the first one\n"));
796 /* Load the section in memory if needed, and make an hunk out of it */
797 if (sh
[i
].flags
& SHF_ALLOC
&& sh
[i
].size
> 0)
799 hh
[i
] = calloc(sizeof(struct hunkheader
), 1);
800 hh
[i
]->size
= sh
[i
].size
;
801 hh
[i
]->hunk
= hunks
++;
803 if (sh
[i
].type
== SHT_NOBITS
) {
805 hh
[i
]->type
= HUNK_BSS
;
809 if (sh
[i
].flags
& SHF_EXECINSTR
) {
810 hh
[i
]->type
= HUNK_CODE
;
811 exec_hunk_seen
= TRUE
;
813 hh
[i
]->type
= HUNK_DATA
;
815 hh
[i
]->data
= load_block(file
, sh
[i
].offset
, sh
[i
].size
);
821 D(bug("section %s\n", strtab
+ sh
[i
].name
));
822 nameext
= strrchr(strtab
+ sh
[i
].name
, '.');
824 if (strcmp(nameext
, ".MEMF_CHIP")==0) {
825 hh
[i
]->memflags
|= MEMF_CHIP
;
826 } else if (strcmp(nameext
, ".MEMF_LOCAL")==0) {
827 hh
[i
]->memflags
|= MEMF_LOCAL
;
828 } else if (strcmp(nameext
, ".MEMF_KICK")==0) {
829 hh
[i
]->memflags
|= MEMF_KICK
;
830 } else if (strcmp(nameext
, ".MEMF_FAST")==0) {
831 hh
[i
]->memflags
|= MEMF_FAST
;
838 /* Relocate the sections */
839 D(bug("Convert relocation tables\n"));
840 for (i
= 0; i
< int_shnum
; i
++)
842 /* Does this relocation section refer to a hunk? If so, addr must be != 0 */
843 if ((sh
[i
].type
== AROS_ELF_REL
)
845 && hh
[sh
[i
].info
]->data
)
847 void *reloc
= load_block(file
, sh
[i
].offset
, sh
[i
].size
);
849 if (!relocate(&eh
, sh
, i
, symtab_shndx
, reloc
, hh
))
856 D(bug("HUNK_HEADER: \"%s\", hunks=%d, first=%d, last=%d\n", libname
, hunks
, 0, hunks
-1));
858 wlong(hunk_fd
, HUNK_HEADER
);
859 if (libname
== NULL
) {
860 wlong(hunk_fd
, 0); /* No name */
862 int lsize
= (strlen(libname
) + 4) / 4;
863 wlong(hunk_fd
, lsize
);
864 err
= write(hunk_fd
, libname
, lsize
* 4);
868 wlong(hunk_fd
, hunks
);
869 wlong(hunk_fd
, 0); /* First hunk is #0 */
870 wlong(hunk_fd
, hunks
- 1); /* Last hunk is hunks-1 */
872 /* Write all allocatable hunk sizes */
873 for (i
= 0; i
< int_shnum
; i
++) {
876 if (hh
[i
]==NULL
|| hh
[i
]->hunk
< 0)
879 count
= (hh
[i
]->size
+ 4) / 4;
880 switch (hh
[i
]->memflags
) {
890 count
|= HUNKF_MEMFLAGS
;
894 D(bug("\tHunk #%d, %s, lsize=%d\n", hh
[i
]->hunk
, names
[hh
[i
]->type
- HUNK_CODE
], (int)(hh
[i
]->size
+4)/4));
895 wlong(hunk_fd
, count
);
897 if ((count
& HUNKF_MEMFLAGS
) == HUNKF_MEMFLAGS
)
898 wlong(hunk_fd
, hh
[i
]->memflags
| MEMF_PUBLIC
| MEMF_CLEAR
);
901 /* Write all hunks */
902 for (i
= hunks
= 0; i
< int_shnum
; i
++) {
905 if (hh
[i
]==NULL
|| hh
[i
]->hunk
< 0)
908 wlong(hunk_fd
, hh
[i
]->type
);
909 wlong(hunk_fd
, (hh
[i
]->size
+ 4) / 4);
911 switch (hh
[i
]->type
) {
914 bug("HUNK_BSS: %d longs\n", (int)((hh
[i
]->size
+ 4) / 4));
915 for (s
= 0; s
< int_shnum
; s
++) {
916 if (hh
[s
] && hh
[s
]->type
== HUNK_SYMBOL
)
917 sym_dump(hunk_fd
, sh
, hh
, i
, s
);
921 wlong(hunk_fd
, HUNK_END
);
926 D(bug("#%d HUNK_%s: %d longs\n", hh
[i
]->hunk
, hh
[i
]->type
== HUNK_CODE
? "CODE" : "DATA", (int)((hh
[i
]->size
+ 4) / 4)));
927 err
= write(hunk_fd
, hh
[i
]->data
, ((hh
[i
]->size
+ 4)/4)*4);
931 for (s
= 0; s
< int_shnum
; s
++) {
932 if (hh
[s
] && hh
[s
]->type
== HUNK_SYMBOL
)
933 sym_dump(hunk_fd
, sh
, hh
, i
, s
);
936 reloc_dump(hunk_fd
, hh
, i
);
937 wlong(hunk_fd
, HUNK_END
);
938 D(bug("\tHUNK_END\n"));
941 D(bug("Unsupported allocatable hunk type %d\n", (int)hh
[i
]->type
));
946 /* Free all blocks */
947 for (i
= 0; i
< int_shnum
; i
++) {
962 D(bug("All good, all done.\n"));
969 static int copy(const char *src
, const char *dst
, int flags
);
971 static BOOL
valid_dir(const char *dir
)
973 /* Don't convert anything in a Developer directory */
974 if (strcasecmp(dir
, "Developer") == 0)
979 static int copy_dir(const char *src
, const char *dst
, int flags
)
983 char spath
[PATH_MAX
], dpath
[PATH_MAX
];
986 int err
= EXIT_SUCCESS
;
994 snprintf(spath
, sizeof(spath
), "%s/", src
);
995 spath
[sizeof(spath
)-1] = 0;
996 sp
= &spath
[strlen(spath
)];
997 sleft
= &spath
[sizeof(spath
)-1] - sp
;
999 snprintf(dpath
, sizeof(dpath
), "%s/", dst
);
1000 dpath
[sizeof(dpath
)-1] = 0;
1001 dp
= &dpath
[strlen(dpath
)];
1002 dleft
= &dpath
[sizeof(dpath
)-1] - dp
;
1004 while ((de
= readdir(sdir
)) != NULL
) {
1007 if ((strcmp(de
->d_name
, ".") == 0) ||
1008 (strcmp(de
->d_name
, "..") == 0))
1011 /* Don't convert anything if its an invalid directory */
1012 if (!valid_dir(de
->d_name
))
1013 eflags
|= F_NOCONVERT
;
1015 strncpy(sp
, de
->d_name
, sleft
);
1017 strncpy(dp
, de
->d_name
, dleft
);
1019 err
= copy(spath
, dpath
, flags
| eflags
);
1020 if (err
!= EXIT_SUCCESS
)
1029 static int copy(const char *src
, const char *dst
, int flags
)
1031 int src_fd
, hunk_fd
;
1035 if (flags
& F_VERBOSE
)
1036 printf("%s ->\n %s\n", src
, dst
);
1038 if (stat(src
, &st
) >= 0) {
1044 if (S_ISDIR(mode
)) {
1047 return copy_dir(src
, dst
, flags
);
1050 src_fd
= open(src
, O_RDONLY
);
1053 return EXIT_FAILURE
;
1056 if (strcmp(dst
,"-") == 0)
1057 hunk_fd
= 1; /* stdout */
1060 hunk_fd
= open(dst
, O_RDWR
| O_CREAT
| O_TRUNC
, mode
);
1064 return EXIT_FAILURE
;
1067 ret
= elf2hunk(src_fd
, hunk_fd
, NULL
, flags
);
1078 int main(int argc
, char **argv
)
1082 if (argc
== 4 && strcmp(argv
[1],"-v") == 0) {
1089 fprintf(stderr
, "Usage:\n%s file.elf file.hunk\n", argv
[0]);
1090 fprintf(stderr
, "%s src-dir dest-dir\n", argv
[0]);
1091 return EXIT_FAILURE
;
1094 return copy(argv
[1], argv
[2], flags
);