Print this page
11506 smatch resync
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/tools/smatch/src/graph.c
+++ new/usr/src/tools/smatch/src/graph.c
1 -/* Copyright © International Business Machines Corp., 2006
1 +/* Copyright © International Business Machines Corp., 2006
2 2 * Adelard LLP, 2007
3 3 *
4 4 * Author: Josh Triplett <josh@freedesktop.org>
5 5 * Dan Sheridan <djs@adelard.com>
6 6 *
7 7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 8 * of this software and associated documentation files (the "Software"), to deal
9 9 * in the Software without restriction, including without limitation the rights
10 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 11 * copies of the Software, and to permit persons to whom the Software is
12 12 * furnished to do so, subject to the following conditions:
13 13 *
14 14 * The above copyright notice and this permission notice shall be included in
15 15 * all copies or substantial portions of the Software.
16 16 *
17 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 23 * THE SOFTWARE.
24 24 */
25 25 #include <stdarg.h>
26 26 #include <stdlib.h>
27 27 #include <stdio.h>
28 28 #include <string.h>
29 29 #include <ctype.h>
30 30 #include <unistd.h>
31 31 #include <fcntl.h>
32 32
33 33 #include "lib.h"
34 34 #include "allocate.h"
35 35 #include "token.h"
36 36 #include "parse.h"
37 37 #include "symbol.h"
38 38 #include "expression.h"
39 39 #include "linearize.h"
40 40
41 41
42 42 /* Draw the subgraph for a given entrypoint. Includes details of loads
43 43 * and stores for globals, and marks return bbs */
44 44 static void graph_ep(struct entrypoint *ep)
45 45 {
46 46 struct basic_block *bb;
47 47 struct instruction *insn;
48 48
49 49 const char *fname, *sname;
50 50
51 51 fname = show_ident(ep->name->ident);
52 52 sname = stream_name(ep->entry->bb->pos.stream);
53 53
54 54 printf("subgraph cluster%p {\n"
55 55 " color=blue;\n"
56 56 " label=<<TABLE BORDER=\"0\" CELLBORDER=\"0\">\n"
57 57 " <TR><TD>%s</TD></TR>\n"
58 58 " <TR><TD><FONT POINT-SIZE=\"21\">%s()</FONT></TD></TR>\n"
59 59 " </TABLE>>;\n"
60 60 " file=\"%s\";\n"
61 61 " fun=\"%s\";\n"
62 62 " ep=bb%p;\n",
63 63 ep, sname, fname, sname, fname, ep->entry->bb);
64 64
65 65 FOR_EACH_PTR(ep->bbs, bb) {
66 66 struct basic_block *child;
67 67 int ret = 0;
68 68 const char * s = ", ls=\"[";
69 69
70 70 /* Node for the bb */
71 71 printf(" bb%p [shape=ellipse,label=%d,line=%d,col=%d",
72 72 bb, bb->pos.line, bb->pos.line, bb->pos.pos);
73 73
74 74
75 75 /* List loads and stores */
76 76 FOR_EACH_PTR(bb->insns, insn) {
77 77 switch(insn->opcode) {
78 78 case OP_STORE:
79 79 if (insn->symbol->type == PSEUDO_SYM) {
80 80 printf("%s store(%s)", s, show_ident(insn->symbol->sym->ident));
81 81 s = ",";
82 82 }
83 83 break;
84 84
85 85 case OP_LOAD:
86 86 if (insn->symbol->type == PSEUDO_SYM) {
87 87 printf("%s load(%s)", s, show_ident(insn->symbol->sym->ident));
88 88 s = ",";
89 89 }
90 90 break;
91 91
92 92 case OP_RET:
93 93 ret = 1;
94 94 break;
95 95
96 96 }
97 97 } END_FOR_EACH_PTR(insn);
98 98 if (s[1] == 0)
99 99 printf("]\"");
100 100 if (ret)
101 101 printf(",op=ret");
102 102 printf("];\n");
103 103
104 104 /* Edges between bbs; lower weight for upward edges */
105 105 FOR_EACH_PTR(bb->children, child) {
106 106 printf(" bb%p -> bb%p [op=br, %s];\n", bb, child,
107 107 (bb->pos.line > child->pos.line) ? "weight=5" : "weight=10");
108 108 } END_FOR_EACH_PTR(child);
109 109 } END_FOR_EACH_PTR(bb);
110 110
111 111 printf("}\n");
112 112 }
113 113
114 114
115 115 /* Insert edges for intra- or inter-file calls, depending on the value
116 116 * of internal. Bold edges are used for calls with destinations;
117 117 * dashed for calls to external functions */
118 118 static void graph_calls(struct entrypoint *ep, int internal)
119 119 {
120 120 struct basic_block *bb;
121 121 struct instruction *insn;
122 122
123 123 show_ident(ep->name->ident);
124 124 stream_name(ep->entry->bb->pos.stream);
125 125
126 126 FOR_EACH_PTR(ep->bbs, bb) {
127 127 if (!bb)
128 128 continue;
129 129 if (!bb->parents && !bb->children && !bb->insns && verbose < 2)
130 130 continue;
131 131
132 132 FOR_EACH_PTR(bb->insns, insn) {
133 133 if (insn->opcode == OP_CALL &&
134 134 internal == !(insn->func->sym->ctype.modifiers & MOD_EXTERN)) {
135 135
136 136 /* Find the symbol for the callee's definition */
137 137 struct symbol * sym;
138 138 if (insn->func->type == PSEUDO_SYM) {
139 139 for (sym = insn->func->sym->ident->symbols;
140 140 sym; sym = sym->next_id) {
141 141 if (sym->namespace & NS_SYMBOL && sym->ep)
142 142 break;
143 143 }
144 144
145 145 if (sym)
146 146 printf("bb%p -> bb%p"
147 147 "[label=%d,line=%d,col=%d,op=call,style=bold,weight=30];\n",
148 148 bb, sym->ep->entry->bb,
149 149 insn->pos.line, insn->pos.line, insn->pos.pos);
150 150 else
151 151 printf("bb%p -> \"%s\" "
152 152 "[label=%d,line=%d,col=%d,op=extern,style=dashed];\n",
153 153 bb, show_pseudo(insn->func),
154 154 insn->pos.line, insn->pos.line, insn->pos.pos);
155 155 }
156 156 }
157 157 } END_FOR_EACH_PTR(insn);
158 158 } END_FOR_EACH_PTR(bb);
159 159 }
160 160
161 161 int main(int argc, char **argv)
162 162 {
163 163 struct string_list *filelist = NULL;
164 164 char *file;
165 165 struct symbol *sym;
166 166
167 167 struct symbol_list *fsyms, *all_syms=NULL;
168 168
169 169 printf("digraph call_graph {\n");
170 170 fsyms = sparse_initialize(argc, argv, &filelist);
171 171 concat_symbol_list(fsyms, &all_syms);
172 172
173 173 /* Linearize all symbols, graph internal basic block
174 174 * structures and intra-file calls */
175 175 FOR_EACH_PTR_NOTAG(filelist, file) {
176 176
177 177 fsyms = sparse(file);
178 178 concat_symbol_list(fsyms, &all_syms);
179 179
180 180 FOR_EACH_PTR(fsyms, sym) {
181 181 expand_symbol(sym);
182 182 linearize_symbol(sym);
183 183 } END_FOR_EACH_PTR(sym);
184 184
185 185 FOR_EACH_PTR(fsyms, sym) {
186 186 if (sym->ep) {
187 187 graph_ep(sym->ep);
188 188 graph_calls(sym->ep, 1);
189 189 }
190 190 } END_FOR_EACH_PTR_NOTAG(sym);
191 191
192 192 } END_FOR_EACH_PTR_NOTAG(file);
193 193
194 194 /* Graph inter-file calls */
195 195 FOR_EACH_PTR(all_syms, sym) {
196 196 if (sym->ep)
197 197 graph_calls(sym->ep, 0);
198 198 } END_FOR_EACH_PTR_NOTAG(sym);
199 199
200 200 printf("}\n");
201 201 return 0;
202 202 }
↓ open down ↓ |
191 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX