1
0
mirror of https://github.com/cahirwpz/amigaos-cross-toolchain synced 2025-11-22 19:53:11 +00:00

add support for SHN_COMMON (#50)

This commit is contained in:
bebbodl
2016-10-09 16:31:14 +02:00
committed by Krystian Bacławski
parent ca8a4a74d5
commit d8d27e078a

View File

@ -1,5 +1,5 @@
/* /*
Copyright © 1995-2001, The AROS Development Team. All rights reserved. Copyright <EFBFBD> 1995-2001, The AROS Development Team. All rights reserved.
*/ */
#define PROTOTYPES #define PROTOTYPES
@ -12,10 +12,8 @@
#include <assert.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <limits.h> #include <limits.h>
#include <dirent.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -23,10 +21,42 @@
#define F_VERBOSE (1 << 0) #define F_VERBOSE (1 << 0)
#define F_NOCONVERT (1 << 1) #define F_NOCONVERT (1 << 1)
#if defined(__GNUC__)&&defined(WIN32) #if defined(_MSC_VER)
#include <io.h>
#include <direct.h>
#define ATTRIBUTE_PACKED
#define ATTRIBUTE_UNUSED
#define lseek _lseek
#define read _read
#define write _write
#define open _open
#define unlink _unlink
#define close _close
#define mkdir(a,b) _mkdir(a)
#include "msdirent.h"
#include <winsock2.h>
#define S_ISDIR(a) (a == 16895)
#define strcasecmp strcmp
#else
#include <unistd.h>
#include <dirent.h>
#define ATTRIBUTE_PACKED __attribute__((packed))
#define ATTRIBUTE_UNUSED __attribute__((unused))
#endif
#if !defined(O_BINARY)
#define O_BINARY 0
#endif
#if (defined(__GNUC__))&&defined(WIN32)
#include <winsock2.h> #include <winsock2.h>
#define mkdir(path, mode) mkdir(path) #define mkdir(path, mode) mkdir(path)
#else #elif !defined(_MSC_VER)
#include <arpa/inet.h> #include <arpa/inet.h>
typedef uint32_t ULONG; typedef uint32_t ULONG;
typedef int BOOL; typedef int BOOL;
@ -181,7 +211,7 @@ struct elfheader
UWORD shentsize; UWORD shentsize;
UWORD shnum; UWORD shnum;
UWORD shstrndx; UWORD shstrndx;
} __attribute__((packed)); } ATTRIBUTE_PACKED;
struct sheader struct sheader
{ {
@ -195,7 +225,7 @@ struct sheader
ULONG info; ULONG info;
IPTR addralign; IPTR addralign;
IPTR entsize; IPTR entsize;
} __attribute__((packed)); } ATTRIBUTE_PACKED;
#define PT_LOAD 1 #define PT_LOAD 1
@ -209,7 +239,7 @@ struct pheader
ULONG memsz; ULONG memsz;
ULONG flags; ULONG flags;
ULONG align; ULONG align;
} __attribute__((packed)); } ATTRIBUTE_PACKED;
struct symbol struct symbol
{ {
@ -219,7 +249,7 @@ struct symbol
UBYTE info; /* What kind of symbol is this ? (global, variable, etc) */ UBYTE info; /* What kind of symbol is this ? (global, variable, etc) */
UBYTE other; /* undefined */ UBYTE other; /* undefined */
UWORD shindex; /* In which section is the symbol defined ? */ UWORD shindex; /* In which section is the symbol defined ? */
} __attribute__((packed)); } ATTRIBUTE_PACKED;
#define ELF_R_SYM(val) ((val) >> 8) #define ELF_R_SYM(val) ((val) >> 8)
#define ELF_R_TYPE(val) ((val) & 0xff) #define ELF_R_TYPE(val) ((val) & 0xff)
@ -276,10 +306,20 @@ static void set_error(int err)
#define D(x) #define D(x)
#define DB2(x) #define DB2(x)
#endif #endif
#if defined(_MSC_VER)
#define bug(fmt,...) fprintf(stderr, fmt , __VA_ARGS__ )
#else
#define bug(fmt,args...) fprintf(stderr, fmt ,##args ) #define bug(fmt,args...) fprintf(stderr, fmt ,##args )
#endif
static int must_swap = -1; static int must_swap = -1;
// hack for SHN_COMMON
static struct hunkheader *theBSS;
static int bssIndex;
static void eh_fixup(struct elfheader *eh) static void eh_fixup(struct elfheader *eh)
{ {
/* Endian swaps */ /* Endian swaps */
@ -348,8 +388,9 @@ static void *load_block (int file,ULONG offset,ULONG size)
ULONG lsize = (size + sizeof(ULONG) - 1) / sizeof(ULONG); ULONG lsize = (size + sizeof(ULONG) - 1) / sizeof(ULONG);
D(bug("[ELF2HUNK] Load Block\n")); D(bug("[ELF2HUNK] Load Block\n"));
D(bug("[ELF2HUNK] (size=%d)\n",(int)size)); D(bug("[ELF2HUNK] (size=%d)\n",(int)size));
void *block = malloc(lsize * sizeof(ULONG)); ULONG *block = (ULONG *)malloc(lsize * sizeof(ULONG));
if (block) { if (block) {
block[lsize - 1] = 0;
lseek(file, offset, SEEK_SET); lseek(file, offset, SEEK_SET);
if (read(file, block, size) == size) { if (read(file, block, size) == size) {
return block; return block;
@ -441,18 +482,20 @@ static int load_header(int file, struct elfheader *eh)
return 1; return 1;
} }
struct hunkheader {
ULONG type;
ULONG memflags; /* Memory flags */
ULONG size; /* Size in ULONGs */
void *data;
ULONG relocs;
int hunk; /* Allocatable hunk ID */
struct hunkreloc { struct hunkreloc {
ULONG shid; /* ELF hunk base to add to... */ ULONG shid; /* ELF hunk base to add to... */
ULONG offset; /* offset in this hunk. */ ULONG offset; /* offset in this hunk. */
const char *symbol; const char *symbol;
} *reloc; };
struct hunkheader {
ULONG type;
ULONG memflags; /* Memory flags */
ULONG size; /* Size in ULONGs */
char *data;
ULONG relocs;
int hunk; /* Allocatable hunk ID */
struct hunkreloc *reloc;
}; };
static int relocate static int relocate
@ -486,7 +529,7 @@ static int relocate
hrels = h->relocs; hrels = h->relocs;
h->relocs += numrel; h->relocs += numrel;
h->reloc = realloc(h->reloc, h->relocs * sizeof(struct hunkreloc)); h->reloc = (struct hunkreloc *)realloc(h->reloc, h->relocs * sizeof(struct hunkreloc));
struct hunkreloc *hrel = &h->reloc[hrels]; struct hunkreloc *hrel = &h->reloc[hrels];
for (i=0; i<numrel; i++, rel++) for (i=0; i<numrel; i++, rel++)
@ -510,7 +553,8 @@ static int relocate
continue; continue;
#endif #endif
sym = symtab[ELF_R_SYM(rel->info)]; struct symbol * symptr = &symtab[ELF_R_SYM(rel->info)];
sym = *symptr;
sym_fixup(&sym); sym_fixup(&sym);
offset = rel->offset; offset = rel->offset;
symname = (const char *)(hh[shsymtab->link]->data + sym.name); symname = (const char *)(hh[shsymtab->link]->data + sym.name);
@ -541,11 +585,13 @@ static int relocate
break; break;
case SHN_COMMON: case SHN_COMMON:
bug("[ELF2HUNK] SHN_COMMON symbol '%s' unsupported\n", symname); hunk = bssIndex;
set_error(EINVAL); value = theBSS->size;
theBSS->size += (sym.size + 3) & ~3;
return 0;
symptr->shindex = htons(bssIndex);
symptr->value = htonl(value);
break;
case SHN_ABS: case SHN_ABS:
hunk = ~0; value = sym.value; hunk = ~0; value = sym.value;
break; break;
@ -598,7 +644,7 @@ static int relocate
int reloc_cmp(const void *a, const void *b) int reloc_cmp(const void *a, const void *b)
{ {
const struct hunkreloc *ha = a, *hb = b; const struct hunkreloc *ha = (const struct hunkreloc *)a, *hb = (const struct hunkreloc *)b;
if (ha->shid != hb->shid) if (ha->shid != hb->shid)
return hb->shid - ha->shid; return hb->shid - ha->shid;
@ -614,7 +660,7 @@ static int wlong(int fd, ULONG val)
int sym_dump(int hunk_fd, struct sheader *sh, struct hunkheader **hh, int shid, int symtabndx) int sym_dump(int hunk_fd, struct sheader *sh, struct hunkheader **hh, int shid, int symtabndx)
{ {
int i, err, syms; int i, err, syms;
struct symbol *sym = hh[symtabndx]->data; struct symbol *sym = (struct symbol *)hh[symtabndx]->data;
struct sheader *symtab = &sh[symtabndx]; struct sheader *symtab = &sh[symtabndx];
syms = symtab->size / sizeof(struct symbol); syms = symtab->size / sizeof(struct symbol);
@ -708,11 +754,11 @@ static int copy_to(int in, int out)
int elf2hunk(int file, int hunk_fd, const char *libname, int flags) int elf2hunk(int file, int hunk_fd, const char *libname, int flags)
{ {
const __attribute__((unused)) char *names[3]={ "CODE", "DATA", "BSS" }; const ATTRIBUTE_UNUSED char *names[3] = { "CODE", "DATA", "BSS" };
struct hunkheader **hh; struct hunkheader **hh;
struct elfheader eh; struct elfheader eh;
struct sheader *sh; struct sheader *sh;
char *strtab; char *strtab = 0;
int symtab_shndx = -1; int symtab_shndx = -1;
int err; int err;
ULONG i; ULONG i;
@ -739,7 +785,7 @@ int elf2hunk(int file, int hunk_fd, const char *libname, int flags)
/* load section headers */ /* load section headers */
D(bug("Load %d Section Headers @0x%08x\n", int_shnum, (int)eh.shoff)); D(bug("Load %d Section Headers @0x%08x\n", int_shnum, (int)eh.shoff));
if (!(sh = load_block(file, eh.shoff, int_shnum * eh.shentsize))) if (!(sh = (struct sheader *)load_block(file, eh.shoff, int_shnum * eh.shentsize)))
return EXIT_FAILURE; return EXIT_FAILURE;
sh_fixup(sh, int_shnum); sh_fixup(sh, int_shnum);
@ -747,13 +793,13 @@ int elf2hunk(int file, int hunk_fd, const char *libname, int flags)
/* Looks like we have a valid executable. Generate a /* Looks like we have a valid executable. Generate a
* HUNK header set. Not all may be filled in. * HUNK header set. Not all may be filled in.
*/ */
hh = calloc(sizeof(*hh), int_shnum); hh = (struct hunkheader **)calloc(sizeof(*hh), int_shnum);
/* Look for the string table */ /* Look for the string table */
D(bug("Look for string table\n")); D(bug("Look for string table\n"));
for (i = 0; i < int_shnum; i++) { for (i = 0; i < int_shnum; i++) {
if (sh[i].type == SHT_STRTAB) { if (sh[i].type == SHT_STRTAB) {
strtab = load_block(file, sh[i].offset, sh[i].size); strtab = (char *)load_block(file, sh[i].offset, sh[i].size);
break; break;
} }
} }
@ -773,11 +819,11 @@ int elf2hunk(int file, int hunk_fd, const char *libname, int flags)
(int)i, (int)sh[i].type, (int)sh[i].offset, (int)sh[i].size)); (int)i, (int)sh[i].type, (int)sh[i].offset, (int)sh[i].size));
if (sh[i].type == SHT_SYMTAB || sh[i].type == SHT_STRTAB || sh[i].type == SHT_SYMTAB_SHNDX) if (sh[i].type == SHT_SYMTAB || sh[i].type == SHT_STRTAB || sh[i].type == SHT_SYMTAB_SHNDX)
{ {
hh[i] = calloc(sizeof(struct hunkheader), 1); hh[i] = (struct hunkheader *)calloc(sizeof(struct hunkheader), 1);
hh[i]->type = (sh[i].type == SHT_SYMTAB) ? HUNK_SYMBOL : 0; hh[i]->type = (sh[i].type == SHT_SYMTAB) ? HUNK_SYMBOL : 0;
hh[i]->memflags = 0; hh[i]->memflags = 0;
hh[i]->hunk = -1; hh[i]->hunk = -1;
hh[i]->data = load_block(file, sh[i].offset, sh[i].size); hh[i]->data = (char *)load_block(file, sh[i].offset, sh[i].size);
if (!hh[i]->data) if (!hh[i]->data)
goto error; goto error;
@ -792,7 +838,7 @@ int elf2hunk(int file, int hunk_fd, const char *libname, int flags)
/* Load the section in memory if needed, and make an hunk out of it */ /* Load the section in memory if needed, and make an hunk out of it */
if (sh[i].flags & SHF_ALLOC && sh[i].size > 0) if (sh[i].flags & SHF_ALLOC && sh[i].size > 0)
{ {
hh[i] = calloc(sizeof(struct hunkheader), 1); hh[i] = (struct hunkheader *)calloc(sizeof(struct hunkheader), 1);
hh[i]->size = sh[i].size; hh[i]->size = sh[i].size;
hh[i]->hunk = hunks++; hh[i]->hunk = hunks++;
@ -801,6 +847,12 @@ int elf2hunk(int file, int hunk_fd, const char *libname, int flags)
hh[i]->type = HUNK_BSS; hh[i]->type = HUNK_BSS;
hh[i]->memflags = 0; hh[i]->memflags = 0;
hh[i]->data = NULL; hh[i]->data = NULL;
if (theBSS == 0) {
theBSS = hh[i];
bssIndex = i;
}
} else { } else {
if (sh[i].flags & SHF_EXECINSTR) { if (sh[i].flags & SHF_EXECINSTR) {
hh[i]->type = HUNK_CODE; hh[i]->type = HUNK_CODE;
@ -808,7 +860,7 @@ int elf2hunk(int file, int hunk_fd, const char *libname, int flags)
} else { } else {
hh[i]->type = HUNK_DATA; hh[i]->type = HUNK_DATA;
} }
hh[i]->data = load_block(file, sh[i].offset, sh[i].size); hh[i]->data = (char *)load_block(file, sh[i].offset, sh[i].size);
} }
if (strtab) { if (strtab) {
@ -840,7 +892,7 @@ int elf2hunk(int file, int hunk_fd, const char *libname, int flags)
&& hh[sh[i].info] && hh[sh[i].info]
&& hh[sh[i].info]->data) && hh[sh[i].info]->data)
{ {
void *reloc = load_block(file, sh[i].offset, sh[i].size); struct relo *reloc = (struct relo *)load_block(file, sh[i].offset, sh[i].size);
if (!relocate(&eh, sh, i, symtab_shndx, reloc, hh)) if (!relocate(&eh, sh, i, symtab_shndx, reloc, hh))
return EXIT_FAILURE; return EXIT_FAILURE;
@ -872,7 +924,7 @@ int elf2hunk(int file, int hunk_fd, const char *libname, int flags)
if (hh[i]==NULL || hh[i]->hunk < 0) if (hh[i]==NULL || hh[i]->hunk < 0)
continue; continue;
count = (hh[i]->size + 4) / 4; count = (hh[i]->size + 3) / 4;
switch (hh[i]->memflags) { switch (hh[i]->memflags) {
case MEMF_CHIP: case MEMF_CHIP:
count |= HUNKF_CHIP; count |= HUNKF_CHIP;
@ -887,7 +939,7 @@ int elf2hunk(int file, int hunk_fd, const char *libname, int flags)
break; break;
} }
D(bug("\tHunk #%d, %s, lsize=%d\n", hh[i]->hunk, names[hh[i]->type - HUNK_CODE], (int)(hh[i]->size+4)/4)); D(bug("\tHunk #%d, %s, lsize=%d\n", hh[i]->hunk, names[hh[i]->type - HUNK_CODE], (int)(hh[i]->size + 3) / 4)); // ? + 4
wlong(hunk_fd, count); wlong(hunk_fd, count);
if ((count & HUNKF_MEMFLAGS) == HUNKF_MEMFLAGS) if ((count & HUNKF_MEMFLAGS) == HUNKF_MEMFLAGS)
@ -902,11 +954,11 @@ int elf2hunk(int file, int hunk_fd, const char *libname, int flags)
continue; continue;
wlong(hunk_fd, hh[i]->type); wlong(hunk_fd, hh[i]->type);
wlong(hunk_fd, (hh[i]->size + 4) / 4); wlong(hunk_fd, (hh[i]->size + 3) / 4);
switch (hh[i]->type) { switch (hh[i]->type) {
case HUNK_BSS: case HUNK_BSS:
D(bug("HUNK_BSS: %d longs\n", (int)((hh[i]->size + 4) / 4))); D(bug("HUNK_BSS: %d longs\n", (int)((hh[i]->size + 3) / 4)));
if (0) { if (0) {
for (s = 0; s < int_shnum; s++) { for (s = 0; s < int_shnum; s++) {
if (hh[s] && hh[s]->type == HUNK_SYMBOL) if (hh[s] && hh[s]->type == HUNK_SYMBOL)
@ -918,8 +970,8 @@ if (0) {
break; break;
case HUNK_CODE: case HUNK_CODE:
case HUNK_DATA: case HUNK_DATA:
D(bug("#%d HUNK_%s: %d longs\n", hh[i]->hunk, hh[i]->type == HUNK_CODE ? "CODE" : "DATA", (int)((hh[i]->size + 4) / 4))); D(bug("#%d HUNK_%s: %d longs\n", hh[i]->hunk, hh[i]->type == HUNK_CODE ? "CODE" : "DATA", (int)((hh[i]->size + 3) / 4)));
err = write(hunk_fd, hh[i]->data, ((hh[i]->size + 4)/4)*4); err = write(hunk_fd, hh[i]->data, ((hh[i]->size + 3)/4)*4);
if (err < 0) if (err < 0)
return EXIT_FAILURE; return EXIT_FAILURE;
if (0) { if (0) {
@ -1034,7 +1086,7 @@ static int copy(const char *src, const char *dst, int flags)
return copy_dir(src, dst, flags); return copy_dir(src, dst, flags);
} }
src_fd = open(src, O_RDONLY); src_fd = open(src, O_RDONLY | O_BINARY);
if (src_fd < 0) { if (src_fd < 0) {
perror(src); perror(src);
return EXIT_FAILURE; return EXIT_FAILURE;
@ -1044,7 +1096,7 @@ static int copy(const char *src, const char *dst, int flags)
hunk_fd = 1; /* stdout */ hunk_fd = 1; /* stdout */
else { else {
unlink(dst); unlink(dst);
hunk_fd = open(dst, O_RDWR | O_CREAT | O_TRUNC, mode); hunk_fd = open(dst, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, mode);
} }
if (hunk_fd < 0) { if (hunk_fd < 0) {
perror(dst); perror(dst);