Commit f701d860 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf fixes from Ingo Molnar:
 "This is mostly tooling fixes, plus an instruction pointer filtering
  fix.

  It's more fixes than usual - Arnaldo got back from a longer vacation
  and there was a backlog"

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (27 commits)
  perf symbols: Kill dso__build_id_is_kmod()
  perf symbols: Keep DSO->symtab_type after decompress
  perf tests: Decompress kernel module before objdump
  perf tools: Consolidate error path in __open_dso()
  perf tools: Decompress kernel module when reading DSO data
  perf annotate: Use dso__decompress_kmodule_path()
  perf tools: Introduce dso__decompress_kmodule_{fd,path}
  perf tools: Fix a memory leak in __open_dso()
  perf annotate: Fix symbolic link of build-id cache
  perf/core: Drop kernel samples even though :u is specified
  perf script python: Remove dups in documentation examples
  perf script python: Updated trace_unhandled() signature
  perf script python: Fix wrong code snippets in documentation
  perf script: Fix documentation errors
  perf script: Fix outdated comment for perf-trace-python
  perf probe: Fix examples section of documentation
  perf report: Ensure the perf DSO mapping matches what libdw sees
  perf report: Include partial stacks unwound with libdw
  perf annotate: Add missing powerpc triplet
  perf test: Disable breakpoint signal tests for powerpc
  ...
