scc

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

commit 47f7f09b8f01ed0cd8d25d509299ae6066cb7ffa
parent dd72d0408912f58bc41cfc2f8462dc5943d24d17
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Mon, 12 Mar 2018 14:30:10 +0100

[nm] Improve error handling

Diffstat:
Mnm/coff32.c | 68+++++++++++++++++++++++++++++++++++++++-----------------------------
Mnm/main.c | 63++++++++++++++++++++++++++++++++++-----------------------------
Mnm/nm.h | 4++--
3 files changed, 75 insertions(+), 60 deletions(-)

diff --git a/nm/coff32.c b/nm/coff32.c @@ -34,7 +34,7 @@ typeof(SYMENT *ent) c = '?'; break; case N_ABS: - c = 'A'; + c = 'a'; break; case N_UNDEF: c = 'U'; @@ -53,20 +53,21 @@ typeof(SYMENT *ent) else c = '?'; - if (ent->n_sclass == C_EXT) - c = toupper(c); - break; } + + if (ent->n_sclass == C_EXT) + c = toupper(c); + return c; } static char * -getsname(FILE *fp, SYMENT *ent) +getsname(char *fname, FILE *fp, SYMENT *ent) { int c; size_t len; - char *s; + char *s, *err; fpos_t pos; if (ent->n_zeroes != 0) { @@ -76,7 +77,6 @@ getsname(FILE *fp, SYMENT *ent) s[len] = '\0'; return memcpy(s, ent->n_name, len); } - fgetpos(fp, &pos); fseek(fp, stringtbl, SEEK_SET); @@ -97,10 +97,9 @@ getsname(FILE *fp, SYMENT *ent) return s; error: - fprintf(stderr, - "nm::%s\n", - (ferror(fp)) ? strerror(errno) : "broken string table"); - exit(1); + err = (!ferror(fp)) ? + "EOF before reading strings" : strerror(errno); + die("nm: %s: %s", fname, err); } static void @@ -120,7 +119,8 @@ getfsym(unsigned char *buff, SYMENT *ent) } static void -getsymbol(FILE *fp, unsigned char *buff, SYMENT *ent, struct symbol *sym) +getsymbol(char *fname, FILE *fp, + unsigned char *buff, SYMENT *ent, struct symbol *sym) { char *nam; @@ -133,7 +133,7 @@ getsymbol(FILE *fp, unsigned char *buff, SYMENT *ent, struct symbol *sym) ent->n_zeroes = zero; ent->n_offset = offset; } - sym->name = getsname(fp, ent); + sym->name = getsname(fname, fp, ent); sym->type = typeof(ent); sym->value = ent->n_value; } @@ -153,7 +153,7 @@ getsyms(char *fname, char *member, FILE *fp, FILHDR *hdr) syms = xcalloc(sizeof(*syms), n); if (fseek(fp, hdr->f_symptr, SEEK_SET) == EOF) - die("nm:%s:%s", member, strerror(errno)); + die("nm:%s:%s", fname, strerror(errno)); aux = nsyms = 0; for (i = 0; i < n; i++) { @@ -163,13 +163,15 @@ getsyms(char *fname, char *member, FILE *fp, FILHDR *hdr) aux--; continue; } - getsymbol(fp, buff, &ent, &syms[nsyms++]); + getsymbol(member, fp, buff, &ent, &syms[nsyms++]); aux = ent.n_numaux; } if (n != i) { - die("nm:%s:%s", - member, - (ferror(fp)) ? strerror(errno) : "EOF before reading symbols"); + char *err; + + err = (!ferror(fp)) ? + "EOF before reading symbols" : strerror(errno); + die("nm: %s: %s", fname, err); } } @@ -216,11 +218,11 @@ getsects(char *fname, char *member, FILE *fp, FILHDR *hdr) getfsec(buff, &sections[i]); } if (i != nsect) { - fprintf(stderr, - "nm:%s:%s\n", - member, - (ferror(fp)) ? strerror(errno) : "EOF before reading sections"); - exit(1); + char *err; + + err = (!ferror(fp)) ? + "EOF before reading sections" : strerror(errno); + die("nm: %s: %s", fname, err); } } @@ -241,15 +243,18 @@ getfhdr(unsigned char *buff, FILHDR *hdr) assert(n == FILHSZ); } -static void +static int nm(char *fname, char *member, FILE *fp) { unsigned char buff[FILHSZ]; FILHDR hdr; unsigned magic; - if (fread(buff, FILHSZ, 1, fp) != 1) - return; + if (fread(buff, FILHSZ, 1, fp) != 1) { + if (!ferror(fp)) + return 0; + die("nm: %s: %s", fname, strerror(errno)); + } magic = buff[0] | buff[1] << 8; @@ -264,9 +269,10 @@ nm(char *fname, char *member, FILE *fp) getfhdr(buff, &hdr); if ((hdr.f_flags & F_SYMS) != 0 || hdr.f_nsyms == 0) { fprintf(stderr, "nm: %s: no symbols\n", member); - return; + return 1; } + /* TODO: Check overflow */ stringtbl = hdr.f_symptr + hdr.f_nsyms* SYMESZ; getsects(fname, member, fp, &hdr); @@ -275,21 +281,25 @@ nm(char *fname, char *member, FILE *fp) free(sections); free(syms); + return 1; } static int -probe(FILE *fp) +probe(char *fname, char *member, FILE *fp) { int c; int c1, c2; fpos_t pos; - static unsigned short magic; + unsigned short magic; fgetpos(fp, &pos); c1 = getc(fp); c2 = getc(fp); fsetpos(fp, &pos); + if (ferror(fp)) + die("nm: %s: %s", fname, strerror(errno)); + if (c1 == EOF || c2 == EOF) return 0; magic = c1 | c2 << 8; diff --git a/nm/main.c b/nm/main.c @@ -31,13 +31,12 @@ object(char *fname, char *member, FILE *fp) for (p = formats; *p; ++p) { obj = *p; - if ((*obj->probe)(fp)) + if ((*obj->probe)(fname, member, fp)) break; } if (*p == NULL) return 0; - (*obj->nm)(fname, member, fp); - return 1; + return (*obj->nm)(fname, member, fp); } static char * @@ -65,7 +64,8 @@ ar(char *fname, FILE *fp) char member[SARNAM+1]; arflag = 1; - fseek(fp, sizeof(struct ar_hdr), SEEK_CUR); + if (fseek(fp, SARMAG, SEEK_SET) == EOF) + goto file_error; while (fread(&hdr, sizeof(hdr), 1, fp) == 1) { pos = ftell(fp); @@ -79,27 +79,27 @@ ar(char *fname, FILE *fp) if (siz & 1) siz++; - if (pos == -1 || pos > LONG_MAX - siz) { - fprintf(stderr, - "nm: %s: overflow in size of archive\n", - fname); - exit(1); - } + if (pos == -1 || pos > LONG_MAX - siz) + die("nm: %s: overflow in size of archive", fname); pos += siz; getfname(&hdr, member); - if (!object(member, member, fp)) { + if (!object(fname, member, fp)) { fprintf(stderr, "nm: skipping member %s in archive %s\n", member, fname); } - fseek(fp, pos, SEEK_SET); + if (fseek(fp, pos, SEEK_SET) == EOF) + goto file_error; } + if (ferror(fp)) + goto file_error; return; corrupted: - fprintf(stderr, "nm: %s: corrupted archive\n", fname); - exit(1); + die("nm: %s: corrupted archive", fname); +file_error: + die("nm: %s: %s", fname, strerror(errno)); } static int @@ -113,7 +113,7 @@ archive(char *fname, FILE *fp) fsetpos(fp, &pos); if (ferror(fp)) - return 0; + die("nm: %s: %s", fname, strerror(errno)); if (strncmp(magic, ARMAG, SARMAG) != 0) return 0; @@ -122,16 +122,18 @@ archive(char *fname, FILE *fp) } static void -print(char *file, char *member, struct symbol *sym) +printsym(char *file, char *member, struct symbol *sym) { char *fmt; int type = sym->type; if (type == '?') return; + if (uflag && type != 'U') return; - if (gflag && type != 'A' && type != 'B' && type != 'D') + + if (gflag && !isupper(type)) return; if (Aflag) @@ -179,30 +181,29 @@ printsyms(char *file, char *member, struct symbol *syms, size_t nsyms) qsort(syms, nsyms, sizeof(*syms), cmp); while (nsyms--) - print(file, member, syms++); + printsym(file, member, syms++); } -void +static void doit(char *fname) { FILE *fp; arflag = 0; - if ((fp = fopen(fname, "rb")) == NULL) { - perror("nm"); - exit(1); - } + + if ((fp = fopen(fname, "rb")) == NULL) + die("nm: %s: %s", fname, strerror(errno)); if (!object(fname, fname, fp) && !archive(fname, fp)) - fprintf(stderr, "nm: %s: File format not recognized\n", fname); + die("nm: %s: File format not recognized", fname); - if (ferror(fp) || fclose(fp) == EOF) { - perror("nm"); - exit(1); - } + if (ferror(fp)) + die("nm: %s: %s", fname, strerror(errno)); + + fclose(fp); } -void +static void usage(void) { fputs("nm [-APv][ -g| -u][-t format] [file...]\n", stderr); @@ -252,5 +253,9 @@ main(int argc, char *argv[]) doit(*argv); } + fflush(stdout); + if (ferror(stdout)) + die("nm: error writing in output"); + return 0; } diff --git a/nm/nm.h b/nm/nm.h @@ -7,8 +7,8 @@ struct symbol { }; struct objfile { - int (*probe)(FILE *fp); - void (*nm)(char *fname, char *member, FILE *fp); + int (*probe)(char *fname, char *member, FILE *fp); + int (*nm)(char *fname, char *member, FILE *fp); }; /* main.c */