probe-finder.c (a820cd3d25c2891028b5f296a8a871ce6dd92c0d) probe-finder.c (293d5b43948309434568f4dcbb36cce4c3c51bd5)
1/*
2 * probe-finder.c : C expression to kprobe event converter
3 *
4 * Written by Masami Hiramatsu <mhiramat@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or

--- 25 unchanged lines hidden (view full) ---

34#include <linux/bitops.h>
35#include "event.h"
36#include "dso.h"
37#include "debug.h"
38#include "intlist.h"
39#include "util.h"
40#include "symbol.h"
41#include "probe-finder.h"
1/*
2 * probe-finder.c : C expression to kprobe event converter
3 *
4 * Written by Masami Hiramatsu <mhiramat@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or

--- 25 unchanged lines hidden (view full) ---

34#include <linux/bitops.h>
35#include "event.h"
36#include "dso.h"
37#include "debug.h"
38#include "intlist.h"
39#include "util.h"
40#include "symbol.h"
41#include "probe-finder.h"
42#include "probe-file.h"
42
43/* Kprobe tracer basic type is up to u64 */
44#define MAX_BASIC_TYPE_BITS 64
45
46/* Dwarf FL wrappers */
47static char *debuginfo_path; /* Currently dummy */
48
49static const Dwfl_Callbacks offline_callbacks = {

--- 115 unchanged lines hidden (view full) ---

165/*
166 * Convert a location into trace_arg.
167 * If tvar == NULL, this just checks variable can be converted.
168 * If fentry == true and vr_die is a parameter, do huristic search
169 * for the location fuzzed by function entry mcount.
170 */
171static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
172 Dwarf_Op *fb_ops, Dwarf_Die *sp_die,
43
44/* Kprobe tracer basic type is up to u64 */
45#define MAX_BASIC_TYPE_BITS 64
46
47/* Dwarf FL wrappers */
48static char *debuginfo_path; /* Currently dummy */
49
50static const Dwfl_Callbacks offline_callbacks = {

--- 115 unchanged lines hidden (view full) ---

166/*
167 * Convert a location into trace_arg.
168 * If tvar == NULL, this just checks variable can be converted.
169 * If fentry == true and vr_die is a parameter, do huristic search
170 * for the location fuzzed by function entry mcount.
171 */
172static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
173 Dwarf_Op *fb_ops, Dwarf_Die *sp_die,
174 unsigned int machine,
173 struct probe_trace_arg *tvar)
174{
175 Dwarf_Attribute attr;
176 Dwarf_Addr tmp = 0;
177 Dwarf_Op *op;
178 size_t nops;
179 unsigned int regn;
180 Dwarf_Word offs = 0;

--- 79 unchanged lines hidden (view full) ---

260 } else {
261 pr_debug("DW_OP %x is not supported.\n", op->atom);
262 return -ENOTSUP;
263 }
264
265 if (!tvar)
266 return ret2;
267
175 struct probe_trace_arg *tvar)
176{
177 Dwarf_Attribute attr;
178 Dwarf_Addr tmp = 0;
179 Dwarf_Op *op;
180 size_t nops;
181 unsigned int regn;
182 Dwarf_Word offs = 0;

--- 79 unchanged lines hidden (view full) ---

262 } else {
263 pr_debug("DW_OP %x is not supported.\n", op->atom);
264 return -ENOTSUP;
265 }
266
267 if (!tvar)
268 return ret2;
269
268 regs = get_arch_regstr(regn);
270 regs = get_dwarf_regstr(regn, machine);
269 if (!regs) {
270 /* This should be a bug in DWARF or this tool */
271 pr_warning("Mapping for the register number %u "
272 "missing on this architecture.\n", regn);
273 return -ENOTSUP;
274 }
275
276 tvar->value = strdup(regs);

--- 15 unchanged lines hidden (view full) ---

