57 " <TR><TD>%s</TD></TR>\n"
58 " <TR><TD><FONT POINT-SIZE=\"21\">%s()</FONT></TD></TR>\n"
59 " </TABLE>>;\n"
60 " file=\"%s\";\n"
61 " fun=\"%s\";\n"
62 " ep=bb%p;\n",
63 ep, sname, fname, sname, fname, ep->entry->bb);
64
65 FOR_EACH_PTR(ep->bbs, bb) {
66 struct basic_block *child;
67 int ret = 0;
68 const char * s = ", ls=\"[";
69
70 /* Node for the bb */
71 printf(" bb%p [shape=ellipse,label=%d,line=%d,col=%d",
72 bb, bb->pos.line, bb->pos.line, bb->pos.pos);
73
74
75 /* List loads and stores */
76 FOR_EACH_PTR(bb->insns, insn) {
77 switch(insn->opcode) {
78 case OP_STORE:
79 if (insn->symbol->type == PSEUDO_SYM) {
80 printf("%s store(%s)", s, show_ident(insn->symbol->sym->ident));
81 s = ",";
82 }
83 break;
84
85 case OP_LOAD:
86 if (insn->symbol->type == PSEUDO_SYM) {
87 printf("%s load(%s)", s, show_ident(insn->symbol->sym->ident));
88 s = ",";
89 }
90 break;
91
92 case OP_RET:
93 ret = 1;
94 break;
95
96 }
97 } END_FOR_EACH_PTR(insn);
98 if (s[1] == 0)
99 printf("]\"");
100 if (ret)
101 printf(",op=ret");
102 printf("];\n");
103
104 /* Edges between bbs; lower weight for upward edges */
105 FOR_EACH_PTR(bb->children, child) {
106 printf(" bb%p -> bb%p [op=br, %s];\n", bb, child,
107 (bb->pos.line > child->pos.line) ? "weight=5" : "weight=10");
113
114
115 /* Insert edges for intra- or inter-file calls, depending on the value
116 * of internal. Bold edges are used for calls with destinations;
117 * dashed for calls to external functions */
118 static void graph_calls(struct entrypoint *ep, int internal)
119 {
120 struct basic_block *bb;
121 struct instruction *insn;
122
123 show_ident(ep->name->ident);
124 stream_name(ep->entry->bb->pos.stream);
125
126 FOR_EACH_PTR(ep->bbs, bb) {
127 if (!bb)
128 continue;
129 if (!bb->parents && !bb->children && !bb->insns && verbose < 2)
130 continue;
131
132 FOR_EACH_PTR(bb->insns, insn) {
133 if (insn->opcode == OP_CALL &&
134 internal == !(insn->func->sym->ctype.modifiers & MOD_EXTERN)) {
135
136 /* Find the symbol for the callee's definition */
137 struct symbol * sym;
138 if (insn->func->type == PSEUDO_SYM) {
139 for (sym = insn->func->sym->ident->symbols;
140 sym; sym = sym->next_id) {
141 if (sym->namespace & NS_SYMBOL && sym->ep)
142 break;
143 }
144
145 if (sym)
146 printf("bb%p -> bb%p"
147 "[label=%d,line=%d,col=%d,op=call,style=bold,weight=30];\n",
148 bb, sym->ep->entry->bb,
149 insn->pos.line, insn->pos.line, insn->pos.pos);
150 else
151 printf("bb%p -> \"%s\" "
152 "[label=%d,line=%d,col=%d,op=extern,style=dashed];\n",
155 }
156 }
157 } END_FOR_EACH_PTR(insn);
158 } END_FOR_EACH_PTR(bb);
159 }
160
161 int main(int argc, char **argv)
162 {
163 struct string_list *filelist = NULL;
164 char *file;
165 struct symbol *sym;
166
167 struct symbol_list *fsyms, *all_syms=NULL;
168
169 printf("digraph call_graph {\n");
170 fsyms = sparse_initialize(argc, argv, &filelist);
171 concat_symbol_list(fsyms, &all_syms);
172
173 /* Linearize all symbols, graph internal basic block
174 * structures and intra-file calls */
175 FOR_EACH_PTR_NOTAG(filelist, file) {
176
177 fsyms = sparse(file);
178 concat_symbol_list(fsyms, &all_syms);
179
180 FOR_EACH_PTR(fsyms, sym) {
181 expand_symbol(sym);
182 linearize_symbol(sym);
183 } END_FOR_EACH_PTR(sym);
184
185 FOR_EACH_PTR(fsyms, sym) {
186 if (sym->ep) {
187 graph_ep(sym->ep);
188 graph_calls(sym->ep, 1);
189 }
190 } END_FOR_EACH_PTR_NOTAG(sym);
191
192 } END_FOR_EACH_PTR_NOTAG(file);
193
194 /* Graph inter-file calls */
195 FOR_EACH_PTR(all_syms, sym) {
196 if (sym->ep)
197 graph_calls(sym->ep, 0);
198 } END_FOR_EACH_PTR_NOTAG(sym);
199
200 printf("}\n");
201 return 0;
202 }
|
57 " <TR><TD>%s</TD></TR>\n"
58 " <TR><TD><FONT POINT-SIZE=\"21\">%s()</FONT></TD></TR>\n"
59 " </TABLE>>;\n"
60 " file=\"%s\";\n"
61 " fun=\"%s\";\n"
62 " ep=bb%p;\n",
63 ep, sname, fname, sname, fname, ep->entry->bb);
64
65 FOR_EACH_PTR(ep->bbs, bb) {
66 struct basic_block *child;
67 int ret = 0;
68 const char * s = ", ls=\"[";
69
70 /* Node for the bb */
71 printf(" bb%p [shape=ellipse,label=%d,line=%d,col=%d",
72 bb, bb->pos.line, bb->pos.line, bb->pos.pos);
73
74
75 /* List loads and stores */
76 FOR_EACH_PTR(bb->insns, insn) {
77 if (!insn->bb)
78 continue;
79 switch(insn->opcode) {
80 case OP_STORE:
81 if (insn->src->type == PSEUDO_SYM) {
82 printf("%s store(%s)", s, show_ident(insn->src->sym->ident));
83 s = ",";
84 }
85 break;
86
87 case OP_LOAD:
88 if (insn->src->type == PSEUDO_SYM) {
89 printf("%s load(%s)", s, show_ident(insn->src->sym->ident));
90 s = ",";
91 }
92 break;
93
94 case OP_RET:
95 ret = 1;
96 break;
97
98 }
99 } END_FOR_EACH_PTR(insn);
100 if (s[1] == 0)
101 printf("]\"");
102 if (ret)
103 printf(",op=ret");
104 printf("];\n");
105
106 /* Edges between bbs; lower weight for upward edges */
107 FOR_EACH_PTR(bb->children, child) {
108 printf(" bb%p -> bb%p [op=br, %s];\n", bb, child,
109 (bb->pos.line > child->pos.line) ? "weight=5" : "weight=10");
115
116
117 /* Insert edges for intra- or inter-file calls, depending on the value
118 * of internal. Bold edges are used for calls with destinations;
119 * dashed for calls to external functions */
120 static void graph_calls(struct entrypoint *ep, int internal)
121 {
122 struct basic_block *bb;
123 struct instruction *insn;
124
125 show_ident(ep->name->ident);
126 stream_name(ep->entry->bb->pos.stream);
127
128 FOR_EACH_PTR(ep->bbs, bb) {
129 if (!bb)
130 continue;
131 if (!bb->parents && !bb->children && !bb->insns && verbose < 2)
132 continue;
133
134 FOR_EACH_PTR(bb->insns, insn) {
135 if (!insn->bb)
136 continue;
137 if (insn->opcode == OP_CALL &&
138 internal == !(insn->func->sym->ctype.modifiers & MOD_EXTERN)) {
139
140 /* Find the symbol for the callee's definition */
141 struct symbol * sym;
142 if (insn->func->type == PSEUDO_SYM) {
143 for (sym = insn->func->sym->ident->symbols;
144 sym; sym = sym->next_id) {
145 if (sym->namespace & NS_SYMBOL && sym->ep)
146 break;
147 }
148
149 if (sym)
150 printf("bb%p -> bb%p"
151 "[label=%d,line=%d,col=%d,op=call,style=bold,weight=30];\n",
152 bb, sym->ep->entry->bb,
153 insn->pos.line, insn->pos.line, insn->pos.pos);
154 else
155 printf("bb%p -> \"%s\" "
156 "[label=%d,line=%d,col=%d,op=extern,style=dashed];\n",
159 }
160 }
161 } END_FOR_EACH_PTR(insn);
162 } END_FOR_EACH_PTR(bb);
163 }
164
165 int main(int argc, char **argv)
166 {
167 struct string_list *filelist = NULL;
168 char *file;
169 struct symbol *sym;
170
171 struct symbol_list *fsyms, *all_syms=NULL;
172
173 printf("digraph call_graph {\n");
174 fsyms = sparse_initialize(argc, argv, &filelist);
175 concat_symbol_list(fsyms, &all_syms);
176
177 /* Linearize all symbols, graph internal basic block
178 * structures and intra-file calls */
179 FOR_EACH_PTR(filelist, file) {
180
181 fsyms = sparse(file);
182 concat_symbol_list(fsyms, &all_syms);
183
184 FOR_EACH_PTR(fsyms, sym) {
185 expand_symbol(sym);
186 linearize_symbol(sym);
187 } END_FOR_EACH_PTR(sym);
188
189 FOR_EACH_PTR(fsyms, sym) {
190 if (sym->ep) {
191 graph_ep(sym->ep);
192 graph_calls(sym->ep, 1);
193 }
194 } END_FOR_EACH_PTR(sym);
195
196 } END_FOR_EACH_PTR(file);
197
198 /* Graph inter-file calls */
199 FOR_EACH_PTR(all_syms, sym) {
200 if (sym->ep)
201 graph_calls(sym->ep, 0);
202 } END_FOR_EACH_PTR(sym);
203
204 printf("}\n");
205 return 0;
206 }
|