shithub: scc

Download patch

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, &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,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 */