diff blobstat/grokmap.c @ 293:23e5b940cb8b

blobstat: mostly complete
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 21 Sep 2019 21:07:45 +0000
parents
children ff2a6433687f
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/blobstat/grokmap.c	Sat Sep 21 21:07:45 2019 +0000
@@ -0,0 +1,247 @@
+#include <sys/types.h>
+#include <ctype.h>
+#include <string.h>
+#include <strings.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "struct.h"
+
+extern struct libentry *libentry_list;
+
+static FILE *mapfile;
+static char linebuf[1024];
+static int lineno;
+static char *filename_for_errs;
+
+static struct category *
+find_category_of_object(libname, member)
+	char *libname, *member;
+{
+	struct libentry *p;
+
+	for (p = libentry_list; p; p = p->next) {
+		if (strcmp(p->libname, libname))
+			continue;
+		if (!p->member || !strcmp(p->member, member))
+			return(p->cat);
+	}
+	return(0);
+}
+
+static void
+getline()
+{
+	char *cp;
+
+	if (!fgets(linebuf, sizeof linebuf, mapfile)) {
+		fprintf(stderr, "%s: premature EOF\n", filename_for_errs);
+		exit(1);
+	}
+	lineno++;
+	cp = index(linebuf, '\n');
+	if (!cp) {
+		fprintf(stderr, "%s line %d: too long or unterminated\n",
+			filename_for_errs, lineno);
+		exit(1);
+	}
+	if (cp > linebuf && cp[-1] == '\r')
+		*--cp = '\0';
+}
+
+static
+valid_section_name_char(c, first)
+{
+	if (isalpha(c) || c == '_' || c == '.' || c == '$')
+		return(1);
+	else if (isdigit(c) && !first)
+		return(1);
+	else
+		return(0);
+}
+
+static
+parse_input_section_line(libnameout, memberout)
+	char *libnameout, **memberout;
+{
+	int i;
+	char *cp;
+
+	for (i = 0; i < 18; i++)
+		if (linebuf[i] != ' ') {
+inv_input_sec_line:	fprintf(stderr,
+				"%s line %d: invalid input section line\n",
+				filename_for_errs, lineno);
+			exit(1);
+		}
+	while (i < 26)
+		if (!isxdigit(linebuf[i++]))
+			goto inv_input_sec_line;
+	while (i < 30)
+		if (linebuf[i++] != ' ')
+			goto inv_input_sec_line;
+	while (i < 38)
+		if (!isxdigit(linebuf[i++]))
+			goto inv_input_sec_line;
+	while (i < 43)
+		if (linebuf[i++] != ' ')
+			goto inv_input_sec_line;
+	if (isalpha(linebuf[43])) {
+		cp = linebuf + 43;
+		while (isalnum(*cp) || *cp == '_')
+			cp++;
+		if (strncmp(cp, ".lib : ", 7))
+			return(0);
+		cp += 4;
+		*cp++ = '\0';
+		strcpy(libnameout, linebuf + 43);
+		cp += 2;
+		if (!isalpha(*cp))
+			goto inv_input_sec_line;
+		*memberout = cp;
+		while (isalnum(*cp) || *cp == '_' || *cp == '.')
+			cp++;
+		if (*cp != ' ')
+			goto inv_input_sec_line;
+		*cp = '\0';
+		return(1);
+	} else if (linebuf[43] == ' ') {
+		cp = linebuf + 43;
+		while (*cp == ' ')
+			cp++;
+		if (*cp++ != ':')
+			goto inv_input_sec_line;
+		if (*cp++ != ' ')
+			goto inv_input_sec_line;
+		if (!isalpha(*cp))
+			goto inv_input_sec_line;
+		*memberout = cp;
+		while (isalnum(*cp) || *cp == '_' || *cp == '.')
+			cp++;
+		if (*cp != ' ')
+			goto inv_input_sec_line;
+		*cp = '\0';
+		return(1);
+	} else
+		return(0);
+}
+
+static
+process_output_section()
+{
+	int c, i;
+	int uninit;
+	char libname[1024], *member;
+	struct category *cat;
+
+	getline();
+	if (!linebuf[0])
+		return(1);
+	if (!valid_section_name_char(linebuf[0], 1)) {
+inv_outsec_line:
+		fprintf(stderr,
+			"%s line %d: invalid output section beginning line\n",
+			filename_for_errs, lineno);
+		exit(1);
+	}
+	for (i = 1; ; i++) {
+		c = linebuf[i];
+		if (c == '\0' || c == ' ')
+			break;
+		if (!valid_section_name_char(c, 0))
+			goto inv_outsec_line;
+	}
+	if (!c) {
+		if (i < 8)
+			goto inv_outsec_line;
+		getline();
+		for (i = 0; i < 8; i++)
+			if (linebuf[i] != ' ')
+				goto inv_outsec_line;
+	} else {
+		if (i > 7)
+			goto inv_outsec_line;
+		for (; i < 8; i++)
+			if (linebuf[i] != ' ')
+				goto inv_outsec_line;
+	}
+	if (linebuf[i++] != '0')
+		goto inv_outsec_line;
+	while (i < 13)
+		if (linebuf[i++] != ' ')
+			goto inv_outsec_line;
+	while (i < 21)
+		if (!isxdigit(linebuf[i++]))
+			goto inv_outsec_line;
+	while (i < 25)
+		if (linebuf[i++] != ' ')
+			goto inv_outsec_line;
+	while (i < 33)
+		if (!isxdigit(linebuf[i++]))
+			goto inv_outsec_line;
+	while (i < 38)
+		if (linebuf[i++] != ' ')
+			goto inv_outsec_line;
+	uninit = !strcmp(linebuf + 38, "UNINITIALIZED");
+	/* input section lines */
+	libname[0] = '\0';
+	for (;;) {
+		getline();
+		if (!linebuf[0])
+			break;
+		if (!parse_input_section_line(libname, &member))
+			continue;
+		if (!libname[0]) {
+			fprintf(stderr, "%s line %d: missing library name\n",
+				filename_for_errs, lineno);
+			exit(1);
+		}
+		cat = find_category_of_object(libname, member);
+		if (!cat) {
+			fprintf(stderr, "%s line %d: unknown library object\n",
+				filename_for_errs, lineno);
+			exit(1);
+		}
+		if (!uninit)
+			cat->accum += strtoul(linebuf + 30, 0, 16);
+	}
+	return(0);
+}
+
+process_map_file(filename)
+	char *filename;
+{
+	filename_for_errs = filename;
+	mapfile = fopen(filename, "r");
+	if (!mapfile) {
+		perror(filename);
+		exit(1);
+	}
+	do
+		getline();
+	while (strcmp(linebuf, "SECTION ALLOCATION MAP"));
+	/* 4 fixed info lines */
+	getline();
+	if (linebuf[0]) {
+bad_sectionmap_hdr:
+		fprintf(stderr,
+		"%s line %d: wrong lines after SECTION ALLOCATION MAP\n",
+			filename_for_errs, lineno);
+		exit(1);
+	}
+	getline();
+	if (strcmp(linebuf,
+		" output                                  attributes/"))
+		goto bad_sectionmap_hdr;
+	getline();
+	if (strcmp(linebuf,
+		"section   page    origin      length       input sections"))
+		goto bad_sectionmap_hdr;
+	getline();
+	if (strcmp(linebuf,
+		"--------  ----  ----------  ----------   ----------------"))
+		goto bad_sectionmap_hdr;
+	while (!process_output_section())
+		;
+	fclose(mapfile);
+	return(0);
+}