FreeCalypso > hg > freecalypso-reveng
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); +}