mirror of
https://frontier.innolan.net/github/amigaos-cross-toolchain6.git
synced 2024-10-19 10:29:55 +00:00
add support for SHN_COMMON (#50)
This commit is contained in:
committed by
Krystian Bacławski
parent
ca8a4a74d5
commit
d8d27e078a
136
tools/elf2hunk.c
136
tools/elf2hunk.c
@ -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
|
||||
@ -12,10 +12,8 @@
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
@ -23,10 +21,42 @@
|
||||
#define F_VERBOSE (1 << 0)
|
||||
#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>
|
||||
#define mkdir(path, mode) mkdir(path)
|
||||
#else
|
||||
#elif !defined(_MSC_VER)
|
||||
#include <arpa/inet.h>
|
||||
typedef uint32_t ULONG;
|
||||
typedef int BOOL;
|
||||
@ -181,7 +211,7 @@ struct elfheader
|
||||
UWORD shentsize;
|
||||
UWORD shnum;
|
||||
UWORD shstrndx;
|
||||
} __attribute__((packed));
|
||||
} ATTRIBUTE_PACKED;
|
||||
|
||||
struct sheader
|
||||
{
|
||||
@ -195,7 +225,7 @@ struct sheader
|
||||
ULONG info;
|
||||
IPTR addralign;
|
||||
IPTR entsize;
|
||||
} __attribute__((packed));
|
||||
} ATTRIBUTE_PACKED;
|
||||
|
||||
#define PT_LOAD 1
|
||||
|
||||
@ -209,7 +239,7 @@ struct pheader
|
||||
ULONG memsz;
|
||||
ULONG flags;
|
||||
ULONG align;
|
||||
} __attribute__((packed));
|
||||
} ATTRIBUTE_PACKED;
|
||||
|
||||
struct symbol
|
||||
{
|
||||
@ -219,7 +249,7 @@ struct symbol
|
||||
UBYTE info; /* What kind of symbol is this ? (global, variable, etc) */
|
||||
UBYTE other; /* undefined */
|
||||
UWORD shindex; /* In which section is the symbol defined ? */
|
||||
} __attribute__((packed));
|
||||
} ATTRIBUTE_PACKED;
|
||||
|
||||
#define ELF_R_SYM(val) ((val) >> 8)
|
||||
#define ELF_R_TYPE(val) ((val) & 0xff)
|
||||
@ -276,10 +306,20 @@ static void set_error(int err)
|
||||
#define D(x)
|
||||
#define DB2(x)
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define bug(fmt,...) fprintf(stderr, fmt , __VA_ARGS__ )
|
||||
#else
|
||||
#define bug(fmt,args...) fprintf(stderr, fmt ,##args )
|
||||
#endif
|
||||
|
||||
static int must_swap = -1;
|
||||
|
||||
// hack for SHN_COMMON
|
||||
static struct hunkheader *theBSS;
|
||||
static int bssIndex;
|
||||
|
||||
|
||||
static void eh_fixup(struct elfheader *eh)
|
||||
{
|
||||
/* Endian swaps */
|
||||
@ -348,8 +388,9 @@ static void *load_block (int file,ULONG offset,ULONG size)
|
||||
ULONG lsize = (size + sizeof(ULONG) - 1) / sizeof(ULONG);
|
||||
D(bug("[ELF2HUNK] Load Block\n"));
|
||||
D(bug("[ELF2HUNK] (size=%d)\n",(int)size));
|
||||
void *block = malloc(lsize * sizeof(ULONG));
|
||||
ULONG *block = (ULONG *)malloc(lsize * sizeof(ULONG));
|
||||
if (block) {
|
||||
block[lsize - 1] = 0;
|
||||
lseek(file, offset, SEEK_SET);
|
||||
if (read(file, block, size) == size) {
|
||||
return block;
|
||||
@ -441,18 +482,20 @@ static int load_header(int file, struct elfheader *eh)
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct hunkreloc {
|
||||
ULONG shid; /* ELF hunk base to add to... */
|
||||
ULONG offset; /* offset in this hunk. */
|
||||
const char *symbol;
|
||||
};
|
||||
|
||||
struct hunkheader {
|
||||
ULONG type;
|
||||
ULONG memflags; /* Memory flags */
|
||||
ULONG size; /* Size in ULONGs */
|
||||
void *data;
|
||||
char *data;
|
||||
ULONG relocs;
|
||||
int hunk; /* Allocatable hunk ID */
|
||||
struct hunkreloc {
|
||||
ULONG shid; /* ELF hunk base to add to... */
|
||||
ULONG offset; /* offset in this hunk. */
|
||||
const char *symbol;
|
||||
} *reloc;
|
||||
struct hunkreloc *reloc;
|
||||
};
|
||||
|
||||
static int relocate
|
||||
@ -486,7 +529,7 @@ static int relocate
|
||||
|
||||
hrels = h->relocs;
|
||||
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];
|
||||
|
||||
for (i=0; i<numrel; i++, rel++)
|
||||
@ -510,7 +553,8 @@ static int relocate
|
||||
continue;
|
||||
#endif
|
||||
|
||||
sym = symtab[ELF_R_SYM(rel->info)];
|
||||
struct symbol * symptr = &symtab[ELF_R_SYM(rel->info)];
|
||||
sym = *symptr;
|
||||
sym_fixup(&sym);
|
||||
offset = rel->offset;
|
||||
symname = (const char *)(hh[shsymtab->link]->data + sym.name);
|
||||
@ -541,11 +585,13 @@ static int relocate
|
||||
break;
|
||||
|
||||
case SHN_COMMON:
|
||||
bug("[ELF2HUNK] SHN_COMMON symbol '%s' unsupported\n", symname);
|
||||
set_error(EINVAL);
|
||||
|
||||
return 0;
|
||||
hunk = bssIndex;
|
||||
value = theBSS->size;
|
||||
theBSS->size += (sym.size + 3) & ~3;
|
||||
|
||||
symptr->shindex = htons(bssIndex);
|
||||
symptr->value = htonl(value);
|
||||
break;
|
||||
case SHN_ABS:
|
||||
hunk = ~0; value = sym.value;
|
||||
break;
|
||||
@ -598,7 +644,7 @@ static int relocate
|
||||
|
||||
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)
|
||||
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 i, err, syms;
|
||||
struct symbol *sym = hh[symtabndx]->data;
|
||||
struct symbol *sym = (struct symbol *)hh[symtabndx]->data;
|
||||
struct sheader *symtab = &sh[symtabndx];
|
||||
|
||||
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)
|
||||
{
|
||||
const __attribute__((unused)) char *names[3]={ "CODE", "DATA", "BSS" };
|
||||
const ATTRIBUTE_UNUSED char *names[3] = { "CODE", "DATA", "BSS" };
|
||||
struct hunkheader **hh;
|
||||
struct elfheader eh;
|
||||
struct sheader *sh;
|
||||
char *strtab;
|
||||
char *strtab = 0;
|
||||
int symtab_shndx = -1;
|
||||
int err;
|
||||
ULONG i;
|
||||
@ -739,7 +785,7 @@ int elf2hunk(int file, int hunk_fd, const char *libname, int flags)
|
||||
|
||||
/* load section headers */
|
||||
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;
|
||||
|
||||
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
|
||||
* 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 */
|
||||
D(bug("Look for string table\n"));
|
||||
for (i = 0; i < int_shnum; i++) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -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));
|
||||
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]->memflags = 0;
|
||||
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)
|
||||
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 */
|
||||
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]->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]->memflags = 0;
|
||||
hh[i]->data = NULL;
|
||||
|
||||
if (theBSS == 0) {
|
||||
theBSS = hh[i];
|
||||
bssIndex = i;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (sh[i].flags & SHF_EXECINSTR) {
|
||||
hh[i]->type = HUNK_CODE;
|
||||
@ -808,7 +860,7 @@ int elf2hunk(int file, int hunk_fd, const char *libname, int flags)
|
||||
} else {
|
||||
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) {
|
||||
@ -840,7 +892,7 @@ int elf2hunk(int file, int hunk_fd, const char *libname, int flags)
|
||||
&& hh[sh[i].info]
|
||||
&& 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))
|
||||
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)
|
||||
continue;
|
||||
|
||||
count = (hh[i]->size + 4) / 4;
|
||||
count = (hh[i]->size + 3) / 4;
|
||||
switch (hh[i]->memflags) {
|
||||
case MEMF_CHIP:
|
||||
count |= HUNKF_CHIP;
|
||||
@ -887,7 +939,7 @@ int elf2hunk(int file, int hunk_fd, const char *libname, int flags)
|
||||
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);
|
||||
|
||||
if ((count & HUNKF_MEMFLAGS) == HUNKF_MEMFLAGS)
|
||||
@ -902,11 +954,11 @@ int elf2hunk(int file, int hunk_fd, const char *libname, int flags)
|
||||
continue;
|
||||
|
||||
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) {
|
||||
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) {
|
||||
for (s = 0; s < int_shnum; s++) {
|
||||
if (hh[s] && hh[s]->type == HUNK_SYMBOL)
|
||||
@ -918,8 +970,8 @@ if (0) {
|
||||
break;
|
||||
case HUNK_CODE:
|
||||
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)));
|
||||
err = write(hunk_fd, hh[i]->data, ((hh[i]->size + 4)/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 + 3)/4)*4);
|
||||
if (err < 0)
|
||||
return EXIT_FAILURE;
|
||||
if (0) {
|
||||
@ -1034,7 +1086,7 @@ static int copy(const char *src, const char *dst, int 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) {
|
||||
perror(src);
|
||||
return EXIT_FAILURE;
|
||||
@ -1044,7 +1096,7 @@ static int copy(const char *src, const char *dst, int flags)
|
||||
hunk_fd = 1; /* stdout */
|
||||
else {
|
||||
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) {
|
||||
perror(dst);
|
||||
|
||||
Reference in New Issue
Block a user