ref: 5d34077110dc3c09b256f68ea3fe017dd0451273
parent: b468bd384fac1892386db9ff7a4da8c081ca9138
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Mon Mar 12 10:30:10 EDT 2018
[nm] Improve error handling
--- a/nm/coff32.c
+++ b/nm/coff32.c
@@ -34,7 +34,7 @@
c = '?';
break;
case N_ABS:
- c = 'A';
+ c = 'a';
break;
case N_UNDEF:
c = 'U';
@@ -53,20 +53,21 @@
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 @@
s[len] = '\0';
return memcpy(s, ent->n_name, len);
}
-
fgetpos(fp, &pos);
fseek(fp, stringtbl, SEEK_SET);
@@ -97,10 +97,9 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
getfsec(buff, §ions[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,7 +243,7 @@
assert(n == FILHSZ);
}
-static void
+static int
nm(char *fname, char *member, FILE *fp)
{
unsigned char buff[FILHSZ];
@@ -248,8 +250,11 @@
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 @@
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,20 +281,24 @@
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;
--- a/nm/main.c
+++ b/nm/main.c
@@ -31,13 +31,12 @@
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 @@
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 @@
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 @@
fsetpos(fp, &pos);
if (ferror(fp))
- return 0;
+ die("nm: %s: %s", fname, strerror(errno));
if (strncmp(magic, ARMAG, SARMAG) != 0)
return 0;
@@ -122,7 +122,7 @@
}
static void
-print(char *file, char *member, struct symbol *sym)
+printsym(char *file, char *member, struct symbol *sym)
{
char *fmt;
int type = sym->type;
@@ -129,9 +129,11 @@
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 @@
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);
@@ -251,6 +252,10 @@
for ( ; *argv; ++argv)
doit(*argv);
}
+
+ fflush(stdout);
+ if (ferror(stdout))
+ die("nm: error writing in output");
return 0;
}
--- a/nm/nm.h
+++ b/nm/nm.h
@@ -7,8 +7,8 @@
};
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 */