/*------------------------------------------------------------------------*/ GRAPH* build_graph_u(VINDEX vertex_size, EINDEX edge_size, MEM_POOL* m) { GRAPH *g; int i; GR_ASSERT(vertex_size >= 0, "build_graph_u vertex_size < 0\n"); GR_ASSERT(edge_size >= 0, "build_graph_u edge_size < 0\n"); g = (GRAPH*) MEM_POOL_Alloc(m, sizeof(GRAPH)); GR_ASSERT (g != 0, "build_graph_u g == 0\n"); memset(g, 0, sizeof(GRAPH)); if (vertex_size != 0) /* build the vertices */ { GRAPH_v(g) = (VERTEX*) MEM_POOL_Alloc(m, sizeof(VERTEX)*vertex_size); GR_ASSERT (GRAPH_v(g) != 0, "build_graph_u graph_v(g) == 0\n"); memset(GRAPH_v(g), 0, sizeof(VERTEX)*vertex_size); } if (edge_size != 0) /* build the edges */ { GRAPH_e(g) = (EDGE*) MEM_POOL_Alloc(m, sizeof(EDGE)*edge_size); GR_ASSERT (GRAPH_e(g) != 0, "build_graph_u graph_e(g) == 0\n"); memset(GRAPH_e(g), 0, sizeof(EDGE)*edge_size); } /*----------------------------set up the vertices-------------------------*/ GRAPH_vcnt(g) = 0; /* used vertices */ for (i = 0; i<vertex_size; ++i) { VERTEX_from(&GRAPH_v_i(g,i)) = i+1; /* set the linked list of free vertices */ VERTEX_fcnt(&GRAPH_v_i(g,i)) = -1; /* node is not being used */ } /* last free vertex points to no entry */ VERTEX_from(&GRAPH_v_i(g,vertex_size-1)) = INVALID_VINDEX; GRAPH_vfree(g) = 0; /* free vertices = total added vertices */ GRAPH_vmax(g) = vertex_size; /* max vertices = new maximum */ /*----------------------------set up the edges----------------------------*/ GRAPH_ecnt(g) = 0; /* used edges */ for (i = 0; i<edge_size; ++i) { EDGE_nfrom(&GRAPH_e_i(g,i)) = i+1; /* set the linked list of free edges */ EDGE_from(&GRAPH_e_i(g,i)) = INVALID_VINDEX; /* edge is not being used */ } /* last free edge points to no entry */ EDGE_nfrom(&GRAPH_e_i(g, edge_size-1)) = -1; GRAPH_efree(g) = 0; /* free edges */ GRAPH_emax(g) = edge_size; /* total edges */ GRAPH_root(g) = INVALID_VINDEX; /* no root */ GRAPH_m(g) = m; return g; }
DFN * Depth_First_Ordering ( GRAPH *g, MEM_POOL* m ) { VINDEX vertex_count = GRAPH_vcnt(g); EINDEX edge_count = GRAPH_ecnt(g); int vertex_max = GRAPH_vmax(g); DFN *d; BOOL *visit; /* Validate and trace: */ GR_ASSERT ( GRAPH_root(g) != INVALID_VINDEX, "Invalid root g for graph\n"); printf ("Depth_First_Ordering: vertex count = %d \n", vertex_count ); /* Allocate the DFN struct: */ d = (DFN*) MEM_POOL_Alloc ( m, sizeof(DFN) ); GR_ASSERT(d != NULL, "Depth_First_Ordering: d" ); DFN_v_list(d) = (VINDEX *) MEM_POOL_Alloc ( m, sizeof(VINDEX) * vertex_count ); GR_ASSERT(DFN_v_list(d) != NULL, "Depth_First_Ordering: list" ); DFN_user(d) = (void *) MEM_POOL_Alloc ( m, sizeof(void *) * vertex_count ); GR_ASSERT(DFN_user(d) != NULL, "Depth_First_Ordering: user" ); /* Allocate work array to keep track of visited vertices: */ visit = (BOOL *) MEM_POOL_Alloc ( m, sizeof(BOOL)*vertex_max ); GR_ASSERT ( visit != NULL, "Depth_First_Ordering: visit" ); memset ( visit, 0, sizeof(BOOL)*vertex_max ); /* Initialize the DFN struct -- set end and first to point beyond * the first element: */ DFN_first(d) = DFN_end(d) = vertex_count; /* Go do the depth-first walk from the root: */ Search ( g, GRAPH_root(g), d, visit, INVALID_EINDEX ); /* Free work array: */ MEM_POOL_FREE(m, visit); return(d); }
/*------------------------------------------------------------------------*/ GRAPH* build_graph(MEM_POOL* m) { GRAPH *g; g = (GRAPH*) MEM_POOL_Alloc(m, sizeof(GRAPH)); memset(g, 0, sizeof(GRAPH)); GR_ASSERT (g != 0, "build_graph g == 0\n"); GRAPH_vcnt(g) = 0; /* total vertices */ GRAPH_ecnt(g) = 0; /* total edges */ GRAPH_vfree(g) = -1; /* free vertices */ GRAPH_efree(g) = -1; /* free edges */ GRAPH_root(g) = INVALID_VINDEX; /* no root */ GRAPH_m(g) = m; return g; }
void build_call_graph(counts_entry *pc, long num_entry, Elf64_Sym *symtab, int symcount, int symstart, char *strtab, char *count_strtab) { int i, count, j; long k; char *name; GRAPH *graph; count = 0; pun = MALLOC(num_entry * sizeof(unique_name)); ASSERT(pun, "cannot malloc unique struct"); c = MALLOC(num_entry * sizeof(map2unique)); ASSERT(c, "cannot malloc map2unique array"); for (i = 0; i < num_entry; i++) { name = get_name(pc[i].caller, pc[i].caller_name_idx, symtab, symcount, symstart, strtab, count_strtab); j = add_unique_name(name, pc[i].caller, pun, count); if (j == NOT_FOUND) { c[i].caller = count; count++; } else c[i].caller = j; name = get_name(pc[i].callee, pc[i].callee_name_idx, symtab, symcount, symstart, strtab, count_strtab); j = add_unique_name(name, pc[i].callee, pun, count); if (j == NOT_FOUND) { c[i].callee = count; count++; } else c[i].callee = j; } graph = build_graph_u(DEF_VERTEX_SIZE, DEF_EDGE_SIZE, dummy); for (i = 0; i < count; i++) { VINDEX idx; idx = add_vertex(graph, (void *)&pun[i]); #ifdef _DEBUG printf("add_vertex: %s (%d)\n",pun[i].name, idx); #endif pun[i].idx = idx; } for (i = 0; i < num_entry; i++) { c[i].edge_idx = add_edge(graph, pun[c[i].caller].idx, pun[c[i].callee].idx, &pun[i]); #ifdef _DEBUG printf("add_edge: %s, --> %s (%d)\n",pun[c[i].caller].name, pun[c[i].callee].name, c[i].edge_idx); #endif k = pr_dyn_count(c[i].edge_idx, num_entry); set_edge_u(graph, c[i].edge_idx, &carray[k].count); if (GRAPH_root(graph) == INVALID_VINDEX ) if (strcmp(pun[c[i].caller].name, "main") == 0) GRAPH_root(graph) = pun[c[i].caller].idx; } { DFN *d; d = Depth_First_Ordering(graph, dummy); Print_DFN(d, graph, (void (*)())pr_vertex_name, pr_count); } }