22 #include <sys/utsname.h>
23 #include <sys/types.h>
35 #include <linux/bitops.h>
43 #define MAX_BASIC_TYPE_BITS 64
55 if (ln->
line < line) {
58 }
else if (ln->
line == line)
64 pr_debug(
"line list: add a line %u\n", line);
69 INIT_LIST_HEAD(&ln->
list);
70 list_add(&ln->
list, p);
94 static void line_list__free(
struct list_head *head)
97 while (!list_empty(head)) {
105 static char *debuginfo_path;
107 static const Dwfl_Callbacks offline_callbacks = {
108 .find_debuginfo = dwfl_standard_find_debuginfo,
109 .debuginfo_path = &debuginfo_path,
111 .section_address = dwfl_offline_section_address,
114 .find_elf = dwfl_build_id_find_elf,
118 static int debuginfo__init_offline_dwarf(
struct debuginfo *
self,
128 self->dwfl = dwfl_begin(&offline_callbacks);
132 mod = dwfl_report_offline(self->dwfl,
"",
"", fd);
136 self->dbg = dwfl_module_getdwarf(mod, &self->bias);
143 dwfl_end(self->dwfl);
146 memset(
self, 0,
sizeof(*
self));
151 #if _ELFUTILS_PREREQ(0, 148)
153 static int __linux_kernel_find_elf(Dwfl_Module *mod,
162 pr_debug2(
"Use file %s for %s\n", path, module_name);
166 *file_name = strdup(path);
171 return dwfl_linux_kernel_find_elf(mod, userdata, module_name, base,
175 static const Dwfl_Callbacks kernel_callbacks = {
176 .find_debuginfo = dwfl_standard_find_debuginfo,
177 .debuginfo_path = &debuginfo_path,
179 .find_elf = __linux_kernel_find_elf,
180 .section_address = dwfl_linux_kernel_module_section_address,
184 static int debuginfo__init_online_kernel_dwarf(
struct debuginfo *
self,
187 self->dwfl = dwfl_begin(&kernel_callbacks);
192 dwfl_linux_kernel_report_kernel(self->dwfl);
193 dwfl_linux_kernel_report_modules(self->dwfl);
195 self->dbg = dwfl_addrdwarf(self->dwfl, addr, &self->bias);
198 pr_debug(
"Failed to find kernel dwarf at %lx\n",
199 (
unsigned long)addr);
200 dwfl_end(self->dwfl);
201 memset(
self, 0,
sizeof(*
self));
209 static int debuginfo__init_online_kernel_dwarf(
struct debuginfo *
self,
215 pr_err(
"Failed to find vmlinux path\n");
219 pr_debug2(
"Use file %s for debuginfo\n", path);
220 return debuginfo__init_offline_dwarf(
self, path);
226 struct debuginfo *
self =
zalloc(
sizeof(
struct debuginfo));
230 if (debuginfo__init_offline_dwarf(
self, path) < 0) {
240 struct debuginfo *
self =
zalloc(
sizeof(
struct debuginfo));
244 if (debuginfo__init_online_kernel_dwarf(
self, (Dwarf_Addr)addr) < 0) {
256 dwfl_end(self->dwfl);
278 static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
282 Dwarf_Attribute
attr;
291 if (dwarf_attr(vr_die, DW_AT_external, &attr) !=
NULL)
295 if (dwarf_attr(vr_die, DW_AT_location, &attr) ==
NULL ||
296 dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0 ||
302 if (op->atom == DW_OP_addr) {
307 ret =
strlen(dwarf_diename(vr_die));
311 snprintf(tvar->
value, ret + 2,
"@%s", dwarf_diename(vr_die));
312 tvar->
ref = alloc_trace_arg_ref((
long)offs);
319 if (op->atom == DW_OP_fbreg) {
327 if (op->atom >= DW_OP_breg0 && op->atom <= DW_OP_breg31) {
328 regn = op->atom - DW_OP_breg0;
331 }
else if (op->atom >= DW_OP_reg0 && op->atom <= DW_OP_reg31) {
332 regn = op->atom - DW_OP_reg0;
333 }
else if (op->atom == DW_OP_bregx) {
337 }
else if (op->atom == DW_OP_regx) {
340 pr_debug(
"DW_OP %x is not supported.\n", op->atom);
350 pr_warning(
"Mapping for the register number %u "
351 "missing on this architecture.\n", regn);
355 tvar->
value = strdup(regs);
360 tvar->
ref = alloc_trace_arg_ref((
long)offs);
367 #define BYTES_TO_BITS(nb) ((nb) * BITS_PER_LONG / sizeof(long))
369 static int convert_variable_type(Dwarf_Die *vr_die,
376 int bsize, boffs, total;
380 if (cast &&
strcmp(cast,
"string") != 0) {
382 tvar->
type = strdup(cast);
386 bsize = dwarf_bitsize(vr_die);
389 boffs = dwarf_bitoffset(vr_die);
390 total = dwarf_bytesize(vr_die);
391 if (boffs < 0 || total < 0)
393 ret =
snprintf(buf, 16,
"b%d@%d/%zd", bsize, boffs,
399 pr_warning(
"Failed to get a type information of %s.\n",
400 dwarf_diename(vr_die));
405 dwarf_diename(vr_die), dwarf_diename(&type));
407 if (cast &&
strcmp(cast,
"string") == 0) {
408 ret = dwarf_tag(&type);
409 if (ret != DW_TAG_pointer_type &&
410 ret != DW_TAG_array_type) {
412 "%s(%s) is not a pointer nor array.\n",
413 dwarf_diename(vr_die), dwarf_diename(&type));
416 if (ret == DW_TAG_pointer_type) {
423 ref_ptr = &(*ref_ptr)->
next;
426 if (*ref_ptr ==
NULL) {
434 "%s is not (unsigned) char *.\n",
435 dwarf_diename(vr_die));
438 tvar->
type = strdup(cast);
442 ret = dwarf_bytesize(&type);
450 pr_info(
"%s exceeds max-bitwidth. Cut down to %d bits.\n",
458 if (ret < 0 || ret >= 16) {
461 pr_warning(
"Failed to convert variable type: %s\n",
465 tvar->
type = strdup(buf);
471 static int convert_variable_fields(Dwarf_Die *vr_die,
const char *varname,
481 pr_debug(
"converting %s in %s\n", field->
name, varname);
483 pr_warning(
"Failed to get the type of %s.\n", varname);
486 pr_debug2(
"Var real type: (%x)\n", (
unsigned)dwarf_dieoffset(&type));
487 tag = dwarf_tag(&type);
489 if (field->
name[0] ==
'[' &&
490 (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)) {
493 memcpy(die_mem, &type,
sizeof(*die_mem));
496 pr_warning(
"Failed to get the type of %s.\n", varname);
500 (
unsigned)dwarf_dieoffset(&type));
501 if (tag == DW_TAG_pointer_type) {
506 (*ref_ptr)->next = ref;
510 ref->
offset += dwarf_bytesize(&type) * field->
index;
513 memcpy(die_mem, vr_die,
sizeof(*die_mem));
515 }
else if (tag == DW_TAG_pointer_type) {
518 pr_err(
"Semantic error: %s must be referred by '->'\n",
524 pr_warning(
"Failed to get the type of %s.\n", varname);
528 tag = dwarf_tag(&type);
529 if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) {
530 pr_warning(
"%s is not a data structure nor an union.\n",
539 (*ref_ptr)->next = ref;
544 if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) {
545 pr_warning(
"%s is not a data structure nor an union.\n",
549 if (field->
name[0] ==
'[') {
550 pr_err(
"Semantic error: %s is not a pointor"
551 " nor array.\n", varname);
555 pr_err(
"Semantic error: %s must be referred by '.'\n",
567 pr_warning(
"%s(tyep:%s) has no member %s.\n", varname,
568 dwarf_diename(&type), field->
name);
573 if (tag == DW_TAG_union_type) {
578 pr_warning(
"Failed to get the offset of %s.\n",
588 return convert_variable_fields(die_mem, field->
name,
589 field->
next, &ref, die_mem);
595 static int convert_variable(Dwarf_Die *vr_die,
struct probe_finder *
pf)
600 pr_debug(
"Converting variable %s into trace event.\n",
601 dwarf_diename(vr_die));
603 ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
606 pr_err(
"Failed to find the location of %s at this address.\n"
607 " Perhaps, it has been optimized out.\n", pf->pvar->var);
609 pr_err(
"Sorry, we don't support this variable location yet.\n");
610 else if (pf->pvar->field) {
611 ret = convert_variable_fields(vr_die, pf->pvar->var,
612 pf->pvar->field, &pf->tvar->ref,
617 ret = convert_variable_type(vr_die, pf->tvar, pf->pvar->type);
623 static int find_variable(Dwarf_Die *sc_die,
struct probe_finder *pf)
629 if (!is_c_varname(pf->pvar->var)) {
631 pf->tvar->value = strdup(pf->pvar->var);
632 if (pf->tvar->value ==
NULL)
634 if (pf->pvar->type) {
635 pf->tvar->type = strdup(pf->pvar->type);
636 if (pf->tvar->type ==
NULL)
639 if (pf->pvar->name) {
640 pf->tvar->name = strdup(pf->pvar->name);
641 if (pf->tvar->name ==
NULL)
644 pf->tvar->name =
NULL;
649 pf->tvar->name = strdup(pf->pvar->name);
657 pf->tvar->name = strdup(buf);
659 if (pf->tvar->name ==
NULL)
662 pr_debug(
"Searching '%s' variable in context.\n", pf->pvar->var);
670 ret = convert_variable(&vr_die, pf);
673 pr_warning(
"Failed to find '%s' in this function.\n",
679 static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr
paddr,
682 Dwarf_Addr eaddr, highaddr;
686 name = dwarf_diename(sp_die);
688 if (dwarf_entrypc(sp_die, &eaddr) != 0) {
689 pr_warning(
"Failed to get entry address of %s\n",
690 dwarf_diename(sp_die));
693 if (dwarf_highpc(sp_die, &highaddr) != 0) {
694 pr_warning(
"Failed to get end address of %s\n",
695 dwarf_diename(sp_die));
698 if (paddr > highaddr) {
699 pr_warning(
"Offset specified is greater than size of %s\n",
700 dwarf_diename(sp_die));
703 tp->
symbol = strdup(name);
713 if (eaddr != paddr) {
714 pr_warning(
"Return probe must be on the head of"
715 " a real function.\n");
725 static int call_probe_finder(Dwarf_Die *sc_die,
struct probe_finder *pf)
727 Dwarf_Attribute fb_attr;
732 pr_err(
"Caller must pass a scope DIE. Program error.\n");
737 if (dwarf_tag(sc_die) != DW_TAG_subprogram) {
739 pr_warning(
"Failed to find probe point in any "
744 memcpy(&pf->sp_die, sc_die,
sizeof(Dwarf_Die));
747 dwarf_attr(&pf->sp_die, DW_AT_frame_base, &fb_attr);
748 ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1);
749 if (ret <= 0 || nops == 0) {
751 #if _ELFUTILS_PREREQ(0, 142)
752 }
else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
755 if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 ||
756 dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
757 pr_warning(
"Failed to get call frame on 0x%jx\n",
758 (uintmax_t)pf->addr);
765 ret = pf->callback(sc_die, pf);
774 const char *
function;
782 static int find_best_scope_cb(Dwarf_Die *fn_die,
void *
data)
790 file = dwarf_decl_file(fn_die);
803 dwarf_decl_line(fn_die, &lno);
804 if (lno < fsp->line && fsp->
diff > fsp->
line - lno) {
815 static Dwarf_Die *find_best_scope(
struct probe_finder *pf, Dwarf_Die *die_mem)
818 .
function = pf->pev->point.function,
831 static int probe_point_line_walker(
const char *
fname,
int lineno,
832 Dwarf_Addr addr,
void *data)
834 struct probe_finder *pf =
data;
835 Dwarf_Die *sc_die, die_mem;
838 if (lineno != pf->lno ||
strtailcmp(fname, pf->fname) != 0)
842 sc_die = find_best_scope(pf, &die_mem);
844 pr_warning(
"Failed to find scope of probe point.\n");
848 ret = call_probe_finder(sc_die, pf);
851 return ret < 0 ? ret : 0;
855 static int find_probe_point_by_line(
struct probe_finder *pf)
861 static int find_lazy_match_lines(
struct list_head *head,
862 const char *fname,
const char *
pat)
868 int count = 0, linenum = 1;
870 fp = fopen(fname,
"r");
876 while ((len = getline(&line, &line_len, fp)) > 0) {
878 if (line[len - 1] ==
'\n')
879 line[len - 1] =
'\0';
882 line_list__add_line(head, linenum);
894 pr_debug(
"No matched lines found in %s.\n", fname);
898 static int probe_point_lazy_walker(
const char *fname,
int lineno,
899 Dwarf_Addr addr,
void *data)
901 struct probe_finder *pf =
data;
902 Dwarf_Die *sc_die, die_mem;
905 if (!line_list__has_line(&pf->lcache, lineno) ||
909 pr_debug(
"Probe line found: line:%d addr:0x%llx\n",
910 lineno, (
unsigned long long)addr);
913 sc_die = find_best_scope(pf, &die_mem);
915 pr_warning(
"Failed to find scope of probe point.\n");
919 ret = call_probe_finder(sc_die, pf);
925 return ret < 0 ? ret : 0;
929 static int find_probe_point_lazy(Dwarf_Die *sp_die,
struct probe_finder *pf)
933 if (list_empty(&pf->lcache)) {
935 ret = find_lazy_match_lines(&pf->lcache, pf->fname,
936 pf->pev->point.lazy_line);
944 static int probe_point_inline_cb(Dwarf_Die *in_die,
void *data)
946 struct probe_finder *pf =
data;
952 ret = find_probe_point_lazy(in_die, pf);
955 if (dwarf_entrypc(in_die, &addr) != 0) {
956 pr_warning(
"Failed to get entry address of %s.\n",
957 dwarf_diename(in_die));
962 pr_debug(
"found inline addr: 0x%jx\n",
963 (uintmax_t)pf->addr);
965 ret = call_probe_finder(in_die, pf);
978 static int probe_point_search_cb(Dwarf_Die *sp_die,
void *data)
981 struct probe_finder *pf = param->
data;
983 Dwarf_Attribute
attr;
986 if (dwarf_tag(sp_die) != DW_TAG_subprogram ||
988 dwarf_attr(sp_die, DW_AT_declaration, &attr))
995 pf->fname = dwarf_decl_file(sp_die);
997 dwarf_decl_line(sp_die, &pf->lno);
999 param->
retval = find_probe_point_by_line(pf);
1000 }
else if (!dwarf_func_inline(sp_die)) {
1003 param->
retval = find_probe_point_lazy(sp_die, pf);
1005 if (dwarf_entrypc(sp_die, &pf->addr) != 0) {
1007 "%s.\n", dwarf_diename(sp_die));
1009 return DWARF_CB_ABORT;
1013 param->
retval = call_probe_finder(sp_die, pf);
1018 probe_point_inline_cb, (
void *)pf);
1020 return DWARF_CB_ABORT;
1023 static int find_probe_point_by_func(
struct probe_finder *pf)
1027 dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, &_param, 0);
1039 static int pubname_search_cb(Dwarf *
dbg, Dwarf_Global *gl,
void *data)
1043 if (dwarf_offdie(dbg, gl->die_offset, param->
sp_die)) {
1044 if (dwarf_tag(param->
sp_die) != DW_TAG_subprogram)
1048 if (!dwarf_offdie(dbg, gl->cu_offset, param->
cu_die))
1056 return DWARF_CB_ABORT;
1064 static int debuginfo__find_probes(
struct debuginfo *
self,
1065 struct probe_finder *pf)
1068 Dwarf_Off off, noff;
1073 #if _ELFUTILS_PREREQ(0, 142)
1075 pf->cfi = dwarf_getcfi(self->dbg);
1079 line_list__init(&pf->lcache);
1086 .cu_die = &pf->cu_die,
1087 .sp_die = &pf->sp_die,
1094 dwarf_getpubnames(self->dbg, pubname_search_cb,
1096 if (pubname_param.
found) {
1097 ret = probe_point_search_cb(&pf->sp_die, &probe_param);
1104 while (!dwarf_nextcu(self->dbg, off, &noff, &cuhl,
NULL,
NULL,
NULL)) {
1106 diep = dwarf_offdie(self->dbg, off + cuhl, &pf->cu_die);
1116 if (!pp->
file || pf->fname) {
1118 ret = find_probe_point_by_func(pf);
1120 ret = find_probe_point_lazy(
NULL, pf);
1123 ret = find_probe_point_by_line(pf);
1132 line_list__free(&pf->lcache);
1138 static int add_probe_trace_event(Dwarf_Die *sc_die,
struct probe_finder *pf)
1140 struct trace_event_finder *
tf =
1146 if (tf->ntevs == tf->max_tevs) {
1147 pr_warning(
"Too many( > %d) probe point found.\n",
1151 tev = &tf->tevs[tf->ntevs++];
1154 ret = convert_to_trace_point(&pf->sp_die, pf->addr,
1155 pf->pev->point.retprobe, &tev->
point);
1163 tev->
nargs = pf->pev->nargs;
1167 for (i = 0; i < pf->pev->nargs; i++) {
1168 pf->pvar = &pf->pev->args[
i];
1169 pf->tvar = &tev->
args[
i];
1171 ret = find_variable(sc_die, pf);
1184 struct trace_event_finder tf = {
1185 .pf = {.pev = pev, .callback = add_probe_trace_event},
1186 .max_tevs = max_tevs};
1197 ret = debuginfo__find_probes(
self, &tf.pf);
1204 return (ret < 0) ? ret : tf.ntevs;
1207 #define MAX_VAR_LEN 64
1210 static int collect_variables_cb(Dwarf_Die *die_mem,
void *data)
1212 struct available_var_finder *af =
data;
1217 vl = &af->vls[af->nvls - 1];
1219 tag = dwarf_tag(die_mem);
1220 if (tag == DW_TAG_formal_parameter ||
1221 tag == DW_TAG_variable) {
1222 ret = convert_variable_location(die_mem, af->pf.addr,
1223 af->pf.fb_ops,
NULL);
1232 if (af->child && dwarf_haspc(die_mem, af->pf.addr))
1239 static int add_available_vars(Dwarf_Die *sc_die,
struct probe_finder *pf)
1241 struct available_var_finder *af =
1248 if (af->nvls == af->max_vls) {
1249 pr_warning(
"Too many( > %d) probe point found.\n", af->max_vls);
1252 vl = &af->vls[af->nvls++];
1255 ret = convert_to_trace_point(&pf->sp_die, pf->addr,
1256 pf->pev->point.retprobe, &vl->
point);
1268 die_find_child(sc_die, collect_variables_cb, (
void *)af, &die_mem);
1275 die_find_child(&pf->cu_die, collect_variables_cb, (
void *)af, &die_mem);
1278 if (strlist__empty(vl->
vars)) {
1290 int max_vls,
bool externs)
1292 struct available_var_finder af = {
1293 .pf = {.pev = pev, .callback = add_available_vars},
1294 .max_vls = max_vls, .externs = externs};
1305 ret = debuginfo__find_probes(
self, &af.pf);
1309 if (af.vls[af.nvls].point.symbol)
1310 free(af.vls[af.nvls].point.symbol);
1311 if (af.vls[af.nvls].vars)
1319 return (ret < 0) ? ret : af.nvls;
1326 Dwarf_Die cudie, spdie, indie;
1327 Dwarf_Addr _addr, baseaddr;
1329 int baseline = 0, lineno = 0, ret = 0;
1335 if (!dwarf_addrdie(self->dbg, (Dwarf_Addr)addr - self->bias, &cudie)) {
1336 pr_warning(
"Failed to find debug information for address %lx\n",
1349 tmp = dwarf_diename(&spdie);
1351 dwarf_entrypc(&spdie, &baseaddr) != 0 ||
1352 dwarf_decl_line(&spdie, &baseline) != 0)
1356 if (addr == (
unsigned long)baseaddr)
1361 if (dwarf_entrypc(&indie, &_addr) == 0 &&
1376 tmp = dwarf_diename(&indie);
1378 dwarf_decl_line(&spdie, &baseline) == 0)
1387 ppt->
line = lineno - baseline;
1389 ppt->
offset = addr - (
unsigned long)baseaddr;
1400 ppt->
file = strdup(fname);
1411 if (ret == 0 && (fname || func))
1417 static int line_range_add_line(
const char *
src,
unsigned int lineno,
1422 lr->
path = strdup(src);
1426 return line_list__add_line(&lr->
line_list, lineno);
1429 static int line_range_walk_cb(
const char *fname,
int lineno,
1430 Dwarf_Addr addr __maybe_unused,
1433 struct line_finder *lf =
data;
1436 (lf->lno_s > lineno || lf->lno_e < lineno))
1439 if (line_range_add_line(fname, lineno, lf->lr) < 0)
1446 static int find_line_range_by_line(Dwarf_Die *sp_die,
struct line_finder *lf)
1450 ret =
die_walk_lines(sp_die ?: &lf->cu_die, line_range_walk_cb, lf);
1454 if (!list_empty(&lf->lr->line_list))
1455 ret = lf->found = 1;
1460 lf->lr->path =
NULL;
1465 static int line_range_inline_cb(Dwarf_Die *in_die,
void *data)
1467 find_line_range_by_line(in_die, data);
1478 static int line_range_search_cb(Dwarf_Die *sp_die,
void *data)
1481 struct line_finder *lf = param->
data;
1488 if (dwarf_tag(sp_die) == DW_TAG_subprogram &&
1490 lf->fname = dwarf_decl_file(sp_die);
1491 dwarf_decl_line(sp_die, &lr->
offset);
1499 pr_debug(
"New line range: %d to %d\n", lf->lno_s, lf->lno_e);
1500 lr->
start = lf->lno_s;
1501 lr->
end = lf->lno_e;
1502 if (dwarf_func_inline(sp_die))
1504 line_range_inline_cb, lf);
1506 param->
retval = find_line_range_by_line(sp_die, lf);
1507 return DWARF_CB_ABORT;
1512 static int find_line_range_by_func(
struct line_finder *lf)
1515 dwarf_getfuncs(&lf->cu_die, line_range_search_cb, ¶m, 0);
1521 struct line_finder lf = {.lr =
lr, .found = 0};
1523 Dwarf_Off off = 0, noff;
1526 const char *comp_dir;
1532 .cu_die = &lf.cu_die, .sp_die = &lf.sp_die, .found = 0};
1536 dwarf_getpubnames(self->dbg, pubname_search_cb,
1538 if (pubname_param.
found) {
1539 line_range_search_cb(&lf.sp_die, &line_range_param);
1546 while (!lf.found && ret >= 0) {
1547 if (dwarf_nextcu(self->dbg, off, &noff, &cuhl,
1552 diep = dwarf_offdie(self->dbg, off + cuhl, &lf.cu_die);
1562 if (!lr->
file || lf.fname) {
1564 ret = find_line_range_by_func(&lf);
1566 lf.lno_s = lr->
start;
1568 ret = find_line_range_by_line(
NULL, &lf);
1586 return (ret < 0) ? ret : lf.found;