perf report: Support LLVM for addr2line()
In addition to the existing support for libbfd and calling out to
an external addr2line command, add support for using libllvm directly.
This is both faster than libbfd, and can be enabled in distro builds
(the LLVM license has an explicit provision for GPLv2 compatibility).
Thus, it is set as the primary choice if available.
As an example, running 'perf report' on a medium-size profile with
DWARF-based backtraces took 58 seconds with LLVM, 78 seconds with
libbfd, 153 seconds with external llvm-addr2line, and I got tired and
aborted the test after waiting for 55 minutes with external bfd
addr2line (which is the default for perf as compiled by distributions
today).
Evidently, for this case, the bfd addr2line process needs 18 seconds (on
a 5.2 GHz Zen 3) to load the .debug ELF in question, hits the 1-second
timeout and gets killed during initialization, getting restarted anew
every time. Having an in-process addr2line makes this much more robust.
As future extensions, libllvm can be used in many other places where
we currently use libbfd or other libraries:
- Symbol enumeration (in particular, for PE binaries).
- Demangling (including non-Itanium demangling, e.g. Microsoft
or Rust).
- Disassembling (perf annotate).
However, these are much less pressing; most people don't profile PE
binaries, and perf has non-bfd paths for ELF. The same with demangling;
the default _cxa_demangle path works fine for most users, and while bfd
objdump can be slow on large binaries, it is possible to use
--objdump=llvm-objdump to get the speed benefits. (It appears
LLVM-based demangling is very simple, should we want that.)
Tested with LLVM 14, 15, 16, 18 and 19. For some reason, LLVM 12 was not
correctly detected using feature_check, and thus was not tested.
Committer notes:
Added the name and a __maybe_unused to address:
1 13.50 almalinux:8 : FAIL gcc version 8.5.0 20210514 (Red Hat 8.5.0-22) (GCC)
util/srcline.c: In function 'dso__free_a2l':
util/srcline.c:184:20: error: parameter name omitted
void dso__free_a2l(struct dso *)
^~~~~~~~~~~~
make[3]: *** [/git/perf-6.11.0-rc3/tools/build/Makefile.build:158: util] Error 2
Signed-off-by: Steinar H. Gunderson <sesse@google.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Ian Rogers <irogers@google.com>
Link: https://lore.kernel.org/r/20240803152008.2818485-1-sesse@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2024-08-03 08:20:06 -07:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Must come before the linux/compiler.h include, which defines several
|
|
|
|
* macros (e.g. noinline) that conflict with compiler builtins used
|
|
|
|
* by LLVM.
|
|
|
|
*/
|
|
|
|
#pragma GCC diagnostic push
|
|
|
|
#pragma GCC diagnostic ignored "-Wunused-parameter" /* Needed for LLVM <= 15 */
|
|
|
|
#include <llvm/DebugInfo/Symbolize/Symbolize.h>
|
perf annotate: LLVM-based disassembler
Support using LLVM as a disassembler method, allowing helperless
annotation in non-distro builds. (It is also much faster than
using libbfd or bfd objdump on binaries with a lot of debug
information.)
This is nearly identical to the output of llvm-objdump; there are
some very rare whitespace differences, some minor changes to demangling
(since we use perf's regular demangling and not LLVM's own) and
the occasional case where llvm-objdump makes a different choice
when multiple symbols share the same address.
It should work across all of LLVM's supported architectures, although
I've only tested 64-bit x86, and finding the right triple from perf's
idea of machine architecture can sometimes be a bit tricky. Ideally, we
should have some way of finding the triplet just from the file itself.
Committer notes:
Address this on 32-bit systems by using PRIu64 from inttypes.h
3 17.58 almalinux:9-i386 : FAIL gcc version 11.4.1 20231218 (Red Hat 11.4.1-3) (GCC)
util/llvm-c-helpers.cpp: In function ‘char* make_symbol_relative_string(dso*, const char*, u64, u64)’:
util/llvm-c-helpers.cpp:150:52: error: format ‘%lx’ expects argument of type ‘long unsigned int’, but argument 5 has type ‘u64’ {aka
+‘long long unsigned int’} [-Werror=format=]
150 | snprintf(buf, sizeof(buf), "%s+0x%lx",
| ~~^
| |
| long unsigned int
| %llx
151 | demangled ? demangled : sym_name, addr - base_addr);
| ~~~~~~~~~~~~~~~~
| |
| u64 {aka long long unsigned int}
cc1plus: all warnings being treated as errors
Signed-off-by: Steinar H. Gunderson <sesse@google.com>
Cc: Ian Rogers <irogers@google.com>
Link: https://lore.kernel.org/r/20240803152008.2818485-3-sesse@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2024-08-03 08:20:08 -07:00
|
|
|
#include <llvm/Support/TargetSelect.h>
|
perf report: Support LLVM for addr2line()
In addition to the existing support for libbfd and calling out to
an external addr2line command, add support for using libllvm directly.
This is both faster than libbfd, and can be enabled in distro builds
(the LLVM license has an explicit provision for GPLv2 compatibility).
Thus, it is set as the primary choice if available.
As an example, running 'perf report' on a medium-size profile with
DWARF-based backtraces took 58 seconds with LLVM, 78 seconds with
libbfd, 153 seconds with external llvm-addr2line, and I got tired and
aborted the test after waiting for 55 minutes with external bfd
addr2line (which is the default for perf as compiled by distributions
today).
Evidently, for this case, the bfd addr2line process needs 18 seconds (on
a 5.2 GHz Zen 3) to load the .debug ELF in question, hits the 1-second
timeout and gets killed during initialization, getting restarted anew
every time. Having an in-process addr2line makes this much more robust.
As future extensions, libllvm can be used in many other places where
we currently use libbfd or other libraries:
- Symbol enumeration (in particular, for PE binaries).
- Demangling (including non-Itanium demangling, e.g. Microsoft
or Rust).
- Disassembling (perf annotate).
However, these are much less pressing; most people don't profile PE
binaries, and perf has non-bfd paths for ELF. The same with demangling;
the default _cxa_demangle path works fine for most users, and while bfd
objdump can be slow on large binaries, it is possible to use
--objdump=llvm-objdump to get the speed benefits. (It appears
LLVM-based demangling is very simple, should we want that.)
Tested with LLVM 14, 15, 16, 18 and 19. For some reason, LLVM 12 was not
correctly detected using feature_check, and thus was not tested.
Committer notes:
Added the name and a __maybe_unused to address:
1 13.50 almalinux:8 : FAIL gcc version 8.5.0 20210514 (Red Hat 8.5.0-22) (GCC)
util/srcline.c: In function 'dso__free_a2l':
util/srcline.c:184:20: error: parameter name omitted
void dso__free_a2l(struct dso *)
^~~~~~~~~~~~
make[3]: *** [/git/perf-6.11.0-rc3/tools/build/Makefile.build:158: util] Error 2
Signed-off-by: Steinar H. Gunderson <sesse@google.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Ian Rogers <irogers@google.com>
Link: https://lore.kernel.org/r/20240803152008.2818485-1-sesse@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2024-08-03 08:20:06 -07:00
|
|
|
#pragma GCC diagnostic pop
|
|
|
|
|
perf annotate: LLVM-based disassembler
Support using LLVM as a disassembler method, allowing helperless
annotation in non-distro builds. (It is also much faster than
using libbfd or bfd objdump on binaries with a lot of debug
information.)
This is nearly identical to the output of llvm-objdump; there are
some very rare whitespace differences, some minor changes to demangling
(since we use perf's regular demangling and not LLVM's own) and
the occasional case where llvm-objdump makes a different choice
when multiple symbols share the same address.
It should work across all of LLVM's supported architectures, although
I've only tested 64-bit x86, and finding the right triple from perf's
idea of machine architecture can sometimes be a bit tricky. Ideally, we
should have some way of finding the triplet just from the file itself.
Committer notes:
Address this on 32-bit systems by using PRIu64 from inttypes.h
3 17.58 almalinux:9-i386 : FAIL gcc version 11.4.1 20231218 (Red Hat 11.4.1-3) (GCC)
util/llvm-c-helpers.cpp: In function ‘char* make_symbol_relative_string(dso*, const char*, u64, u64)’:
util/llvm-c-helpers.cpp:150:52: error: format ‘%lx’ expects argument of type ‘long unsigned int’, but argument 5 has type ‘u64’ {aka
+‘long long unsigned int’} [-Werror=format=]
150 | snprintf(buf, sizeof(buf), "%s+0x%lx",
| ~~^
| |
| long unsigned int
| %llx
151 | demangled ? demangled : sym_name, addr - base_addr);
| ~~~~~~~~~~~~~~~~
| |
| u64 {aka long long unsigned int}
cc1plus: all warnings being treated as errors
Signed-off-by: Steinar H. Gunderson <sesse@google.com>
Cc: Ian Rogers <irogers@google.com>
Link: https://lore.kernel.org/r/20240803152008.2818485-3-sesse@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2024-08-03 08:20:08 -07:00
|
|
|
#include <inttypes.h>
|
perf report: Support LLVM for addr2line()
In addition to the existing support for libbfd and calling out to
an external addr2line command, add support for using libllvm directly.
This is both faster than libbfd, and can be enabled in distro builds
(the LLVM license has an explicit provision for GPLv2 compatibility).
Thus, it is set as the primary choice if available.
As an example, running 'perf report' on a medium-size profile with
DWARF-based backtraces took 58 seconds with LLVM, 78 seconds with
libbfd, 153 seconds with external llvm-addr2line, and I got tired and
aborted the test after waiting for 55 minutes with external bfd
addr2line (which is the default for perf as compiled by distributions
today).
Evidently, for this case, the bfd addr2line process needs 18 seconds (on
a 5.2 GHz Zen 3) to load the .debug ELF in question, hits the 1-second
timeout and gets killed during initialization, getting restarted anew
every time. Having an in-process addr2line makes this much more robust.
As future extensions, libllvm can be used in many other places where
we currently use libbfd or other libraries:
- Symbol enumeration (in particular, for PE binaries).
- Demangling (including non-Itanium demangling, e.g. Microsoft
or Rust).
- Disassembling (perf annotate).
However, these are much less pressing; most people don't profile PE
binaries, and perf has non-bfd paths for ELF. The same with demangling;
the default _cxa_demangle path works fine for most users, and while bfd
objdump can be slow on large binaries, it is possible to use
--objdump=llvm-objdump to get the speed benefits. (It appears
LLVM-based demangling is very simple, should we want that.)
Tested with LLVM 14, 15, 16, 18 and 19. For some reason, LLVM 12 was not
correctly detected using feature_check, and thus was not tested.
Committer notes:
Added the name and a __maybe_unused to address:
1 13.50 almalinux:8 : FAIL gcc version 8.5.0 20210514 (Red Hat 8.5.0-22) (GCC)
util/srcline.c: In function 'dso__free_a2l':
util/srcline.c:184:20: error: parameter name omitted
void dso__free_a2l(struct dso *)
^~~~~~~~~~~~
make[3]: *** [/git/perf-6.11.0-rc3/tools/build/Makefile.build:158: util] Error 2
Signed-off-by: Steinar H. Gunderson <sesse@google.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Ian Rogers <irogers@google.com>
Link: https://lore.kernel.org/r/20240803152008.2818485-1-sesse@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2024-08-03 08:20:06 -07:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <linux/compiler.h>
|
|
|
|
extern "C" {
|
|
|
|
#include <linux/zalloc.h>
|
|
|
|
}
|
|
|
|
#include "symbol_conf.h"
|
|
|
|
#include "llvm-c-helpers.h"
|
|
|
|
|
perf annotate: LLVM-based disassembler
Support using LLVM as a disassembler method, allowing helperless
annotation in non-distro builds. (It is also much faster than
using libbfd or bfd objdump on binaries with a lot of debug
information.)
This is nearly identical to the output of llvm-objdump; there are
some very rare whitespace differences, some minor changes to demangling
(since we use perf's regular demangling and not LLVM's own) and
the occasional case where llvm-objdump makes a different choice
when multiple symbols share the same address.
It should work across all of LLVM's supported architectures, although
I've only tested 64-bit x86, and finding the right triple from perf's
idea of machine architecture can sometimes be a bit tricky. Ideally, we
should have some way of finding the triplet just from the file itself.
Committer notes:
Address this on 32-bit systems by using PRIu64 from inttypes.h
3 17.58 almalinux:9-i386 : FAIL gcc version 11.4.1 20231218 (Red Hat 11.4.1-3) (GCC)
util/llvm-c-helpers.cpp: In function ‘char* make_symbol_relative_string(dso*, const char*, u64, u64)’:
util/llvm-c-helpers.cpp:150:52: error: format ‘%lx’ expects argument of type ‘long unsigned int’, but argument 5 has type ‘u64’ {aka
+‘long long unsigned int’} [-Werror=format=]
150 | snprintf(buf, sizeof(buf), "%s+0x%lx",
| ~~^
| |
| long unsigned int
| %llx
151 | demangled ? demangled : sym_name, addr - base_addr);
| ~~~~~~~~~~~~~~~~
| |
| u64 {aka long long unsigned int}
cc1plus: all warnings being treated as errors
Signed-off-by: Steinar H. Gunderson <sesse@google.com>
Cc: Ian Rogers <irogers@google.com>
Link: https://lore.kernel.org/r/20240803152008.2818485-3-sesse@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2024-08-03 08:20:08 -07:00
|
|
|
extern "C"
|
|
|
|
char *dso__demangle_sym(struct dso *dso, int kmodule, const char *elf_name);
|
|
|
|
|
perf report: Support LLVM for addr2line()
In addition to the existing support for libbfd and calling out to
an external addr2line command, add support for using libllvm directly.
This is both faster than libbfd, and can be enabled in distro builds
(the LLVM license has an explicit provision for GPLv2 compatibility).
Thus, it is set as the primary choice if available.
As an example, running 'perf report' on a medium-size profile with
DWARF-based backtraces took 58 seconds with LLVM, 78 seconds with
libbfd, 153 seconds with external llvm-addr2line, and I got tired and
aborted the test after waiting for 55 minutes with external bfd
addr2line (which is the default for perf as compiled by distributions
today).
Evidently, for this case, the bfd addr2line process needs 18 seconds (on
a 5.2 GHz Zen 3) to load the .debug ELF in question, hits the 1-second
timeout and gets killed during initialization, getting restarted anew
every time. Having an in-process addr2line makes this much more robust.
As future extensions, libllvm can be used in many other places where
we currently use libbfd or other libraries:
- Symbol enumeration (in particular, for PE binaries).
- Demangling (including non-Itanium demangling, e.g. Microsoft
or Rust).
- Disassembling (perf annotate).
However, these are much less pressing; most people don't profile PE
binaries, and perf has non-bfd paths for ELF. The same with demangling;
the default _cxa_demangle path works fine for most users, and while bfd
objdump can be slow on large binaries, it is possible to use
--objdump=llvm-objdump to get the speed benefits. (It appears
LLVM-based demangling is very simple, should we want that.)
Tested with LLVM 14, 15, 16, 18 and 19. For some reason, LLVM 12 was not
correctly detected using feature_check, and thus was not tested.
Committer notes:
Added the name and a __maybe_unused to address:
1 13.50 almalinux:8 : FAIL gcc version 8.5.0 20210514 (Red Hat 8.5.0-22) (GCC)
util/srcline.c: In function 'dso__free_a2l':
util/srcline.c:184:20: error: parameter name omitted
void dso__free_a2l(struct dso *)
^~~~~~~~~~~~
make[3]: *** [/git/perf-6.11.0-rc3/tools/build/Makefile.build:158: util] Error 2
Signed-off-by: Steinar H. Gunderson <sesse@google.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Ian Rogers <irogers@google.com>
Link: https://lore.kernel.org/r/20240803152008.2818485-1-sesse@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2024-08-03 08:20:06 -07:00
|
|
|
using namespace llvm;
|
|
|
|
using llvm::symbolize::LLVMSymbolizer;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Allocate a static LLVMSymbolizer, which will live to the end of the program.
|
|
|
|
* Unlike the bfd paths, LLVMSymbolizer has its own cache, so we do not need
|
|
|
|
* to store anything in the dso struct.
|
|
|
|
*/
|
|
|
|
static LLVMSymbolizer *get_symbolizer()
|
|
|
|
{
|
|
|
|
static LLVMSymbolizer *instance = nullptr;
|
|
|
|
if (instance == nullptr) {
|
|
|
|
LLVMSymbolizer::Options opts;
|
|
|
|
/*
|
|
|
|
* LLVM sometimes demangles slightly different from the rest
|
|
|
|
* of the code, and this mismatch can cause new_inline_sym()
|
|
|
|
* to get confused and mark non-inline symbol as inlined
|
|
|
|
* (since the name does not properly match up with base_sym).
|
|
|
|
* Thus, disable the demangling and let the rest of the code
|
|
|
|
* handle it.
|
|
|
|
*/
|
|
|
|
opts.Demangle = false;
|
|
|
|
instance = new LLVMSymbolizer(opts);
|
|
|
|
}
|
|
|
|
return instance;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Returns 0 on error, 1 on success. */
|
|
|
|
static int extract_file_and_line(const DILineInfo &line_info, char **file,
|
|
|
|
unsigned int *line)
|
|
|
|
{
|
|
|
|
if (file) {
|
|
|
|
if (line_info.FileName == "<invalid>") {
|
|
|
|
/* Match the convention of libbfd. */
|
|
|
|
*file = nullptr;
|
|
|
|
} else {
|
|
|
|
/* The caller expects to get something it can free(). */
|
|
|
|
*file = strdup(line_info.FileName.c_str());
|
|
|
|
if (*file == nullptr)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (line)
|
|
|
|
*line = line_info.Line;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C"
|
|
|
|
int llvm_addr2line(const char *dso_name, u64 addr,
|
|
|
|
char **file, unsigned int *line,
|
|
|
|
bool unwind_inlines,
|
|
|
|
llvm_a2l_frame **inline_frames)
|
|
|
|
{
|
|
|
|
LLVMSymbolizer *symbolizer = get_symbolizer();
|
|
|
|
object::SectionedAddress sectioned_addr = {
|
|
|
|
addr,
|
|
|
|
object::SectionedAddress::UndefSection
|
|
|
|
};
|
|
|
|
|
|
|
|
if (unwind_inlines) {
|
|
|
|
Expected<DIInliningInfo> res_or_err =
|
|
|
|
symbolizer->symbolizeInlinedCode(dso_name,
|
|
|
|
sectioned_addr);
|
|
|
|
if (!res_or_err)
|
|
|
|
return 0;
|
|
|
|
unsigned num_frames = res_or_err->getNumberOfFrames();
|
|
|
|
if (num_frames == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (extract_file_and_line(res_or_err->getFrame(0),
|
|
|
|
file, line) == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
*inline_frames = (llvm_a2l_frame *)calloc(
|
|
|
|
num_frames, sizeof(**inline_frames));
|
|
|
|
if (*inline_frames == nullptr)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < num_frames; ++i) {
|
|
|
|
const DILineInfo &src = res_or_err->getFrame(i);
|
|
|
|
|
|
|
|
llvm_a2l_frame &dst = (*inline_frames)[i];
|
|
|
|
if (src.FileName == "<invalid>")
|
|
|
|
/* Match the convention of libbfd. */
|
|
|
|
dst.filename = nullptr;
|
|
|
|
else
|
|
|
|
dst.filename = strdup(src.FileName.c_str());
|
|
|
|
dst.funcname = strdup(src.FunctionName.c_str());
|
|
|
|
dst.line = src.Line;
|
|
|
|
|
|
|
|
if (dst.filename == nullptr ||
|
|
|
|
dst.funcname == nullptr) {
|
|
|
|
for (unsigned j = 0; j <= i; ++j) {
|
|
|
|
zfree(&(*inline_frames)[j].filename);
|
|
|
|
zfree(&(*inline_frames)[j].funcname);
|
|
|
|
}
|
|
|
|
zfree(inline_frames);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return num_frames;
|
|
|
|
} else {
|
|
|
|
if (inline_frames)
|
|
|
|
*inline_frames = nullptr;
|
|
|
|
|
|
|
|
Expected<DILineInfo> res_or_err =
|
|
|
|
symbolizer->symbolizeCode(dso_name, sectioned_addr);
|
|
|
|
if (!res_or_err)
|
|
|
|
return 0;
|
|
|
|
return extract_file_and_line(*res_or_err, file, line);
|
|
|
|
}
|
|
|
|
}
|
perf annotate: LLVM-based disassembler
Support using LLVM as a disassembler method, allowing helperless
annotation in non-distro builds. (It is also much faster than
using libbfd or bfd objdump on binaries with a lot of debug
information.)
This is nearly identical to the output of llvm-objdump; there are
some very rare whitespace differences, some minor changes to demangling
(since we use perf's regular demangling and not LLVM's own) and
the occasional case where llvm-objdump makes a different choice
when multiple symbols share the same address.
It should work across all of LLVM's supported architectures, although
I've only tested 64-bit x86, and finding the right triple from perf's
idea of machine architecture can sometimes be a bit tricky. Ideally, we
should have some way of finding the triplet just from the file itself.
Committer notes:
Address this on 32-bit systems by using PRIu64 from inttypes.h
3 17.58 almalinux:9-i386 : FAIL gcc version 11.4.1 20231218 (Red Hat 11.4.1-3) (GCC)
util/llvm-c-helpers.cpp: In function ‘char* make_symbol_relative_string(dso*, const char*, u64, u64)’:
util/llvm-c-helpers.cpp:150:52: error: format ‘%lx’ expects argument of type ‘long unsigned int’, but argument 5 has type ‘u64’ {aka
+‘long long unsigned int’} [-Werror=format=]
150 | snprintf(buf, sizeof(buf), "%s+0x%lx",
| ~~^
| |
| long unsigned int
| %llx
151 | demangled ? demangled : sym_name, addr - base_addr);
| ~~~~~~~~~~~~~~~~
| |
| u64 {aka long long unsigned int}
cc1plus: all warnings being treated as errors
Signed-off-by: Steinar H. Gunderson <sesse@google.com>
Cc: Ian Rogers <irogers@google.com>
Link: https://lore.kernel.org/r/20240803152008.2818485-3-sesse@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2024-08-03 08:20:08 -07:00
|
|
|
|
|
|
|
static char *
|
|
|
|
make_symbol_relative_string(struct dso *dso, const char *sym_name,
|
|
|
|
u64 addr, u64 base_addr)
|
|
|
|
{
|
|
|
|
if (!strcmp(sym_name, "<invalid>"))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
char *demangled = dso__demangle_sym(dso, 0, sym_name);
|
|
|
|
if (base_addr && base_addr != addr) {
|
|
|
|
char buf[256];
|
|
|
|
snprintf(buf, sizeof(buf), "%s+0x%" PRIx64,
|
|
|
|
demangled ? demangled : sym_name, addr - base_addr);
|
|
|
|
free(demangled);
|
|
|
|
return strdup(buf);
|
|
|
|
} else {
|
|
|
|
if (demangled)
|
|
|
|
return demangled;
|
|
|
|
else
|
|
|
|
return strdup(sym_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C"
|
|
|
|
char *llvm_name_for_code(struct dso *dso, const char *dso_name, u64 addr)
|
|
|
|
{
|
|
|
|
LLVMSymbolizer *symbolizer = get_symbolizer();
|
|
|
|
object::SectionedAddress sectioned_addr = {
|
|
|
|
addr,
|
|
|
|
object::SectionedAddress::UndefSection
|
|
|
|
};
|
|
|
|
Expected<DILineInfo> res_or_err =
|
|
|
|
symbolizer->symbolizeCode(dso_name, sectioned_addr);
|
|
|
|
if (!res_or_err) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return make_symbol_relative_string(
|
|
|
|
dso, res_or_err->FunctionName.c_str(),
|
|
|
|
addr, res_or_err->StartAddress ? *res_or_err->StartAddress : 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C"
|
|
|
|
char *llvm_name_for_data(struct dso *dso, const char *dso_name, u64 addr)
|
|
|
|
{
|
|
|
|
LLVMSymbolizer *symbolizer = get_symbolizer();
|
|
|
|
object::SectionedAddress sectioned_addr = {
|
|
|
|
addr,
|
|
|
|
object::SectionedAddress::UndefSection
|
|
|
|
};
|
|
|
|
Expected<DIGlobal> res_or_err =
|
|
|
|
symbolizer->symbolizeData(dso_name, sectioned_addr);
|
|
|
|
if (!res_or_err) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return make_symbol_relative_string(
|
|
|
|
dso, res_or_err->Name.c_str(),
|
|
|
|
addr, res_or_err->Start);
|
|
|
|
}
|