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 --- |