scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit 4dc9905bcd18e15446a589cdb4060b31050b5607
parent 29ccac8d84406c05b0b6a444da9daa597c7658f3
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Thu, 31 May 2018 08:31:14 +0100

[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.

Diffstat:
Mld/coff32.c | 227++++++++++++++++++++-----------------------------------------------------------
Mld/ld.h | 4++--
Mld/obj.c | 15+--------------
3 files changed, 60 insertions(+), 186 deletions(-)

diff --git a/ld/coff32.c b/ld/coff32.c @@ -140,7 +140,7 @@ readsects(Obj *obj, long off) } 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 @@ getsym(Obj *obj, unsigned char *buff, SYMENT *ent) (*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) - outmem(); - 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; + if ((ents = malloc((nsyms * sizeof(SYMENT)))) == NULL) + outmem(); + obj->enthdr = ents; + 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); - - if (ent.n_scnum <= 0) - continue; - - 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; - } - - obj->symbols[i] = sym; + getent(obj, buff, &ents[i]); } return 0; } +/* + * 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; + + if (off > LONG_MAX - ptr) + return -1; + off += ptr; + + if (size > 0) { + if (nitem > LONG_MAX / size) + return -1; + size *= nitem; + } + + 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 @@ load(Obj *obj) 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); -} - -static void -unload(Obj *obj) -{ - /* TODO */ - pop(obj); - delobj(obj); + fprintf(stderr, + "ld: %s: %s\n", + obj->fname, + (ferror(obj->fp)) ? strerror(errno) : "corrupted file"); + exit(EXIT_FAILURE); } 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 diff --git a/ld/ld.h b/ld/ld.h @@ -12,6 +12,7 @@ struct obj { void *filhdr; void *scnhdr; + void *enthdr; Symbol **symbols; Symbol **sections; @@ -49,9 +50,8 @@ struct objfmt { /* 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); diff --git a/ld/obj.c b/ld/obj.c @@ -17,21 +17,8 @@ Symbol *sectlst; 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;