mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-13 22:56:27 +08:00
perf/urgent fixes:
. Check for SIGINT in more loops, allowing tools such as 'perf report' to react faster to control+C. . Fix objdump line parsing offset validation in the annotate code, from Adrian Hunter. . Fix buildid cache handling of kallsyms with kcore, from Adrian Hunter. . Fix compile with libelf without get_phdrnum, from Adrian Hunter. . Sharpen the libaudit dependencies test, refusing to build with older libraries that doesn't have all the functions used by 'perf trace", fix from Ingo Molnar. . Fill in new definitions for madvise()/mmap() flags to fix the build in older systems, from Ingo Molnar. . Fix old GCC build error in older systems in the kallsyms parsing code in trace-event-parse.c, from Ingo Molnar. . Ignore DWARF declaration tags, allowing, for instance, that the $ perf probe -L getname command succeeds in showing the source code for the 'getname' kernel function, telling in which lines probes can be inserted, fix from Masami Hiramatsu. . Fix linux/magic.h related build breakage in some systems, fix from Vinson Lee. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.14 (GNU/Linux) iQIcBAABAgAGBQJSO0DtAAoJENZQFvNTUqpAIewP/iYqGiu6rG7fHLaYQFl1oOP3 tY65xo+22FG6pIsets1I958Bs+IefSAddsFCIkVZcHFcf3W/c+LlV5RRQqFNZvHQ 6ovPUWPILYIp5omKlB2/f3HPQHEdO5Ijftb+QUSwJbJkcWYgwm4ThEA5G5qr5s3n /f7vbMHQGG7fogCKY3cNbDZdjJqF+TlMXxnIHev9roXwdgdzHd/1GGbM7KBWZ2fB aUhCKQw5A7X4BQwMbtA/6Dx6uXihzGXWPInPqtP1jtLR41hRCfYlHRvoQ09MdzjN OHQp7cqSS4ThVZSxuFTRYgsUHeFc45PO2tTHNXWlZ+2wtzti6l3jAHNrdCgz1Elr iZeF4H9mw9t25siax1RAZq6LSZMzJoeJn0DXMPaQyWWn+bT8GfUGXrgDo8WWdW4L 0wKTe7vdM+4NboJCPduxIwP50FukvVhpvFBlgTXBHmItKapUlSytkVLp5PryZhAJ X3vVJ9570cFE32xfAsedFLUEYENgiRoQfh7TflRzVQYylf+efAvxGBrS0xGFxs2y RomwGbr/v+ou98Kj0k1LQqEA+9LxZG6L0MOBGDBqe38lCxTYntGKG1eJx6qVY7Th bTcoPyO0EZU1uwfvyjGK7HTKMgYc3/7KqOLP/5ipeB3L6/mW7shFHFjB1f0fP2dX CPqcaqIzCDzffUhE0h0P =8a1R -----END PGP SIGNATURE----- Merge tag 'perf-urgent-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent Pull perf/urgent fixes from Arnaldo Carvalho de Melo: * Check for SIGINT in more loops, allowing tools such as 'perf report' to react faster to Ctrl+C, from Arnaldo Carvalho de Melo. * Fix objdump line parsing offset validation in the annotate code, from Adrian Hunter. * Fix buildid cache handling of kallsyms with kcore, from Adrian Hunter. * Fix compile with libelf without get_phdrnum, from Adrian Hunter. * Sharpen the libaudit dependencies test, refusing to build with older libraries that doesn't have all the functions used by 'perf trace", fix from Ingo Molnar. * Fill in new definitions for madvise()/mmap() flags to fix the build in older systems, from Ingo Molnar. * Fix old GCC build error in older systems in the kallsyms parsing code in trace-event-parse.c, from Ingo Molnar. * Ignore DWARF declaration tags, allowing, for instance, that the $ perf probe -L getname command succeeds in showing the source code for the 'getname' kernel function, telling in which lines probes can be inserted, fix from Masami Hiramatsu. * Fix linux/magic.h related build breakage in some systems, fix from Vinson Lee. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
commit
24e31f0bef
@ -5,7 +5,6 @@
|
||||
#include <stdbool.h>
|
||||
#include <sys/vfs.h>
|
||||
#include <sys/mount.h>
|
||||
#include <linux/magic.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include "debugfs.h"
|
||||
|
@ -321,8 +321,6 @@ found:
|
||||
return perf_event__repipe(tool, event_sw, &sample_sw, machine);
|
||||
}
|
||||
|
||||
extern volatile int session_done;
|
||||
|
||||
static void sig_handler(int sig __maybe_unused)
|
||||
{
|
||||
session_done = 1;
|
||||
|
@ -401,8 +401,6 @@ static int perf_report__setup_sample_type(struct perf_report *rep)
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern volatile int session_done;
|
||||
|
||||
static void sig_handler(int sig __maybe_unused)
|
||||
{
|
||||
session_done = 1;
|
||||
@ -568,6 +566,9 @@ static int __cmd_report(struct perf_report *rep)
|
||||
}
|
||||
}
|
||||
|
||||
if (session_done())
|
||||
return 0;
|
||||
|
||||
if (nr_samples == 0) {
|
||||
ui__error("The %s file has no samples!\n", session->filename);
|
||||
return 0;
|
||||
|
@ -553,8 +553,6 @@ static struct perf_tool perf_script = {
|
||||
.ordering_requires_timestamps = true,
|
||||
};
|
||||
|
||||
extern volatile int session_done;
|
||||
|
||||
static void sig_handler(int sig __maybe_unused)
|
||||
{
|
||||
session_done = 1;
|
||||
|
@ -16,6 +16,23 @@
|
||||
#include <sys/mman.h>
|
||||
#include <linux/futex.h>
|
||||
|
||||
/* For older distros: */
|
||||
#ifndef MAP_STACK
|
||||
# define MAP_STACK 0x20000
|
||||
#endif
|
||||
|
||||
#ifndef MADV_HWPOISON
|
||||
# define MADV_HWPOISON 100
|
||||
#endif
|
||||
|
||||
#ifndef MADV_MERGEABLE
|
||||
# define MADV_MERGEABLE 12
|
||||
#endif
|
||||
|
||||
#ifndef MADV_UNMERGEABLE
|
||||
# define MADV_UNMERGEABLE 13
|
||||
#endif
|
||||
|
||||
static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
|
||||
unsigned long arg,
|
||||
u8 arg_idx __maybe_unused,
|
||||
|
@ -180,6 +180,9 @@ FLAGS_LIBELF=$(CFLAGS) $(LDFLAGS) $(EXTLIBS)
|
||||
ifeq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_LIBELF),-DLIBELF_MMAP),y)
|
||||
CFLAGS += -DLIBELF_MMAP
|
||||
endif
|
||||
ifeq ($(call try-cc,$(SOURCE_ELF_GETPHDRNUM),$(FLAGS_LIBELF),-DHAVE_ELF_GETPHDRNUM),y)
|
||||
CFLAGS += -DHAVE_ELF_GETPHDRNUM
|
||||
endif
|
||||
|
||||
# include ARCH specific config
|
||||
-include $(src-perf)/arch/$(ARCH)/Makefile
|
||||
|
@ -61,6 +61,15 @@ int main(void)
|
||||
}
|
||||
endef
|
||||
|
||||
define SOURCE_ELF_GETPHDRNUM
|
||||
#include <libelf.h>
|
||||
int main(void)
|
||||
{
|
||||
size_t dst;
|
||||
return elf_getphdrnum(0, &dst);
|
||||
}
|
||||
endef
|
||||
|
||||
ifndef NO_SLANG
|
||||
define SOURCE_SLANG
|
||||
#include <slang.h>
|
||||
@ -210,6 +219,7 @@ define SOURCE_LIBAUDIT
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf(\"error message: %s\n\", audit_errno_to_name(0));
|
||||
return audit_open();
|
||||
}
|
||||
endef
|
||||
|
@ -809,7 +809,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
|
||||
end = map__rip_2objdump(map, sym->end);
|
||||
|
||||
offset = line_ip - start;
|
||||
if (offset < 0 || (u64)line_ip > end)
|
||||
if ((u64)line_ip < start || (u64)line_ip > end)
|
||||
offset = -1;
|
||||
else
|
||||
parsed_line = tmp2 + 1;
|
||||
|
@ -262,6 +262,21 @@ bool die_is_signed_type(Dwarf_Die *tp_die)
|
||||
ret == DW_ATE_signed_fixed);
|
||||
}
|
||||
|
||||
/**
|
||||
* die_is_func_def - Ensure that this DIE is a subprogram and definition
|
||||
* @dw_die: a DIE
|
||||
*
|
||||
* Ensure that this DIE is a subprogram and NOT a declaration. This
|
||||
* returns true if @dw_die is a function definition.
|
||||
**/
|
||||
bool die_is_func_def(Dwarf_Die *dw_die)
|
||||
{
|
||||
Dwarf_Attribute attr;
|
||||
|
||||
return (dwarf_tag(dw_die) == DW_TAG_subprogram &&
|
||||
dwarf_attr(dw_die, DW_AT_declaration, &attr) == NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* die_get_data_member_location - Get the data-member offset
|
||||
* @mb_die: a DIE of a member of a data structure
|
||||
@ -392,6 +407,10 @@ static int __die_search_func_cb(Dwarf_Die *fn_die, void *data)
|
||||
{
|
||||
struct __addr_die_search_param *ad = data;
|
||||
|
||||
/*
|
||||
* Since a declaration entry doesn't has given pc, this always returns
|
||||
* function definition entry.
|
||||
*/
|
||||
if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
|
||||
dwarf_haspc(fn_die, ad->addr)) {
|
||||
memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
|
||||
|
@ -38,6 +38,9 @@ extern int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr,
|
||||
extern int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
|
||||
int (*callback)(Dwarf_Die *, void *), void *data);
|
||||
|
||||
/* Ensure that this DIE is a subprogram and definition (not declaration) */
|
||||
extern bool die_is_func_def(Dwarf_Die *dw_die);
|
||||
|
||||
/* Compare diename and tname */
|
||||
extern bool die_compare_name(Dwarf_Die *dw_die, const char *tname);
|
||||
|
||||
|
@ -199,9 +199,11 @@ static int write_buildid(char *name, size_t name_len, u8 *build_id,
|
||||
return write_padded(fd, name, name_len + 1, len);
|
||||
}
|
||||
|
||||
static int __dsos__write_buildid_table(struct list_head *head, pid_t pid,
|
||||
u16 misc, int fd)
|
||||
static int __dsos__write_buildid_table(struct list_head *head,
|
||||
struct machine *machine,
|
||||
pid_t pid, u16 misc, int fd)
|
||||
{
|
||||
char nm[PATH_MAX];
|
||||
struct dso *pos;
|
||||
|
||||
dsos__for_each_with_build_id(pos, head) {
|
||||
@ -215,6 +217,10 @@ static int __dsos__write_buildid_table(struct list_head *head, pid_t pid,
|
||||
if (is_vdso_map(pos->short_name)) {
|
||||
name = (char *) VDSO__MAP_NAME;
|
||||
name_len = sizeof(VDSO__MAP_NAME) + 1;
|
||||
} else if (dso__is_kcore(pos)) {
|
||||
machine__mmap_name(machine, nm, sizeof(nm));
|
||||
name = nm;
|
||||
name_len = strlen(nm) + 1;
|
||||
} else {
|
||||
name = pos->long_name;
|
||||
name_len = pos->long_name_len + 1;
|
||||
@ -240,10 +246,10 @@ static int machine__write_buildid_table(struct machine *machine, int fd)
|
||||
umisc = PERF_RECORD_MISC_GUEST_USER;
|
||||
}
|
||||
|
||||
err = __dsos__write_buildid_table(&machine->kernel_dsos, machine->pid,
|
||||
kmisc, fd);
|
||||
err = __dsos__write_buildid_table(&machine->kernel_dsos, machine,
|
||||
machine->pid, kmisc, fd);
|
||||
if (err == 0)
|
||||
err = __dsos__write_buildid_table(&machine->user_dsos,
|
||||
err = __dsos__write_buildid_table(&machine->user_dsos, machine,
|
||||
machine->pid, umisc, fd);
|
||||
return err;
|
||||
}
|
||||
@ -375,23 +381,31 @@ out_free:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int dso__cache_build_id(struct dso *dso, const char *debugdir)
|
||||
static int dso__cache_build_id(struct dso *dso, struct machine *machine,
|
||||
const char *debugdir)
|
||||
{
|
||||
bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
|
||||
bool is_vdso = is_vdso_map(dso->short_name);
|
||||
char *name = dso->long_name;
|
||||
char nm[PATH_MAX];
|
||||
|
||||
return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id),
|
||||
dso->long_name, debugdir,
|
||||
is_kallsyms, is_vdso);
|
||||
if (dso__is_kcore(dso)) {
|
||||
is_kallsyms = true;
|
||||
machine__mmap_name(machine, nm, sizeof(nm));
|
||||
name = nm;
|
||||
}
|
||||
return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name,
|
||||
debugdir, is_kallsyms, is_vdso);
|
||||
}
|
||||
|
||||
static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir)
|
||||
static int __dsos__cache_build_ids(struct list_head *head,
|
||||
struct machine *machine, const char *debugdir)
|
||||
{
|
||||
struct dso *pos;
|
||||
int err = 0;
|
||||
|
||||
dsos__for_each_with_build_id(pos, head)
|
||||
if (dso__cache_build_id(pos, debugdir))
|
||||
if (dso__cache_build_id(pos, machine, debugdir))
|
||||
err = -1;
|
||||
|
||||
return err;
|
||||
@ -399,8 +413,9 @@ static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir)
|
||||
|
||||
static int machine__cache_build_ids(struct machine *machine, const char *debugdir)
|
||||
{
|
||||
int ret = __dsos__cache_build_ids(&machine->kernel_dsos, debugdir);
|
||||
ret |= __dsos__cache_build_ids(&machine->user_dsos, debugdir);
|
||||
int ret = __dsos__cache_build_ids(&machine->kernel_dsos, machine,
|
||||
debugdir);
|
||||
ret |= __dsos__cache_build_ids(&machine->user_dsos, machine, debugdir);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -611,6 +611,8 @@ void hists__collapse_resort(struct hists *hists)
|
||||
next = rb_first(root);
|
||||
|
||||
while (next) {
|
||||
if (session_done())
|
||||
break;
|
||||
n = rb_entry(next, struct hist_entry, rb_node_in);
|
||||
next = rb_next(&n->rb_node_in);
|
||||
|
||||
|
@ -734,7 +734,7 @@ static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf)
|
||||
}
|
||||
|
||||
/* If not a real subprogram, find a real one */
|
||||
if (dwarf_tag(sc_die) != DW_TAG_subprogram) {
|
||||
if (!die_is_func_def(sc_die)) {
|
||||
if (!die_find_realfunc(&pf->cu_die, pf->addr, &pf->sp_die)) {
|
||||
pr_warning("Failed to find probe point in any "
|
||||
"functions.\n");
|
||||
@ -980,12 +980,10 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
|
||||
struct dwarf_callback_param *param = data;
|
||||
struct probe_finder *pf = param->data;
|
||||
struct perf_probe_point *pp = &pf->pev->point;
|
||||
Dwarf_Attribute attr;
|
||||
|
||||
/* Check tag and diename */
|
||||
if (dwarf_tag(sp_die) != DW_TAG_subprogram ||
|
||||
!die_compare_name(sp_die, pp->function) ||
|
||||
dwarf_attr(sp_die, DW_AT_declaration, &attr))
|
||||
if (!die_is_func_def(sp_die) ||
|
||||
!die_compare_name(sp_die, pp->function))
|
||||
return DWARF_CB_OK;
|
||||
|
||||
/* Check declared file */
|
||||
@ -1474,7 +1472,7 @@ static int line_range_inline_cb(Dwarf_Die *in_die, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Search function from function name */
|
||||
/* Search function definition from function name */
|
||||
static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
|
||||
{
|
||||
struct dwarf_callback_param *param = data;
|
||||
@ -1485,7 +1483,7 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
|
||||
if (lr->file && strtailcmp(lr->file, dwarf_decl_file(sp_die)))
|
||||
return DWARF_CB_OK;
|
||||
|
||||
if (dwarf_tag(sp_die) == DW_TAG_subprogram &&
|
||||
if (die_is_func_def(sp_die) &&
|
||||
die_compare_name(sp_die, lr->function)) {
|
||||
lf->fname = dwarf_decl_file(sp_die);
|
||||
dwarf_decl_line(sp_die, &lr->offset);
|
||||
|
@ -531,6 +531,9 @@ static int flush_sample_queue(struct perf_session *s,
|
||||
return 0;
|
||||
|
||||
list_for_each_entry_safe(iter, tmp, head, list) {
|
||||
if (session_done())
|
||||
return 0;
|
||||
|
||||
if (iter->timestamp > limit)
|
||||
break;
|
||||
|
||||
@ -1160,7 +1163,6 @@ static void perf_session__warn_about_errors(const struct perf_session *session,
|
||||
}
|
||||
}
|
||||
|
||||
#define session_done() (*(volatile int *)(&session_done))
|
||||
volatile int session_done;
|
||||
|
||||
static int __perf_session__process_pipe_events(struct perf_session *self,
|
||||
@ -1372,10 +1374,13 @@ more:
|
||||
"Processing events...");
|
||||
}
|
||||
|
||||
err = 0;
|
||||
if (session_done())
|
||||
goto out_err;
|
||||
|
||||
if (file_pos < file_size)
|
||||
goto more;
|
||||
|
||||
err = 0;
|
||||
/* do the final flush for ordered samples */
|
||||
session->ordered_samples.next_flush = ULLONG_MAX;
|
||||
err = flush_sample_queue(session, tool);
|
||||
|
@ -124,4 +124,8 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session,
|
||||
|
||||
#define perf_session__set_tracepoints_handlers(session, array) \
|
||||
__perf_session__set_tracepoints_handlers(session, array, ARRAY_SIZE(array))
|
||||
|
||||
extern volatile int session_done;
|
||||
|
||||
#define session_done() (*(volatile int *)(&session_done))
|
||||
#endif /* __PERF_SESSION_H */
|
||||
|
@ -8,6 +8,22 @@
|
||||
#include "symbol.h"
|
||||
#include "debug.h"
|
||||
|
||||
#ifndef HAVE_ELF_GETPHDRNUM
|
||||
static int elf_getphdrnum(Elf *elf, size_t *dst)
|
||||
{
|
||||
GElf_Ehdr gehdr;
|
||||
GElf_Ehdr *ehdr;
|
||||
|
||||
ehdr = gelf_getehdr(elf, &gehdr);
|
||||
if (!ehdr)
|
||||
return -1;
|
||||
|
||||
*dst = ehdr->e_phnum;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NT_GNU_BUILD_ID
|
||||
#define NT_GNU_BUILD_ID 3
|
||||
#endif
|
||||
|
@ -186,7 +186,7 @@ void parse_proc_kallsyms(struct pevent *pevent,
|
||||
char *next = NULL;
|
||||
char *addr_str;
|
||||
char *mod;
|
||||
char *fmt;
|
||||
char *fmt = NULL;
|
||||
|
||||
line = strtok_r(file, "\n", &next);
|
||||
while (line) {
|
||||
|
Loading…
Reference in New Issue
Block a user