diff options
Diffstat (limited to 'tools/perf/util')
| -rw-r--r-- | tools/perf/util/probe-finder.c | 85 |
1 files changed, 55 insertions, 30 deletions
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 3991d73d1cf..ddf4d455632 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
| @@ -117,28 +117,6 @@ static void line_list__free(struct list_head *head) | |||
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | /* Dwarf FL wrappers */ | 119 | /* Dwarf FL wrappers */ |
| 120 | |||
| 121 | static int __linux_kernel_find_elf(Dwfl_Module *mod, | ||
| 122 | void **userdata, | ||
| 123 | const char *module_name, | ||
| 124 | Dwarf_Addr base, | ||
| 125 | char **file_name, Elf **elfp) | ||
| 126 | { | ||
| 127 | int fd; | ||
| 128 | const char *path = kernel_get_module_path(module_name); | ||
| 129 | |||
| 130 | if (path) { | ||
| 131 | fd = open(path, O_RDONLY); | ||
| 132 | if (fd >= 0) { | ||
| 133 | *file_name = strdup(path); | ||
| 134 | return fd; | ||
| 135 | } | ||
| 136 | } | ||
| 137 | /* If failed, try to call standard method */ | ||
| 138 | return dwfl_linux_kernel_find_elf(mod, userdata, module_name, base, | ||
| 139 | file_name, elfp); | ||
| 140 | } | ||
| 141 | |||
| 142 | static char *debuginfo_path; /* Currently dummy */ | 120 | static char *debuginfo_path; /* Currently dummy */ |
| 143 | 121 | ||
| 144 | static const Dwfl_Callbacks offline_callbacks = { | 122 | static const Dwfl_Callbacks offline_callbacks = { |
| @@ -151,14 +129,6 @@ static const Dwfl_Callbacks offline_callbacks = { | |||
| 151 | .find_elf = dwfl_build_id_find_elf, | 129 | .find_elf = dwfl_build_id_find_elf, |
| 152 | }; | 130 | }; |
| 153 | 131 | ||
| 154 | static const Dwfl_Callbacks kernel_callbacks = { | ||
| 155 | .find_debuginfo = dwfl_standard_find_debuginfo, | ||
| 156 | .debuginfo_path = &debuginfo_path, | ||
| 157 | |||
| 158 | .find_elf = __linux_kernel_find_elf, | ||
| 159 | .section_address = dwfl_linux_kernel_module_section_address, | ||
| 160 | }; | ||
| 161 | |||
| 162 | /* Get a Dwarf from offline image */ | 132 | /* Get a Dwarf from offline image */ |
| 163 | static Dwarf *dwfl_init_offline_dwarf(int fd, Dwfl **dwflp, Dwarf_Addr *bias) | 133 | static Dwarf *dwfl_init_offline_dwarf(int fd, Dwfl **dwflp, Dwarf_Addr *bias) |
| 164 | { | 134 | { |
| @@ -185,6 +155,38 @@ error: | |||
| 185 | return dbg; | 155 | return dbg; |
| 186 | } | 156 | } |
| 187 | 157 | ||
| 158 | #if _ELFUTILS_PREREQ(0, 148) | ||
| 159 | /* This method is buggy if elfutils is older than 0.148 */ | ||
| 160 | static int __linux_kernel_find_elf(Dwfl_Module *mod, | ||
| 161 | void **userdata, | ||
| 162 | const char *module_name, | ||
| 163 | Dwarf_Addr base, | ||
| 164 | char **file_name, Elf **elfp) | ||
| 165 | { | ||
| 166 | int fd; | ||
| 167 | const char *path = kernel_get_module_path(module_name); | ||
| 168 | |||
| 169 | pr_debug2("Use file %s for %s\n", path, module_name); | ||
| 170 | if (path) { | ||
| 171 | fd = open(path, O_RDONLY); | ||
| 172 | if (fd >= 0) { | ||
| 173 | *file_name = strdup(path); | ||
| 174 | return fd; | ||
| 175 | } | ||
| 176 | } | ||
| 177 | /* If failed, try to call standard method */ | ||
| 178 | return dwfl_linux_kernel_find_elf(mod, userdata, module_name, base, | ||
| 179 | file_name, elfp); | ||
| 180 | } | ||
| 181 | |||
| 182 | static const Dwfl_Callbacks kernel_callbacks = { | ||
| 183 | .find_debuginfo = dwfl_standard_find_debuginfo, | ||
| 184 | .debuginfo_path = &debuginfo_path, | ||
| 185 | |||
| 186 | .find_elf = __linux_kernel_find_elf, | ||
| 187 | .section_address = dwfl_linux_kernel_module_section_address, | ||
| 188 | }; | ||
| 189 | |||
| 188 | /* Get a Dwarf from live kernel image */ | 190 | /* Get a Dwarf from live kernel image */ |
| 189 | static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr, Dwfl **dwflp, | 191 | static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr, Dwfl **dwflp, |
| 190 | Dwarf_Addr *bias) | 192 | Dwarf_Addr *bias) |
| @@ -205,11 +207,34 @@ static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr, Dwfl **dwflp, | |||
| 205 | dbg = dwfl_addrdwarf(*dwflp, addr, bias); | 207 | dbg = dwfl_addrdwarf(*dwflp, addr, bias); |
| 206 | /* Here, check whether we could get a real dwarf */ | 208 | /* Here, check whether we could get a real dwarf */ |
| 207 | if (!dbg) { | 209 | if (!dbg) { |
| 210 | pr_debug("Failed to find kernel dwarf at %lx\n", | ||
| 211 | (unsigned long)addr); | ||
| 208 | dwfl_end(*dwflp); | 212 | dwfl_end(*dwflp); |
| 209 | *dwflp = NULL; | 213 | *dwflp = NULL; |
| 210 | } | 214 | } |
| 211 | return dbg; | 215 | return dbg; |
| 212 | } | 216 | } |
| 217 | #else | ||
| 218 | /* With older elfutils, this just support kernel module... */ | ||
| 219 | static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr __used, Dwfl **dwflp, | ||
| 220 | Dwarf_Addr *bias) | ||
| 221 | { | ||
| 222 | int fd; | ||
| 223 | const char *path = kernel_get_module_path("kernel"); | ||
| 224 | |||
| 225 | if (!path) { | ||
| 226 | pr_err("Failed to find vmlinux path\n"); | ||
| 227 | return NULL; | ||
| 228 | } | ||
| 229 | |||
| 230 | pr_debug2("Use file %s for debuginfo\n", path); | ||
| 231 | fd = open(path, O_RDONLY); | ||
| 232 | if (fd < 0) | ||
| 233 | return NULL; | ||
| 234 | |||
| 235 | return dwfl_init_offline_dwarf(fd, dwflp, bias); | ||
| 236 | } | ||
| 237 | #endif | ||
| 213 | 238 | ||
| 214 | /* Dwarf wrappers */ | 239 | /* Dwarf wrappers */ |
| 215 | 240 | ||
