5 #include <linux/kernel.h>
9 #include "util/debug.h"
11 #ifdef HAVE_LIBBFD_SUPPORT
14 * Implement addr2line using libbfd.
16 #define PACKAGE "perf"
32 static int bfd_error(const char *string
)
36 errmsg
= bfd_errmsg(bfd_get_error());
40 pr_debug("%s: %s\n", string
, errmsg
);
42 pr_debug("%s\n", errmsg
);
47 static int slurp_symtab(bfd
*abfd
, struct a2l_data
*a2l
)
52 bfd_boolean dynamic
= FALSE
;
54 if ((bfd_get_file_flags(abfd
) & HAS_SYMS
) == 0)
55 return bfd_error(bfd_get_filename(abfd
));
57 storage
= bfd_get_symtab_upper_bound(abfd
);
59 storage
= bfd_get_dynamic_symtab_upper_bound(abfd
);
63 return bfd_error(bfd_get_filename(abfd
));
65 syms
= malloc(storage
);
67 symcount
= bfd_canonicalize_dynamic_symtab(abfd
, syms
);
69 symcount
= bfd_canonicalize_symtab(abfd
, syms
);
73 return bfd_error(bfd_get_filename(abfd
));
80 static void find_address_in_section(bfd
*abfd
, asection
*section
, void *data
)
84 struct a2l_data
*a2l
= data
;
89 if ((bfd_get_section_flags(abfd
, section
) & SEC_ALLOC
) == 0)
93 vma
= bfd_get_section_vma(abfd
, section
);
94 size
= bfd_get_section_size(section
);
96 if (pc
< vma
|| pc
>= vma
+ size
)
99 a2l
->found
= bfd_find_nearest_line(abfd
, section
, a2l
->syms
, pc
- vma
,
100 &a2l
->filename
, &a2l
->funcname
,
104 static struct a2l_data
*addr2line_init(const char *path
)
107 struct a2l_data
*a2l
= NULL
;
109 abfd
= bfd_openr(path
, NULL
);
113 if (!bfd_check_format(abfd
, bfd_object
))
116 a2l
= zalloc(sizeof(*a2l
));
121 a2l
->input
= strdup(path
);
122 if (a2l
->input
== NULL
)
125 if (slurp_symtab(abfd
, a2l
))
132 free((void *)a2l
->input
);
139 static void addr2line_cleanup(struct a2l_data
*a2l
)
142 bfd_close(a2l
->abfd
);
143 free((void *)a2l
->input
);
148 static int addr2line(const char *dso_name
, unsigned long addr
,
149 char **file
, unsigned int *line
)
152 struct a2l_data
*a2l
;
154 a2l
= addr2line_init(dso_name
);
156 pr_warning("addr2line_init failed for %s\n", dso_name
);
161 bfd_map_over_sections(a2l
->abfd
, find_address_in_section
, a2l
);
163 if (a2l
->found
&& a2l
->filename
) {
164 *file
= strdup(a2l
->filename
);
171 addr2line_cleanup(a2l
);
175 #else /* HAVE_LIBBFD_SUPPORT */
177 static int addr2line(const char *dso_name
, unsigned long addr
,
178 char **file
, unsigned int *line_nr
)
182 char *filename
= NULL
;
187 scnprintf(cmd
, sizeof(cmd
), "addr2line -e %s %016"PRIx64
,
190 fp
= popen(cmd
, "r");
192 pr_warning("popen failed for %s\n", dso_name
);
196 if (getline(&filename
, &len
, fp
) < 0 || !len
) {
197 pr_warning("addr2line has no output for %s\n", dso_name
);
201 sep
= strchr(filename
, '\n');
205 if (!strcmp(filename
, "??:0")) {
206 pr_debug("no debugging info in %s\n", dso_name
);
211 sep
= strchr(filename
, ':');
215 *line_nr
= strtoul(sep
, NULL
, 0);
222 #endif /* HAVE_LIBBFD_SUPPORT */
224 char *get_srcline(struct dso
*dso
, unsigned long addr
)
229 char *dso_name
= dso
->long_name
;
232 if (!dso
->has_srcline
)
233 return SRCLINE_UNKNOWN
;
235 if (dso_name
[0] == '[')
238 if (!strncmp(dso_name
, "/tmp/perf-", 10))
241 if (!addr2line(dso_name
, addr
, &file
, &line
))
244 /* just calculate actual length */
245 size
= snprintf(NULL
, 0, "%s:%u", file
, line
) + 1;
247 srcline
= malloc(size
);
249 snprintf(srcline
, size
, "%s:%u", file
, line
);
251 srcline
= SRCLINE_UNKNOWN
;
257 dso
->has_srcline
= 0;
258 return SRCLINE_UNKNOWN
;
261 void free_srcline(char *srcline
)
263 if (srcline
&& strcmp(srcline
, SRCLINE_UNKNOWN
) != 0)
This page took 0.037429 seconds and 5 git commands to generate.