diff options
Diffstat (limited to 'tools/perf/util/probe-finder.c')
-rw-r--r-- | tools/perf/util/probe-finder.c | 250 |
1 files changed, 177 insertions, 73 deletions
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index c09e0a9fdf4c..ffb657ffd327 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
@@ -115,7 +115,7 @@ static const Dwfl_Callbacks offline_callbacks = { | |||
115 | }; | 115 | }; |
116 | 116 | ||
117 | /* Get a Dwarf from offline image */ | 117 | /* Get a Dwarf from offline image */ |
118 | static int debuginfo__init_offline_dwarf(struct debuginfo *self, | 118 | static int debuginfo__init_offline_dwarf(struct debuginfo *dbg, |
119 | const char *path) | 119 | const char *path) |
120 | { | 120 | { |
121 | int fd; | 121 | int fd; |
@@ -124,25 +124,25 @@ static int debuginfo__init_offline_dwarf(struct debuginfo *self, | |||
124 | if (fd < 0) | 124 | if (fd < 0) |
125 | return fd; | 125 | return fd; |
126 | 126 | ||
127 | self->dwfl = dwfl_begin(&offline_callbacks); | 127 | dbg->dwfl = dwfl_begin(&offline_callbacks); |
128 | if (!self->dwfl) | 128 | if (!dbg->dwfl) |
129 | goto error; | 129 | goto error; |
130 | 130 | ||
131 | self->mod = dwfl_report_offline(self->dwfl, "", "", fd); | 131 | dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd); |
132 | if (!self->mod) | 132 | if (!dbg->mod) |
133 | goto error; | 133 | goto error; |
134 | 134 | ||
135 | self->dbg = dwfl_module_getdwarf(self->mod, &self->bias); | 135 | dbg->dbg = dwfl_module_getdwarf(dbg->mod, &dbg->bias); |
136 | if (!self->dbg) | 136 | if (!dbg->dbg) |
137 | goto error; | 137 | goto error; |
138 | 138 | ||
139 | return 0; | 139 | return 0; |
140 | error: | 140 | error: |
141 | if (self->dwfl) | 141 | if (dbg->dwfl) |
142 | dwfl_end(self->dwfl); | 142 | dwfl_end(dbg->dwfl); |
143 | else | 143 | else |
144 | close(fd); | 144 | close(fd); |
145 | memset(self, 0, sizeof(*self)); | 145 | memset(dbg, 0, sizeof(*dbg)); |
146 | 146 | ||
147 | return -ENOENT; | 147 | return -ENOENT; |
148 | } | 148 | } |
@@ -180,24 +180,24 @@ static const Dwfl_Callbacks kernel_callbacks = { | |||
180 | }; | 180 | }; |
181 | 181 | ||
182 | /* Get a Dwarf from live kernel image */ | 182 | /* Get a Dwarf from live kernel image */ |
183 | static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self, | 183 | static int debuginfo__init_online_kernel_dwarf(struct debuginfo *dbg, |
184 | Dwarf_Addr addr) | 184 | Dwarf_Addr addr) |
185 | { | 185 | { |
186 | self->dwfl = dwfl_begin(&kernel_callbacks); | 186 | dbg->dwfl = dwfl_begin(&kernel_callbacks); |
187 | if (!self->dwfl) | 187 | if (!dbg->dwfl) |
188 | return -EINVAL; | 188 | return -EINVAL; |
189 | 189 | ||
190 | /* Load the kernel dwarves: Don't care the result here */ | 190 | /* Load the kernel dwarves: Don't care the result here */ |
191 | dwfl_linux_kernel_report_kernel(self->dwfl); | 191 | dwfl_linux_kernel_report_kernel(dbg->dwfl); |
192 | dwfl_linux_kernel_report_modules(self->dwfl); | 192 | dwfl_linux_kernel_report_modules(dbg->dwfl); |
193 | 193 | ||
194 | self->dbg = dwfl_addrdwarf(self->dwfl, addr, &self->bias); | 194 | dbg->dbg = dwfl_addrdwarf(dbg->dwfl, addr, &dbg->bias); |
195 | /* Here, check whether we could get a real dwarf */ | 195 | /* Here, check whether we could get a real dwarf */ |
196 | if (!self->dbg) { | 196 | if (!dbg->dbg) { |
197 | pr_debug("Failed to find kernel dwarf at %lx\n", | 197 | pr_debug("Failed to find kernel dwarf at %lx\n", |
198 | (unsigned long)addr); | 198 | (unsigned long)addr); |
199 | dwfl_end(self->dwfl); | 199 | dwfl_end(dbg->dwfl); |
200 | memset(self, 0, sizeof(*self)); | 200 | memset(dbg, 0, sizeof(*dbg)); |
201 | return -ENOENT; | 201 | return -ENOENT; |
202 | } | 202 | } |
203 | 203 | ||
@@ -205,7 +205,7 @@ static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self, | |||
205 | } | 205 | } |
206 | #else | 206 | #else |
207 | /* With older elfutils, this just support kernel module... */ | 207 | /* With older elfutils, this just support kernel module... */ |
208 | static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self, | 208 | static int debuginfo__init_online_kernel_dwarf(struct debuginfo *dbg, |
209 | Dwarf_Addr addr __maybe_unused) | 209 | Dwarf_Addr addr __maybe_unused) |
210 | { | 210 | { |
211 | const char *path = kernel_get_module_path("kernel"); | 211 | const char *path = kernel_get_module_path("kernel"); |
@@ -216,44 +216,45 @@ static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self, | |||
216 | } | 216 | } |
217 | 217 | ||
218 | pr_debug2("Use file %s for debuginfo\n", path); | 218 | pr_debug2("Use file %s for debuginfo\n", path); |
219 | return debuginfo__init_offline_dwarf(self, path); | 219 | return debuginfo__init_offline_dwarf(dbg, path); |
220 | } | 220 | } |
221 | #endif | 221 | #endif |
222 | 222 | ||
223 | struct debuginfo *debuginfo__new(const char *path) | 223 | struct debuginfo *debuginfo__new(const char *path) |
224 | { | 224 | { |
225 | struct debuginfo *self = zalloc(sizeof(struct debuginfo)); | 225 | struct debuginfo *dbg = zalloc(sizeof(*dbg)); |
226 | if (!self) | 226 | if (!dbg) |
227 | return NULL; | 227 | return NULL; |
228 | 228 | ||
229 | if (debuginfo__init_offline_dwarf(self, path) < 0) { | 229 | if (debuginfo__init_offline_dwarf(dbg, path) < 0) { |
230 | free(self); | 230 | free(dbg); |
231 | self = NULL; | 231 | dbg = NULL; |
232 | } | 232 | } |
233 | 233 | ||
234 | return self; | 234 | return dbg; |
235 | } | 235 | } |
236 | 236 | ||
237 | struct debuginfo *debuginfo__new_online_kernel(unsigned long addr) | 237 | struct debuginfo *debuginfo__new_online_kernel(unsigned long addr) |
238 | { | 238 | { |
239 | struct debuginfo *self = zalloc(sizeof(struct debuginfo)); | 239 | struct debuginfo *dbg = zalloc(sizeof(*dbg)); |
240 | if (!self) | 240 | |
241 | if (!dbg) | ||
241 | return NULL; | 242 | return NULL; |
242 | 243 | ||
243 | if (debuginfo__init_online_kernel_dwarf(self, (Dwarf_Addr)addr) < 0) { | 244 | if (debuginfo__init_online_kernel_dwarf(dbg, (Dwarf_Addr)addr) < 0) { |
244 | free(self); | 245 | free(dbg); |
245 | self = NULL; | 246 | dbg = NULL; |
246 | } | 247 | } |
247 | 248 | ||
248 | return self; | 249 | return dbg; |
249 | } | 250 | } |
250 | 251 | ||
251 | void debuginfo__delete(struct debuginfo *self) | 252 | void debuginfo__delete(struct debuginfo *dbg) |
252 | { | 253 | { |
253 | if (self) { | 254 | if (dbg) { |
254 | if (self->dwfl) | 255 | if (dbg->dwfl) |
255 | dwfl_end(self->dwfl); | 256 | dwfl_end(dbg->dwfl); |
256 | free(self); | 257 | free(dbg); |
257 | } | 258 | } |
258 | } | 259 | } |
259 | 260 | ||
@@ -273,12 +274,15 @@ static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs) | |||
273 | /* | 274 | /* |
274 | * Convert a location into trace_arg. | 275 | * Convert a location into trace_arg. |
275 | * If tvar == NULL, this just checks variable can be converted. | 276 | * If tvar == NULL, this just checks variable can be converted. |
277 | * If fentry == true and vr_die is a parameter, do huristic search | ||
278 | * for the location fuzzed by function entry mcount. | ||
276 | */ | 279 | */ |
277 | static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr, | 280 | static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr, |
278 | Dwarf_Op *fb_ops, | 281 | Dwarf_Op *fb_ops, Dwarf_Die *sp_die, |
279 | struct probe_trace_arg *tvar) | 282 | struct probe_trace_arg *tvar) |
280 | { | 283 | { |
281 | Dwarf_Attribute attr; | 284 | Dwarf_Attribute attr; |
285 | Dwarf_Addr tmp = 0; | ||
282 | Dwarf_Op *op; | 286 | Dwarf_Op *op; |
283 | size_t nops; | 287 | size_t nops; |
284 | unsigned int regn; | 288 | unsigned int regn; |
@@ -291,12 +295,29 @@ static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr, | |||
291 | goto static_var; | 295 | goto static_var; |
292 | 296 | ||
293 | /* TODO: handle more than 1 exprs */ | 297 | /* TODO: handle more than 1 exprs */ |
294 | if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL || | 298 | if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL) |
295 | dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0 || | 299 | return -EINVAL; /* Broken DIE ? */ |
296 | nops == 0) { | 300 | if (dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0) { |
297 | /* TODO: Support const_value */ | 301 | ret = dwarf_entrypc(sp_die, &tmp); |
302 | if (ret || addr != tmp || | ||
303 | dwarf_tag(vr_die) != DW_TAG_formal_parameter || | ||
304 | dwarf_highpc(sp_die, &tmp)) | ||
305 | return -ENOENT; | ||
306 | /* | ||
307 | * This is fuzzed by fentry mcount. We try to find the | ||
308 | * parameter location at the earliest address. | ||
309 | */ | ||
310 | for (addr += 1; addr <= tmp; addr++) { | ||
311 | if (dwarf_getlocation_addr(&attr, addr, &op, | ||
312 | &nops, 1) > 0) | ||
313 | goto found; | ||
314 | } | ||
298 | return -ENOENT; | 315 | return -ENOENT; |
299 | } | 316 | } |
317 | found: | ||
318 | if (nops == 0) | ||
319 | /* TODO: Support const_value */ | ||
320 | return -ENOENT; | ||
300 | 321 | ||
301 | if (op->atom == DW_OP_addr) { | 322 | if (op->atom == DW_OP_addr) { |
302 | static_var: | 323 | static_var: |
@@ -563,7 +584,7 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, | |||
563 | } | 584 | } |
564 | 585 | ||
565 | if (die_find_member(&type, field->name, die_mem) == NULL) { | 586 | if (die_find_member(&type, field->name, die_mem) == NULL) { |
566 | pr_warning("%s(tyep:%s) has no member %s.\n", varname, | 587 | pr_warning("%s(type:%s) has no member %s.\n", varname, |
567 | dwarf_diename(&type), field->name); | 588 | dwarf_diename(&type), field->name); |
568 | return -EINVAL; | 589 | return -EINVAL; |
569 | } | 590 | } |
@@ -600,7 +621,7 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf) | |||
600 | dwarf_diename(vr_die)); | 621 | dwarf_diename(vr_die)); |
601 | 622 | ||
602 | ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops, | 623 | ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops, |
603 | pf->tvar); | 624 | &pf->sp_die, pf->tvar); |
604 | if (ret == -ENOENT) | 625 | if (ret == -ENOENT) |
605 | pr_err("Failed to find the location of %s at this address.\n" | 626 | pr_err("Failed to find the location of %s at this address.\n" |
606 | " Perhaps, it has been optimized out.\n", pf->pvar->var); | 627 | " Perhaps, it has been optimized out.\n", pf->pvar->var); |
@@ -1063,7 +1084,7 @@ static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data) | |||
1063 | } | 1084 | } |
1064 | 1085 | ||
1065 | /* Find probe points from debuginfo */ | 1086 | /* Find probe points from debuginfo */ |
1066 | static int debuginfo__find_probes(struct debuginfo *self, | 1087 | static int debuginfo__find_probes(struct debuginfo *dbg, |
1067 | struct probe_finder *pf) | 1088 | struct probe_finder *pf) |
1068 | { | 1089 | { |
1069 | struct perf_probe_point *pp = &pf->pev->point; | 1090 | struct perf_probe_point *pp = &pf->pev->point; |
@@ -1074,7 +1095,7 @@ static int debuginfo__find_probes(struct debuginfo *self, | |||
1074 | 1095 | ||
1075 | #if _ELFUTILS_PREREQ(0, 142) | 1096 | #if _ELFUTILS_PREREQ(0, 142) |
1076 | /* Get the call frame information from this dwarf */ | 1097 | /* Get the call frame information from this dwarf */ |
1077 | pf->cfi = dwarf_getcfi(self->dbg); | 1098 | pf->cfi = dwarf_getcfi(dbg->dbg); |
1078 | #endif | 1099 | #endif |
1079 | 1100 | ||
1080 | off = 0; | 1101 | off = 0; |
@@ -1093,7 +1114,7 @@ static int debuginfo__find_probes(struct debuginfo *self, | |||
1093 | .data = pf, | 1114 | .data = pf, |
1094 | }; | 1115 | }; |
1095 | 1116 | ||
1096 | dwarf_getpubnames(self->dbg, pubname_search_cb, | 1117 | dwarf_getpubnames(dbg->dbg, pubname_search_cb, |
1097 | &pubname_param, 0); | 1118 | &pubname_param, 0); |
1098 | if (pubname_param.found) { | 1119 | if (pubname_param.found) { |
1099 | ret = probe_point_search_cb(&pf->sp_die, &probe_param); | 1120 | ret = probe_point_search_cb(&pf->sp_die, &probe_param); |
@@ -1103,9 +1124,9 @@ static int debuginfo__find_probes(struct debuginfo *self, | |||
1103 | } | 1124 | } |
1104 | 1125 | ||
1105 | /* Loop on CUs (Compilation Unit) */ | 1126 | /* Loop on CUs (Compilation Unit) */ |
1106 | while (!dwarf_nextcu(self->dbg, off, &noff, &cuhl, NULL, NULL, NULL)) { | 1127 | while (!dwarf_nextcu(dbg->dbg, off, &noff, &cuhl, NULL, NULL, NULL)) { |
1107 | /* Get the DIE(Debugging Information Entry) of this CU */ | 1128 | /* Get the DIE(Debugging Information Entry) of this CU */ |
1108 | diep = dwarf_offdie(self->dbg, off + cuhl, &pf->cu_die); | 1129 | diep = dwarf_offdie(dbg->dbg, off + cuhl, &pf->cu_die); |
1109 | if (!diep) | 1130 | if (!diep) |
1110 | continue; | 1131 | continue; |
1111 | 1132 | ||
@@ -1136,12 +1157,80 @@ found: | |||
1136 | return ret; | 1157 | return ret; |
1137 | } | 1158 | } |
1138 | 1159 | ||
1160 | struct local_vars_finder { | ||
1161 | struct probe_finder *pf; | ||
1162 | struct perf_probe_arg *args; | ||
1163 | int max_args; | ||
1164 | int nargs; | ||
1165 | int ret; | ||
1166 | }; | ||
1167 | |||
1168 | /* Collect available variables in this scope */ | ||
1169 | static int copy_variables_cb(Dwarf_Die *die_mem, void *data) | ||
1170 | { | ||
1171 | struct local_vars_finder *vf = data; | ||
1172 | struct probe_finder *pf = vf->pf; | ||
1173 | int tag; | ||
1174 | |||
1175 | tag = dwarf_tag(die_mem); | ||
1176 | if (tag == DW_TAG_formal_parameter || | ||
1177 | tag == DW_TAG_variable) { | ||
1178 | if (convert_variable_location(die_mem, vf->pf->addr, | ||
1179 | vf->pf->fb_ops, &pf->sp_die, | ||
1180 | NULL) == 0) { | ||
1181 | vf->args[vf->nargs].var = (char *)dwarf_diename(die_mem); | ||
1182 | if (vf->args[vf->nargs].var == NULL) { | ||
1183 | vf->ret = -ENOMEM; | ||
1184 | return DIE_FIND_CB_END; | ||
1185 | } | ||
1186 | pr_debug(" %s", vf->args[vf->nargs].var); | ||
1187 | vf->nargs++; | ||
1188 | } | ||
1189 | } | ||
1190 | |||
1191 | if (dwarf_haspc(die_mem, vf->pf->addr)) | ||
1192 | return DIE_FIND_CB_CONTINUE; | ||
1193 | else | ||
1194 | return DIE_FIND_CB_SIBLING; | ||
1195 | } | ||
1196 | |||
1197 | static int expand_probe_args(Dwarf_Die *sc_die, struct probe_finder *pf, | ||
1198 | struct perf_probe_arg *args) | ||
1199 | { | ||
1200 | Dwarf_Die die_mem; | ||
1201 | int i; | ||
1202 | int n = 0; | ||
1203 | struct local_vars_finder vf = {.pf = pf, .args = args, | ||
1204 | .max_args = MAX_PROBE_ARGS, .ret = 0}; | ||
1205 | |||
1206 | for (i = 0; i < pf->pev->nargs; i++) { | ||
1207 | /* var never be NULL */ | ||
1208 | if (strcmp(pf->pev->args[i].var, "$vars") == 0) { | ||
1209 | pr_debug("Expanding $vars into:"); | ||
1210 | vf.nargs = n; | ||
1211 | /* Special local variables */ | ||
1212 | die_find_child(sc_die, copy_variables_cb, (void *)&vf, | ||
1213 | &die_mem); | ||
1214 | pr_debug(" (%d)\n", vf.nargs - n); | ||
1215 | if (vf.ret < 0) | ||
1216 | return vf.ret; | ||
1217 | n = vf.nargs; | ||
1218 | } else { | ||
1219 | /* Copy normal argument */ | ||
1220 | args[n] = pf->pev->args[i]; | ||
1221 | n++; | ||
1222 | } | ||
1223 | } | ||
1224 | return n; | ||
1225 | } | ||
1226 | |||
1139 | /* Add a found probe point into trace event list */ | 1227 | /* Add a found probe point into trace event list */ |
1140 | static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf) | 1228 | static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf) |
1141 | { | 1229 | { |
1142 | struct trace_event_finder *tf = | 1230 | struct trace_event_finder *tf = |
1143 | container_of(pf, struct trace_event_finder, pf); | 1231 | container_of(pf, struct trace_event_finder, pf); |
1144 | struct probe_trace_event *tev; | 1232 | struct probe_trace_event *tev; |
1233 | struct perf_probe_arg *args; | ||
1145 | int ret, i; | 1234 | int ret, i; |
1146 | 1235 | ||
1147 | /* Check number of tevs */ | 1236 | /* Check number of tevs */ |
@@ -1161,31 +1250,45 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf) | |||
1161 | pr_debug("Probe point found: %s+%lu\n", tev->point.symbol, | 1250 | pr_debug("Probe point found: %s+%lu\n", tev->point.symbol, |
1162 | tev->point.offset); | 1251 | tev->point.offset); |
1163 | 1252 | ||
1164 | /* Find each argument */ | 1253 | /* Expand special probe argument if exist */ |
1165 | tev->nargs = pf->pev->nargs; | 1254 | args = zalloc(sizeof(struct perf_probe_arg) * MAX_PROBE_ARGS); |
1166 | tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs); | 1255 | if (args == NULL) |
1167 | if (tev->args == NULL) | ||
1168 | return -ENOMEM; | 1256 | return -ENOMEM; |
1169 | for (i = 0; i < pf->pev->nargs; i++) { | 1257 | |
1170 | pf->pvar = &pf->pev->args[i]; | 1258 | ret = expand_probe_args(sc_die, pf, args); |
1259 | if (ret < 0) | ||
1260 | goto end; | ||
1261 | |||
1262 | tev->nargs = ret; | ||
1263 | tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs); | ||
1264 | if (tev->args == NULL) { | ||
1265 | ret = -ENOMEM; | ||
1266 | goto end; | ||
1267 | } | ||
1268 | |||
1269 | /* Find each argument */ | ||
1270 | for (i = 0; i < tev->nargs; i++) { | ||
1271 | pf->pvar = &args[i]; | ||
1171 | pf->tvar = &tev->args[i]; | 1272 | pf->tvar = &tev->args[i]; |
1172 | /* Variable should be found from scope DIE */ | 1273 | /* Variable should be found from scope DIE */ |
1173 | ret = find_variable(sc_die, pf); | 1274 | ret = find_variable(sc_die, pf); |
1174 | if (ret != 0) | 1275 | if (ret != 0) |
1175 | return ret; | 1276 | break; |
1176 | } | 1277 | } |
1177 | 1278 | ||
1178 | return 0; | 1279 | end: |
1280 | free(args); | ||
1281 | return ret; | ||
1179 | } | 1282 | } |
1180 | 1283 | ||
1181 | /* Find probe_trace_events specified by perf_probe_event from debuginfo */ | 1284 | /* Find probe_trace_events specified by perf_probe_event from debuginfo */ |
1182 | int debuginfo__find_trace_events(struct debuginfo *self, | 1285 | int debuginfo__find_trace_events(struct debuginfo *dbg, |
1183 | struct perf_probe_event *pev, | 1286 | struct perf_probe_event *pev, |
1184 | struct probe_trace_event **tevs, int max_tevs) | 1287 | struct probe_trace_event **tevs, int max_tevs) |
1185 | { | 1288 | { |
1186 | struct trace_event_finder tf = { | 1289 | struct trace_event_finder tf = { |
1187 | .pf = {.pev = pev, .callback = add_probe_trace_event}, | 1290 | .pf = {.pev = pev, .callback = add_probe_trace_event}, |
1188 | .mod = self->mod, .max_tevs = max_tevs}; | 1291 | .mod = dbg->mod, .max_tevs = max_tevs}; |
1189 | int ret; | 1292 | int ret; |
1190 | 1293 | ||
1191 | /* Allocate result tevs array */ | 1294 | /* Allocate result tevs array */ |
@@ -1196,7 +1299,7 @@ int debuginfo__find_trace_events(struct debuginfo *self, | |||
1196 | tf.tevs = *tevs; | 1299 | tf.tevs = *tevs; |
1197 | tf.ntevs = 0; | 1300 | tf.ntevs = 0; |
1198 | 1301 | ||
1199 | ret = debuginfo__find_probes(self, &tf.pf); | 1302 | ret = debuginfo__find_probes(dbg, &tf.pf); |
1200 | if (ret < 0) { | 1303 | if (ret < 0) { |
1201 | free(*tevs); | 1304 | free(*tevs); |
1202 | *tevs = NULL; | 1305 | *tevs = NULL; |
@@ -1222,7 +1325,8 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data) | |||
1222 | if (tag == DW_TAG_formal_parameter || | 1325 | if (tag == DW_TAG_formal_parameter || |
1223 | tag == DW_TAG_variable) { | 1326 | tag == DW_TAG_variable) { |
1224 | ret = convert_variable_location(die_mem, af->pf.addr, | 1327 | ret = convert_variable_location(die_mem, af->pf.addr, |
1225 | af->pf.fb_ops, NULL); | 1328 | af->pf.fb_ops, &af->pf.sp_die, |
1329 | NULL); | ||
1226 | if (ret == 0) { | 1330 | if (ret == 0) { |
1227 | ret = die_get_varname(die_mem, buf, MAX_VAR_LEN); | 1331 | ret = die_get_varname(die_mem, buf, MAX_VAR_LEN); |
1228 | pr_debug2("Add new var: %s\n", buf); | 1332 | pr_debug2("Add new var: %s\n", buf); |
@@ -1286,14 +1390,14 @@ out: | |||
1286 | } | 1390 | } |
1287 | 1391 | ||
1288 | /* Find available variables at given probe point */ | 1392 | /* Find available variables at given probe point */ |
1289 | int debuginfo__find_available_vars_at(struct debuginfo *self, | 1393 | int debuginfo__find_available_vars_at(struct debuginfo *dbg, |
1290 | struct perf_probe_event *pev, | 1394 | struct perf_probe_event *pev, |
1291 | struct variable_list **vls, | 1395 | struct variable_list **vls, |
1292 | int max_vls, bool externs) | 1396 | int max_vls, bool externs) |
1293 | { | 1397 | { |
1294 | struct available_var_finder af = { | 1398 | struct available_var_finder af = { |
1295 | .pf = {.pev = pev, .callback = add_available_vars}, | 1399 | .pf = {.pev = pev, .callback = add_available_vars}, |
1296 | .mod = self->mod, | 1400 | .mod = dbg->mod, |
1297 | .max_vls = max_vls, .externs = externs}; | 1401 | .max_vls = max_vls, .externs = externs}; |
1298 | int ret; | 1402 | int ret; |
1299 | 1403 | ||
@@ -1305,7 +1409,7 @@ int debuginfo__find_available_vars_at(struct debuginfo *self, | |||
1305 | af.vls = *vls; | 1409 | af.vls = *vls; |
1306 | af.nvls = 0; | 1410 | af.nvls = 0; |
1307 | 1411 | ||
1308 | ret = debuginfo__find_probes(self, &af.pf); | 1412 | ret = debuginfo__find_probes(dbg, &af.pf); |
1309 | if (ret < 0) { | 1413 | if (ret < 0) { |
1310 | /* Free vlist for error */ | 1414 | /* Free vlist for error */ |
1311 | while (af.nvls--) { | 1415 | while (af.nvls--) { |
@@ -1323,7 +1427,7 @@ int debuginfo__find_available_vars_at(struct debuginfo *self, | |||
1323 | } | 1427 | } |
1324 | 1428 | ||
1325 | /* Reverse search */ | 1429 | /* Reverse search */ |
1326 | int debuginfo__find_probe_point(struct debuginfo *self, unsigned long addr, | 1430 | int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, |
1327 | struct perf_probe_point *ppt) | 1431 | struct perf_probe_point *ppt) |
1328 | { | 1432 | { |
1329 | Dwarf_Die cudie, spdie, indie; | 1433 | Dwarf_Die cudie, spdie, indie; |
@@ -1332,10 +1436,10 @@ int debuginfo__find_probe_point(struct debuginfo *self, unsigned long addr, | |||
1332 | int baseline = 0, lineno = 0, ret = 0; | 1436 | int baseline = 0, lineno = 0, ret = 0; |
1333 | 1437 | ||
1334 | /* Adjust address with bias */ | 1438 | /* Adjust address with bias */ |
1335 | addr += self->bias; | 1439 | addr += dbg->bias; |
1336 | 1440 | ||
1337 | /* Find cu die */ | 1441 | /* Find cu die */ |
1338 | if (!dwarf_addrdie(self->dbg, (Dwarf_Addr)addr - self->bias, &cudie)) { | 1442 | if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr - dbg->bias, &cudie)) { |
1339 | pr_warning("Failed to find debug information for address %lx\n", | 1443 | pr_warning("Failed to find debug information for address %lx\n", |
1340 | addr); | 1444 | addr); |
1341 | ret = -EINVAL; | 1445 | ret = -EINVAL; |
@@ -1357,10 +1461,10 @@ int debuginfo__find_probe_point(struct debuginfo *self, unsigned long addr, | |||
1357 | goto post; | 1461 | goto post; |
1358 | } | 1462 | } |
1359 | 1463 | ||
1464 | fname = dwarf_decl_file(&spdie); | ||
1360 | if (addr == (unsigned long)baseaddr) { | 1465 | if (addr == (unsigned long)baseaddr) { |
1361 | /* Function entry - Relative line number is 0 */ | 1466 | /* Function entry - Relative line number is 0 */ |
1362 | lineno = baseline; | 1467 | lineno = baseline; |
1363 | fname = dwarf_decl_file(&spdie); | ||
1364 | goto post; | 1468 | goto post; |
1365 | } | 1469 | } |
1366 | 1470 | ||
@@ -1536,7 +1640,7 @@ static int find_line_range_by_func(struct line_finder *lf) | |||
1536 | return param.retval; | 1640 | return param.retval; |
1537 | } | 1641 | } |
1538 | 1642 | ||
1539 | int debuginfo__find_line_range(struct debuginfo *self, struct line_range *lr) | 1643 | int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr) |
1540 | { | 1644 | { |
1541 | struct line_finder lf = {.lr = lr, .found = 0}; | 1645 | struct line_finder lf = {.lr = lr, .found = 0}; |
1542 | int ret = 0; | 1646 | int ret = 0; |
@@ -1553,7 +1657,7 @@ int debuginfo__find_line_range(struct debuginfo *self, struct line_range *lr) | |||
1553 | struct dwarf_callback_param line_range_param = { | 1657 | struct dwarf_callback_param line_range_param = { |
1554 | .data = (void *)&lf, .retval = 0}; | 1658 | .data = (void *)&lf, .retval = 0}; |
1555 | 1659 | ||
1556 | dwarf_getpubnames(self->dbg, pubname_search_cb, | 1660 | dwarf_getpubnames(dbg->dbg, pubname_search_cb, |
1557 | &pubname_param, 0); | 1661 | &pubname_param, 0); |
1558 | if (pubname_param.found) { | 1662 | if (pubname_param.found) { |
1559 | line_range_search_cb(&lf.sp_die, &line_range_param); | 1663 | line_range_search_cb(&lf.sp_die, &line_range_param); |
@@ -1564,12 +1668,12 @@ int debuginfo__find_line_range(struct debuginfo *self, struct line_range *lr) | |||
1564 | 1668 | ||
1565 | /* Loop on CUs (Compilation Unit) */ | 1669 | /* Loop on CUs (Compilation Unit) */ |
1566 | while (!lf.found && ret >= 0) { | 1670 | while (!lf.found && ret >= 0) { |
1567 | if (dwarf_nextcu(self->dbg, off, &noff, &cuhl, | 1671 | if (dwarf_nextcu(dbg->dbg, off, &noff, &cuhl, |
1568 | NULL, NULL, NULL) != 0) | 1672 | NULL, NULL, NULL) != 0) |
1569 | break; | 1673 | break; |
1570 | 1674 | ||
1571 | /* Get the DIE(Debugging Information Entry) of this CU */ | 1675 | /* Get the DIE(Debugging Information Entry) of this CU */ |
1572 | diep = dwarf_offdie(self->dbg, off + cuhl, &lf.cu_die); | 1676 | diep = dwarf_offdie(dbg->dbg, off + cuhl, &lf.cu_die); |
1573 | if (!diep) | 1677 | if (!diep) |
1574 | continue; | 1678 | continue; |
1575 | 1679 | ||