parents 9376906c 47c1ded7
......@@ -7316,6 +7316,21 @@ int perf_event_account_interrupt(struct perf_event *event)
return __perf_event_account_interrupt(event, 1);
}
static bool sample_is_allowed(struct perf_event *event, struct pt_regs *regs)
{
/*
* Due to interrupt latency (AKA "skid"), we may enter the
* kernel before taking an overflow, even if the PMU is only
* counting user events.
* To avoid leaking information to userspace, we must always
* reject kernel samples when exclude_kernel is set.
*/
if (event->attr.exclude_kernel && !user_mode(regs))
return false;
return true;
}
/*
* Generic event overflow handling, sampling.
*/
......@@ -7336,6 +7351,12 @@ static int __perf_event_overflow(struct perf_event *event,
ret = __perf_event_account_interrupt(event, throttle);
/*
* For security, drop the skid kernel samples if necessary.
*/
if (!sample_is_allowed(event, regs))
return ret;
/*
* XXX event_limit might not quite work as expected on inherited
* events
......
......@@ -240,9 +240,13 @@ Add a probe on schedule() function 12th line with recording cpu local variable:
or
./perf probe --add='schedule:12 cpu'
this will add one or more probes which has the name start with "schedule".
Add one or more probes which has the name start with "schedule".
Add probes on lines in schedule() function which calls update_rq_clock().
./perf probe schedule*
or
./perf probe --add='schedule*'
Add probes on lines in schedule() function which calls update_rq_clock().
./perf probe 'schedule;update_rq_clock*'
or
......
......@@ -39,7 +39,7 @@ EVENT HANDLERS
When perf script is invoked using a trace script, a user-defined
'handler function' is called for each event in the trace. If there's
no handler function defined for a given event type, the event is
ignored (or passed to a 'trace_handled' function, see below) and the
ignored (or passed to a 'trace_unhandled' function, see below) and the
next event is processed.
Most of the event's field values are passed as arguments to the
......
......@@ -149,10 +149,8 @@ def raw_syscalls__sys_enter(event_name, context, common_cpu,
print "id=%d, args=%s\n" % \
(id, args),
def trace_unhandled(event_name, context, common_cpu, common_secs, common_nsecs,
common_pid, common_comm):
print_header(event_name, common_cpu, common_secs, common_nsecs,
common_pid, common_comm)
def trace_unhandled(event_name, context, event_fields_dict):
print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())])
def print_header(event_name, cpu, secs, nsecs, pid, comm):
print "%-20s %5u %05u.%09u %8u %-20s " % \
......@@ -321,7 +319,7 @@ So those are the essential steps in writing and running a script. The
process can be generalized to any tracepoint or set of tracepoints
you're interested in - basically find the tracepoint(s) you're
interested in by looking at the list of available events shown by
'perf list' and/or look in /sys/kernel/debug/tracing events for
'perf list' and/or look in /sys/kernel/debug/tracing/events/ for
detailed event and field info, record the corresponding trace data
using 'perf record', passing it the list of interesting events,
generate a skeleton script using 'perf script -g python' and modify the
......@@ -334,7 +332,7 @@ right place, you can have your script listed alongside the other
scripts listed by the 'perf script -l' command e.g.:
----
root@tropicana:~# perf script -l
# perf script -l
List of available trace scripts:
wakeup-latency system-wide min/max/avg wakeup latency
rw-by-file <comm> r/w activity for a program, by file
......@@ -383,8 +381,6 @@ source tree:
----
# ls -al kernel-source/tools/perf/scripts/python
root@tropicana:/home/trz/src/tip# ls -al tools/perf/scripts/python
total 32
drwxr-xr-x 4 trz trz 4096 2010-01-26 22:30 .
drwxr-xr-x 4 trz trz 4096 2010-01-26 22:29 ..
......@@ -399,7 +395,7 @@ otherwise your script won't show up at run-time), 'perf script -l'
should show a new entry for your script:
----
root@tropicana:~# perf script -l
# perf script -l
List of available trace scripts:
wakeup-latency system-wide min/max/avg wakeup latency
rw-by-file <comm> r/w activity for a program, by file
......@@ -437,7 +433,7 @@ EVENT HANDLERS
When perf script is invoked using a trace script, a user-defined
'handler function' is called for each event in the trace. If there's
no handler function defined for a given event type, the event is
ignored (or passed to a 'trace_handled' function, see below) and the
ignored (or passed to a 'trace_unhandled' function, see below) and the
next event is processed.
Most of the event's field values are passed as arguments to the
......@@ -532,7 +528,7 @@ can implement a set of optional functions:
gives scripts a chance to do setup tasks:
----
def trace_begin:
def trace_begin():
pass
----
......@@ -541,7 +537,7 @@ def trace_begin:
as display results:
----
def trace_end:
def trace_end():
pass
----
......@@ -550,8 +546,7 @@ def trace_end:
of common arguments are passed into it:
----
def trace_unhandled(event_name, context, common_cpu, common_secs,
common_nsecs, common_pid, common_comm):
def trace_unhandled(event_name, context, event_fields_dict):
pass
----
......
......@@ -26,6 +26,7 @@ const char *const arm64_triplets[] = {
const char *const powerpc_triplets[] = {
"powerpc-unknown-linux-gnu-",
"powerpc-linux-gnu-",
"powerpc64-unknown-linux-gnu-",
"powerpc64-linux-gnu-",
"powerpc64le-linux-gnu-",
......
......@@ -1578,6 +1578,7 @@ static void print_header(int argc, const char **argv)
static void print_footer(void)
{
FILE *output = stat_config.output;
int n;
if (!null_run)
fprintf(output, "\n");
......@@ -1590,7 +1591,9 @@ static void print_footer(void)
}
fprintf(output, "\n\n");
if (print_free_counters_hint)
if (print_free_counters_hint &&
sysctl__read_int("kernel/nmi_watchdog", &n) >= 0 &&
n > 0)
fprintf(output,
"Some events weren't counted. Try disabling the NMI watchdog:\n"
" echo 0 > /proc/sys/kernel/nmi_watchdog\n"
......
......@@ -681,6 +681,10 @@ static struct syscall_fmt {
{ .name = "mlockall", .errmsg = true,
.arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
{ .name = "mmap", .hexret = true,
/* The standard mmap maps to old_mmap on s390x */
#if defined(__s390x__)
.alias = "old_mmap",
#endif
.arg_scnprintf = { [0] = SCA_HEX, /* addr */
[2] = SCA_MMAP_PROT, /* prot */
[3] = SCA_MMAP_FLAGS, /* flags */ }, },
......
......@@ -288,3 +288,17 @@ int test__bp_signal(int subtest __maybe_unused)
return count1 == 1 && overflows == 3 && count2 == 3 && overflows_2 == 3 && count3 == 2 ?
TEST_OK : TEST_FAIL;
}
bool test__bp_signal_is_supported(void)
{
/*
* The powerpc so far does not have support to even create
* instruction breakpoint using the perf event interface.
* Once it's there we can release this.
*/
#ifdef __powerpc__
return false;
#else
return true;
#endif
}
......@@ -97,10 +97,12 @@ static struct test generic_tests[] = {
{
.desc = "Breakpoint overflow signal handler",
.func = test__bp_signal,
.is_supported = test__bp_signal_is_supported,
},
{
.desc = "Breakpoint overflow sampling",
.func = test__bp_signal_overflow,
.is_supported = test__bp_signal_is_supported,
},
{
.desc = "Number of exit events of a simple workload",
......@@ -401,6 +403,11 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
if (!perf_test__matches(t, curr, argc, argv))
continue;
if (t->is_supported && !t->is_supported()) {
pr_debug("%2d: %-*s: Disabled\n", i, width, t->desc);
continue;
}
pr_info("%2d: %-*s:", i, width, t->desc);
if (intlist__find(skiplist, i)) {
......
......@@ -229,6 +229,8 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
unsigned char buf2[BUFSZ];
size_t ret_len;
u64 objdump_addr;
const char *objdump_name;
char decomp_name[KMOD_DECOMP_LEN];
int ret;
pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr);
......@@ -289,9 +291,25 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
state->done[state->done_cnt++] = al.map->start;
}
objdump_name = al.map->dso->long_name;
if (dso__needs_decompress(al.map->dso)) {
if (dso__decompress_kmodule_path(al.map->dso, objdump_name,
decomp_name,
sizeof(decomp_name)) < 0) {
pr_debug("decompression failed\n");
return -1;
}
objdump_name = decomp_name;
}
/* Read the object code using objdump */
objdump_addr = map__rip_2objdump(al.map, al.addr);
ret = read_via_objdump(al.map->dso->long_name, objdump_addr, buf2, len);
ret = read_via_objdump(objdump_name, objdump_addr, buf2, len);
if (dso__needs_decompress(al.map->dso))
unlink(objdump_name);
if (ret > 0) {
/*
* The kernel maps are inaccurate - assume objdump is right in
......
......@@ -34,6 +34,7 @@ struct test {
int (*get_nr)(void);
const char *(*get_desc)(int subtest);
} subtest;
bool (*is_supported)(void);
};
/* Tests */
......@@ -99,6 +100,8 @@ const char *test__clang_subtest_get_desc(int subtest);
int test__clang_subtest_get_nr(void);
int test__unit_number__scnprint(int subtest);
bool test__bp_signal_is_supported(void);
#if defined(__arm__) || defined(__aarch64__)
#ifdef HAVE_DWARF_UNWIND_SUPPORT
struct thread;
......
......@@ -239,10 +239,20 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op
const char *s = strchr(ops->raw, '+');
const char *c = strchr(ops->raw, ',');
if (c++ != NULL)
/*
* skip over possible up to 2 operands to get to address, e.g.:
* tbnz w0, #26, ffff0000083cd190 <security_file_permission+0xd0>
*/
if (c++ != NULL) {
ops->target.addr = strtoull(c, NULL, 16);
else
if (!ops->target.addr) {
c = strchr(c, ',');
if (c++ != NULL)
ops->target.addr = strtoull(c, NULL, 16);
}
} else {
ops->target.addr = strtoull(ops->raw, NULL, 16);
}
if (s++ != NULL) {
ops->target.offset = strtoull(s, NULL, 16);
......@@ -257,10 +267,27 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op
static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
struct ins_operands *ops)
{
const char *c = strchr(ops->raw, ',');
if (!ops->target.addr || ops->target.offset < 0)
return ins__raw_scnprintf(ins, bf, size, ops);
return scnprintf(bf, size, "%-6.6s %" PRIx64, ins->name, ops->target.offset);
if (c != NULL) {
const char *c2 = strchr(c + 1, ',');
/* check for 3-op insn */
if (c2 != NULL)
c = c2;
c++;
/* mirror arch objdump's space-after-comma style */
if (*c == ' ')
c++;
}
return scnprintf(bf, size, "%-6.6s %.*s%" PRIx64,
ins->name, c ? c - ops->raw : 0, ops->raw,
ops->target.offset);
}
static struct ins_ops jump_ops = {
......@@ -1294,6 +1321,7 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
char linkname[PATH_MAX];
char *build_id_filename;
char *build_id_path = NULL;
char *pos;
if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
!dso__is_kcore(dso))
......@@ -1313,7 +1341,14 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
if (!build_id_path)
return -1;
dirname(build_id_path);
/*
* old style build-id cache has name of XX/XXXXXXX.. while
* new style has XX/XXXXXXX../{elf,kallsyms,vdso}.
* extract the build-id part of dirname in the new style only.
*/
pos = strrchr(build_id_path, '/');
if (pos && strlen(pos) < SBUILD_ID_SIZE - 2)
dirname(build_id_path);
if (dso__is_kcore(dso) ||
readlink(build_id_path, linkname, sizeof(linkname)) < 0 ||
......@@ -1396,31 +1431,10 @@ int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_na
sizeof(symfs_filename));
}
} else if (dso__needs_decompress(dso)) {
char tmp[PATH_MAX];
struct kmod_path m;
int fd;
bool ret;
if (kmod_path__parse_ext(&m, symfs_filename))
goto out;
snprintf(tmp, PATH_MAX, "/tmp/perf-kmod-XXXXXX");
fd = mkstemp(tmp);
if (fd < 0) {
free(m.ext);
goto out;
}
ret = decompress_to_file(m.ext, symfs_filename, fd);
if (ret)
pr_err("Cannot decompress %s %s\n", m.ext, symfs_filename);
free(m.ext);
close(fd);
char tmp[KMOD_DECOMP_LEN];
if (!ret)
if (dso__decompress_kmodule_path(dso, symfs_filename,
tmp, sizeof(tmp)) < 0)
goto out;
strcpy(symfs_filename, tmp);
......@@ -1429,7 +1443,7 @@ int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_na
snprintf(command, sizeof(command),
"%s %s%s --start-address=0x%016" PRIx64
" --stop-address=0x%016" PRIx64
" -l -d %s %s -C %s 2>/dev/null|grep -v %s:|expand",
" -l -d %s %s -C \"%s\" 2>/dev/null|grep -v \"%s:\"|expand",
objdump_path ? objdump_path : "objdump",
disassembler_style ? "-M " : "",
disassembler_style ? disassembler_style : "",
......
......@@ -278,51 +278,6 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
return bf;
}
bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size)
{
char *id_name = NULL, *ch;
struct stat sb;
char sbuild_id[SBUILD_ID_SIZE];
if (!dso->has_build_id)
goto err;
build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
id_name = build_id_cache__linkname(sbuild_id, NULL, 0);
if (!id_name)
goto err;
if (access(id_name, F_OK))
goto err;
if (lstat(id_name, &sb) == -1)
goto err;
if ((size_t)sb.st_size > size - 1)
goto err;
if (readlink(id_name, bf, size - 1) < 0)
goto err;
bf[sb.st_size] = '\0';
/*
* link should be:
* ../../lib/modules/4.4.0-rc4/kernel/net/ipv4/netfilter/nf_nat_ipv4.ko/a09fe3eb3147dafa4e3b31dbd6257e4d696bdc92
*/
ch = strrchr(bf, '/');
if (!ch)
goto err;
if (ch - 3 < bf)
goto err;
free(id_name);
return strncmp(".ko", ch - 3, 3) == 0;
err:
pr_err("Invalid build id: %s\n", id_name ? :
dso->long_name ? :
dso->short_name ? :
"[unknown]");
free(id_name);
return false;
}
#define dsos__for_each_with_build_id(pos, head) \
list_for_each_entry(pos, head, node) \
if (!pos->has_build_id) \
......
......@@ -17,7 +17,6 @@ char *build_id_cache__kallsyms_path(const char *sbuild_id, char *bf,
size_t size);
char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size);
bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size);
int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event,
struct perf_sample *sample, struct perf_evsel *evsel,
......
......@@ -248,6 +248,64 @@ bool dso__needs_decompress(struct dso *dso)
dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP;
}
static int decompress_kmodule(struct dso *dso, const char *name, char *tmpbuf)
{
int fd = -1;
struct kmod_path m;
if (!dso__needs_decompress(dso))
return -1;
if (kmod_path__parse_ext(&m, dso->long_name))
return -1;
if (!m.comp)
goto out;
fd = mkstemp(tmpbuf);
if (fd < 0) {
dso->load_errno = errno;
goto out;
}
if (!decompress_to_file(m.ext, name, fd)) {
dso->load_errno = DSO_LOAD_ERRNO__DECOMPRESSION_FAILURE;
close(fd);
fd = -1;
}
out:
free(m.ext);
return fd;
}
int dso__decompress_kmodule_fd(struct dso *dso, const char *name)
{
char tmpbuf[] = KMOD_DECOMP_NAME;
int fd;
fd = decompress_kmodule(dso, name, tmpbuf);
unlink(tmpbuf);
return fd;
}
int dso__decompress_kmodule_path(struct dso *dso, const char *name,
char *pathname, size_t len)
{
char tmpbuf[] = KMOD_DECOMP_NAME;
int fd;
fd = decompress_kmodule(dso, name, tmpbuf);
if (fd < 0) {
unlink(tmpbuf);
return -1;
}
strncpy(pathname, tmpbuf, len);
close(fd);
return 0;
}
/*
* Parses kernel module specified in @path and updates
* @m argument like:
......@@ -335,6 +393,21 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
return 0;
}
void dso__set_module_info(struct dso *dso, struct kmod_path *m,
struct machine *machine)
{
if (machine__is_host(machine))
dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
else
dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
/* _KMODULE_COMP should be next to _KMODULE */
if (m->kmod && m->comp)
dso->symtab_type++;
dso__set_short_name(dso, strdup(m->name), true);
}
/*
* Global list of open DSOs and the counter.
*/
......@@ -381,7 +454,7 @@ static int do_open(char *name)
static int __open_dso(struct dso *dso, struct machine *machine)
{
int fd;
int fd = -EINVAL;
char *root_dir = (char *)"";
char *name = malloc(PATH_MAX);
......@@ -392,15 +465,30 @@ static int __open_dso(struct dso *dso, struct machine *machine)
root_dir = machine->root_dir;
if (dso__read_binary_type_filename(dso, dso->binary_type,
root_dir, name, PATH_MAX)) {
free(name);
return -EINVAL;
}
root_dir, name, PATH_MAX))
goto out;
if (!is_regular_file(name))
return -EINVAL;
goto out;
if (dso__needs_decompress(dso)) {
char newpath[KMOD_DECOMP_LEN];
size_t len = sizeof(newpath);
if (dso__decompress_kmodule_path(dso, name, newpath, len) < 0) {
fd = -dso->load_errno;
goto out;
}
strcpy(name, newpath);
}
fd = do_open(name);
if (dso__needs_decompress(dso))
unlink(name);
out:
free(name);
return fd;
}
......
......@@ -244,6 +244,12 @@ bool is_supported_compression(const char *ext);
bool is_kernel_module(const char *pathname, int cpumode);
bool decompress_to_file(const char *ext, const char *filename, int output_fd);
bool dso__needs_decompress(struct dso *dso);
int dso__decompress_kmodule_fd(struct dso *dso, const char *name);
int dso__decompress_kmodule_path(struct dso *dso, const char *name,
char *pathname, size_t len);
#define KMOD_DECOMP_NAME "/tmp/perf-kmod-XXXXXX"
#define KMOD_DECOMP_LEN sizeof(KMOD_DECOMP_NAME)
struct kmod_path {
char *name;
......@@ -259,6 +265,9 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
#define kmod_path__parse_name(__m, __p) __kmod_path__parse(__m, __p, true , false)
#define kmod_path__parse_ext(__m, __p) __kmod_path__parse(__m, __p, false, true)
void dso__set_module_info(struct dso *dso, struct kmod_path *m,
struct machine *machine);
/*
* The dso__data_* external interface provides following functions:
* dso__data_get_fd
......
......@@ -1469,8 +1469,16 @@ static int __event_process_build_id(struct build_id_event *bev,
dso__set_build_id(dso, &bev->build_id);
if (!is_kernel_module(filename, cpumode))
dso->kernel = dso_type;
if (dso_type != DSO_TYPE_USER) {
struct kmod_path m = { .name = NULL, };
if (!kmod_path__parse_name(&m, filename) && m.kmod)
dso__set_module_info(dso, &m, machine);
else
dso->kernel = dso_type;
free(m.name);
}
build_id__sprintf(dso->build_id, sizeof(dso->build_id),
sbuild_id);
......
......@@ -572,16 +572,7 @@ static struct dso *machine__findnew_module_dso(struct machine *machine,
if (dso == NULL)
goto out_unlock;
if (machine__is_host(machine))
dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
else
dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
/* _KMODULE_COMP should be next to _KMODULE */
if (m->kmod && m->comp)
dso->symtab_type++;
dso__set_short_name(dso, strdup(m->name), true);
dso__set_module_info(dso, m, machine);
dso__set_long_name(dso, strdup(filename), true);
}
......
......@@ -1219,7 +1219,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
fprintf(ofp, "# be retrieved using Python functions of the form "
"common_*(context).\n");
fprintf(ofp, "# See the perf-trace-python Documentation for the list "
fprintf(ofp, "# See the perf-script-python Documentation for the list "
"of available functions.\n\n");
fprintf(ofp, "import os\n");
......
......@@ -637,43 +637,6 @@ static int dso__swap_init(struct dso *dso, unsigned char eidata)
return 0;
}
static int decompress_kmodule(struct dso *dso, const char *name,
enum dso_binary_type type)
{
int fd = -1;
char tmpbuf[] = "/tmp/perf-kmod-XXXXXX";
struct kmod_path m;
if (type != DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP &&
type != DSO_BINARY_TYPE__GUEST_KMODULE_COMP &&
type != DSO_BINARY_TYPE__BUILD_ID_CACHE)
return -1;
if (type == DSO_BINARY_TYPE__BUILD_ID_CACHE)
name = dso->long_name;
if (kmod_path__parse_ext(&m, name) || !m.comp)
return -1;
fd = mkstemp(tmpbuf);
if (fd < 0) {
dso->load_errno = errno;
goto out;
}
if (!decompress_to_file(m.ext, name, fd)) {
dso->load_errno = DSO_LOAD_ERRNO__DECOMPRESSION_FAILURE;
close(fd);
fd = -1;
}
unlink(tmpbuf);
out:
free(m.ext);
return fd;
}
bool symsrc__possibly_runtime(struct symsrc *ss)
{
return ss->dynsym || ss->opdsec;
......@@ -705,9 +668,11 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
int fd;
if (dso__needs_decompress(dso)) {
fd = decompress_kmodule(dso, name, type);
fd = dso__decompress_kmodule_fd(dso, name);
if (fd < 0)
return -1;
type = dso->symtab_type;
} else {
fd = open(name, O_RDONLY);
if (fd < 0) {
......
......@@ -1562,10 +1562,6 @@ int dso__load(struct dso *dso, struct map *map)
if (!runtime_ss && syms_ss)
runtime_ss = syms_ss;
if (syms_ss && syms_ss->type == DSO_BINARY_TYPE__BUILD_ID_CACHE)
if (dso__build_id_is_kmod(dso, name, PATH_MAX))
kmod = true;
if (syms_ss)
ret = dso__load_sym(dso, map, syms_ss, runtime_ss, kmod);
else
......
......@@ -39,6 +39,14 @@ static int __report_module(struct addr_location *al, u64 ip,
return 0;
mod = dwfl_addrmodule(ui->dwfl, ip);