diff options
author | Pierre-Loup A. Griffais <pgriffais@nvidia.com> | 2012-06-22 14:38:13 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-06-27 12:14:18 -0400 |
commit | 209bd9e3e14712d74c8bebb028afda905d689f1c (patch) | |
tree | b106bcd49dc71e958f0c78f67cdaae6eba940c62 /tools/perf/util/symbol.c | |
parent | da3789628f88684d3f0fb4e6a6bc086c395ac3cb (diff) |
perf symbols: Follow .gnu_debuglink section to find separate symbols
The .gnu_debuglink section is specified to contain the filename of the
debug info file, as well as a CRC that can be used to validate it.
This doesn't currently use the checksum and relies on the usual build-id
matching for validation.
This provides more context:
http://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
Signed-off-by: Pierre-Loup A. Griffais <pgriffais@nvidia.com>
Reported-by: Mike Sartain <mikesart@valvesoftware.com>
Tested-by: Mike Sartain <mikesart@valvesoftware.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Sartain <mikesart@valvesoftware.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/4FE4BB95.3080309@nvidia.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/symbol.c')
-rw-r--r-- | tools/perf/util/symbol.c | 65 |
1 files changed, 64 insertions, 1 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 3e2e5ea0f03f..994f4ffdcd05 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -1590,11 +1590,62 @@ out: | |||
1590 | return err; | 1590 | return err; |
1591 | } | 1591 | } |
1592 | 1592 | ||
1593 | static int filename__read_debuglink(const char *filename, | ||
1594 | char *debuglink, size_t size) | ||
1595 | { | ||
1596 | int fd, err = -1; | ||
1597 | Elf *elf; | ||
1598 | GElf_Ehdr ehdr; | ||
1599 | GElf_Shdr shdr; | ||
1600 | Elf_Data *data; | ||
1601 | Elf_Scn *sec; | ||
1602 | Elf_Kind ek; | ||
1603 | |||
1604 | fd = open(filename, O_RDONLY); | ||
1605 | if (fd < 0) | ||
1606 | goto out; | ||
1607 | |||
1608 | elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); | ||
1609 | if (elf == NULL) { | ||
1610 | pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename); | ||
1611 | goto out_close; | ||
1612 | } | ||
1613 | |||
1614 | ek = elf_kind(elf); | ||
1615 | if (ek != ELF_K_ELF) | ||
1616 | goto out_close; | ||
1617 | |||
1618 | if (gelf_getehdr(elf, &ehdr) == NULL) { | ||
1619 | pr_err("%s: cannot get elf header.\n", __func__); | ||
1620 | goto out_close; | ||
1621 | } | ||
1622 | |||
1623 | sec = elf_section_by_name(elf, &ehdr, &shdr, | ||
1624 | ".gnu_debuglink", NULL); | ||
1625 | if (sec == NULL) | ||
1626 | goto out_close; | ||
1627 | |||
1628 | data = elf_getdata(sec, NULL); | ||
1629 | if (data == NULL) | ||
1630 | goto out_close; | ||
1631 | |||
1632 | /* the start of this section is a zero-terminated string */ | ||
1633 | strncpy(debuglink, data->d_buf, size); | ||
1634 | |||
1635 | elf_end(elf); | ||
1636 | |||
1637 | out_close: | ||
1638 | close(fd); | ||
1639 | out: | ||
1640 | return err; | ||
1641 | } | ||
1642 | |||
1593 | char dso__symtab_origin(const struct dso *dso) | 1643 | char dso__symtab_origin(const struct dso *dso) |
1594 | { | 1644 | { |
1595 | static const char origin[] = { | 1645 | static const char origin[] = { |
1596 | [SYMTAB__KALLSYMS] = 'k', | 1646 | [SYMTAB__KALLSYMS] = 'k', |
1597 | [SYMTAB__JAVA_JIT] = 'j', | 1647 | [SYMTAB__JAVA_JIT] = 'j', |
1648 | [SYMTAB__DEBUGLINK] = 'l', | ||
1598 | [SYMTAB__BUILD_ID_CACHE] = 'B', | 1649 | [SYMTAB__BUILD_ID_CACHE] = 'B', |
1599 | [SYMTAB__FEDORA_DEBUGINFO] = 'f', | 1650 | [SYMTAB__FEDORA_DEBUGINFO] = 'f', |
1600 | [SYMTAB__UBUNTU_DEBUGINFO] = 'u', | 1651 | [SYMTAB__UBUNTU_DEBUGINFO] = 'u', |
@@ -1662,10 +1713,22 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) | |||
1662 | */ | 1713 | */ |
1663 | want_symtab = 1; | 1714 | want_symtab = 1; |
1664 | restart: | 1715 | restart: |
1665 | for (dso->symtab_type = SYMTAB__BUILD_ID_CACHE; | 1716 | for (dso->symtab_type = SYMTAB__DEBUGLINK; |
1666 | dso->symtab_type != SYMTAB__NOT_FOUND; | 1717 | dso->symtab_type != SYMTAB__NOT_FOUND; |
1667 | dso->symtab_type++) { | 1718 | dso->symtab_type++) { |
1668 | switch (dso->symtab_type) { | 1719 | switch (dso->symtab_type) { |
1720 | case SYMTAB__DEBUGLINK: { | ||
1721 | char *debuglink; | ||
1722 | strncpy(name, dso->long_name, size); | ||
1723 | debuglink = name + dso->long_name_len; | ||
1724 | while (debuglink != name && *debuglink != '/') | ||
1725 | debuglink--; | ||
1726 | if (*debuglink == '/') | ||
1727 | debuglink++; | ||
1728 | filename__read_debuglink(dso->long_name, debuglink, | ||
1729 | size - (debuglink - name)); | ||
1730 | } | ||
1731 | break; | ||
1669 | case SYMTAB__BUILD_ID_CACHE: | 1732 | case SYMTAB__BUILD_ID_CACHE: |
1670 | /* skip the locally configured cache if a symfs is given */ | 1733 | /* skip the locally configured cache if a symfs is given */ |
1671 | if (symbol_conf.symfs[0] || | 1734 | if (symbol_conf.symfs[0] || |