view ticoff/symtab.c @ 118:193926ccd1ec

tiobjd: better handling of section-relative relocs
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Thu, 03 Apr 2014 07:47:03 +0000
parents 5f4141ee175b
children fb1e47bebe00
line wrap: on
line source

/*
 * Code for working with the symbol table
 */

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include "filestruct.h"
#include "intstruct.h"
#include "coffconst.h"
#include "globals.h"

static struct classmap {
	int	code;
	char	*str;
} classtab[] = {
	{C_NULL, "NULL"},
	{C_AUTO, "AUTO"},
	{C_EXT, "EXT"},
	{C_STAT, "STAT"},
	{C_REG, "REG"},
	{C_EXTREF, "EXTREF"},
	{C_LABEL, "LABEL"},
	{C_ULABEL, "ULABEL"},
	{C_MOS, "MOS"},
	{C_ARG, "ARG"},
	{C_STRTAG, "STRTAG"},
	{C_MOU, "MOU"},
	{C_UNTAG, "UNTAG"},
	{C_TPDEF, "TPDEF"},
	{C_USTATIC, "USTATIC"},
	{C_ENTAG, "ENTAG"},
	{C_MOE, "MOE"},
	{C_REGPARM, "REGPARM"},
	{C_FIELD, "FIELD"},
	{C_UEXT, "UEXT"},
	{C_STATLAB, "STATLAB"},
	{C_EXTLAB, "EXTLAB"},
	{C_SYSTEM, "SYSTEM"},
	{C_VARARG, "VARARG"},
	{C_BLOCK, "BLOCK"},
	{C_FCN, "FCN"},
	{C_EOS, "EOS"},
	{C_FILE, "FILE"},
	{C_LINE, "LINE"},
	{0, 0}
};

char *
storage_class_to_string(code, numbuf)
	char *numbuf;
{
	struct classmap *tp;

	for (tp = classtab; tp->str; tp++)
		if (tp->code == code)
			return(tp->str);
	sprintf(numbuf, "%d", code);
	return(numbuf);
}

dump_symtab()
{
	unsigned n;
	struct internal_syment *sym;
	char *sec, secstr[8];
	char *class, classbuf[8];

	printf("%-5s %-30s %-4s %-7s %-12s %-8s\n",
		"Num", "Name", "Type", "Class", "Section", "Value");
	for (n = 0; n < nsymtab; n++) {
		sym = symtab[n];
		if (!sym)
			continue;
		if (sym->section)
			sec = sym->section->name;
		else {
			sprintf(secstr, "%d", sym->scnum);
			sec = secstr;
		}
		class = storage_class_to_string(sym->class, classbuf);
		printf("%-5u %-30s %04X %-7s %-12s %08X%s\n",
			n, sym->name, sym->type, class,
			sec, sym->value, sym->aux ? " Aux" : "");
	}
	return(0);
}

extern_profile_report(heading)
	char *heading;
{
	unsigned n;
	int first_extern = -1, last_extern;
	struct internal_syment *sym;
	int defs_started = 0;

	for (n = 0; n < nsymtab; n++) {
		sym = symtab[n];
		if (!sym)
			continue;
		if (sym->class != C_EXT)
			continue;
		if (sym->scnum < 0) {
			fprintf(stderr,
		"symbol entry #%u: unexpected negative scnum for C_EXT\n", n);
			exit(1);
		}
		if (sym->scnum == 0) {	/* undef external ref */
			if (first_extern < 0)
				first_extern = n;
			last_extern = n;
			continue;
		}
		if (!defs_started) {
			printf("%s defines:\n\n", heading);
			defs_started = 1;
		}
		printf("%s (%s)\n", sym->name, sym->section->name);
	}
	if (defs_started)
		putchar('\n');
	if (first_extern < 0)
		return(0);
	printf("%s references:\n\n", heading);
	for (n = first_extern; n <= last_extern; n++) {
		sym = symtab[n];
		if (!sym)
			continue;
		if (sym->class != C_EXT || sym->scnum)
			continue;
		printf("%s\n", sym->name);
	}
	putchar('\n');
	return(0);
}

cmd_profile()
{
	get_int_section_table();
	get_int_symbol_table();
	extern_profile_report(objfilename);
	exit(0);
}

static void
initial_fill_for_sort(sec)
	struct internal_scnhdr *sec;
{
	unsigned n, m;
	struct internal_syment *sym;

	m = 0;
	for (n = 0; n < nsymtab; n++) {
		sym = symtab[n];
		if (!sym)
			continue;
		if (sym->section != sec)
			continue;
		sec->sorted_symbols[m++] = sym;
	}
}

static int
compare_for_sort(p1, p2)
	struct internal_syment **p1, **p2;
{
	/* sort by value first */
	if ((*p1)->value < (*p2)->value)
		return(-1);
	if ((*p1)->value > (*p2)->value)
		return(1);
	/* if same value, retain the original symtab order */
	if ((*p1)->number < (*p2)->number)
		return(-1);
	if ((*p1)->number > (*p2)->number)
		return(1);
	else
		return(0);
}

void
sort_symbols_of_sec(sec)
	struct internal_scnhdr *sec;
{
	if (sec->sorted_symbols)
		return;
	if (!sec->nsymbols) {
		fprintf(stderr,
	"BUG: sort_symbols_of_sec() called for section \"%s\" w/o symbols\n",
			sec->name);
		exit(1);
	}
	sec->sorted_symbols = malloc(sizeof(void *) * sec->nsymbols);
	if (!sec->sorted_symbols) {
		perror("malloc");
		exit(1);
	}
	initial_fill_for_sort(sec);
	qsort(sec->sorted_symbols, sec->nsymbols, sizeof(void *),
		compare_for_sort);
}

void
sort_symbols_of_all_sec()
{
	unsigned n;
	struct internal_scnhdr *sec;

	for (n = 0; n < nsections; n++) {
		sec = sections + n;
		if (!sec->nsymbols)
			continue;
		sort_symbols_of_sec(sec);
	}
}

cmd_nm()
{
	unsigned n, m;
	struct internal_scnhdr *sec;
	struct internal_syment *sym;
	char classbuf[8];

	get_int_section_table();
	get_int_symbol_table();
	for (n = 0; n < nsections; n++) {
		sec = sections + n;
		if (!sec->nsymbols)
			continue;
		printf("%s:\n\n", sec->name);
		sort_symbols_of_sec(sec);
		for (m = 0; m < sec->nsymbols; m++) {
			sym = sec->sorted_symbols[m];
			printf("%08X %-7s %s\n", sym->value,
				storage_class_to_string(sym->class, classbuf),
				sym->name);
		}
		putchar('\n');
	}
	exit(0);
}