On 23/08/16 13:22, Jiri Olsa wrote: > On Tue, Aug 23, 2016 at 07:09:18AM +0200, Matija Glavinic Pecotic wrote: >> On 22/08/16 17:19, Jiri Olsa wrote: >>> should you also set following? >>> >>> *offset = ofs >>> dso->debug_frame_offset = ofs; >>> >>> I guess if we found the debuglink section with file having .debug_frame >>> section, we want to use it for this dso from now on.. >> >> I omitted this at first as I was thinking whether it is correct to do so. For >> our case, stripped dso, symbols in debug file, we are marking offset in other >> file, and not *this* dso. But I agree to you now, I have checked, and debug >> frame offset is not used anywhere, so it is a future problem. Someone might >> be surprised though that offset is marked, but for the other file. >> >>> I'd think let's have read_unwind_spec_debug_frame to find .debug_frame >>> and provide that info under dso object for subsequent reads >> >> Yes, that sounds. >> >>> so in case we find debuglink-ed file, it has precedence over the file >>> we found symtab in? assuming thats what dso->symsrc_filename is.. >> >> Thanks for pointing that one out, I haven't seen before we could use it. >> It was introduced with 0058aef65eda9c9dde8253af702d542ba7eef697 and it is >> aimed to keep name of the file with debug symbols, similar as needed here. >> >> I would then propose something like this below. This significantly changes >> dso__read_binary_type_filename, but I would say it wasn't proper before and >> it is not in sync with the rest of the cases in it. Idea of this function is >> to provide path to dso, and DSO_BINARY_TYPE__DEBUGLINK implies one location, >> which is not entirely correct. >> >> gdb and objcopy docs give points what debug link might be, and where debug >> file might reside. Debug link might be absolute path, or just name, in which >> case debug file should be looked up in several places. Here is what gdb does: >> >> So, for example, suppose you ask gdb to debug /usr/bin/ls, which has a debug >> link that specifies the file ls.debug, and a build ID whose value in hex is >> abcdef1234. If the list of the global debug directories includes >> /usr/lib/debug, then gdb will look for the following debug information files, >> in the indicated order: >> >> - /usr/lib/debug/.build-id/ab/cdef1234.debug >> - /usr/bin/ls.debug >> - /usr/bin/.debug/ls.debug >> - /usr/lib/debug/usr/bin/ls.debug. >> >> https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html >> https://sourceware.org/binutils/docs/binutils/objcopy.html >> >> Could you please tell me what are your thoughts on this kind of approach? >> >> --- >> tools/perf/util/dso.c | 40 >> ++++++++++++++++++++++++++++++++ >> tools/perf/util/unwind-libunwind-local.c | 28 +++++++++++++++++++++- >> 2 files changed, 67 insertions(+), 1 deletion(-) >> >> diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c >> index 774f6ec..ecc859e 100644 >> --- a/tools/perf/util/dso.c >> +++ b/tools/perf/util/dso.c >> @@ -46,11 +46,14 @@ int dso__read_binary_type_filename(const struct dso *dso, >> switch (type) { >> case DSO_BINARY_TYPE__DEBUGLINK: { >> char *debuglink; >> + char *dir; >> + char symfile[PATH_MAX]; >> >> len = __symbol__join_symfs(filename, size, dso->long_name); >> debuglink = filename + len; >> while (debuglink != filename && *debuglink != '/') >> debuglink--; >> + dir = debuglink; >> if (*debuglink == '/') >> debuglink++; >> >> @@ -60,8 +63,45 @@ int dso__read_binary_type_filename(const struct dso *dso, >> >> ret = filename__read_debuglink(filename, debuglink, >> size - (debuglink - filename)); >> + if (ret) >> + break; >> + >> + /* Check predefined locations where debug file might reside: >> + * - if debuglink is absolute path, check only that one >> + * If debuglink provides just name: >> + * - in the same directory as dso >> + * - in the .debug subdirectory of dso directory >> + * - in the /usr/lib/debug/[path to dso directory] >> + * */ >> + if (*debuglink == '/') { >> + ret = is_regular_file(debuglink); >> + break; >> + } >> + >> + snprintf(symfile, PATH_MAX, "%s/%s", dir, debuglink); >> + ret = is_regular_file(symfile); >> + if(!ret) { >> + strncpy(debuglink, symfile, size); >> + break; >> + } >> + >> + snprintf(symfile, PATH_MAX, "%s/.debug/%s", dir, debuglink); >> + ret = is_regular_file(symfile); >> + if(!ret) { >> + strncpy(debuglink, symfile, size); >> + break; >> + } >> + >> + snprintf(symfile, PATH_MAX, "/usr/bin/debug/%s/%s", dir, >> debuglink); >> + ret = is_regular_file(symfile); >> + if(!ret) { >> + strncpy(debuglink, symfile, size); >> + break; >> + } >> + >> } >> break; >> + >> case DSO_BINARY_TYPE__BUILD_ID_CACHE: >> if (dso__build_id_filename(dso, filename, size) == NULL) >> ret = -1; >> diff --git a/tools/perf/util/unwind-libunwind-local.c >> b/tools/perf/util/unwind-libunwind-local.c >> index 97c0f8f..a1d3c93 100644 >> --- a/tools/perf/util/unwind-libunwind-local.c >> +++ b/tools/perf/util/unwind-libunwind-local.c >> @@ -35,6 +35,7 @@ >> #include "util.h" >> #include "debug.h" >> #include "asm/bug.h" >> +#include "dso.h" >> >> extern int >> UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, >> @@ -296,6 +297,8 @@ static int read_unwind_spec_debug_frame(struct dso *dso, >> { >> int fd; >> u64 ofs = dso->data.debug_frame_offset; >> + char *debuglink = malloc(PATH_MAX); >> + int ret = 0; >> >> if (ofs == 0) { >> fd = dso__data_get_fd(dso, machine); >> @@ -304,8 +307,31 @@ static int read_unwind_spec_debug_frame(struct dso *dso, >> >> /* Check the .debug_frame section for unwinding info */ >> ofs = elf_section_offset(fd, ".debug_frame"); >> - dso->data.debug_frame_offset = ofs; >> dso__data_put_fd(dso); >> + >> + if (!ofs) { >> + /* If not found, try to lookup in debuglink */ >> + ret = dso__read_binary_type_filename( >> + dso, DSO_BINARY_TYPE__DEBUGLINK, >> + machine->root_dir, debuglink, PATH_MAX); >> + if (!ret) { >> + fd = open(debuglink, O_RDONLY); >> + if (fd < 0) >> + return -EINVAL; >> + >> + ofs = elf_section_offset(fd, ".debug_frame"); >> + close(fd); >> + >> + if (ofs) { >> + dso->symsrc_filename = debuglink; > > symsrc_filename is initialized with file that has symtab, > which I'm not sure is guaranteed in here as well.. > > Namhyung, Massami?
Yes, I see it. This file could also be debuglink, but that is not guaranteed. I would propose to look in symsrc_filename for .debug_frame. If its not there, we could still take a look into debuglink as a last resort. What I wonder, would it be fine in such a case to store debuglink to symsrc, if its already set? Though, this case is somewhat unlikely, but not entirely impossible Thanks, Matija > thanks, > jirka > >> + } >> + } >> + } >> + >> + pr_debug("%s: dso: %s, ret: %d, debuglink: <%s>\n", >> + __func__, dso->short_name, ret, debuglink); >> + >> + dso->data.debug_frame_offset = ofs; >> } >> >> *offset = ofs; >> -- >> 2.1.4 >> >>