ref: 6f1a568924aa209ad591f3c540251f00006c655e
parent: 751095831f3fdd1004805a31342c6da6c6976eca
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Thu May 31 04:31:14 EDT 2018
[as/coff32] Refactor readobj() Readobj() only reads the file object, without trying to install the new symbols. This makes the code more orthogonal and it prepares the code for unloading objects.
--- a/ld/coff32.c
+++ b/ld/coff32.c
@@ -140,7 +140,7 @@
}
static void
-getsym(Obj *obj, unsigned char *buff, SYMENT *ent)
+getent(Obj *obj, unsigned char *buff, SYMENT *ent)
{
int n;
long off, zero;
@@ -161,179 +161,66 @@
(*obj->unpack)(buff, "ll", &ent->n_zeroes, &ent->n_offset);
}
-static char *
-symname(Obj *obj, SYMENT *ent)
-{
- long off;
-
- if (ent->n_zeroes != 0)
- return ent->n_name;
-
- off = ent->n_offset;
- if (off >= obj->strsiz) {
- fprintf(stderr,
- "ld: invalid offset in symbol table: %zd\n", off);
- return "";
- }
-
- return &obj->strtbl[off];
-}
-
-static char
-typeof(Obj *obj, SYMENT *ent)
-{
- SCNHDR *sec;
- FILHDR *hdr;
- int c, n;
- long flags;
-
- switch (ent->n_scnum) {
- case N_DEBUG:
- c = 'n';
- break;
- case N_ABS:
- c = 'a';
- break;
- case N_UNDEF:
- c = (ent->n_value != 0) ? 'C' : 'U';
- break;
- default:
- sec = obj->scnhdr;
- hdr = obj->filhdr;
- n = ent->n_scnum;
- if (n > hdr->f_nscns)
- return '?';
- sec = &sec[n-1];
- flags = sec->s_flags;
- if (flags & STYP_TEXT)
- c = 't';
- else if (flags & STYP_DATA)
- c = 'd';
- else if (flags & STYP_BSS)
- c = 'b';
- else
- c = '?';
- break;
- }
-
- if (ent->n_sclass == C_EXT)
- c = toupper(c);
-
- return c;
-}
-
-static TUINT
-getval(Obj *obj, SYMENT *ent)
-{
- FILHDR *hdr = obj->filhdr;;
- SCNHDR *scn;
- Symbol *sym;
- unsigned n;
-
- if (ent->n_scnum > hdr->f_nscns) {
- fprintf(stderr,
- "ld: %s: incorrect section number\n",
- obj->fname,
- ent->n_scnum);
- exit(EXIT_FAILURE);
- }
-
- n = ent->n_scnum-1;
- scn = obj->scnhdr;
- scn = &scn[n];
- sym = obj->sections[n];
-
-
- return ent->n_value + (sym->size - scn->s_size);
-}
-
static int
-readsyms(Obj *obj, long off)
+readents(Obj *obj, long off)
{
- int type;
- unsigned i, n, aux;
+ SYMENT *ent, *ents;
FILHDR *hdr = obj->filhdr;;
+ long i, nsyms = hdr->f_nsyms;
+ unsigned char buff[SYMESZ];
+
if (fseek(obj->fp, off, SEEK_SET) == EOF)
return -1;
- if (hdr->f_nsyms > SIZE_MAX / sizeof(Symbol *)) {
+ if (nsyms > SIZE_MAX/sizeof(SYMENT)) {
fprintf(stderr,
"ld: %s: overflow in size of symbol redirection\n",
obj->fname);
exit(EXIT_FAILURE);
}
- obj->symbols = malloc(sizeof(Symbol *) * sizeof(Symbol *));
- if (!obj->symbols)
+
+ if ((ents = malloc((nsyms * sizeof(SYMENT)))) == NULL)
outmem();
+ obj->enthdr = ents;
- hdr = obj->filhdr;
- aux = n = 0;
- for (i = 0; i < hdr->f_nsyms; i++) {
- Symbol *sym;
- TUINT value;
- SYMENT ent;
- unsigned char buff[SYMESZ];
- char *name;
-
+ for (ent = ents; ent < &ents[nsyms]; ++ent) {
if (fread(buff, SYMESZ, 1, obj->fp) != 1)
return -1;
- if (aux > 0) {
- aux--;
- continue;
- }
- getsym(obj, buff, &ent);
- aux = ent.n_numaux;
- name = symname(obj, &ent);
- type = typeof(obj, &ent);
- sym = lookup(name);
+ getent(obj, buff, &ents[i]);
+ }
- if (ent.n_scnum <= 0)
- continue;
+ return 0;
+}
- switch (sym->type) {
- case 'U':
- sym->type = type;
- sym->value = getval(obj, &ent);
- if (type != 'U') {
- obj->define = 1;
- sym->where = obj;
- }
- if (type == 'C')
- sym->size = ent.n_value;
- break;
- case 'C':
- switch (type) {
- case 'U':
- case 'C':
- if (ent.n_value > sym->size)
- sym->size = ent.n_value;
- break;
- default:
- obj->define = 1;
- sym->where = obj;
- sym->type = type;
- sym->value = getval(obj, &ent);
- break;
- }
- break;
- default:
- if (type != 'U') {
- fprintf(stderr,
- "ld: %s: redifinition of symbol '%s'\n",
- obj->fname, sym->name);
- }
- break;
- }
+/*
+ * check overflow in: off + ptr + nitem*size
+ */
+static long
+fileptr(long off, long ptr, long nitem, long size)
+{
+ if (off < 0 || ptr < 0 || nitem < 0 || size < 0)
+ return -1;
- obj->symbols[i] = sym;
+ if (off > LONG_MAX - ptr)
+ return -1;
+ off += ptr;
+
+ if (size > 0) {
+ if (nitem > LONG_MAX / size)
+ return -1;
+ size *= nitem;
}
- return 0;
+ if (off > LONG_MAX - size)
+ return -1;
+ off += size;
+
+ return off;
}
static void
-load(Obj *obj)
+readobj(Obj *obj)
{
unsigned char buff[FILHSZ];
FILHDR *hdr;
@@ -349,38 +236,38 @@
getfhdr(obj, buff, hdr);
obj->filhdr = hdr;
- stroff = pos + hdr->f_symptr + hdr->f_nsyms*SYMESZ;
- symoff = pos + hdr->f_symptr;
- secoff = pos + FILHSZ + hdr->f_opthdr;
+ stroff = fileptr(pos, hdr->f_symptr, hdr->f_nsyms, SYMESZ);
+ symoff = fileptr(pos, hdr->f_symptr, 0, 0);
+ secoff = fileptr(pos, hdr->f_opthdr, 1, FILHSZ);
+ if (stroff < 0 || symoff < 0 || secoff < 0)
+ goto bad_file;
+
if (readstr(obj, stroff) < 0)
goto bad_file;
if (readsects(obj, secoff) < 0)
goto bad_file;
- if (readsyms(obj, symoff) < 0)
+ if (readents(obj, symoff) < 0)
goto bad_file;
return;
bad_file:
- if (ferror(obj->fp))
- die("ld: %s: %s", obj->fname, strerror(errno));
- die("ld: %s: corrupted file", obj->fname);
+ fprintf(stderr,
+ "ld: %s: %s\n",
+ obj->fname,
+ (ferror(obj->fp)) ? strerror(errno) : "corrupted file");
+ exit(EXIT_FAILURE);
}
static void
-unload(Obj *obj)
-{
- /* TODO */
- pop(obj);
- delobj(obj);
-}
-
-static void
pass1(Obj *obj)
{
- load(obj);
- if (obj->member && !obj->define)
- unload(obj);
+ readobj(obj);
+ if (obj->member && !obj->define) {
+ delobj(obj);
+ return;
+ }
+ add(obj);
}
static void
--- a/ld/ld.h
+++ b/ld/ld.h
@@ -12,6 +12,7 @@
void *filhdr;
void *scnhdr;
+ void *enthdr;
Symbol **symbols;
Symbol **sections;
@@ -49,9 +50,8 @@
/* obj.c */
extern Obj *newobj(char *fname, char *member, FILE *fp);
+extern void add(Obj *obj);
extern void delobj(Obj *obj);
-extern void pop(Obj *obj);
-extern void push(Obj *obj);
extern void newsect(Symbol *sym);
extern Symbol *lookup(char *name);
--- a/ld/obj.c
+++ b/ld/obj.c
@@ -17,21 +17,8 @@
static Symbol *secttail;
static Symbol *symtbl[NR_SYM_HASH];
-/*
- * This function is always called with the last object created,
- * so we can be sure that we only have to pop off the last
- * object created
- */
void
-pop(Obj *obj)
-{
- objtail = objtail->prev;
- if (!objtail)
- objlst = NULL;
-}
-
-void
-push(Obj *obj)
+add(Obj *obj)
{
obj->prev = objlst;
obj->next = NULL;