view blobstat/grokmap.c @ 406:1a852266ba74 default tip

tfo moved to gsm-net-reveng repository
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 24 May 2024 21:19:59 +0000
parents 99f72069d867
children
line wrap: on
line source

#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
get_line()
{
	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 (!isalnum(*cp) && *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 (!isalnum(*cp) && *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;

	get_line();
	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;
		get_line();
		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 (;;) {
		get_line();
		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
		get_line();
	while (strcmp(linebuf, "SECTION ALLOCATION MAP"));
	/* 4 fixed info lines */
	get_line();
	if (linebuf[0]) {
bad_sectionmap_hdr:
		fprintf(stderr,
		"%s line %d: wrong lines after SECTION ALLOCATION MAP\n",
			filename_for_errs, lineno);
		exit(1);
	}
	get_line();
	if (strcmp(linebuf,
		" output                                  attributes/"))
		goto bad_sectionmap_hdr;
	get_line();
	if (strcmp(linebuf,
		"section   page    origin      length       input sections"))
		goto bad_sectionmap_hdr;
	get_line();
	if (strcmp(linebuf,
		"--------  ----  ----------  ----------   ----------------"))
		goto bad_sectionmap_hdr;
	while (!process_output_section())
		;
	fclose(mapfile);
	return(0);
}