diff ticoff/profile.c @ 119:fb1e47bebe00

tiobjd: sorted profile output
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Fri, 04 Apr 2014 05:11:32 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ticoff/profile.c	Fri Apr 04 05:11:32 2014 +0000
@@ -0,0 +1,158 @@
+/*
+ * It is handy to have a "profile" of what functions and variables
+ * a given module defines (presents to the rest of the fw) and what
+ * it references.  This profile is constructed from the symbol table.
+ *
+ * Experience indicates that the order of these symbols in the
+ * artifact symtab is often "random", and an alphabetic sort is
+ * expected to improve readability.  This module contains the
+ * messy code.
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include "intstruct.h"
+#include "coffconst.h"
+#include "globals.h"
+
+static int
+is_symbol_text_def(sym)
+	struct internal_syment *sym;
+{
+	if (!sym->section)
+		return(0);
+	if (!strncmp(sym->section->name, ".text", 5))
+		return(1);
+	else
+		return(0);
+}
+
+static int
+is_symbol_nontext_def(sym)
+	struct internal_syment *sym;
+{
+	if (!sym->section)
+		return(0);
+	if (!strncmp(sym->section->name, ".text", 5))
+		return(0);
+	else
+		return(1);
+}
+
+static int
+is_symbol_extref(sym)
+	struct internal_syment *sym;
+{
+	if (sym->section)
+		return(0);
+	else
+		return(1);
+}
+
+static int
+compare_for_sort(p1, p2)
+	struct internal_syment **p1, **p2;
+{
+	return strcmp((*p1)->name, (*p2)->name);
+}
+
+static void
+list_class(firstidx, lastidx, total, checkfunc, printsec)
+	unsigned firstidx, lastidx, total;
+	int (*checkfunc)();
+{
+	struct internal_syment **array, *sym;
+	unsigned n, m;
+
+	array = malloc(sizeof(void *) * total);
+	if (!array) {
+		perror("malloc");
+		exit(1);
+	}
+	m = 0;
+	for (n = firstidx; n <= lastidx; n++) {
+		sym = symtab[n];
+		if (!sym)
+			continue;
+		if (sym->class != C_EXT)
+			continue;
+		if (!checkfunc(sym))
+			continue;
+		array[m++] = sym;
+	}
+	if (m != total) {
+		fprintf(stderr, "BUG: symbol class miscount in profile gen\n");
+		exit(1);
+	}
+	qsort(array, total, sizeof(void *), compare_for_sort);
+	for (n = 0; n < total; n++) {
+		sym = array[n];
+		if (printsec)
+			printf("%s (%s)\n", sym->name, sym->section->name);
+		else
+			printf("%s\n", sym->name);
+	}
+	free(array);
+	putchar('\n');
+}
+
+extern_profile_report(heading)
+	char *heading;
+{
+	unsigned n;
+	int first_extern = -1, last_extern;
+	struct internal_syment *sym;
+	unsigned defs_text = 0, defs_nontext = 0, extrefs = 0;
+
+	for (n = 0; n < nsymtab; n++) {
+		sym = symtab[n];
+		if (!sym)
+			continue;
+		if (sym->class != C_EXT)
+			continue;
+		if (first_extern < 0)
+			first_extern = n;
+		last_extern = n;
+		if (sym->scnum < 0) {
+			fprintf(stderr,
+		"symbol entry #%u: unexpected negative scnum for C_EXT\n", n);
+			exit(1);
+		}
+		if (sym->scnum == 0)
+			extrefs++;
+		else if (!strncmp(sym->section->name, ".text", 5))
+			defs_text++;
+		else
+			defs_nontext++;
+	}
+	if (first_extern < 0) {
+		printf("%s has no external symbols!\n", heading);
+		return(1);
+	}
+	if (defs_text || defs_nontext) {
+		printf("%s defines:\n\n", heading);
+		if (defs_text)
+			list_class(first_extern, last_extern, defs_text,
+					is_symbol_text_def, 1);
+		if (defs_nontext)
+			list_class(first_extern, last_extern, defs_nontext,
+					is_symbol_nontext_def, 1);
+	}
+	if (extrefs) {
+		printf("%s references:\n\n", heading);
+		list_class(first_extern, last_extern, extrefs,
+				is_symbol_extref, 0);
+	}
+	return(0);
+}
+
+cmd_profile()
+{
+	get_int_section_table();
+	get_int_symbol_table();
+	extern_profile_report(objfilename);
+	exit(0);
+}