perf/urgent fixes:
- Fixes for handling compressed kernel modules (Namhyung Kim) - Fix handling old style build-id cache ($HOME/.debug/) (Namhyung Kim) - 'perf script' python/perl documentation fixes: outdated comments, invalid code snippets, etc (SeongJae Park) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABCAAGBQJZOb/yAAoJENZQFvNTUqpAxnQP/1fzzDOFV/yqdocftOsLaWbx VtOTp8B8NrGz6Aa/XzIwNdvKSEEZGi8tLiLBoFKuIS4Q1tVJ/6yxJ20nNnt9ORui L4GMugCExIJJQ7IdPt77P3O8JzFWko3L/Pi8q87wwueXLQlswgPNBWWAdWAqOrED KCyLSq40iiuGjGKuXGIx2rlKSIJ6/T9ia68Jf0gv/NEk3H25x0wx688Eit0cWjYg odExpgDRsLxP67NFtaBMjL1CQ2Bi0cDJDz3lRYzjML5dJo4w6Ria3FJg1MgTm1jN O4gCAUT4o7otfDXGJJM9wFodNsz+YkL8rIjr5ao7cCXaZTswYzN0YxI0dX/9kgzx afSbL3OJNo0AjYBHcp4LrU0ez74tVbf3juNv11g5HnN2jwWHXY2nvVP5d5tRrK76 l3GZTR7xCinDVT7aBG2XRbMn58YXNU6V3G9DAVeNkzJmSuQrSIuGuf+MlUKcmXZY I01wLH8qVY9t4+EbLJ2OjD8/cXrFxGiyH60uNtLwtx7M7vu1JT2dhjiEJFRhf7tm Gb03CKyZFB0vQYobz+dIgnchcgWPKeRrVMr6UUc0u2StnOgk3S9ZDW3u+9iP9u4n SnqnWhMUcJ/O1t3VA1/6kdX0sUeRbw+EDOHFrhh7fIi3M4+wacI8f4dFmXrX9pRU n/1C+NP4ZOjHNzsgKDtr =qHQl -----END PGP SIGNATURE----- Merge tag 'perf-urgent-for-mingo-4.12-20170608' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent Pull perf/urgent fixes from Arnaldo Carvalho de Melo: - Fixes for handling compressed kernel modules (Namhyung Kim) - Fix handling old style build-id cache ($HOME/.debug/) (Namhyung Kim) - 'perf script' python/perl documentation fixes: outdated comments, invalid code snippets, etc (SeongJae Park) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
commit
47c1ded7fe
@ -240,7 +240,11 @@ Add a probe on schedule() function 12th line with recording cpu local variable:
|
|||||||
or
|
or
|
||||||
./perf probe --add='schedule:12 cpu'
|
./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".
|
||||||
|
|
||||||
|
./perf probe schedule*
|
||||||
|
or
|
||||||
|
./perf probe --add='schedule*'
|
||||||
|
|
||||||
Add probes on lines in schedule() function which calls update_rq_clock().
|
Add probes on lines in schedule() function which calls update_rq_clock().
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ EVENT HANDLERS
|
|||||||
When perf script is invoked using a trace script, a user-defined
|
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
|
'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
|
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.
|
next event is processed.
|
||||||
|
|
||||||
Most of the event's field values are passed as arguments to the
|
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" % \
|
print "id=%d, args=%s\n" % \
|
||||||
(id, args),
|
(id, args),
|
||||||
|
|
||||||
def trace_unhandled(event_name, context, common_cpu, common_secs, common_nsecs,
|
def trace_unhandled(event_name, context, event_fields_dict):
|
||||||
common_pid, common_comm):
|
print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())])
|
||||||
print_header(event_name, common_cpu, common_secs, common_nsecs,
|
|
||||||
common_pid, common_comm)
|
|
||||||
|
|
||||||
def print_header(event_name, cpu, secs, nsecs, pid, comm):
|
def print_header(event_name, cpu, secs, nsecs, pid, comm):
|
||||||
print "%-20s %5u %05u.%09u %8u %-20s " % \
|
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
|
process can be generalized to any tracepoint or set of tracepoints
|
||||||
you're interested in - basically find the tracepoint(s) you're
|
you're interested in - basically find the tracepoint(s) you're
|
||||||
interested in by looking at the list of available events shown by
|
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
|
detailed event and field info, record the corresponding trace data
|
||||||
using 'perf record', passing it the list of interesting events,
|
using 'perf record', passing it the list of interesting events,
|
||||||
generate a skeleton script using 'perf script -g python' and modify the
|
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.:
|
scripts listed by the 'perf script -l' command e.g.:
|
||||||
|
|
||||||
----
|
----
|
||||||
root@tropicana:~# perf script -l
|
# perf script -l
|
||||||
List of available trace scripts:
|
List of available trace scripts:
|
||||||
wakeup-latency system-wide min/max/avg wakeup latency
|
wakeup-latency system-wide min/max/avg wakeup latency
|
||||||
rw-by-file <comm> r/w activity for a program, by file
|
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
|
# ls -al kernel-source/tools/perf/scripts/python
|
||||||
|
|
||||||
root@tropicana:/home/trz/src/tip# ls -al tools/perf/scripts/python
|
|
||||||
total 32
|
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:30 .
|
||||||
drwxr-xr-x 4 trz trz 4096 2010-01-26 22:29 ..
|
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:
|
should show a new entry for your script:
|
||||||
|
|
||||||
----
|
----
|
||||||
root@tropicana:~# perf script -l
|
# perf script -l
|
||||||
List of available trace scripts:
|
List of available trace scripts:
|
||||||
wakeup-latency system-wide min/max/avg wakeup latency
|
wakeup-latency system-wide min/max/avg wakeup latency
|
||||||
rw-by-file <comm> r/w activity for a program, by file
|
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
|
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
|
'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
|
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.
|
next event is processed.
|
||||||
|
|
||||||
Most of the event's field values are passed as arguments to the
|
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:
|
gives scripts a chance to do setup tasks:
|
||||||
|
|
||||||
----
|
----
|
||||||
def trace_begin:
|
def trace_begin():
|
||||||
pass
|
pass
|
||||||
----
|
----
|
||||||
|
|
||||||
@ -541,7 +537,7 @@ def trace_begin:
|
|||||||
as display results:
|
as display results:
|
||||||
|
|
||||||
----
|
----
|
||||||
def trace_end:
|
def trace_end():
|
||||||
pass
|
pass
|
||||||
----
|
----
|
||||||
|
|
||||||
@ -550,8 +546,7 @@ def trace_end:
|
|||||||
of common arguments are passed into it:
|
of common arguments are passed into it:
|
||||||
|
|
||||||
----
|
----
|
||||||
def trace_unhandled(event_name, context, common_cpu, common_secs,
|
def trace_unhandled(event_name, context, event_fields_dict):
|
||||||
common_nsecs, common_pid, common_comm):
|
|
||||||
pass
|
pass
|
||||||
----
|
----
|
||||||
|
|
||||||
|
@ -229,6 +229,8 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
|
|||||||
unsigned char buf2[BUFSZ];
|
unsigned char buf2[BUFSZ];
|
||||||
size_t ret_len;
|
size_t ret_len;
|
||||||
u64 objdump_addr;
|
u64 objdump_addr;
|
||||||
|
const char *objdump_name;
|
||||||
|
char decomp_name[KMOD_DECOMP_LEN];
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr);
|
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;
|
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 */
|
/* Read the object code using objdump */
|
||||||
objdump_addr = map__rip_2objdump(al.map, al.addr);
|
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) {
|
if (ret > 0) {
|
||||||
/*
|
/*
|
||||||
* The kernel maps are inaccurate - assume objdump is right in
|
* The kernel maps are inaccurate - assume objdump is right in
|
||||||
|
@ -1321,6 +1321,7 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
|
|||||||
char linkname[PATH_MAX];
|
char linkname[PATH_MAX];
|
||||||
char *build_id_filename;
|
char *build_id_filename;
|
||||||
char *build_id_path = NULL;
|
char *build_id_path = NULL;
|
||||||
|
char *pos;
|
||||||
|
|
||||||
if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
|
if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
|
||||||
!dso__is_kcore(dso))
|
!dso__is_kcore(dso))
|
||||||
@ -1340,6 +1341,13 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
|
|||||||
if (!build_id_path)
|
if (!build_id_path)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
dirname(build_id_path);
|
||||||
|
|
||||||
if (dso__is_kcore(dso) ||
|
if (dso__is_kcore(dso) ||
|
||||||
@ -1423,31 +1431,10 @@ int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_na
|
|||||||
sizeof(symfs_filename));
|
sizeof(symfs_filename));
|
||||||
}
|
}
|
||||||
} else if (dso__needs_decompress(dso)) {
|
} else if (dso__needs_decompress(dso)) {
|
||||||
char tmp[PATH_MAX];
|
char tmp[KMOD_DECOMP_LEN];
|
||||||
struct kmod_path m;
|
|
||||||
int fd;
|
|
||||||
bool ret;
|
|
||||||
|
|
||||||
if (kmod_path__parse_ext(&m, symfs_filename))
|
if (dso__decompress_kmodule_path(dso, symfs_filename,
|
||||||
goto out;
|
tmp, sizeof(tmp)) < 0)
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
if (!ret)
|
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
strcpy(symfs_filename, tmp);
|
strcpy(symfs_filename, tmp);
|
||||||
|
@ -278,51 +278,6 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
|
|||||||
return bf;
|
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) \
|
#define dsos__for_each_with_build_id(pos, head) \
|
||||||
list_for_each_entry(pos, head, node) \
|
list_for_each_entry(pos, head, node) \
|
||||||
if (!pos->has_build_id) \
|
if (!pos->has_build_id) \
|
||||||
|
@ -17,7 +17,6 @@ char *build_id_cache__kallsyms_path(const char *sbuild_id, char *bf,
|
|||||||
size_t size);
|
size_t size);
|
||||||
|
|
||||||
char *dso__build_id_filename(const struct dso *dso, 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,
|
int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event,
|
||||||
struct perf_sample *sample, struct perf_evsel *evsel,
|
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;
|
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
|
* Parses kernel module specified in @path and updates
|
||||||
* @m argument like:
|
* @m argument like:
|
||||||
@ -396,7 +454,7 @@ static int do_open(char *name)
|
|||||||
|
|
||||||
static int __open_dso(struct dso *dso, struct machine *machine)
|
static int __open_dso(struct dso *dso, struct machine *machine)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd = -EINVAL;
|
||||||
char *root_dir = (char *)"";
|
char *root_dir = (char *)"";
|
||||||
char *name = malloc(PATH_MAX);
|
char *name = malloc(PATH_MAX);
|
||||||
|
|
||||||
@ -407,15 +465,30 @@ static int __open_dso(struct dso *dso, struct machine *machine)
|
|||||||
root_dir = machine->root_dir;
|
root_dir = machine->root_dir;
|
||||||
|
|
||||||
if (dso__read_binary_type_filename(dso, dso->binary_type,
|
if (dso__read_binary_type_filename(dso, dso->binary_type,
|
||||||
root_dir, name, PATH_MAX)) {
|
root_dir, name, PATH_MAX))
|
||||||
free(name);
|
goto out;
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_regular_file(name))
|
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);
|
fd = do_open(name);
|
||||||
|
|
||||||
|
if (dso__needs_decompress(dso))
|
||||||
|
unlink(name);
|
||||||
|
|
||||||
|
out:
|
||||||
free(name);
|
free(name);
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
@ -244,6 +244,12 @@ bool is_supported_compression(const char *ext);
|
|||||||
bool is_kernel_module(const char *pathname, int cpumode);
|
bool is_kernel_module(const char *pathname, int cpumode);
|
||||||
bool decompress_to_file(const char *ext, const char *filename, int output_fd);
|
bool decompress_to_file(const char *ext, const char *filename, int output_fd);
|
||||||
bool dso__needs_decompress(struct dso *dso);
|
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 {
|
struct kmod_path {
|
||||||
char *name;
|
char *name;
|
||||||
|
@ -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 "
|
fprintf(ofp, "# be retrieved using Python functions of the form "
|
||||||
"common_*(context).\n");
|
"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");
|
"of available functions.\n\n");
|
||||||
|
|
||||||
fprintf(ofp, "import os\n");
|
fprintf(ofp, "import os\n");
|
||||||
|
@ -637,40 +637,6 @@ static int dso__swap_init(struct dso *dso, unsigned char eidata)
|
|||||||
return 0;
|
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 (kmod_path__parse_ext(&m, dso->long_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)
|
bool symsrc__possibly_runtime(struct symsrc *ss)
|
||||||
{
|
{
|
||||||
return ss->dynsym || ss->opdsec;
|
return ss->dynsym || ss->opdsec;
|
||||||
@ -702,9 +668,11 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
|
|||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if (dso__needs_decompress(dso)) {
|
if (dso__needs_decompress(dso)) {
|
||||||
fd = decompress_kmodule(dso, name, type);
|
fd = dso__decompress_kmodule_fd(dso, name);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
type = dso->symtab_type;
|
||||||
} else {
|
} else {
|
||||||
fd = open(name, O_RDONLY);
|
fd = open(name, O_RDONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
@ -1562,10 +1562,6 @@ int dso__load(struct dso *dso, struct map *map)
|
|||||||
if (!runtime_ss && syms_ss)
|
if (!runtime_ss && syms_ss)
|
||||||
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)
|
if (syms_ss)
|
||||||
ret = dso__load_sym(dso, map, syms_ss, runtime_ss, kmod);
|
ret = dso__load_sym(dso, map, syms_ss, runtime_ss, kmod);
|
||||||
else
|
else
|
||||||
|
Loading…
Reference in New Issue
Block a user