#include "libiberty.h"
#include "gprof.h"
#include "search_list.h"
#include "source.h"
#include "symtab.h"
#include "cg_arcs.h"
#include "cg_print.h"
#include "hist.h"
#include "utils.h"
#include "corefile.h"
#define LESSTHAN -1
#define EQUALTO 0
#define GREATERTHAN 1
static void print_header (void);
static void print_cycle (Sym *);
static int cmp_member (Sym *, Sym *);
static void sort_members (Sym *);
static void print_members (Sym *);
static int cmp_arc (Arc *, Arc *);
static void sort_parents (Sym *);
static void print_parents (Sym *);
static void sort_children (Sym *);
static void print_children (Sym *);
static void print_line (Sym *);
static int cmp_name (const PTR, const PTR);
static int cmp_arc_count (const PTR, const PTR);
static int cmp_fun_nuses (const PTR, const PTR);
static void order_and_dump_functions_by_arcs
(Arc **, unsigned long, int, Arc **, unsigned long *);
extern void bsd_callg_blurb (FILE * fp);
extern void fsf_callg_blurb (FILE * fp);
double print_time = 0.0;
static void
print_header ()
{
if (first_output)
first_output = FALSE;
else
printf ("\f\n");
if (!bsd_style_output)
{
if (print_descriptions)
printf (_("\t\t Call graph (explanation follows)\n\n"));
else
printf (_("\t\t\tCall graph\n\n"));
}
printf (_("\ngranularity: each sample hit covers %ld byte(s)"),
(long) hist_scale * sizeof (UNIT));
if (print_time > 0.0)
printf (_(" for %.2f%% of %.2f seconds\n\n"),
100.0 / print_time, print_time / hz);
else
{
printf (_(" no time propagated\n\n"));
print_time = 1.0;
}
if (bsd_style_output)
{
printf ("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n",
"", "", "", "", _("called"), _("total"), _("parents"));
printf ("%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n",
_("index"), _("%time"), _("self"), _("descendants"),
_("called"), _("self"), _("name"), _("index"));
printf ("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n",
"", "", "", "", _("called"), _("total"), _("children"));
printf ("\n");
}
else
{
printf (_("index %% time self children called name\n"));
}
}
static void
print_cycle (Sym *cyc)
{
char buf[BUFSIZ];
sprintf (buf, "[%d]", cyc->cg.index);
printf (bsd_style_output
? "%-6.6s %5.1f %7.2f %11.2f %7lu"
: "%-6.6s %5.1f %7.2f %7.2f %7lu", buf,
100 * (cyc->cg.prop.self + cyc->cg.prop.child) / print_time,
cyc->cg.prop.self / hz, cyc->cg.prop.child / hz, cyc->ncalls);
if (cyc->cg.self_calls != 0)
printf ("+%-7lu", cyc->cg.self_calls);
else
printf (" %7.7s", "");
printf (_(" <cycle %d as a whole> [%d]\n"), cyc->cg.cyc.num, cyc->cg.index);
}
static int
cmp_member (Sym *left, Sym *right)
{
double left_time = left->cg.prop.self + left->cg.prop.child;
double right_time = right->cg.prop.self + right->cg.prop.child;
unsigned long left_calls = left->ncalls + left->cg.self_calls;
unsigned long right_calls = right->ncalls + right->cg.self_calls;
if (left_time > right_time)
return GREATERTHAN;
if (left_time < right_time)
return LESSTHAN;
if (left_calls > right_calls)
return GREATERTHAN;
if (left_calls < right_calls)
return LESSTHAN;
return EQUALTO;
}
static void
sort_members (Sym *cyc)
{
Sym *todo, *doing, *prev;
todo = cyc->cg.cyc.next;
cyc->cg.cyc.next = 0;
for (doing = todo; doing && doing->cg.cyc.next; doing = todo)
{
todo = doing->cg.cyc.next;
for (prev = cyc; prev->cg.cyc.next; prev = prev->cg.cyc.next)
{
if (cmp_member (doing, prev->cg.cyc.next) == GREATERTHAN)
break;
}
doing->cg.cyc.next = prev->cg.cyc.next;
prev->cg.cyc.next = doing;
}
}
static void
print_members (Sym *cyc)
{
Sym *member;
sort_members (cyc);
for (member = cyc->cg.cyc.next; member; member = member->cg.cyc.next)
{
printf (bsd_style_output
? "%6.6s %5.5s %7.2f %11.2f %7lu"
: "%6.6s %5.5s %7.2f %7.2f %7lu",
"", "", member->cg.prop.self / hz, member->cg.prop.child / hz,
member->ncalls);
if (member->cg.self_calls != 0)
printf ("+%-7lu", member->cg.self_calls);
else
printf (" %7.7s", "");
printf (" ");
print_name (member);
printf ("\n");
}
}
static int
cmp_arc (Arc *left, Arc *right)
{
Sym *left_parent = left->parent;
Sym *left_child = left->child;
Sym *right_parent = right->parent;
Sym *right_child = right->child;
double left_time, right_time;
DBG (TIMEDEBUG,
printf ("[cmp_arc] ");
print_name (left_parent);
printf (" calls ");
print_name (left_child);
printf (" %f + %f %lu/%lu\n", left->time, left->child_time,
left->count, left_child->ncalls);
printf ("[cmp_arc] ");
print_name (right_parent);
printf (" calls ");
print_name (right_child);
printf (" %f + %f %lu/%lu\n", right->time, right->child_time,
right->count, right_child->ncalls);
printf ("\n");
);
if (left_parent == left_child)
return LESSTHAN;
if (right_parent == right_child)
return GREATERTHAN;
if (left_parent->cg.cyc.num != 0 && left_child->cg.cyc.num != 0
&& left_parent->cg.cyc.num == left_child->cg.cyc.num)
{
if (right_parent->cg.cyc.num != 0 && right_child->cg.cyc.num != 0
&& right_parent->cg.cyc.num == right_child->cg.cyc.num)
{
if (left->count < right->count)
return LESSTHAN;
if (left->count > right->count)
return GREATERTHAN;
return EQUALTO;
}
else
{
return LESSTHAN;
}
}
else
{
if (right_parent->cg.cyc.num != 0 && right_child->cg.cyc.num != 0
&& right_parent->cg.cyc.num == right_child->cg.cyc.num)
{
return GREATERTHAN;
}
else
{
left_time = left->time + left->child_time;
right_time = right->time + right->child_time;
if (left_time < right_time)
return LESSTHAN;
if (left_time > right_time)
return GREATERTHAN;
if (left->count < right->count)
return LESSTHAN;
if (left->count > right->count)
return GREATERTHAN;
return EQUALTO;
}
}
}
static void
sort_parents (Sym * child)
{
Arc *arc, *detached, sorted, *prev;
sorted.next_parent = 0;
for (arc = child->cg.parents; arc; arc = detached)
{
detached = arc->next_parent;
for (prev = &sorted; prev->next_parent; prev = prev->next_parent)
{
if (cmp_arc (arc, prev->next_parent) != GREATERTHAN)
break;
}
arc->next_parent = prev->next_parent;
prev->next_parent = arc;
}
child->cg.parents = sorted.next_parent;
}
static void
print_parents (Sym *child)
{
Sym *parent;
Arc *arc;
Sym *cycle_head;
if (child->cg.cyc.head != 0)
cycle_head = child->cg.cyc.head;
else
cycle_head = child;
if (!child->cg.parents)
{
printf (bsd_style_output
? _("%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s <spontaneous>\n")
: _("%6.6s %5.5s %7.7s %7.7s %7.7s %7.7s <spontaneous>\n"),
"", "", "", "", "", "");
return;
}
sort_parents (child);
for (arc = child->cg.parents; arc; arc = arc->next_parent)
{
parent = arc->parent;
if (child == parent || (child->cg.cyc.num != 0
&& parent->cg.cyc.num == child->cg.cyc.num))
{
printf (bsd_style_output
? "%6.6s %5.5s %7.7s %11.11s %7lu %7.7s "
: "%6.6s %5.5s %7.7s %7.7s %7lu %7.7s ",
"", "", "", "",
arc->count, "");
print_name (parent);
printf ("\n");
}
else
{
printf (bsd_style_output
? "%6.6s %5.5s %7.2f %11.2f %7lu/%-7lu "
: "%6.6s %5.5s %7.2f %7.2f %7lu/%-7lu ",
"", "",
arc->time / hz, arc->child_time / hz,
arc->count, cycle_head->ncalls);
print_name (parent);
printf ("\n");
}
}
}
static void
sort_children (Sym *parent)
{
Arc *arc, *detached, sorted, *prev;
sorted.next_child = 0;
for (arc = parent->cg.children; arc; arc = detached)
{
detached = arc->next_child;
for (prev = &sorted; prev->next_child; prev = prev->next_child)
{
if (cmp_arc (arc, prev->next_child) != LESSTHAN)
break;
}
arc->next_child = prev->next_child;
prev->next_child = arc;
}
parent->cg.children = sorted.next_child;
}
static void
print_children (Sym *parent)
{
Sym *child;
Arc *arc;
sort_children (parent);
arc = parent->cg.children;
for (arc = parent->cg.children; arc; arc = arc->next_child)
{
child = arc->child;
if (child == parent || (child->cg.cyc.num != 0
&& child->cg.cyc.num == parent->cg.cyc.num))
{
printf (bsd_style_output
? "%6.6s %5.5s %7.7s %11.11s %7lu %7.7s "
: "%6.6s %5.5s %7.7s %7.7s %7lu %7.7s ",
"", "", "", "", arc->count, "");
print_name (child);
printf ("\n");
}
else
{
printf (bsd_style_output
? "%6.6s %5.5s %7.2f %11.2f %7lu/%-7lu "
: "%6.6s %5.5s %7.2f %7.2f %7lu/%-7lu ",
"", "",
arc->time / hz, arc->child_time / hz,
arc->count, child->cg.cyc.head->ncalls);
print_name (child);
printf ("\n");
}
}
}
static void
print_line (Sym *np)
{
char buf[BUFSIZ];
sprintf (buf, "[%d]", np->cg.index);
printf (bsd_style_output
? "%-6.6s %5.1f %7.2f %11.2f"
: "%-6.6s %5.1f %7.2f %7.2f", buf,
100 * (np->cg.prop.self + np->cg.prop.child) / print_time,
np->cg.prop.self / hz, np->cg.prop.child / hz);
if ((np->ncalls + np->cg.self_calls) != 0)
{
printf (" %7lu", np->ncalls);
if (np->cg.self_calls != 0)
printf ("+%-7lu ", np->cg.self_calls);
else
printf (" %7.7s ", "");
}
else
{
printf (" %7.7s %7.7s ", "", "");
}
print_name (np);
printf ("\n");
}
void
cg_print (Sym ** timesortsym)
{
unsigned int index;
Sym *parent;
if (print_descriptions && bsd_style_output)
bsd_callg_blurb (stdout);
print_header ();
for (index = 0; index < symtab.len + num_cycles; ++index)
{
parent = timesortsym[index];
if ((ignore_zeros && parent->ncalls == 0
&& parent->cg.self_calls == 0 && parent->cg.prop.self == 0
&& parent->cg.prop.child == 0)
|| !parent->cg.print_flag
|| (line_granularity && ! parent->is_func))
continue;
if (!parent->name && parent->cg.cyc.num != 0)
{
print_cycle (parent);
print_members (parent);
}
else
{
print_parents (parent);
print_line (parent);
print_children (parent);
}
if (bsd_style_output)
printf ("\n");
printf ("-----------------------------------------------\n");
if (bsd_style_output)
printf ("\n");
}
free (timesortsym);
if (print_descriptions && !bsd_style_output)
fsf_callg_blurb (stdout);
}
static int
cmp_name (const PTR left, const PTR right)
{
const Sym **npp1 = (const Sym **) left;
const Sym **npp2 = (const Sym **) right;
return strcmp ((*npp1)->name, (*npp2)->name);
}
void
cg_print_index ()
{
unsigned int index;
unsigned int nnames, todo, i, j;
int col, starting_col;
Sym **name_sorted_syms, *sym;
const char *filename;
char buf[20];
int column_width = (output_width - 1) / 3;
name_sorted_syms = (Sym **) xmalloc ((symtab.len + num_cycles) * sizeof (Sym *));
for (index = 0, nnames = 0; index < symtab.len; index++)
{
if (ignore_zeros && symtab.base[index].ncalls == 0
&& symtab.base[index].hist.time == 0)
continue;
name_sorted_syms[nnames++] = &symtab.base[index];
}
qsort (name_sorted_syms, nnames, sizeof (Sym *), cmp_name);
for (index = 1, todo = nnames; index <= num_cycles; index++)
name_sorted_syms[todo++] = &cycle_header[index];
printf ("\f\n");
printf (_("Index by function name\n\n"));
index = (todo + 2) / 3;
for (i = 0; i < index; i++)
{
col = 0;
starting_col = 0;
for (j = i; j < todo; j += index)
{
sym = name_sorted_syms[j];
if (sym->cg.print_flag)
sprintf (buf, "[%d]", sym->cg.index);
else
sprintf (buf, "(%d)", sym->cg.index);
if (j < nnames)
{
if (bsd_style_output)
{
printf ("%6.6s %-19.19s", buf, sym->name);
}
else
{
col += strlen (buf);
for (; col < starting_col + 5; ++col)
putchar (' ');
printf (" %s ", buf);
col += print_name_only (sym);
if (!line_granularity && sym->is_static && sym->file)
{
filename = sym->file->name;
if (!print_path)
{
filename = strrchr (filename, '/');
if (filename)
++filename;
else
filename = sym->file->name;
}
printf (" (%s)", filename);
col += strlen (filename) + 3;
}
}
}
else
{
if (bsd_style_output)
{
printf ("%6.6s ", buf);
sprintf (buf, _("<cycle %d>"), sym->cg.cyc.num);
printf ("%-19.19s", buf);
}
else
{
col += strlen (buf);
for (; col < starting_col + 5; ++col)
putchar (' ');
printf (" %s ", buf);
sprintf (buf, _("<cycle %d>"), sym->cg.cyc.num);
printf ("%s", buf);
col += strlen (buf);
}
}
starting_col += column_width;
}
printf ("\n");
}
free (name_sorted_syms);
}
static int
cmp_arc_count (const PTR left, const PTR right)
{
const Arc **npp1 = (const Arc **) left;
const Arc **npp2 = (const Arc **) right;
if ((*npp1)->count > (*npp2)->count)
return -1;
else if ((*npp1)->count < (*npp2)->count)
return 1;
else
return 0;
}
static int
cmp_fun_nuses (const PTR left, const PTR right)
{
const Sym **npp1 = (const Sym **) left;
const Sym **npp2 = (const Sym **) right;
if ((*npp1)->nuses > (*npp2)->nuses)
return -1;
else if ((*npp1)->nuses < (*npp2)->nuses)
return 1;
else
return 0;
}
void
cg_print_function_ordering ()
{
unsigned long index, used, unused, scratch_index;
unsigned long unplaced_arc_count, high_arc_count, scratch_arc_count;
#ifdef __GNUC__
unsigned long long total_arcs, tmp_arcs_count;
#else
unsigned long total_arcs, tmp_arcs_count;
#endif
Sym **unused_syms, **used_syms, **scratch_syms;
Arc **unplaced_arcs, **high_arcs, **scratch_arcs;
index = 0;
used = 0;
unused = 0;
scratch_index = 0;
unplaced_arc_count = 0;
high_arc_count = 0;
scratch_arc_count = 0;
unused_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
used_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
scratch_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
high_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
scratch_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
unplaced_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
for (index = 0, used = 0, unused = 0; index < symtab.len; index++)
{
if (symtab.base[index].ncalls == 0)
{
if (strcmp (symtab.base[index].name, "<locore>")
&& strcmp (symtab.base[index].name, "<hicore>"))
{
unused_syms[unused++] = &symtab.base[index];
symtab.base[index].has_been_placed = 1;
}
}
else
{
used_syms[used++] = &symtab.base[index];
symtab.base[index].has_been_placed = 0;
symtab.base[index].next = 0;
symtab.base[index].prev = 0;
symtab.base[index].nuses = 0;
}
}
qsort (arcs, numarcs, sizeof (Arc *), cmp_arc_count);
total_arcs = 0;
for (index = 0; index < numarcs; index++)
{
total_arcs += arcs[index]->count;
arcs[index]->has_been_placed = 0;
}
tmp_arcs_count = 0;
for (index = 0; index < numarcs; index++)
{
tmp_arcs_count += arcs[index]->count;
if ((double)tmp_arcs_count / (double)total_arcs > 0.90)
break;
arcs[index]->child->nuses++;
}
memcpy (scratch_syms, used_syms, used * sizeof (Sym *));
qsort (scratch_syms, used, sizeof (Sym *), cmp_fun_nuses);
for (index = 0; index < used / 80; index++)
{
Sym *sym = scratch_syms[index];
Arc *arc;
if (sym->nuses == 5)
break;
arc = sym->cg.children;
while (arc)
{
if (arc->parent != arc->child)
scratch_arcs[scratch_arc_count++] = arc;
arc->has_been_placed = 1;
arc = arc->next_child;
}
arc = sym->cg.parents;
while (arc)
{
if (arc->parent != arc->child)
scratch_arcs[scratch_arc_count++] = arc;
arc->has_been_placed = 1;
arc = arc->next_parent;
}
scratch_index = index;
sym->has_been_placed = 1;
}
for (index = 0; index < scratch_arc_count; index++)
{
Arc *arc = scratch_arcs[index];
if (arc->child->has_been_placed
&& arc->parent->has_been_placed)
{
high_arcs[high_arc_count++] = scratch_arcs[index];
arc->child->has_been_placed = 0;
arc->parent->has_been_placed = 0;
}
}
for (index = 0; index < scratch_index; index++)
{
if (scratch_syms[index]->has_been_placed)
printf ("%s\n", scratch_syms[index]->name);
}
qsort (high_arcs, high_arc_count, sizeof (Arc *), cmp_arc_count);
order_and_dump_functions_by_arcs (high_arcs, high_arc_count, 1,
unplaced_arcs, &unplaced_arc_count);
order_and_dump_functions_by_arcs (arcs, numarcs, 0,
unplaced_arcs, &unplaced_arc_count);
order_and_dump_functions_by_arcs (unplaced_arcs, unplaced_arc_count, 1,
scratch_arcs, &scratch_arc_count);
for (index = 0; index < used; index++)
if (used_syms[index]->has_been_placed == 0)
printf("%s\n", used_syms[index]->name);
for (index = 0; index < unused; index++)
printf("%s\n", unused_syms[index]->name);
unused_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
used_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
scratch_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
high_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
scratch_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
unplaced_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
free (unused_syms);
free (used_syms);
free (scratch_syms);
free (high_arcs);
free (scratch_arcs);
free (unplaced_arcs);
}
#define MOST 0.99
static void
order_and_dump_functions_by_arcs (the_arcs, arc_count, all,
unplaced_arcs, unplaced_arc_count)
Arc **the_arcs;
unsigned long arc_count;
int all;
Arc **unplaced_arcs;
unsigned long *unplaced_arc_count;
{
#ifdef __GNUC__
unsigned long long tmp_arcs, total_arcs;
#else
unsigned long tmp_arcs, total_arcs;
#endif
unsigned int index;
if (! all)
{
total_arcs = 0;
for (index = 0; index < arc_count; index++)
total_arcs += the_arcs[index]->count;
}
else
total_arcs = 0;
tmp_arcs = 0;
for (index = 0; index < arc_count; index++)
{
Sym *sym1, *sym2;
Sym *child, *parent;
tmp_arcs += the_arcs[index]->count;
if (the_arcs[index]->has_been_placed)
continue;
child = the_arcs[index]->child;
parent = the_arcs[index]->parent;
if ((! all && (double)tmp_arcs / (double)total_arcs > MOST)
|| child->has_been_placed || parent->has_been_placed)
{
unplaced_arcs[(*unplaced_arc_count)++] = the_arcs[index];
continue;
}
if (parent->next && parent->prev && child->next && child->prev)
{
unplaced_arcs[(*unplaced_arc_count)++] = the_arcs[index];
continue;
}
if (!parent->next && !parent->prev)
{
int next_count = 0;
int prev_count = 0;
Sym *prev = child;
Sym *next = child;
while (next->next)
{
next = next->next;
next_count++;
}
while (prev->prev)
{
prev = prev->prev;
prev_count++;
}
child = next_count < prev_count ? next : prev;
}
else if (! child->next && !child->prev)
{
int next_count = 0;
int prev_count = 0;
Sym *prev = parent;
Sym *next = parent;
while (next->next)
{
next = next->next;
next_count++;
}
while (prev->prev)
{
prev = prev->prev;
prev_count++;
}
parent = prev_count < next_count ? prev : next;
}
else
{
unplaced_arcs[(*unplaced_arc_count)++] = the_arcs[index];
continue;
}
sym1 = parent;
if (sym1->next)
while (sym1->next)
sym1 = sym1->next;
else
while (sym1->prev)
sym1 = sym1->prev;
sym2 = child;
if (sym2->next)
while (sym2->next)
sym2 = sym2->next;
else
while (sym2->prev)
sym2 = sym2->prev;
if (sym1 == child
&& sym2 == parent)
{
unplaced_arcs[(*unplaced_arc_count)++] = the_arcs[index];
continue;
}
if (parent->next)
{
if (! child->next)
{
parent->prev = child;
child->next = parent;
the_arcs[index]->has_been_placed = 1;
}
}
else if (parent->prev)
{
if (! child->prev)
{
parent->next = child;
child->prev = parent;
the_arcs[index]->has_been_placed = 1;
}
}
else
{
if (child->prev)
{
parent->prev = child;
child->next = parent;
the_arcs[index]->has_been_placed = 1;
}
else
{
parent->next = child;
child->prev = parent;
the_arcs[index]->has_been_placed = 1;
}
}
}
for (index = 0; index < arc_count; index++)
{
Sym *sym;
if (the_arcs[index]->parent->has_been_placed
|| the_arcs[index]->child->has_been_placed)
continue;
sym = the_arcs[index]->parent;
if (sym->next == NULL
&& sym->prev == NULL)
continue;
while (sym->prev)
sym = sym->prev;
while (sym)
{
sym->has_been_placed = 1;
printf ("%s\n", sym->name);
sym = sym->next;
}
}
if (all)
for (index = 0; index < arc_count; index++)
{
Sym *sym;
if (the_arcs[index]->parent->has_been_placed
|| the_arcs[index]->child->has_been_placed)
continue;
sym = the_arcs[index]->parent;
sym->has_been_placed = 1;
printf ("%s\n", sym->name);
}
}
void
cg_print_file_ordering ()
{
unsigned long scratch_arc_count, index;
Arc **scratch_arcs;
char *last;
scratch_arc_count = 0;
scratch_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *));
for (index = 0; index < numarcs; index++)
{
if (! arcs[index]->parent->mapped
|| ! arcs[index]->child->mapped)
arcs[index]->has_been_placed = 1;
}
order_and_dump_functions_by_arcs (arcs, numarcs, 0,
scratch_arcs, &scratch_arc_count);
for (index = 0; index < symtab.len; index++)
{
if (symtab.base[index].mapped
&& ! symtab.base[index].has_been_placed)
printf ("%s\n", symtab.base[index].name);
}
last = NULL;
for (index = 0; index < symbol_map_count; index++)
{
unsigned int index2;
if (last && !strcmp (last, symbol_map[index].file_name))
continue;
for (index2 = 0; index2 < symtab.len; index2++)
{
if (! symtab.base[index2].mapped)
continue;
if (!strcmp (symtab.base[index2].name, symbol_map[index].file_name))
break;
}
if (index2 == symtab.len)
printf ("%s\n", symbol_map[index].file_name);
last = symbol_map[index].file_name;
}
}