292 const char *cast)
293{
294 struct probe_trace_arg_ref **ref_ptr = &tvar->ref;
295 Dwarf_Die type;
296 char buf[16];
297 char sbuf[STRERR_BUFSIZE];
298 int bsize, boffs, total;
299 int ret;
271 if (!regs) {
272 /* This should be a bug in DWARF or this tool */
273 pr_warning("Mapping for the register number %u "
274 "missing on this architecture.\n", regn);
275 return -ENOTSUP;
276 }
277
278 tvar->value = strdup(regs);

--- 15 unchanged lines hidden (view full) ---

294 const char *cast)
295{
296 struct probe_trace_arg_ref **ref_ptr = &tvar->ref;
297 Dwarf_Die type;
298 char buf[16];
299 char sbuf[STRERR_BUFSIZE];
300 int bsize, boffs, total;
301 int ret;
300 char sign;
302 char prefix;
301
302 /* TODO: check all types */
303
304 /* TODO: check all types */
303 if (cast && strcmp(cast, "string") != 0 &&
305 if (cast && strcmp(cast, "string") != 0 && strcmp(cast, "x") != 0 &&
304 strcmp(cast, "s") != 0 && strcmp(cast, "u") != 0) {
305 /* Non string type is OK */
306 strcmp(cast, "s") != 0 && strcmp(cast, "u") != 0) {
307 /* Non string type is OK */
306 /* and respect signedness cast */
308 /* and respect signedness/hexadecimal cast */
307 tvar->type = strdup(cast);
308 return (tvar->type == NULL) ? -ENOMEM : 0;
309 }
310
311 bsize = dwarf_bitsize(vr_die);
312 if (bsize > 0) {
313 /* This is a bitfield */
314 boffs = dwarf_bitoffset(vr_die);

--- 45 unchanged lines hidden (view full) ---

360 dwarf_diename(vr_die));
361 return -EINVAL;
362 }
363 tvar->type = strdup(cast);
364 return (tvar->type == NULL) ? -ENOMEM : 0;
365 }
366
367 if (cast && (strcmp(cast, "u") == 0))
309 tvar->type = strdup(cast);
310 return (tvar->type == NULL) ? -ENOMEM : 0;
311 }
312
313 bsize = dwarf_bitsize(vr_die);
314 if (bsize > 0) {
315 /* This is a bitfield */
316 boffs = dwarf_bitoffset(vr_die);

--- 45 unchanged lines hidden (view full) ---

362 dwarf_diename(vr_die));
363 return -EINVAL;
364 }
365 tvar->type = strdup(cast);
366 return (tvar->type == NULL) ? -ENOMEM : 0;
367 }
368
369 if (cast && (strcmp(cast, "u") == 0))
368 sign = 'u';
370 prefix = 'u';
369 else if (cast && (strcmp(cast, "s") == 0))
371 else if (cast && (strcmp(cast, "s") == 0))
370 sign = 's';
372 prefix = 's';
373 else if (cast && (strcmp(cast, "x") == 0) &&
374 probe_type_is_available(PROBE_TYPE_X))
375 prefix = 'x';
371 else
376 else
372 sign = die_is_signed_type(&type) ? 's' : 'u';
377 prefix = die_is_signed_type(&type) ? 's' :
378 probe_type_is_available(PROBE_TYPE_X) ? 'x' : 'u';
373
374 ret = dwarf_bytesize(&type);
375 if (ret <= 0)
376 /* No size ... try to use default type */
377 return 0;
378 ret = BYTES_TO_BITS(ret);
379
380 /* Check the bitwidth */
381 if (ret > MAX_BASIC_TYPE_BITS) {
382 pr_info("%s exceeds max-bitwidth. Cut down to %d bits.\n",
383 dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
384 ret = MAX_BASIC_TYPE_BITS;
385 }
379
380 ret = dwarf_bytesize(&type);
381 if (ret <= 0)
382 /* No size ... try to use default type */
383 return 0;
384 ret = BYTES_TO_BITS(ret);
385
386 /* Check the bitwidth */
387 if (ret > MAX_BASIC_TYPE_BITS) {
388 pr_info("%s exceeds max-bitwidth. Cut down to %d bits.\n",
389 dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
390 ret = MAX_BASIC_TYPE_BITS;
391 }
386 ret = snprintf(buf, 16, "%c%d", sign, ret);
392 ret = snprintf(buf, 16, "%c%d", prefix, ret);
387
388formatted:
389 if (ret < 0 || ret >= 16) {
390 if (ret >= 16)
391 ret = -E2BIG;
392 pr_warning("Failed to convert variable type: %s\n",
393 str_error_r(-ret, sbuf, sizeof(sbuf)));
394 return ret;

--- 138 unchanged lines hidden (view full) ---

533{
534 Dwarf_Die die_mem;
535 int ret;
536
537 pr_debug("Converting variable %s into trace event.\n",
538 dwarf_diename(vr_die));
539
540 ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
393
394formatted:
395 if (ret < 0 || ret >= 16) {
396 if (ret >= 16)
397 ret = -E2BIG;
398 pr_warning("Failed to convert variable type: %s\n",
399 str_error_r(-ret, sbuf, sizeof(sbuf)));
400 return ret;

--- 138 unchanged lines hidden (view full) ---

539{
540 Dwarf_Die die_mem;
541 int ret;
542
543 pr_debug("Converting variable %s into trace event.\n",
544 dwarf_diename(vr_die));
545
546 ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
541 &pf->sp_die, pf->tvar);
547 &pf->sp_die, pf->machine, pf->tvar);
542 if (ret == -ENOENT || ret == -EINVAL) {
543 pr_err("Failed to find the location of the '%s' variable at this address.\n"
544 " Perhaps it has been optimized out.\n"
545 " Use -V with the --range option to show '%s' location range.\n",
546 pf->pvar->var, pf->pvar->var);
547 } else if (ret == -ENOTSUP)
548 pr_err("Sorry, we don't support this variable location yet.\n");
549 else if (ret == 0 && pf->pvar->field) {

--- 546 unchanged lines hidden (view full) ---

1096 return ret;
1097}
1098
1099/* Find probe points from debuginfo */
1100static int debuginfo__find_probes(struct debuginfo *dbg,
1101 struct probe_finder *pf)
1102{
1103 int ret = 0;
548 if (ret == -ENOENT || ret == -EINVAL) {
549 pr_err("Failed to find the location of the '%s' variable at this address.\n"
550 " Perhaps it has been optimized out.\n"
551 " Use -V with the --range option to show '%s' location range.\n",
552 pf->pvar->var, pf->pvar->var);
553 } else if (ret == -ENOTSUP)
554 pr_err("Sorry, we don't support this variable location yet.\n");
555 else if (ret == 0 && pf->pvar->field) {

--- 546 unchanged lines hidden (view full) ---

1102 return ret;
1103}
1104
1105/* Find probe points from debuginfo */
1106static int debuginfo__find_probes(struct debuginfo *dbg,
1107 struct probe_finder *pf)
1108{
1109 int ret = 0;
1104
1105#if _ELFUTILS_PREREQ(0, 142)
1106 Elf *elf;
1107 GElf_Ehdr ehdr;
1110 Elf *elf;
1111 GElf_Ehdr ehdr;
1108 GElf_Shdr shdr;
1109
1110 if (pf->cfi_eh || pf->cfi_dbg)
1111 return debuginfo__find_probe_location(dbg, pf);
1112
1113 /* Get the call frame information from this dwarf */
1114 elf = dwarf_getelf(dbg->dbg);
1115 if (elf == NULL)
1116 return -EINVAL;
1117
1118 if (gelf_getehdr(elf, &ehdr) == NULL)
1119 return -EINVAL;
1120
1112
1113 if (pf->cfi_eh || pf->cfi_dbg)
1114 return debuginfo__find_probe_location(dbg, pf);
1115
1116 /* Get the call frame information from this dwarf */
1117 elf = dwarf_getelf(dbg->dbg);
1118 if (elf == NULL)
1119 return -EINVAL;
1120
1121 if (gelf_getehdr(elf, &ehdr) == NULL)
1122 return -EINVAL;
1123
1121 if (elf_section_by_name(elf, &ehdr, &shdr, ".eh_frame", NULL) &&
1122 shdr.sh_type == SHT_PROGBITS)
1123 pf->cfi_eh = dwarf_getcfi_elf(elf);
1124 pf->machine = ehdr.e_machine;
1124
1125
1125 pf->cfi_dbg = dwarf_getcfi(dbg->dbg);
1126#if _ELFUTILS_PREREQ(0, 142)
1127 do {
1128 GElf_Shdr shdr;
1129
1130 if (elf_section_by_name(elf, &ehdr, &shdr, ".eh_frame", NULL) &&
1131 shdr.sh_type == SHT_PROGBITS)
1132 pf->cfi_eh = dwarf_getcfi_elf(elf);
1133
1134 pf->cfi_dbg = dwarf_getcfi(dbg->dbg);
1135 } while (0);
1126#endif
1127
1128 ret = debuginfo__find_probe_location(dbg, pf);
1129 return ret;
1130}
1131
1132struct local_vars_finder {
1133 struct probe_finder *pf;

--- 11 unchanged lines hidden (view full) ---

1145 struct probe_finder *pf = vf->pf;
1146 int tag;
1147
1148 tag = dwarf_tag(die_mem);
1149 if (tag == DW_TAG_formal_parameter ||
1150 (tag == DW_TAG_variable && vf->vars)) {
1151 if (convert_variable_location(die_mem, vf->pf->addr,
1152 vf->pf->fb_ops, &pf->sp_die,
1136#endif
1137
1138 ret = debuginfo__find_probe_location(dbg, pf);
1139 return ret;
1140}
1141
1142struct local_vars_finder {
1143 struct probe_finder *pf;

--- 11 unchanged lines hidden (view full) ---

1155 struct probe_finder *pf = vf->pf;
1156 int tag;
1157
1158 tag = dwarf_tag(die_mem);
1159 if (tag == DW_TAG_formal_parameter ||
1160 (tag == DW_TAG_variable && vf->vars)) {
1161 if (convert_variable_location(die_mem, vf->pf->addr,
1162 vf->pf->fb_ops, &pf->sp_die,
1153 NULL) == 0) {
1163 pf->machine, NULL) == 0) {
1154 vf->args[vf->nargs].var = (char *)dwarf_diename(die_mem);
1155 if (vf->args[vf->nargs].var == NULL) {
1156 vf->ret = -ENOMEM;
1157 return DIE_FIND_CB_END;
1158 }
1159 pr_debug(" %s", vf->args[vf->nargs].var);
1160 vf->nargs++;
1161 }

--- 146 unchanged lines hidden (view full) ---

1308
1309 vl = &af->vls[af->nvls - 1];
1310
1311 tag = dwarf_tag(die_mem);
1312 if (tag == DW_TAG_formal_parameter ||
1313 tag == DW_TAG_variable) {
1314 ret = convert_variable_location(die_mem, af->pf.addr,
1315 af->pf.fb_ops, &af->pf.sp_die,
1164 vf->args[vf->nargs].var = (char *)dwarf_diename(die_mem);
1165 if (vf->args[vf->nargs].var == NULL) {
1166 vf->ret = -ENOMEM;
1167 return DIE_FIND_CB_END;
1168 }
1169 pr_debug(" %s", vf->args[vf->nargs].var);
1170 vf->nargs++;
1171 }

--- 146 unchanged lines hidden (view full) ---

1318
1319 vl = &af->vls[af->nvls - 1];
1320
1321 tag = dwarf_tag(die_mem);
1322 if (tag == DW_TAG_formal_parameter ||
1323 tag == DW_TAG_variable) {
1324 ret = convert_variable_location(die_mem, af->pf.addr,
1325 af->pf.fb_ops, &af->pf.sp_die,
1316 NULL);
1326 af->pf.machine, NULL);
1317 if (ret == 0 || ret == -ERANGE) {
1318 int ret2;
1319 bool externs = !af->child;
1320
1321 if (strbuf_init(&buf, 64) < 0)
1322 goto error;
1323
1324 if (probe_conf.show_location_range) {

--- 504 unchanged lines hidden ---
1327 if (ret == 0 || ret == -ERANGE) {
1328 int ret2;
1329 bool externs = !af->child;
1330
1331 if (strbuf_init(&buf, 64) < 0)
1332 goto error;
1333
1334 if (probe_conf.show_location_range) {

--- 504 unchanged lines hidden ---