Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
bc4b473f
Commit
bc4b473f
authored
Apr 30, 2010
by
Ingo Molnar
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'perf' of
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6
into perf/core
parents
3ca50496
1c6a800c
Changes
23
Show whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
725 additions
and
351 deletions
+725
-351
tools/perf/Documentation/perf-test.txt
tools/perf/Documentation/perf-test.txt
+22
-0
tools/perf/Makefile
tools/perf/Makefile
+3
-0
tools/perf/builtin-annotate.c
tools/perf/builtin-annotate.c
+1
-1
tools/perf/builtin-buildid-list.c
tools/perf/builtin-buildid-list.c
+1
-1
tools/perf/builtin-kmem.c
tools/perf/builtin-kmem.c
+4
-6
tools/perf/builtin-record.c
tools/perf/builtin-record.c
+17
-19
tools/perf/builtin-report.c
tools/perf/builtin-report.c
+1
-1
tools/perf/builtin-test.c
tools/perf/builtin-test.c
+281
-0
tools/perf/builtin-top.c
tools/perf/builtin-top.c
+7
-8
tools/perf/builtin.h
tools/perf/builtin.h
+1
-0
tools/perf/command-list.txt
tools/perf/command-list.txt
+1
-0
tools/perf/perf.c
tools/perf/perf.c
+1
-0
tools/perf/util/event.c
tools/perf/util/event.c
+42
-47
tools/perf/util/event.h
tools/perf/util/event.h
+2
-2
tools/perf/util/header.c
tools/perf/util/header.c
+33
-37
tools/perf/util/header.h
tools/perf/util/header.h
+1
-1
tools/perf/util/map.c
tools/perf/util/map.c
+64
-57
tools/perf/util/map.h
tools/perf/util/map.h
+48
-38
tools/perf/util/probe-event.c
tools/perf/util/probe-event.c
+11
-9
tools/perf/util/session.c
tools/perf/util/session.c
+4
-5
tools/perf/util/session.h
tools/perf/util/session.h
+39
-1
tools/perf/util/symbol.c
tools/perf/util/symbol.c
+128
-108
tools/perf/util/symbol.h
tools/perf/util/symbol.h
+13
-10
No files found.
tools/perf/Documentation/perf-test.txt
0 → 100644
View file @
bc4b473f
perf-test(1)
============
NAME
----
perf-test - Runs sanity tests.
SYNOPSIS
--------
[verse]
'perf test <options>'
DESCRIPTION
-----------
This command does assorted sanity tests, initially thru linked routines but
also will look for a directory with more tests in the form of scripts.
OPTIONS
-------
-v::
--verbose::
Be more verbose.
tools/perf/Makefile
View file @
bc4b473f
...
...
@@ -187,6 +187,8 @@ ifeq ($(ARCH),x86_64)
ARCH
:=
x86
endif
$(shell
sh
-c
'mkdir -p $(OUTPUT)arch/$(ARCH)/util/'
2>
/dev/null)
# CFLAGS and LDFLAGS are for the users to override from the command line.
#
...
...
@@ -488,6 +490,7 @@ BUILTIN_OBJS += $(OUTPUT)builtin-probe.o
BUILTIN_OBJS
+=
$(OUTPUT)
builtin-kmem.o
BUILTIN_OBJS
+=
$(OUTPUT)
builtin-lock.o
BUILTIN_OBJS
+=
$(OUTPUT)
builtin-kvm.o
BUILTIN_OBJS
+=
$(OUTPUT)
builtin-test.o
PERFLIBS
=
$(LIB_FILE)
...
...
tools/perf/builtin-annotate.c
View file @
bc4b473f
...
...
@@ -571,7 +571,7 @@ static int __cmd_annotate(void)
perf_session__fprintf
(
session
,
stdout
);
if
(
verbose
>
2
)
dsos__fprintf
(
&
session
->
kerninfo_root
,
stdout
);
perf_session__fprintf_dsos
(
session
,
stdout
);
perf_session__collapse_resort
(
&
session
->
hists
);
perf_session__output_resort
(
&
session
->
hists
,
session
->
event_total
[
0
]);
...
...
tools/perf/builtin-buildid-list.c
View file @
bc4b473f
...
...
@@ -46,7 +46,7 @@ static int __cmd_buildid_list(void)
if
(
with_hits
)
perf_session__process_events
(
session
,
&
build_id__mark_dso_hit_ops
);
dsos__fprintf_buildid
(
&
session
->
kerninfo_root
,
stdout
,
with_hits
);
perf_session__fprintf_dsos_buildid
(
session
,
stdout
,
with_hits
);
perf_session__delete
(
session
);
return
err
;
...
...
tools/perf/builtin-kmem.c
View file @
bc4b473f
...
...
@@ -352,7 +352,7 @@ static void __print_result(struct rb_root *root, struct perf_session *session,
int
n_lines
,
int
is_caller
)
{
struct
rb_node
*
next
;
struct
kernel_info
*
kerninfo
;
struct
machine
*
machine
;
printf
(
"%.102s
\n
"
,
graph_dotted_line
);
printf
(
" %-34s |"
,
is_caller
?
"Callsite"
:
"Alloc Ptr"
);
...
...
@@ -361,8 +361,8 @@ static void __print_result(struct rb_root *root, struct perf_session *session,
next
=
rb_first
(
root
);
kerninfo
=
kerninfo__findhost
(
&
session
->
kerninfo_root
);
if
(
!
kerninfo
)
{
machine
=
perf_session__find_host_machine
(
session
);
if
(
!
machine
)
{
pr_err
(
"__print_result: couldn't find kernel information
\n
"
);
return
;
}
...
...
@@ -370,7 +370,6 @@ static void __print_result(struct rb_root *root, struct perf_session *session,
struct
alloc_stat
*
data
=
rb_entry
(
next
,
struct
alloc_stat
,
node
);
struct
symbol
*
sym
=
NULL
;
struct
map_groups
*
kmaps
=
&
kerninfo
->
kmaps
;
struct
map
*
map
;
char
buf
[
BUFSIZ
];
u64
addr
;
...
...
@@ -378,8 +377,7 @@ static void __print_result(struct rb_root *root, struct perf_session *session,
if
(
is_caller
)
{
addr
=
data
->
call_site
;
if
(
!
raw_ip
)
sym
=
map_groups__find_function
(
kmaps
,
addr
,
&
map
,
NULL
);
sym
=
machine__find_kernel_function
(
machine
,
addr
,
&
map
,
NULL
);
}
else
addr
=
data
->
ptr
;
...
...
tools/perf/builtin-record.c
View file @
bc4b473f
...
...
@@ -456,14 +456,14 @@ static void atexit_header(void)
}
}
static
void
event__synthesize_guest_os
(
struct
kernel_info
*
kerninfo
,
void
*
data
__attribute__
((
unused
)))
static
void
event__synthesize_guest_os
(
struct
machine
*
machine
,
void
*
data
)
{
int
err
;
char
*
guest_kallsyms
;
char
path
[
PATH_MAX
];
struct
perf_session
*
psession
=
data
;
if
(
is_host_kernel
(
kerninfo
))
if
(
machine__is_host
(
machine
))
return
;
/*
...
...
@@ -475,16 +475,15 @@ static void event__synthesize_guest_os(struct kernel_info *kerninfo,
*in module instead of in guest kernel.
*/
err
=
event__synthesize_modules
(
process_synthesized_event
,
session
,
kerninfo
);
psession
,
machine
);
if
(
err
<
0
)
pr_err
(
"Couldn't record guest kernel [%d]'s reference"
" relocation symbol.
\n
"
,
kerninfo
->
pid
);
" relocation symbol.
\n
"
,
machine
->
pid
);
if
(
is_default_guest
(
kerninfo
))
if
(
machine__is_default_guest
(
machine
))
guest_kallsyms
=
(
char
*
)
symbol_conf
.
default_guest_kallsyms
;
else
{
sprintf
(
path
,
"%s/proc/kallsyms"
,
kerninfo
->
root_dir
);
sprintf
(
path
,
"%s/proc/kallsyms"
,
machine
->
root_dir
);
guest_kallsyms
=
path
;
}
...
...
@@ -493,13 +492,13 @@ static void event__synthesize_guest_os(struct kernel_info *kerninfo,
* have no _text sometimes.
*/
err
=
event__synthesize_kernel_mmap
(
process_synthesized_event
,
session
,
kerninfo
,
"_text"
);
psession
,
machine
,
"_text"
);
if
(
err
<
0
)
err
=
event__synthesize_kernel_mmap
(
process_synthesized_event
,
session
,
kerninfo
,
"_stext"
);
psession
,
machine
,
"_stext"
);
if
(
err
<
0
)
pr_err
(
"Couldn't record guest kernel [%d]'s reference"
" relocation symbol.
\n
"
,
kerninfo
->
pid
);
" relocation symbol.
\n
"
,
machine
->
pid
);
}
static
int
__cmd_record
(
int
argc
,
const
char
**
argv
)
...
...
@@ -513,7 +512,7 @@ static int __cmd_record(int argc, const char **argv)
int
child_ready_pipe
[
2
],
go_pipe
[
2
];
const
bool
forks
=
argc
>
0
;
char
buf
;
struct
kernel_info
*
kerninfo
;
struct
machine
*
machine
;
page_size
=
sysconf
(
_SC_PAGE_SIZE
);
...
...
@@ -682,31 +681,30 @@ static int __cmd_record(int argc, const char **argv)
advance_output
(
err
);
}
kerninfo
=
kerninfo__findhost
(
&
session
->
kerninfo_root
);
if
(
!
kerninfo
)
{
machine
=
perf_session__find_host_machine
(
session
);
if
(
!
machine
)
{
pr_err
(
"Couldn't find native kernel information.
\n
"
);
return
-
1
;
}
err
=
event__synthesize_kernel_mmap
(
process_synthesized_event
,
session
,
kerninfo
,
"_text"
);
session
,
machine
,
"_text"
);
if
(
err
<
0
)
err
=
event__synthesize_kernel_mmap
(
process_synthesized_event
,
session
,
kerninfo
,
"_stext"
);
session
,
machine
,
"_stext"
);
if
(
err
<
0
)
{
pr_err
(
"Couldn't record kernel reference relocation symbol.
\n
"
);
return
err
;
}
err
=
event__synthesize_modules
(
process_synthesized_event
,
session
,
kerninfo
);
session
,
machine
);
if
(
err
<
0
)
{
pr_err
(
"Couldn't record kernel reference relocation symbol.
\n
"
);
return
err
;
}
if
(
perf_guest
)
kerninfo__process_allkernels
(
&
session
->
kerninfo_root
,
event__synthesize_guest_os
,
session
);
perf_session__process_machines
(
session
,
event__synthesize_guest_os
);
if
(
!
system_wide
&&
profile_cpu
==
-
1
)
event__synthesize_thread
(
target_tid
,
process_synthesized_event
,
...
...
tools/perf/builtin-report.c
View file @
bc4b473f
...
...
@@ -313,7 +313,7 @@ static int __cmd_report(void)
perf_session__fprintf
(
session
,
stdout
);
if
(
verbose
>
2
)
dsos__fprintf
(
&
session
->
kerninfo_root
,
stdout
);
perf_session__fprintf_dsos
(
session
,
stdout
);
next
=
rb_first
(
&
session
->
stats_by_id
);
while
(
next
)
{
...
...
tools/perf/builtin-test.c
0 → 100644
View file @
bc4b473f
/*
* builtin-test.c
*
* Builtin regression testing command: ever growing number of sanity tests
*/
#include "builtin.h"
#include "util/cache.h"
#include "util/debug.h"
#include "util/parse-options.h"
#include "util/session.h"
#include "util/symbol.h"
#include "util/thread.h"
static
long
page_size
;
static
int
vmlinux_matches_kallsyms_filter
(
struct
map
*
map
__used
,
struct
symbol
*
sym
)
{
bool
*
visited
=
symbol__priv
(
sym
);
*
visited
=
true
;
return
0
;
}
static
int
test__vmlinux_matches_kallsyms
(
void
)
{
int
err
=
-
1
;
struct
rb_node
*
nd
;
struct
symbol
*
sym
;
struct
map
*
kallsyms_map
,
*
vmlinux_map
;
struct
machine
kallsyms
,
vmlinux
;
enum
map_type
type
=
MAP__FUNCTION
;
struct
ref_reloc_sym
ref_reloc_sym
=
{
.
name
=
"_stext"
,
};
/*
* Step 1:
*
* Init the machines that will hold kernel, modules obtained from
* both vmlinux + .ko files and from /proc/kallsyms split by modules.
*/
machine__init
(
&
kallsyms
,
""
,
HOST_KERNEL_ID
);
machine__init
(
&
vmlinux
,
""
,
HOST_KERNEL_ID
);
/*
* Step 2:
*
* Create the kernel maps for kallsyms and the DSO where we will then
* load /proc/kallsyms. Also create the modules maps from /proc/modules
* and find the .ko files that match them in /lib/modules/`uname -r`/.
*/
if
(
machine__create_kernel_maps
(
&
kallsyms
)
<
0
)
{
pr_debug
(
"machine__create_kernel_maps "
);
return
-
1
;
}
/*
* Step 3:
*
* Load and split /proc/kallsyms into multiple maps, one per module.
*/
if
(
machine__load_kallsyms
(
&
kallsyms
,
"/proc/kallsyms"
,
type
,
NULL
)
<=
0
)
{
pr_debug
(
"dso__load_kallsyms "
);
goto
out
;
}
/*
* Step 4:
*
* kallsyms will be internally on demand sorted by name so that we can
* find the reference relocation * symbol, i.e. the symbol we will use
* to see if the running kernel was relocated by checking if it has the
* same value in the vmlinux file we load.
*/
kallsyms_map
=
machine__kernel_map
(
&
kallsyms
,
type
);
sym
=
map__find_symbol_by_name
(
kallsyms_map
,
ref_reloc_sym
.
name
,
NULL
);
if
(
sym
==
NULL
)
{
pr_debug
(
"dso__find_symbol_by_name "
);
goto
out
;
}
ref_reloc_sym
.
addr
=
sym
->
start
;
/*
* Step 5:
*
* Now repeat step 2, this time for the vmlinux file we'll auto-locate.
*/
if
(
machine__create_kernel_maps
(
&
vmlinux
)
<
0
)
{
pr_debug
(
"machine__create_kernel_maps "
);
goto
out
;
}
vmlinux_map
=
machine__kernel_map
(
&
vmlinux
,
type
);
map__kmap
(
vmlinux_map
)
->
ref_reloc_sym
=
&
ref_reloc_sym
;
/*
* Step 6:
*
* Locate a vmlinux file in the vmlinux path that has a buildid that
* matches the one of the running kernel.
*
* While doing that look if we find the ref reloc symbol, if we find it
* we'll have its ref_reloc_symbol.unrelocated_addr and then
* maps__reloc_vmlinux will notice and set proper ->[un]map_ip routines
* to fixup the symbols.
*/
if
(
machine__load_vmlinux_path
(
&
vmlinux
,
type
,
vmlinux_matches_kallsyms_filter
)
<=
0
)
{
pr_debug
(
"machine__load_vmlinux_path "
);
goto
out
;
}
err
=
0
;
/*
* Step 7:
*
* Now look at the symbols in the vmlinux DSO and check if we find all of them
* in the kallsyms dso. For the ones that are in both, check its names and
* end addresses too.
*/
for
(
nd
=
rb_first
(
&
vmlinux_map
->
dso
->
symbols
[
type
]);
nd
;
nd
=
rb_next
(
nd
))
{
struct
symbol
*
pair
;
sym
=
rb_entry
(
nd
,
struct
symbol
,
rb_node
);
pair
=
machine__find_kernel_symbol
(
&
kallsyms
,
type
,
sym
->
start
,
NULL
,
NULL
);
if
(
pair
&&
pair
->
start
==
sym
->
start
)
{
next_pair:
if
(
strcmp
(
sym
->
name
,
pair
->
name
)
==
0
)
{
/*
* kallsyms don't have the symbol end, so we
* set that by using the next symbol start - 1,
* in some cases we get this up to a page
* wrong, trace_kmalloc when I was developing
* this code was one such example, 2106 bytes
* off the real size. More than that and we
* _really_ have a problem.
*/
s64
skew
=
sym
->
end
-
pair
->
end
;
if
(
llabs
(
skew
)
<
page_size
)
continue
;
pr_debug
(
"%#Lx: diff end addr for %s v: %#Lx k: %#Lx
\n
"
,
sym
->
start
,
sym
->
name
,
sym
->
end
,
pair
->
end
);
}
else
{
struct
rb_node
*
nnd
=
rb_prev
(
&
pair
->
rb_node
);
if
(
nnd
)
{
struct
symbol
*
next
=
rb_entry
(
nnd
,
struct
symbol
,
rb_node
);
if
(
next
->
start
==
sym
->
start
)
{
pair
=
next
;
goto
next_pair
;
}
}
pr_debug
(
"%#Lx: diff name v: %s k: %s
\n
"
,
sym
->
start
,
sym
->
name
,
pair
->
name
);
}
}
else
pr_debug
(
"%#Lx: %s not on kallsyms
\n
"
,
sym
->
start
,
sym
->
name
);
err
=
-
1
;
}
if
(
!
verbose
)
goto
out
;
pr_info
(
"Maps only in vmlinux:
\n
"
);
for
(
nd
=
rb_first
(
&
vmlinux
.
kmaps
.
maps
[
type
]);
nd
;
nd
=
rb_next
(
nd
))
{
struct
map
*
pos
=
rb_entry
(
nd
,
struct
map
,
rb_node
),
*
pair
;
/*
* If it is the kernel, kallsyms is always "[kernel.kallsyms]", while
* the kernel will have the path for the vmlinux file being used,
* so use the short name, less descriptive but the same ("[kernel]" in
* both cases.
*/
pair
=
map_groups__find_by_name
(
&
kallsyms
.
kmaps
,
type
,
(
pos
->
dso
->
kernel
?
pos
->
dso
->
short_name
:
pos
->
dso
->
name
));
if
(
pair
)
pair
->
priv
=
1
;
else
map__fprintf
(
pos
,
stderr
);
}
pr_info
(
"Maps in vmlinux with a different name in kallsyms:
\n
"
);
for
(
nd
=
rb_first
(
&
vmlinux
.
kmaps
.
maps
[
type
]);
nd
;
nd
=
rb_next
(
nd
))
{
struct
map
*
pos
=
rb_entry
(
nd
,
struct
map
,
rb_node
),
*
pair
;
pair
=
map_groups__find
(
&
kallsyms
.
kmaps
,
type
,
pos
->
start
);
if
(
pair
==
NULL
||
pair
->
priv
)
continue
;
if
(
pair
->
start
==
pos
->
start
)
{
pair
->
priv
=
1
;
pr_info
(
" %Lx-%Lx %Lx %s in kallsyms as"
,
pos
->
start
,
pos
->
end
,
pos
->
pgoff
,
pos
->
dso
->
name
);
if
(
pos
->
pgoff
!=
pair
->
pgoff
||
pos
->
end
!=
pair
->
end
)
pr_info
(
":
\n
*%Lx-%Lx %Lx"
,
pair
->
start
,
pair
->
end
,
pair
->
pgoff
);
pr_info
(
" %s
\n
"
,
pair
->
dso
->
name
);
pair
->
priv
=
1
;
}
}
pr_info
(
"Maps only in kallsyms:
\n
"
);
for
(
nd
=
rb_first
(
&
kallsyms
.
kmaps
.
maps
[
type
]);
nd
;
nd
=
rb_next
(
nd
))
{
struct
map
*
pos
=
rb_entry
(
nd
,
struct
map
,
rb_node
);
if
(
!
pos
->
priv
)
map__fprintf
(
pos
,
stderr
);
}
out:
return
err
;
}
static
struct
test
{
const
char
*
desc
;
int
(
*
func
)(
void
);
}
tests
[]
=
{
{
.
desc
=
"vmlinux symtab matches kallsyms"
,
.
func
=
test__vmlinux_matches_kallsyms
,
},
{
.
func
=
NULL
,
},
};
static
int
__cmd_test
(
void
)
{
int
i
=
0
;
page_size
=
sysconf
(
_SC_PAGE_SIZE
);
while
(
tests
[
i
].
func
)
{
int
err
;
pr_info
(
"%2d: %s:"
,
i
+
1
,
tests
[
i
].
desc
);
pr_debug
(
"
\n
--- start ---
\n
"
);
err
=
tests
[
i
].
func
();
pr_debug
(
"---- end ----
\n
%s:"
,
tests
[
i
].
desc
);
pr_info
(
" %s
\n
"
,
err
?
"FAILED!
\n
"
:
"Ok"
);
++
i
;
}
return
0
;
}
static
const
char
*
const
test_usage
[]
=
{
"perf test [<options>]"
,
NULL
,
};
static
const
struct
option
test_options
[]
=
{
OPT_BOOLEAN
(
'v'
,
"verbose"
,
&
verbose
,
"be more verbose (show symbol address, etc)"
),
OPT_END
()
};
int
cmd_test
(
int
argc
,
const
char
**
argv
,
const
char
*
prefix
__used
)
{
argc
=
parse_options
(
argc
,
argv
,
test_options
,
test_usage
,
0
);
if
(
argc
)
usage_with_options
(
test_usage
,
test_options
);
symbol_conf
.
priv_size
=
sizeof
(
int
);
symbol_conf
.
sort_by_name
=
true
;
symbol_conf
.
try_vmlinux_path
=
true
;
if
(
symbol__init
()
<
0
)
return
-
1
;
setup_pager
();
return
__cmd_test
();
}
tools/perf/builtin-top.c
View file @
bc4b473f
...
...
@@ -854,7 +854,7 @@ static void handle_keypress(struct perf_session *session, int c)
case
'Q'
:
printf
(
"exiting.
\n
"
);
if
(
dump_symtab
)
dsos__fprintf
(
&
session
->
kerninfo_root
,
stderr
);
perf_session__fprintf_dsos
(
session
,
stderr
);
exit
(
0
);
case
's'
:
prompt_symbol
(
&
sym_filter_entry
,
"Enter details symbol"
);
...
...
@@ -982,7 +982,7 @@ static void event__process_sample(const event_t *self,
u64
ip
=
self
->
ip
.
ip
;
struct
sym_entry
*
syme
;
struct
addr_location
al
;
struct
kernel_info
*
kerninfo
;
struct
machine
*
machine
;
u8
origin
=
self
->
header
.
misc
&
PERF_RECORD_MISC_CPUMODE_MASK
;
++
samples
;
...
...
@@ -992,18 +992,17 @@ static void event__process_sample(const event_t *self,
++
us_samples
;
if
(
hide_user_symbols
)
return
;
kerninfo
=
kerninfo__findhost
(
&
session
->
kerninfo_root
);
machine
=
perf_session__find_host_machine
(
session
);
break
;
case
PERF_RECORD_MISC_KERNEL
:
++
kernel_samples
;
if
(
hide_kernel_symbols
)
return
;
kerninfo
=
kerninfo__findhost
(
&
session
->
kerninfo_root
);
machine
=
perf_session__find_host_machine
(
session
);
break
;
case
PERF_RECORD_MISC_GUEST_KERNEL
:
++
guest_kernel_samples
;
kerninfo
=
kerninfo__find
(
&
session
->
kerninfo_root
,
self
->
ip
.
pid
);
machine
=
perf_session__find_machine
(
session
,
self
->
ip
.
pid
);
break
;
case
PERF_RECORD_MISC_GUEST_USER
:
++
guest_us_samples
;
...
...
@@ -1016,7 +1015,7 @@ static void event__process_sample(const event_t *self,
return
;
}
if
(
!
kerninfo
&&
perf_guest
)
{
if
(
!
machine
&&
perf_guest
)
{
pr_err
(
"Can't find guest [%d]'s kernel information
\n
"
,
self
->
ip
.
pid
);
return
;
...
...
@@ -1041,7 +1040,7 @@ static void event__process_sample(const event_t *self,
* --hide-kernel-symbols, even if the user specifies an
* invalid --vmlinux ;-)
*/
if
(
al
.
map
==
kerninfo
->
vmlinux_maps
[
MAP__FUNCTION
]
&&
if
(
al
.
map
==
machine
->
vmlinux_maps
[
MAP__FUNCTION
]
&&
RB_EMPTY_ROOT
(
&
al
.
map
->
dso
->
symbols
[
MAP__FUNCTION
]))
{
pr_err
(
"The %s file can't be used
\n
"
,
symbol_conf
.
vmlinux_name
);
...
...
tools/perf/builtin.h
View file @
bc4b473f
...
...
@@ -33,5 +33,6 @@ extern int cmd_probe(int argc, const char **argv, const char *prefix);
extern
int
cmd_kmem
(
int
argc
,
const
char
**
argv
,
const
char
*
prefix
);
extern
int
cmd_lock
(
int
argc
,
const
char
**
argv
,
const
char
*
prefix
);
extern
int
cmd_kvm
(
int
argc
,
const
char
**
argv
,
const
char
*
prefix
);
extern
int
cmd_test
(
int
argc
,
const
char
**
argv
,
const
char
*
prefix
);
#endif
tools/perf/command-list.txt
View file @
bc4b473f
...
...
@@ -20,3 +20,4 @@ perf-probe mainporcelain common
perf-kmem mainporcelain common
perf-lock mainporcelain common
perf-kvm mainporcelain common
perf-test mainporcelain common
tools/perf/perf.c
View file @
bc4b473f
...
...
@@ -308,6 +308,7 @@ static void handle_internal_command(int argc, const char **argv)
{
"kmem"
,
cmd_kmem
,
0
},
{
"lock"
,
cmd_lock
,
0
},
{
"kvm"
,
cmd_kvm
,
0
},
{
"test"
,
cmd_test
,
0
},
};
unsigned
int
i
;
static
const
char
ext
[]
=
STRIP_EXTENSION
;
...
...
tools/perf/util/event.c
View file @
bc4b473f
...
...
@@ -172,17 +172,17 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid,
int
event__synthesize_modules
(
event__handler_t
process
,
struct
perf_session
*
session
,
struct
kernel_info
*
kerninfo
)
struct
machine
*
machine
)
{
struct
rb_node
*
nd
;
struct
map_groups
*
kmaps
=
&
kerninfo
->
kmaps
;
struct
map_groups
*
kmaps
=
&
machine
->
kmaps
;
u16
misc
;
/*
* kernel uses 0 for user space maps, see kernel/perf_event.c
* __perf_event_mmap
*/
if
(
is_host_kernel
(
kerninfo
))
if
(
machine__is_host
(
machine
))
misc
=
PERF_RECORD_MISC_KERNEL
;
else
misc
=
PERF_RECORD_MISC_GUEST_KERNEL
;
...
...
@@ -204,7 +204,7 @@ int event__synthesize_modules(event__handler_t process,
(
sizeof
(
ev
.
mmap
.
filename
)
-
size
));
ev
.
mmap
.
start
=
pos
->
start
;
ev
.
mmap
.
len
=
pos
->
end
-
pos
->
start
;
ev
.
mmap
.
pid
=
kerninfo
->
pid
;
ev
.
mmap
.
pid
=
machine
->
pid
;
memcpy
(
ev
.
mmap
.
filename
,
pos
->
dso
->
long_name
,
pos
->
dso
->
long_name_len
+
1
);
...
...
@@ -267,7 +267,7 @@ static int find_symbol_cb(void *arg, const char *name, char type, u64 start)
int
event__synthesize_kernel_mmap
(
event__handler_t
process
,
struct
perf_session
*
session
,
struct
kernel_info
*
kerninfo
,
struct
machine
*
machine
,
const
char
*
symbol_name
)
{
size_t
size
;
...
...
@@ -288,8 +288,8 @@ int event__synthesize_kernel_mmap(event__handler_t process,
*/
struct
process_symbol_args
args
=
{
.
name
=
symbol_name
,
};
mmap_name
=
kern_mmap_name
(
kerninfo
,
name_buff
);
if
(
is_host_kernel
(
kerninfo
))
{
mmap_name
=
machine__mmap_name
(
machine
,
name_buff
,
sizeof
(
name_buff
)
);
if
(
machine__is_host
(
machine
))
{
/*
* kernel uses PERF_RECORD_MISC_USER for user space maps,
* see kernel/perf_event.c __perf_event_mmap
...
...
@@ -298,10 +298,10 @@ int event__synthesize_kernel_mmap(event__handler_t process,
filename
=
"/proc/kallsyms"
;
}
else
{
ev
.
header
.
misc
=
PERF_RECORD_MISC_GUEST_KERNEL
;
if
(
is_default_guest
(
kerninfo
))
if
(
machine__is_default_guest
(
machine
))
filename
=
(
char
*
)
symbol_conf
.
default_guest_kallsyms
;
else
{
sprintf
(
path
,
"%s/proc/kallsyms"
,
kerninfo
->
root_dir
);
sprintf
(
path
,
"%s/proc/kallsyms"
,
machine
->
root_dir
);
filename
=
path
;
}
}
...
...
@@ -309,7 +309,7 @@ int event__synthesize_kernel_mmap(event__handler_t process,
if
(
kallsyms__parse
(
filename
,
&
args
,
find_symbol_cb
)
<=
0
)
return
-
ENOENT
;
map
=
kerninfo
->
vmlinux_maps
[
MAP__FUNCTION
];
map
=
machine
->
vmlinux_maps
[
MAP__FUNCTION
];
size
=
snprintf
(
ev
.
mmap
.
filename
,
sizeof
(
ev
.
mmap
.
filename
),
"%s%s"
,
mmap_name
,
symbol_name
)
+
1
;
size
=
ALIGN
(
size
,
sizeof
(
u64
));
...
...
@@ -318,7 +318,7 @@ int event__synthesize_kernel_mmap(event__handler_t process,
ev
.
mmap
.
pgoff
=
args
.
start
;
ev
.
mmap
.
start
=
map
->
start
;
ev
.
mmap
.
len
=
map
->
end
-
ev
.
mmap
.
start
;
ev
.
mmap
.
pid
=
kerninfo
->
pid
;
ev
.
mmap
.
pid
=
machine
->
pid
;
return
process
(
&
ev
,
session
);
}
...
...
@@ -389,18 +389,18 @@ static int event__process_kernel_mmap(event_t *self,
{
struct
map
*
map
;
char
kmmap_prefix
[
PATH_MAX
];
struct
kernel_info
*
kerninfo
;
struct
machine
*
machine
;
enum
dso_kernel_type
kernel_type
;
bool
is_kernel_mmap
;
kerninfo
=
kerninfo__findnew
(
&
session
->
kerninfo_root
,
self
->
mmap
.
pid
);
if
(
!
kerninfo
)
{
pr_err
(
"Can't find id %d's
kerninfo
\n
"
,
self
->
mmap
.
pid
);
machine
=
perf_session__findnew_machine
(
session
,
self
->
mmap
.
pid
);
if
(
!
machine
)
{
pr_err
(
"Can't find id %d's
machine
\n
"
,
self
->
mmap
.
pid
);
goto
out_problem
;
}
kern_mmap_name
(
kerninfo
,
kmmap_prefix
);
if
(
is_host_kernel
(
kerninfo
))
machine__mmap_name
(
machine
,
kmmap_prefix
,
sizeof
(
kmmap_prefix
)
);
if
(
machine__is_host
(
machine
))
kernel_type
=
DSO_TYPE_KERNEL
;
else
kernel_type
=
DSO_TYPE_GUEST_KERNEL
;
...
...
@@ -429,10 +429,8 @@ static int event__process_kernel_mmap(event_t *self,
}
else
strcpy
(
short_module_name
,
self
->
mmap
.
filename
);
map
=
map_groups__new_module
(
&
kerninfo
->
kmaps
,
self
->
mmap
.
start
,
self
->
mmap
.
filename
,
kerninfo
);
map
=
machine__new_module
(
machine
,
self
->
mmap
.
start
,
self
->
mmap
.
filename
);
if
(
map
==
NULL
)
goto
out_problem
;
...
...
@@ -449,26 +447,24 @@ static int event__process_kernel_mmap(event_t *self,
* Should be there already, from the build-id table in
* the header.
*/
struct
dso
*
kernel
=
__dsos__findnew
(
&
kerninfo
->
dsos__kernel
,
struct
dso
*
kernel
=
__dsos__findnew
(
&
machine
->
kernel_dsos
,
kmmap_prefix
);
if
(
kernel
==
NULL
)
goto
out_problem
;
kernel
->
kernel
=
kernel_type
;
if
(
__map_groups__create_kernel_maps
(
&
kerninfo
->
kmaps
,
kerninfo
->
vmlinux_maps
,
kernel
)
<
0
)
if
(
__machine__create_kernel_maps
(
machine
,
kernel
)
<
0
)
goto
out_problem
;
event_set_kernel_mmap_len
(
kerninfo
->
vmlinux_maps
,
self
);
perf_session__set_kallsyms_ref_reloc_sym
(
kerninfo
->
vmlinux_maps
,
event_set_kernel_mmap_len
(
machine
->
vmlinux_maps
,
self
);
perf_session__set_kallsyms_ref_reloc_sym
(
machine
->
vmlinux_maps
,
symbol_name
,
self
->
mmap
.
pgoff
);
if
(
is_default_guest
(
kerninfo
))
{
if
(
machine__is_default_guest
(
machine
))
{
/*
* preload dso of guest kernel and modules
*/
dso__load
(
kernel
,
kerninfo
->
vmlinux_maps
[
MAP__FUNCTION
],
dso__load
(
kernel
,
machine
->
vmlinux_maps
[
MAP__FUNCTION
],
NULL
);
}
}
...
...
@@ -479,7 +475,7 @@ static int event__process_kernel_mmap(event_t *self,
int
event__process_mmap
(
event_t
*
self
,
struct
perf_session
*
session
)
{
struct
kernel_info
*
kerninfo
;
struct
machine
*
machine
;
struct
thread
*
thread
;
struct
map
*
map
;
u8
cpumode
=
self
->
header
.
misc
&
PERF_RECORD_MISC_CPUMODE_MASK
;
...
...
@@ -498,8 +494,8 @@ int event__process_mmap(event_t *self, struct perf_session *session)
}
thread
=
perf_session__findnew
(
session
,
self
->
mmap
.
pid
);
kerninfo
=
kerninfo__findhost
(
&
session
->
kerninfo_root
);
map
=
map__new
(
&
kerninfo
->
dsos__user
,
self
->
mmap
.
start
,
machine
=
perf_session__find_host_machine
(
session
);
map
=
map__new
(
&
machine
->
user_dsos
,
self
->
mmap
.
start
,
self
->
mmap
.
len
,
self
->
mmap
.
pgoff
,
self
->
mmap
.
pid
,
self
->
mmap
.
filename
,
MAP__FUNCTION
,
session
->
cwd
,
session
->
cwdlen
);
...
...
@@ -546,7 +542,7 @@ void thread__find_addr_map(struct thread *self,
struct
addr_location
*
al
)
{
struct
map_groups
*
mg
=
&
self
->
mg
;
struct
kernel_info
*
kerninfo
=
NULL
;
struct
machine
*
machine
=
NULL
;
al
->
thread
=
self
;
al
->
addr
=
addr
;
...
...
@@ -555,19 +551,19 @@ void thread__find_addr_map(struct thread *self,
if
(
cpumode
==
PERF_RECORD_MISC_KERNEL
&&
perf_host
)
{
al
->
level
=
'k'
;
kerninfo
=
kerninfo__findhost
(
&
session
->
kerninfo_root
);
mg
=
&
kerninfo
->
kmaps
;
machine
=
perf_session__find_host_machine
(
session
);
mg
=
&
machine
->
kmaps
;
}
else
if
(
cpumode
==
PERF_RECORD_MISC_USER
&&
perf_host
)
{
al
->
level
=
'.'
;
kerninfo
=
kerninfo__findhost
(
&
session
->
kerninfo_root
);
machine
=
perf_session__find_host_machine
(
session
);
}
else
if
(
cpumode
==
PERF_RECORD_MISC_GUEST_KERNEL
&&
perf_guest
)
{
al
->
level
=
'g'
;
kerninfo
=
kerninfo__find
(
&
session
->
kerninfo_root
,
pid
);
if
(
!
kerninfo
)
{
machine
=
perf_session__find_machine
(
session
,
pid
);
if
(
!
machine
)
{
al
->
map
=
NULL
;
return
;
}
mg
=
&
kerninfo
->
kmaps
;
mg
=
&
machine
->
kmaps
;
}
else
{
/*
* 'u' means guest os user space.
...
...
@@ -604,9 +600,8 @@ void thread__find_addr_map(struct thread *self,
*/
if
((
long
long
)
al
->
addr
<
0
&&
cpumode
==
PERF_RECORD_MISC_KERNEL
&&
kerninfo
&&
mg
!=
&
kerninfo
->
kmaps
)
{
mg
=
&
kerninfo
->
kmaps
;
machine
&&
mg
!=
&
machine
->
kmaps
)
{
mg
=
&
machine
->
kmaps
;
goto
try_again
;
}
}
else
...
...
tools/perf/util/event.h
View file @
bc4b473f
...
...
@@ -156,12 +156,12 @@ void event__synthesize_threads(event__handler_t process,
struct
perf_session
*
session
);
int
event__synthesize_kernel_mmap
(
event__handler_t
process
,
struct
perf_session
*
session
,
struct
kernel_info
*
kerninfo
,
struct
machine
*
machine
,
const
char
*
symbol_name
);
int
event__synthesize_modules
(
event__handler_t
process
,
struct
perf_session
*
session
,
struct
kernel_info
*
kerninfo
);
struct
machine
*
machine
);
int
event__process_comm
(
event_t
*
self
,
struct
perf_session
*
session
);
int
event__process_lost
(
event_t
*
self
,
struct
perf_session
*
session
);
...
...
tools/perf/util/header.c
View file @
bc4b473f
...
...
@@ -229,10 +229,9 @@ static int dsos__write_buildid_table(struct perf_header *header, int fd)
int
err
=
0
;
u16
kmisc
,
umisc
;
for
(
nd
=
rb_first
(
&
session
->
kerninfo_root
);
nd
;
nd
=
rb_next
(
nd
))
{
struct
kernel_info
*
pos
=
rb_entry
(
nd
,
struct
kernel_info
,
rb_node
);
if
(
is_host_kernel
(
pos
))
{
for
(
nd
=
rb_first
(
&
session
->
machines
);
nd
;
nd
=
rb_next
(
nd
))
{
struct
machine
*
pos
=
rb_entry
(
nd
,
struct
machine
,
rb_node
);
if
(
machine__is_host
(
pos
))
{
kmisc
=
PERF_RECORD_MISC_KERNEL
;
umisc
=
PERF_RECORD_MISC_USER
;
}
else
{
...
...
@@ -240,10 +239,10 @@ static int dsos__write_buildid_table(struct perf_header *header, int fd)
umisc
=
PERF_RECORD_MISC_GUEST_USER
;
}
err
=
__dsos__write_buildid_table
(
&
pos
->
dsos__kernel
,
pos
->
pid
,
err
=
__dsos__write_buildid_table
(
&
pos
->
kernel_dsos
,
pos
->
pid
,
kmisc
,
fd
);
if
(
err
==
0
)
err
=
__dsos__write_buildid_table
(
&
pos
->
dsos__user
,
err
=
__dsos__write_buildid_table
(
&
pos
->
user_dsos
,
pos
->
pid
,
umisc
,
fd
);
if
(
err
)
break
;
...
...
@@ -378,11 +377,10 @@ static int dsos__cache_build_ids(struct perf_header *self)
if
(
mkdir
(
debugdir
,
0755
)
!=
0
&&
errno
!=
EEXIST
)
return
-
1
;
for
(
nd
=
rb_first
(
&
session
->
kerninfo_root
);
nd
;
nd
=
rb_next
(
nd
))
{
struct
kernel_info
*
pos
=
rb_entry
(
nd
,
struct
kernel_info
,
rb_node
);
ret
|=
__dsos__cache_build_ids
(
&
pos
->
dsos__kernel
,
debugdir
);
ret
|=
__dsos__cache_build_ids
(
&
pos
->
dsos__user
,
debugdir
);
for
(
nd
=
rb_first
(
&
session
->
machines
);
nd
;
nd
=
rb_next
(
nd
))
{
struct
machine
*
pos
=
rb_entry
(
nd
,
struct
machine
,
rb_node
);
ret
|=
__dsos__cache_build_ids
(
&
pos
->
kernel_dsos
,
debugdir
);
ret
|=
__dsos__cache_build_ids
(
&
pos
->
user_dsos
,
debugdir
);
}
return
ret
?
-
1
:
0
;
}
...
...
@@ -394,11 +392,10 @@ static bool dsos__read_build_ids(struct perf_header *self, bool with_hits)
struct
perf_session
,
header
);
struct
rb_node
*
nd
;
for
(
nd
=
rb_first
(
&
session
->
kerninfo_root
);
nd
;
nd
=
rb_next
(
nd
))
{
struct
kernel_info
*
pos
=
rb_entry
(
nd
,
struct
kernel_info
,
rb_node
);
ret
|=
__dsos__read_build_ids
(
&
pos
->
dsos__kernel
,
with_hits
);
ret
|=
__dsos__read_build_ids
(
&
pos
->
dsos__user
,
with_hits
);
for
(
nd
=
rb_first
(
&
session
->
machines
);
nd
;
nd
=
rb_next
(
nd
))
{
struct
machine
*
pos
=
rb_entry
(
nd
,
struct
machine
,
rb_node
);
ret
|=
__dsos__read_build_ids
(
&
pos
->
kernel_dsos
,
with_hits
);
ret
|=
__dsos__read_build_ids
(
&
pos
->
user_dsos
,
with_hits
);
}
return
ret
;
...
...
@@ -685,13 +682,13 @@ static int __event_process_build_id(struct build_id_event *bev,
{
int
err
=
-
1
;
struct
list_head
*
head
;
struct
kernel_info
*
kerninfo
;
struct
machine
*
machine
;
u16
misc
;
struct
dso
*
dso
;
enum
dso_kernel_type
dso_type
;
kerninfo
=
kerninfo__findnew
(
&
session
->
kerninfo_root
,
bev
->
pid
);
if
(
!
kerninfo
)
machine
=
perf_session__findnew_machine
(
session
,
bev
->
pid
);
if
(
!
machine
)
goto
out
;
misc
=
bev
->
header
.
misc
&
PERF_RECORD_MISC_CPUMODE_MASK
;
...
...
@@ -699,16 +696,16 @@ static int __event_process_build_id(struct build_id_event *bev,
switch
(
misc
)
{
case
PERF_RECORD_MISC_KERNEL
:
dso_type
=
DSO_TYPE_KERNEL
;
head
=
&
kerninfo
->
dsos__kernel
;
head
=
&
machine
->
kernel_dsos
;
break
;
case
PERF_RECORD_MISC_GUEST_KERNEL
:
dso_type
=
DSO_TYPE_GUEST_KERNEL
;
head
=
&
kerninfo
->
dsos__kernel
;
head
=
&
machine
->
kernel_dsos
;
break
;
case
PERF_RECORD_MISC_USER
:
case
PERF_RECORD_MISC_GUEST_USER
:
dso_type
=
DSO_TYPE_USER
;
head
=
&
kerninfo
->
dsos__user
;
head
=
&
machine
->
user_dsos
;
break
;
default:
goto
out
;
...
...
@@ -1113,8 +1110,7 @@ int event__process_tracing_data(event_t *self,
}
int
event__synthesize_build_id
(
struct
dso
*
pos
,
u16
misc
,
event__handler_t
process
,
struct
kernel_info
*
kerninfo
,
event__handler_t
process
,
struct
machine
*
machine
,
struct
perf_session
*
session
)
{
event_t
ev
;
...
...
@@ -1131,7 +1127,7 @@ int event__synthesize_build_id(struct dso *pos, u16 misc,
memcpy
(
&
ev
.
build_id
.
build_id
,
pos
->
build_id
,
sizeof
(
pos
->
build_id
));
ev
.
build_id
.
header
.
type
=
PERF_RECORD_HEADER_BUILD_ID
;
ev
.
build_id
.
header
.
misc
=
misc
;
ev
.
build_id
.
pid
=
kerninfo
->
pid
;
ev
.
build_id
.
pid
=
machine
->
pid
;
ev
.
build_id
.
header
.
size
=
sizeof
(
ev
.
build_id
)
+
len
;
memcpy
(
&
ev
.
build_id
.
filename
,
pos
->
long_name
,
pos
->
long_name_len
);
...
...
@@ -1142,7 +1138,7 @@ int event__synthesize_build_id(struct dso *pos, u16 misc,
static
int
__event_synthesize_build_ids
(
struct
list_head
*
head
,
u16
misc
,
event__handler_t
process
,
struct
kernel_info
*
kerninfo
,
struct
machine
*
machine
,
struct
perf_session
*
session
)
{
struct
dso
*
pos
;
...
...
@@ -1153,7 +1149,7 @@ static int __event_synthesize_build_ids(struct list_head *head, u16 misc,
continue
;
err
=
event__synthesize_build_id
(
pos
,
misc
,
process
,
kerninfo
,
session
);
machine
,
session
);
if
(
err
<
0
)
return
err
;
}
...
...
@@ -1166,15 +1162,15 @@ int event__synthesize_build_ids(event__handler_t process,
{
int
err
=
0
;
u16
kmisc
,
umisc
;
struct
kernel_info
*
pos
;
struct
machine
*
pos
;
struct
rb_node
*
nd
;
if
(
!
dsos__read_build_ids
(
&
session
->
header
,
true
))
return
0
;
for
(
nd
=
rb_first
(
&
session
->
kerninfo_root
);
nd
;
nd
=
rb_next
(
nd
))
{
pos
=
rb_entry
(
nd
,
struct
kernel_info
,
rb_node
);
if
(
is_host_kernel
(
pos
))
{
for
(
nd
=
rb_first
(
&
session
->
machines
);
nd
;
nd
=
rb_next
(
nd
))
{
pos
=
rb_entry
(
nd
,
struct
machine
,
rb_node
);
if
(
machine__is_host
(
pos
))
{
kmisc
=
PERF_RECORD_MISC_KERNEL
;
umisc
=
PERF_RECORD_MISC_USER
;
}
else
{
...
...
@@ -1182,11 +1178,11 @@ int event__synthesize_build_ids(event__handler_t process,
umisc
=
PERF_RECORD_MISC_GUEST_USER
;
}
err
=
__event_synthesize_build_ids
(
&
pos
->
dsos__kernel
,
kmisc
,
process
,
pos
,
session
);
err
=
__event_synthesize_build_ids
(
&
pos
->
kernel_dsos
,
kmisc
,
process
,
pos
,
session
);
if
(
err
==
0
)
err
=
__event_synthesize_build_ids
(
&
pos
->
dsos__user
,
umisc
,
process
,
pos
,
session
);
err
=
__event_synthesize_build_ids
(
&
pos
->
user_dsos
,
umisc
,
process
,
pos
,
session
);
if
(
err
)
break
;
}
...
...
tools/perf/util/header.h
View file @
bc4b473f
...
...
@@ -120,7 +120,7 @@ int event__process_tracing_data(event_t *self,
int
event__synthesize_build_id
(
struct
dso
*
pos
,
u16
misc
,
event__handler_t
process
,
struct
kernel_info
*
kerninfo
,
struct
machine
*
machine
,
struct
perf_session
*
session
);
int
event__synthesize_build_ids
(
event__handler_t
process
,
struct
perf_session
*
session
);
...
...
tools/perf/util/map.c
View file @
bc4b473f
...
...
@@ -245,7 +245,7 @@ void map_groups__init(struct map_groups *self)
self
->
maps
[
i
]
=
RB_ROOT
;
INIT_LIST_HEAD
(
&
self
->
removed_maps
[
i
]);
}
self
->
this_kerninfo
=
NULL
;
self
->
machine
=
NULL
;
}
void
map_groups__flush
(
struct
map_groups
*
self
)
...
...
@@ -513,133 +513,140 @@ struct map *maps__find(struct rb_root *maps, u64 ip)
return
NULL
;
}
struct
kernel_info
*
add_new_kernel_info
(
struct
rb_root
*
kerninfo_root
,
pid_t
pid
,
const
char
*
root_dir
)
int
machine__init
(
struct
machine
*
self
,
const
char
*
root_dir
,
pid_t
pid
)
{
struct
rb_node
**
p
=
&
kerninfo_root
->
rb_node
;
map_groups__init
(
&
self
->
kmaps
);
RB_CLEAR_NODE
(
&
self
->
rb_node
);
INIT_LIST_HEAD
(
&
self
->
user_dsos
);
INIT_LIST_HEAD
(
&
self
->
kernel_dsos
);
self
->
kmaps
.
machine
=
self
;
self
->
pid
=
pid
;
self
->
root_dir
=
strdup
(
root_dir
);
return
self
->
root_dir
==
NULL
?
-
ENOMEM
:
0
;
}
struct
machine
*
machines__add
(
struct
rb_root
*
self
,
pid_t
pid
,
const
char
*
root_dir
)
{
struct
rb_node
**
p
=
&
self
->
rb_node
;
struct
rb_node
*
parent
=
NULL
;
struct
kernel_info
*
kerninfo
,
*
pos
;
struct
machine
*
pos
,
*
machine
=
malloc
(
sizeof
(
*
machine
))
;
kerninfo
=
malloc
(
sizeof
(
struct
kernel_info
));
if
(
!
kerninfo
)
if
(
!
machine
)
return
NULL
;
kerninfo
->
pid
=
pid
;
map_groups__init
(
&
kerninfo
->
kmaps
);
kerninfo
->
root_dir
=
strdup
(
root_dir
);
RB_CLEAR_NODE
(
&
kerninfo
->
rb_node
);
INIT_LIST_HEAD
(
&
kerninfo
->
dsos__user
);
INIT_LIST_HEAD
(
&
kerninfo
->
dsos__kernel
);
kerninfo
->
kmaps
.
this_kerninfo
=
kerninfo
;
if
(
machine__init
(
machine
,
root_dir
,
pid
)
!=
0
)
{
free
(
machine
);
return
NULL
;
}
while
(
*
p
!=
NULL
)
{
parent
=
*
p
;
pos
=
rb_entry
(
parent
,
struct
kernel_info
,
rb_node
);
pos
=
rb_entry
(
parent
,
struct
machine
,
rb_node
);
if
(
pid
<
pos
->
pid
)
p
=
&
(
*
p
)
->
rb_left
;
else
p
=
&
(
*
p
)
->
rb_right
;
}
rb_link_node
(
&
kerninfo
->
rb_node
,
parent
,
p
);
rb_insert_color
(
&
kerninfo
->
rb_node
,
kerninfo_root
);
rb_link_node
(
&
machine
->
rb_node
,
parent
,
p
);
rb_insert_color
(
&
machine
->
rb_node
,
self
);
return
kerninfo
;
return
machine
;
}
struct
kernel_info
*
kerninfo__find
(
struct
rb_root
*
kerninfo_root
,
pid_t
pid
)
struct
machine
*
machines__find
(
struct
rb_root
*
self
,
pid_t
pid
)
{
struct
rb_node
**
p
=
&
kerninfo_root
->
rb_node
;
struct
rb_node
**
p
=
&
self
->
rb_node
;
struct
rb_node
*
parent
=
NULL
;
struct
kernel_info
*
kerninfo
;
struct
kernel_info
*
default_kerninfo
=
NULL
;
struct
machine
*
machine
;
struct
machine
*
default_machine
=
NULL
;
while
(
*
p
!=
NULL
)
{
parent
=
*
p
;
kerninfo
=
rb_entry
(
parent
,
struct
kernel_info
,
rb_node
);
if
(
pid
<
kerninfo
->
pid
)
machine
=
rb_entry
(
parent
,
struct
machine
,
rb_node
);
if
(
pid
<
machine
->
pid
)
p
=
&
(
*
p
)
->
rb_left
;
else
if
(
pid
>
kerninfo
->
pid
)
else
if
(
pid
>
machine
->
pid
)
p
=
&
(
*
p
)
->
rb_right
;
else
return
kerninfo
;
if
(
!
kerninfo
->
pid
)
default_
kerninfo
=
kerninfo
;
return
machine
;
if
(
!
machine
->
pid
)
default_
machine
=
machine
;
}
return
default_
kerninfo
;
return
default_
machine
;
}
struct
kernel_info
*
kerninfo__findhost
(
struct
rb_root
*
kerninfo_root
)
/*
* FIXME: Why repeatedly search for this?
*/
struct
machine
*
machines__find_host
(
struct
rb_root
*
self
)
{
struct
rb_node
**
p
=
&
kerninfo_root
->
rb_node
;
struct
rb_node
**
p
=
&
self
->
rb_node
;
struct
rb_node
*
parent
=
NULL
;
struct
kernel_info
*
kerninfo
;
struct
machine
*
machine
;
pid_t
pid
=
HOST_KERNEL_ID
;
while
(
*
p
!=
NULL
)
{
parent
=
*
p
;
kerninfo
=
rb_entry
(
parent
,
struct
kernel_info
,
rb_node
);
if
(
pid
<
kerninfo
->
pid
)
machine
=
rb_entry
(
parent
,
struct
machine
,
rb_node
);
if
(
pid
<
machine
->
pid
)
p
=
&
(
*
p
)
->
rb_left
;
else
if
(
pid
>
kerninfo
->
pid
)
else
if
(
pid
>
machine
->
pid
)
p
=
&
(
*
p
)
->
rb_right
;
else
return
kerninfo
;
return
machine
;
}
return
NULL
;
}
struct
kernel_info
*
kerninfo__findnew
(
struct
rb_root
*
kerninfo_root
,
pid_t
pid
)
struct
machine
*
machines__findnew
(
struct
rb_root
*
self
,
pid_t
pid
)
{
char
path
[
PATH_MAX
];
const
char
*
root_dir
;
int
ret
;
struct
kernel_info
*
kerninfo
=
kerninfo__find
(
kerninfo_root
,
pid
);
struct
machine
*
machine
=
machines__find
(
self
,
pid
);
if
(
!
kerninfo
||
kerninfo
->
pid
!=
pid
)
{
if
(
!
machine
||
machine
->
pid
!=
pid
)
{
if
(
pid
==
HOST_KERNEL_ID
||
pid
==
DEFAULT_GUEST_KERNEL_ID
)
root_dir
=
""
;
else
{
if
(
!
symbol_conf
.
guestmount
)
goto
out
;
sprintf
(
path
,
"%s/%d"
,
symbol_conf
.
guestmount
,
pid
);
ret
=
access
(
path
,
R_OK
);
if
(
ret
)
{
if
(
access
(
path
,
R_OK
))
{
pr_err
(
"Can't access file %s
\n
"
,
path
);
goto
out
;
}
root_dir
=
path
;
}
kerninfo
=
add_new_kernel_info
(
kerninfo_root
,
pid
,
root_dir
);
machine
=
machines__add
(
self
,
pid
,
root_dir
);
}
out:
return
kerninfo
;
return
machine
;
}
void
kerninfo__process_allkernels
(
struct
rb_root
*
kerninfo_root
,
process_kernel_info
process
,
void
*
data
)
void
machines__process
(
struct
rb_root
*
self
,
machine__process_t
process
,
void
*
data
)
{
struct
rb_node
*
nd
;
for
(
nd
=
rb_first
(
kerninfo_root
);
nd
;
nd
=
rb_next
(
nd
))
{
struct
kernel_info
*
pos
=
rb_entry
(
nd
,
struct
kernel_info
,
rb_node
);
for
(
nd
=
rb_first
(
self
);
nd
;
nd
=
rb_next
(
nd
))
{
struct
machine
*
pos
=
rb_entry
(
nd
,
struct
machine
,
rb_node
);
process
(
pos
,
data
);
}
}
char
*
kern_mmap_name
(
struct
kernel_info
*
kerninfo
,
char
*
buff
)
char
*
machine__mmap_name
(
struct
machine
*
self
,
char
*
bf
,
size_t
size
)
{
if
(
is_host_kernel
(
kerninfo
))
s
printf
(
buff
,
"[%s]"
,
"kernel.kallsyms"
);
else
if
(
is_default_guest
(
kerninfo
))
s
printf
(
buff
,
"[%s]"
,
"guest.kernel.kallsyms"
);
if
(
machine__is_host
(
self
))
s
nprintf
(
bf
,
size
,
"[%s]"
,
"kernel.kallsyms"
);
else
if
(
machine__is_default_guest
(
self
))
s
nprintf
(
bf
,
size
,
"[%s]"
,
"guest.kernel.kallsyms"
);
else
s
printf
(
buff
,
"[%s.%d]"
,
"guest.kernel.kallsyms"
,
kerninfo
->
pid
);
s
nprintf
(
bf
,
size
,
"[%s.%d]"
,
"guest.kernel.kallsyms"
,
self
->
pid
);
return
b
uf
f
;
return
bf
;
}
tools/perf/util/map.h
View file @
bc4b473f
...
...
@@ -5,6 +5,7 @@
#include <linux/list.h>
#include <linux/rbtree.h>
#include <stdio.h>
#include <stdbool.h>
#include "types.h"
enum
map_type
{
...
...
@@ -19,7 +20,7 @@ extern const char *map_type__name[MAP__NR_TYPES];
struct
dso
;
struct
ref_reloc_sym
;
struct
map_groups
;
struct
kernel_info
;
struct
machine
;
struct
map
{
union
{
...
...
@@ -29,6 +30,7 @@ struct map {
u64
start
;
u64
end
;
enum
map_type
type
;
u32
priv
;
u64
pgoff
;
/* ip -> dso rip */
...
...
@@ -48,23 +50,29 @@ struct kmap {
struct
map_groups
{
struct
rb_root
maps
[
MAP__NR_TYPES
];
struct
list_head
removed_maps
[
MAP__NR_TYPES
];
struct
kernel_info
*
this_kerninfo
;
struct
machine
*
machine
;
};
/* Native host kernel uses -1 as pid index in
kernel_info
*/
/* Native host kernel uses -1 as pid index in
machine
*/
#define HOST_KERNEL_ID (-1)
#define DEFAULT_GUEST_KERNEL_ID (0)
struct
kernel_info
{
struct
machine
{
struct
rb_node
rb_node
;
pid_t
pid
;
char
*
root_dir
;
struct
list_head
dsos__user
;
struct
list_head
dsos__kernel
;
struct
list_head
user_dsos
;
struct
list_head
kernel_dsos
;
struct
map_groups
kmaps
;
struct
map
*
vmlinux_maps
[
MAP__NR_TYPES
];
};
static
inline
struct
map
*
machine__kernel_map
(
struct
machine
*
self
,
enum
map_type
type
)
{
return
self
->
vmlinux_maps
[
type
];
}
static
inline
struct
kmap
*
map__kmap
(
struct
map
*
self
)
{
return
(
struct
kmap
*
)(
self
+
1
);
...
...
@@ -124,36 +132,31 @@ int map_groups__clone(struct map_groups *self,
size_t
map_groups__fprintf
(
struct
map_groups
*
self
,
int
verbose
,
FILE
*
fp
);
size_t
map_groups__fprintf_maps
(
struct
map_groups
*
self
,
int
verbose
,
FILE
*
fp
);
struct
kernel_info
*
add_new_kernel_info
(
struct
rb_root
*
kerninfo_root
,
pid_t
pid
,
const
char
*
root_dir
);
struct
kernel_info
*
kerninfo__find
(
struct
rb_root
*
kerninfo_root
,
pid_t
pid
);
struct
kernel_info
*
kerninfo__findnew
(
struct
rb_root
*
kerninfo_root
,
pid_t
pid
);
struct
kernel_info
*
kerninfo__findhost
(
struct
rb_root
*
kerninfo_root
);
char
*
kern_mmap_name
(
struct
kernel_info
*
kerninfo
,
char
*
buff
);
typedef
void
(
*
machine__process_t
)(
struct
machine
*
self
,
void
*
data
);
void
machines__process
(
struct
rb_root
*
self
,
machine__process_t
process
,
void
*
data
);
struct
machine
*
machines__add
(
struct
rb_root
*
self
,
pid_t
pid
,
const
char
*
root_dir
);
struct
machine
*
machines__find_host
(
struct
rb_root
*
self
);
struct
machine
*
machines__find
(
struct
rb_root
*
self
,
pid_t
pid
);
struct
machine
*
machines__findnew
(
struct
rb_root
*
self
,
pid_t
pid
);
char
*
machine__mmap_name
(
struct
machine
*
self
,
char
*
bf
,
size_t
size
);
int
machine__init
(
struct
machine
*
self
,
const
char
*
root_dir
,
pid_t
pid
);
/*
* Default guest kernel is defined by parameter --guestkallsyms
* and --guestmodules
*/
static
inline
int
is_default_guest
(
struct
kernel_info
*
kerninfo
)
static
inline
bool
machine__is_default_guest
(
struct
machine
*
self
)
{
if
(
!
kerninfo
)
return
0
;
return
kerninfo
->
pid
==
DEFAULT_GUEST_KERNEL_ID
;
return
self
?
self
->
pid
==
DEFAULT_GUEST_KERNEL_ID
:
false
;
}
static
inline
int
is_host_kernel
(
struct
kernel_info
*
kerninfo
)
static
inline
bool
machine__is_host
(
struct
machine
*
self
)
{
if
(
!
kerninfo
)
return
0
;
return
kerninfo
->
pid
==
HOST_KERNEL_ID
;
return
self
?
self
->
pid
==
HOST_KERNEL_ID
:
false
;
}
typedef
void
(
*
process_kernel_info
)(
struct
kernel_info
*
kerninfo
,
void
*
data
);
void
kerninfo__process_allkernels
(
struct
rb_root
*
kerninfo_root
,
process_kernel_info
process
,
void
*
data
);
static
inline
void
map_groups__insert
(
struct
map_groups
*
self
,
struct
map
*
map
)
{
maps__insert
(
&
self
->
maps
[
map
->
type
],
map
);
...
...
@@ -178,10 +181,20 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *self,
symbol_filter_t
filter
);
static
inline
struct
symbol
*
map_groups__find_function
(
struct
map_groups
*
self
,
u64
addr
,
struct
map
**
mapp
,
symbol_filter_t
filter
)
struct
symbol
*
machine__find_kernel_symbol
(
struct
machine
*
self
,
enum
map_type
type
,
u64
addr
,
struct
map
**
mapp
,
symbol_filter_t
filter
)
{
return
map_groups__find_symbol
(
&
self
->
kmaps
,
type
,
addr
,
mapp
,
filter
);
}
static
inline
struct
symbol
*
machine__find_kernel_function
(
struct
machine
*
self
,
u64
addr
,
struct
map
**
mapp
,
symbol_filter_t
filter
)
{
return
ma
p_groups__find
_symbol
(
self
,
MAP__FUNCTION
,
addr
,
mapp
,
filter
);
return
ma
chine__find_kernel
_symbol
(
self
,
MAP__FUNCTION
,
addr
,
mapp
,
filter
);
}
static
inline
...
...
@@ -197,10 +210,7 @@ int map_groups__fixup_overlappings(struct map_groups *self, struct map *map,
struct
map
*
map_groups__find_by_name
(
struct
map_groups
*
self
,
enum
map_type
type
,
const
char
*
name
);
struct
map
*
map_groups__new_module
(
struct
map_groups
*
self
,
u64
start
,
const
char
*
filename
,
struct
kernel_info
*
kerninfo
);
struct
map
*
machine__new_module
(
struct
machine
*
self
,
u64
start
,
const
char
*
filename
);
void
map_groups__flush
(
struct
map_groups
*
self
);
...
...
tools/perf/util/probe-event.c
View file @
bc4b473f
...
...
@@ -72,8 +72,7 @@ static int e_snprintf(char *str, size_t size, const char *format, ...)
}
static
char
*
synthesize_perf_probe_point
(
struct
perf_probe_point
*
pp
);
static
struct
map_groups
kmap_groups
;
static
struct
map
*
kmaps
[
MAP__NR_TYPES
];
static
struct
machine
machine
;
/* Initialize symbol maps and path of vmlinux */
static
int
init_vmlinux
(
void
)
...
...
@@ -92,12 +91,15 @@ static int init_vmlinux(void)
goto
out
;
}
ret
=
machine__init
(
&
machine
,
"/"
,
0
);
if
(
ret
<
0
)
goto
out
;
kernel
=
dso__new_kernel
(
symbol_conf
.
vmlinux_name
);
if
(
kernel
==
NULL
)
die
(
"Failed to create kernel dso."
);
map_groups__init
(
&
kmap_groups
);
ret
=
__map_groups__create_kernel_maps
(
&
kmap_groups
,
kmaps
,
kernel
);
ret
=
__machine__create_kernel_maps
(
&
machine
,
kernel
);
if
(
ret
<
0
)
pr_debug
(
"Failed to create kernel maps.
\n
"
);
...
...
@@ -110,12 +112,12 @@ static int init_vmlinux(void)
#ifdef DWARF_SUPPORT
static
int
open_vmlinux
(
void
)
{
if
(
map__load
(
k
maps
[
MAP__FUNCTION
],
NULL
)
<
0
)
{
if
(
map__load
(
machine
.
vmlinux_
maps
[
MAP__FUNCTION
],
NULL
)
<
0
)
{
pr_debug
(
"Failed to load kernel map.
\n
"
);
return
-
EINVAL
;
}
pr_debug
(
"Try to open %s
\n
"
,
k
maps
[
MAP__FUNCTION
]
->
dso
->
long_name
);
return
open
(
k
maps
[
MAP__FUNCTION
]
->
dso
->
long_name
,
O_RDONLY
);
pr_debug
(
"Try to open %s
\n
"
,
machine
.
vmlinux_
maps
[
MAP__FUNCTION
]
->
dso
->
long_name
);
return
open
(
machine
.
vmlinux_
maps
[
MAP__FUNCTION
]
->
dso
->
long_name
,
O_RDONLY
);
}
/* Convert trace point to probe point with debuginfo */
...
...
@@ -125,7 +127,7 @@ static int convert_to_perf_probe_point(struct kprobe_trace_point *tp,
struct
symbol
*
sym
;
int
fd
,
ret
=
-
ENOENT
;
sym
=
map__find_symbol_by_name
(
k
maps
[
MAP__FUNCTION
],
sym
=
map__find_symbol_by_name
(
machine
.
vmlinux_
maps
[
MAP__FUNCTION
],
tp
->
symbol
,
NULL
);
if
(
sym
)
{
fd
=
open_vmlinux
();
...
...
@@ -1466,7 +1468,7 @@ static int convert_to_kprobe_trace_events(struct perf_probe_event *pev,
}
/* Currently just checking function name from symbol map */
sym
=
map__find_symbol_by_name
(
k
maps
[
MAP__FUNCTION
],
sym
=
map__find_symbol_by_name
(
machine
.
vmlinux_
maps
[
MAP__FUNCTION
],
tev
->
point
.
symbol
,
NULL
);
if
(
!
sym
)
{
pr_warning
(
"Kernel symbol
\'
%s
\'
not found.
\n
"
,
...
...
tools/perf/util/session.c
View file @
bc4b473f
...
...
@@ -69,12 +69,11 @@ void perf_session__update_sample_type(struct perf_session *self)
int
perf_session__create_kernel_maps
(
struct
perf_session
*
self
)
{
int
ret
;
struct
rb_root
*
root
=
&
self
->
kerninfo_root
;
struct
rb_root
*
machines
=
&
self
->
machines
;
int
ret
=
machines__create_kernel_maps
(
machines
,
HOST_KERNEL_ID
)
;
ret
=
map_groups__create_kernel_maps
(
root
,
HOST_KERNEL_ID
);
if
(
ret
>=
0
)
ret
=
ma
p_groups__create_guest_kernel_maps
(
root
);
ret
=
ma
chines__create_guest_kernel_maps
(
machines
);
return
ret
;
}
...
...
@@ -97,7 +96,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc
self
->
cwd
=
NULL
;
self
->
cwdlen
=
0
;
self
->
unknown_events
=
0
;
self
->
kerninfo_root
=
RB_ROOT
;
self
->
machines
=
RB_ROOT
;
self
->
ordered_samples
.
flush_limit
=
ULLONG_MAX
;
INIT_LIST_HEAD
(
&
self
->
ordered_samples
.
samples_head
);
...
...
tools/perf/util/session.h
View file @
bc4b473f
...
...
@@ -25,7 +25,7 @@ struct perf_session {
unsigned
long
mmap_window
;
struct
rb_root
threads
;
struct
thread
*
last_match
;
struct
rb_root
kerninfo_root
;
struct
rb_root
machines
;
struct
events_stats
events_stats
;
struct
rb_root
stats_by_id
;
unsigned
long
event_total
[
PERF_RECORD_MAX
];
...
...
@@ -102,4 +102,42 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists,
u64
session_total
,
const
char
*
helpline
,
const
char
*
input_name
);
#endif
static
inline
struct
machine
*
perf_session__find_host_machine
(
struct
perf_session
*
self
)
{
return
machines__find_host
(
&
self
->
machines
);
}
static
inline
struct
machine
*
perf_session__find_machine
(
struct
perf_session
*
self
,
pid_t
pid
)
{
return
machines__find
(
&
self
->
machines
,
pid
);
}
static
inline
struct
machine
*
perf_session__findnew_machine
(
struct
perf_session
*
self
,
pid_t
pid
)
{
return
machines__findnew
(
&
self
->
machines
,
pid
);
}
static
inline
void
perf_session__process_machines
(
struct
perf_session
*
self
,
machine__process_t
process
)
{
return
machines__process
(
&
self
->
machines
,
process
,
self
);
}
static
inline
size_t
perf_session__fprintf_dsos
(
struct
perf_session
*
self
,
FILE
*
fp
)
{
return
machines__fprintf_dsos
(
&
self
->
machines
,
fp
);
}
static
inline
size_t
perf_session__fprintf_dsos_buildid
(
struct
perf_session
*
self
,
FILE
*
fp
,
bool
with_hits
)
{
return
machines__fprintf_dsos_buildid
(
&
self
->
machines
,
fp
,
with_hits
);
}
#endif
/* __PERF_SESSION_H */
tools/perf/util/symbol.c
View file @
bc4b473f
...
...
@@ -485,7 +485,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
symbol_filter_t
filter
)
{
struct
map_groups
*
kmaps
=
map__kmap
(
map
)
->
kmaps
;
struct
kernel_info
*
kerninfo
=
kmaps
->
this_kerninfo
;
struct
machine
*
machine
=
kmaps
->
machine
;
struct
map
*
curr_map
=
map
;
struct
symbol
*
pos
;
int
count
=
0
;
...
...
@@ -509,7 +509,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
if
(
strcmp
(
curr_map
->
dso
->
short_name
,
module
))
{
if
(
curr_map
!=
map
&&
self
->
kernel
==
DSO_TYPE_GUEST_KERNEL
&&
is_default_guest
(
kerninfo
))
{
machine__is_default_guest
(
machine
))
{
/*
* We assume all symbols of a module are
* continuous in * kallsyms, so curr_map
...
...
@@ -527,13 +527,13 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
pr_err
(
"%s/proc/{kallsyms,modules} "
"inconsistency while looking "
"for
\"
%s
\"
module!
\n
"
,
kerninfo
->
root_dir
,
module
);
machine
->
root_dir
,
module
);
curr_map
=
map
;
goto
discard_symbol
;
}
if
(
curr_map
->
dso
->
loaded
&&
!
is_default_guest
(
kmaps
->
this_kerninfo
))
!
machine__is_default_guest
(
machine
))
goto
discard_symbol
;
}
/*
...
...
@@ -586,7 +586,7 @@ discard_symbol: rb_erase(&pos->rb_node, root);
if
(
curr_map
!=
map
&&
self
->
kernel
==
DSO_TYPE_GUEST_KERNEL
&&
is_default_guest
(
kmaps
->
this_kerninfo
))
{
machine__is_default_guest
(
kmaps
->
machine
))
{
dso__set_loaded
(
curr_map
->
dso
,
curr_map
->
type
);
}
...
...
@@ -1291,7 +1291,7 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
char
build_id_hex
[
BUILD_ID_SIZE
*
2
+
1
];
int
ret
=
-
1
;
int
fd
;
struct
kernel_info
*
kerninfo
;
struct
machine
*
machine
;
const
char
*
root_dir
;
dso__set_loaded
(
self
,
map
->
type
);
...
...
@@ -1301,10 +1301,10 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
else
if
(
self
->
kernel
==
DSO_TYPE_GUEST_KERNEL
)
return
dso__load_guest_kernel_sym
(
self
,
map
,
filter
);
if
(
map
->
groups
&&
map
->
groups
->
this_kerninfo
)
kerninfo
=
map
->
groups
->
this_kerninfo
;
if
(
map
->
groups
&&
map
->
groups
->
machine
)
machine
=
map
->
groups
->
machine
;
else
kerninfo
=
NULL
;
machine
=
NULL
;
name
=
malloc
(
size
);
if
(
!
name
)
...
...
@@ -1359,8 +1359,8 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
snprintf
(
name
,
size
,
"%s"
,
self
->
long_name
);
break
;
case
DSO__ORIG_GUEST_KMODULE
:
if
(
map
->
groups
&&
map
->
groups
->
this_kerninfo
)
root_dir
=
map
->
groups
->
this_kerninfo
->
root_dir
;
if
(
map
->
groups
&&
map
->
groups
->
machine
)
root_dir
=
map
->
groups
->
machine
->
root_dir
;
else
root_dir
=
""
;
snprintf
(
name
,
size
,
"%s%s"
,
root_dir
,
self
->
long_name
);
...
...
@@ -1528,21 +1528,20 @@ static char *get_kernel_version(const char *root_dir)
return
strdup
(
name
);
}
static
int
map_groups__set_modules_path
(
struct
map_groups
*
self
,
const
char
*
root_dir
)
static
int
machine__set_modules_path
(
struct
machine
*
self
)
{
char
*
version
;
char
modules_path
[
PATH_MAX
];
version
=
get_kernel_version
(
root_dir
);
version
=
get_kernel_version
(
self
->
root_dir
);
if
(
!
version
)
return
-
1
;
snprintf
(
modules_path
,
sizeof
(
modules_path
),
"%s/lib/modules/%s/kernel"
,
root_dir
,
version
);
self
->
root_dir
,
version
);
free
(
version
);
return
map_groups__set_modules_path_dir
(
self
,
modules_path
);
return
map_groups__set_modules_path_dir
(
&
self
->
kmaps
,
modules_path
);
}
/*
...
...
@@ -1564,14 +1563,12 @@ static struct map *map__new2(u64 start, struct dso *dso, enum map_type type)
return
self
;
}
struct
map
*
map_groups__new_module
(
struct
map_groups
*
self
,
u64
start
,
const
char
*
filename
,
struct
kernel_info
*
kerninfo
)
struct
map
*
machine__new_module
(
struct
machine
*
self
,
u64
start
,
const
char
*
filename
)
{
struct
map
*
map
;
struct
dso
*
dso
;
struct
dso
*
dso
=
__dsos__findnew
(
&
self
->
kernel_dsos
,
filename
)
;
dso
=
__dsos__findnew
(
&
kerninfo
->
dsos__kernel
,
filename
);
if
(
dso
==
NULL
)
return
NULL
;
...
...
@@ -1579,28 +1576,27 @@ struct map *map_groups__new_module(struct map_groups *self, u64 start,
if
(
map
==
NULL
)
return
NULL
;
if
(
is_host_kernel
(
kerninfo
))
if
(
machine__is_host
(
self
))
dso
->
origin
=
DSO__ORIG_KMODULE
;
else
dso
->
origin
=
DSO__ORIG_GUEST_KMODULE
;
map_groups__insert
(
self
,
map
);
map_groups__insert
(
&
self
->
kmaps
,
map
);
return
map
;
}
static
int
ma
p_groups__create_modules
(
struct
kernel_info
*
kerninfo
)
static
int
ma
chine__create_modules
(
struct
machine
*
self
)
{
char
*
line
=
NULL
;
size_t
n
;
FILE
*
file
;
struct
map
*
map
;
const
char
*
root_dir
;
const
char
*
modules
;
char
path
[
PATH_MAX
];
if
(
is_default_guest
(
kerninfo
))
if
(
machine__is_default_guest
(
self
))
modules
=
symbol_conf
.
default_guest_modules
;
else
{
sprintf
(
path
,
"%s/proc/modules"
,
kerninfo
->
root_dir
);
sprintf
(
path
,
"%s/proc/modules"
,
self
->
root_dir
);
modules
=
path
;
}
...
...
@@ -1608,8 +1604,6 @@ static int map_groups__create_modules(struct kernel_info *kerninfo)
if
(
file
==
NULL
)
return
-
1
;
root_dir
=
kerninfo
->
root_dir
;
while
(
!
feof
(
file
))
{
char
name
[
PATH_MAX
];
u64
start
;
...
...
@@ -1638,17 +1632,16 @@ static int map_groups__create_modules(struct kernel_info *kerninfo)
*
sep
=
'\0'
;
snprintf
(
name
,
sizeof
(
name
),
"[%s]"
,
line
);
map
=
map_groups__new_module
(
&
kerninfo
->
kmaps
,
start
,
name
,
kerninfo
);
map
=
machine__new_module
(
self
,
start
,
name
);
if
(
map
==
NULL
)
goto
out_delete_line
;
dso__kernel_module_get_build_id
(
map
->
dso
,
root_dir
);
dso__kernel_module_get_build_id
(
map
->
dso
,
self
->
root_dir
);
}
free
(
line
);
fclose
(
file
);
return
ma
p_groups__set_modules_path
(
&
kerninfo
->
kmaps
,
root_dir
);
return
ma
chine__set_modules_path
(
self
);
out_delete_line:
free
(
line
);
...
...
@@ -1820,16 +1813,16 @@ static int dso__load_guest_kernel_sym(struct dso *self, struct map *map,
{
int
err
;
const
char
*
kallsyms_filename
=
NULL
;
struct
kernel_info
*
kerninfo
;
struct
machine
*
machine
;
char
path
[
PATH_MAX
];
if
(
!
map
->
groups
)
{
pr_debug
(
"Guest kernel map hasn't the point to groups
\n
"
);
return
-
1
;
}
kerninfo
=
map
->
groups
->
this_kerninfo
;
machine
=
map
->
groups
->
machine
;
if
(
is_default_guest
(
kerninfo
))
{
if
(
machine__is_default_guest
(
machine
))
{
/*
* if the user specified a vmlinux filename, use it and only
* it, reporting errors to the user if it cannot be used.
...
...
@@ -1845,7 +1838,7 @@ static int dso__load_guest_kernel_sym(struct dso *self, struct map *map,
if
(
!
kallsyms_filename
)
return
-
1
;
}
else
{
sprintf
(
path
,
"%s/proc/kallsyms"
,
kerninfo
->
root_dir
);
sprintf
(
path
,
"%s/proc/kallsyms"
,
machine
->
root_dir
);
kallsyms_filename
=
path
;
}
...
...
@@ -1856,9 +1849,8 @@ static int dso__load_guest_kernel_sym(struct dso *self, struct map *map,
out_try_fixup:
if
(
err
>
0
)
{
if
(
kallsyms_filename
!=
NULL
)
{
kern_mmap_name
(
kerninfo
,
path
);
dso__set_long_name
(
self
,
strdup
(
path
));
machine__mmap_name
(
machine
,
path
,
sizeof
(
path
));
dso__set_long_name
(
self
,
strdup
(
path
));
}
map__fixup_start
(
map
);
map__fixup_end
(
map
);
...
...
@@ -1897,27 +1889,32 @@ struct dso *__dsos__findnew(struct list_head *head, const char *name)
return
dso
;
}
static
void
__dsos__fprintf
(
struct
list_head
*
head
,
FILE
*
fp
)
static
size_t
__dsos__fprintf
(
struct
list_head
*
head
,
FILE
*
fp
)
{
struct
dso
*
pos
;
size_t
ret
=
0
;
list_for_each_entry
(
pos
,
head
,
node
)
{
int
i
;
for
(
i
=
0
;
i
<
MAP__NR_TYPES
;
++
i
)
dso__fprintf
(
pos
,
i
,
fp
);
ret
+=
dso__fprintf
(
pos
,
i
,
fp
);
}
return
ret
;
}
void
dsos__fprintf
(
struct
rb_root
*
kerninfo_root
,
FILE
*
fp
)
size_t
machines__fprintf_dsos
(
struct
rb_root
*
self
,
FILE
*
fp
)
{
struct
rb_node
*
nd
;
size_t
ret
=
0
;
for
(
nd
=
rb_first
(
kerninfo_root
);
nd
;
nd
=
rb_next
(
nd
))
{
struct
kernel_info
*
pos
=
rb_entry
(
nd
,
struct
kernel_info
,
rb_node
);
__dsos__fprintf
(
&
pos
->
dsos__kernel
,
fp
);
__dsos__fprintf
(
&
pos
->
dsos__user
,
fp
);
for
(
nd
=
rb_first
(
self
);
nd
;
nd
=
rb_next
(
nd
))
{
struct
machine
*
pos
=
rb_entry
(
nd
,
struct
machine
,
rb_node
);
ret
+=
__dsos__fprintf
(
&
pos
->
kernel_dsos
,
fp
);
ret
+=
__dsos__fprintf
(
&
pos
->
user_dsos
,
fp
);
}
return
ret
;
}
static
size_t
__dsos__fprintf_buildid
(
struct
list_head
*
head
,
FILE
*
fp
,
...
...
@@ -1935,19 +1932,15 @@ static size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
return
ret
;
}
size_t
dsos__fprintf_buildid
(
struct
rb_root
*
kerninfo_root
,
FILE
*
fp
,
bool
with_hits
)
size_t
machines__fprintf_dsos_buildid
(
struct
rb_root
*
self
,
FILE
*
fp
,
bool
with_hits
)
{
struct
rb_node
*
nd
;
size_t
ret
=
0
;
for
(
nd
=
rb_first
(
kerninfo_root
);
nd
;
nd
=
rb_next
(
nd
))
{
struct
kernel_info
*
pos
=
rb_entry
(
nd
,
struct
kernel_info
,
rb_node
);
ret
+=
__dsos__fprintf_buildid
(
&
pos
->
dsos__kernel
,
fp
,
with_hits
);
ret
+=
__dsos__fprintf_buildid
(
&
pos
->
dsos__user
,
fp
,
with_hits
);
for
(
nd
=
rb_first
(
self
);
nd
;
nd
=
rb_next
(
nd
))
{
struct
machine
*
pos
=
rb_entry
(
nd
,
struct
machine
,
rb_node
);
ret
+=
__dsos__fprintf_buildid
(
&
pos
->
kernel_dsos
,
fp
,
with_hits
);
ret
+=
__dsos__fprintf_buildid
(
&
pos
->
user_dsos
,
fp
,
with_hits
);
}
return
ret
;
}
...
...
@@ -1964,14 +1957,12 @@ struct dso *dso__new_kernel(const char *name)
return
self
;
}
static
struct
dso
*
dso__new_guest_kernel
(
struct
kernel_info
*
kerninfo
,
static
struct
dso
*
dso__new_guest_kernel
(
struct
machine
*
machine
,
const
char
*
name
)
{
char
b
uf
f
[
PATH_MAX
];
struct
dso
*
self
;
char
bf
[
PATH_MAX
];
struct
dso
*
self
=
dso__new
(
name
?:
machine__mmap_name
(
machine
,
bf
,
sizeof
(
bf
)))
;
kern_mmap_name
(
kerninfo
,
buff
);
self
=
dso__new
(
name
?:
buff
);
if
(
self
!=
NULL
)
{
dso__set_short_name
(
self
,
"[guest.kernel]"
);
self
->
kernel
=
DSO_TYPE_GUEST_KERNEL
;
...
...
@@ -1980,64 +1971,78 @@ static struct dso *dso__new_guest_kernel(struct kernel_info *kerninfo,
return
self
;
}
void
dso__read_running_kernel_build_id
(
struct
dso
*
self
,
struct
kernel_info
*
kerninfo
)
void
dso__read_running_kernel_build_id
(
struct
dso
*
self
,
struct
machine
*
machine
)
{
char
path
[
PATH_MAX
];
if
(
is_default_guest
(
kerninfo
))
if
(
machine__is_default_guest
(
machine
))
return
;
sprintf
(
path
,
"%s/sys/kernel/notes"
,
kerninfo
->
root_dir
);
sprintf
(
path
,
"%s/sys/kernel/notes"
,
machine
->
root_dir
);
if
(
sysfs__read_build_id
(
path
,
self
->
build_id
,
sizeof
(
self
->
build_id
))
==
0
)
self
->
has_build_id
=
true
;
}
static
struct
dso
*
dsos__create_kernel
(
struct
kernel_info
*
kerninfo
)
static
struct
dso
*
machine__create_kernel
(
struct
machine
*
self
)
{
const
char
*
vmlinux_name
=
NULL
;
struct
dso
*
kernel
;
if
(
is_host_kernel
(
kerninfo
))
{
if
(
machine__is_host
(
self
))
{
vmlinux_name
=
symbol_conf
.
vmlinux_name
;
kernel
=
dso__new_kernel
(
vmlinux_name
);
}
else
{
if
(
is_default_guest
(
kerninfo
))
if
(
machine__is_default_guest
(
self
))
vmlinux_name
=
symbol_conf
.
default_guest_vmlinux_name
;
kernel
=
dso__new_guest_kernel
(
kerninfo
,
vmlinux_name
);
kernel
=
dso__new_guest_kernel
(
self
,
vmlinux_name
);
}
if
(
kernel
!=
NULL
)
{
dso__read_running_kernel_build_id
(
kernel
,
kerninfo
);
dsos__add
(
&
kerninfo
->
dsos__kernel
,
kernel
);
dso__read_running_kernel_build_id
(
kernel
,
self
);
dsos__add
(
&
self
->
kernel_dsos
,
kernel
);
}
return
kernel
;
}
int
__map_groups__create_kernel_maps
(
struct
map_groups
*
self
,
struct
map
*
vmlinux_maps
[
MAP__NR_TYPES
],
struct
dso
*
kernel
)
int
__machine__create_kernel_maps
(
struct
machine
*
self
,
struct
dso
*
kernel
)
{
enum
map_type
type
;
for
(
type
=
0
;
type
<
MAP__NR_TYPES
;
++
type
)
{
struct
kmap
*
kmap
;
vmlinux_maps
[
type
]
=
map__new2
(
0
,
kernel
,
type
);
if
(
vmlinux_maps
[
type
]
==
NULL
)
self
->
vmlinux_maps
[
type
]
=
map__new2
(
0
,
kernel
,
type
);
if
(
self
->
vmlinux_maps
[
type
]
==
NULL
)
return
-
1
;
vmlinux_maps
[
type
]
->
map_ip
=
vmlinux_maps
[
type
]
->
unmap_ip
=
identity__map_ip
;
self
->
vmlinux_maps
[
type
]
->
map_ip
=
self
->
vmlinux_maps
[
type
]
->
unmap_ip
=
identity__map_ip
;
kmap
=
map__kmap
(
vmlinux_maps
[
type
]);
kmap
->
kmaps
=
self
;
map_groups__insert
(
self
,
vmlinux_maps
[
type
]);
kmap
=
map__kmap
(
self
->
vmlinux_maps
[
type
]);
kmap
->
kmaps
=
&
self
->
kmaps
;
map_groups__insert
(
&
self
->
kmaps
,
self
->
vmlinux_maps
[
type
]);
}
return
0
;
}
int
machine__create_kernel_maps
(
struct
machine
*
self
)
{
struct
dso
*
kernel
=
machine__create_kernel
(
self
);
if
(
kernel
==
NULL
||
__machine__create_kernel_maps
(
self
,
kernel
)
<
0
)
return
-
1
;
if
(
symbol_conf
.
use_modules
&&
machine__create_modules
(
self
)
<
0
)
pr_debug
(
"Problems creating module maps, continuing anyway...
\n
"
);
/*
* Now that we have all the maps created, just set the ->end of them:
*/
map_groups__fixup_end
(
&
self
->
kmaps
);
return
0
;
}
static
void
vmlinux_path__exit
(
void
)
{
while
(
--
vmlinux_path__nr_entries
>=
0
)
{
...
...
@@ -2154,30 +2159,14 @@ int symbol__init(void)
return
-
1
;
}
int
ma
p_groups__create_kernel_maps
(
struct
rb_root
*
kerninfo_root
,
pid_t
pid
)
int
ma
chines__create_kernel_maps
(
struct
rb_root
*
self
,
pid_t
pid
)
{
struct
kernel_info
*
kerninfo
;
struct
dso
*
kernel
;
kerninfo
=
kerninfo__findnew
(
kerninfo_root
,
pid
);
if
(
kerninfo
==
NULL
)
return
-
1
;
kernel
=
dsos__create_kernel
(
kerninfo
);
if
(
kernel
==
NULL
)
return
-
1
;
struct
machine
*
machine
=
machines__findnew
(
self
,
pid
);
if
(
__map_groups__create_kernel_maps
(
&
kerninfo
->
kmaps
,
kerninfo
->
vmlinux_maps
,
kernel
)
<
0
)
if
(
machine
==
NULL
)
return
-
1
;
if
(
symbol_conf
.
use_modules
&&
map_groups__create_modules
(
kerninfo
)
<
0
)
pr_debug
(
"Problems creating module maps, continuing anyway...
\n
"
);
/*
* Now that we have all the maps created, just set the ->end of them:
*/
map_groups__fixup_end
(
&
kerninfo
->
kmaps
);
return
0
;
return
machine__create_kernel_maps
(
machine
);
}
static
int
hex
(
char
ch
)
...
...
@@ -2223,7 +2212,7 @@ char *strxfrchar(char *s, char from, char to)
return
s
;
}
int
ma
p_groups__create_guest_kernel_maps
(
struct
rb_root
*
kerninfo_root
)
int
ma
chines__create_guest_kernel_maps
(
struct
rb_root
*
self
)
{
int
ret
=
0
;
struct
dirent
**
namelist
=
NULL
;
...
...
@@ -2234,8 +2223,7 @@ int map_groups__create_guest_kernel_maps(struct rb_root *kerninfo_root)
if
(
symbol_conf
.
default_guest_vmlinux_name
||
symbol_conf
.
default_guest_modules
||
symbol_conf
.
default_guest_kallsyms
)
{
map_groups__create_kernel_maps
(
kerninfo_root
,
DEFAULT_GUEST_KERNEL_ID
);
machines__create_kernel_maps
(
self
,
DEFAULT_GUEST_KERNEL_ID
);
}
if
(
symbol_conf
.
guestmount
)
{
...
...
@@ -2256,8 +2244,7 @@ int map_groups__create_guest_kernel_maps(struct rb_root *kerninfo_root)
pr_debug
(
"Can't access file %s
\n
"
,
path
);
goto
failure
;
}
map_groups__create_kernel_maps
(
kerninfo_root
,
pid
);
machines__create_kernel_maps
(
self
,
pid
);
}
failure:
free
(
namelist
);
...
...
@@ -2265,3 +2252,36 @@ int map_groups__create_guest_kernel_maps(struct rb_root *kerninfo_root)
return
ret
;
}
int
machine__load_kallsyms
(
struct
machine
*
self
,
const
char
*
filename
,
enum
map_type
type
,
symbol_filter_t
filter
)
{
struct
map
*
map
=
self
->
vmlinux_maps
[
type
];
int
ret
=
dso__load_kallsyms
(
map
->
dso
,
filename
,
map
,
filter
);
if
(
ret
>
0
)
{
dso__set_loaded
(
map
->
dso
,
type
);
/*
* Since /proc/kallsyms will have multiple sessions for the
* kernel, with modules between them, fixup the end of all
* sections.
*/
__map_groups__fixup_end
(
&
self
->
kmaps
,
type
);
}
return
ret
;
}
int
machine__load_vmlinux_path
(
struct
machine
*
self
,
enum
map_type
type
,
symbol_filter_t
filter
)
{
struct
map
*
map
=
self
->
vmlinux_maps
[
type
];
int
ret
=
dso__load_vmlinux_path
(
map
->
dso
,
map
,
filter
);
if
(
ret
>
0
)
{
dso__set_loaded
(
map
->
dso
,
type
);
map__reloc_vmlinux
(
map
);
}
return
ret
;
}
tools/perf/util/symbol.h
View file @
bc4b473f
...
...
@@ -162,9 +162,13 @@ int dso__load_vmlinux_path(struct dso *self, struct map *map,
symbol_filter_t
filter
);
int
dso__load_kallsyms
(
struct
dso
*
self
,
const
char
*
filename
,
struct
map
*
map
,
symbol_filter_t
filter
);
void
dsos__fprintf
(
struct
rb_root
*
kerninfo_root
,
FILE
*
fp
);
size_t
dsos__fprintf_buildid
(
struct
rb_root
*
kerninfo_root
,
FILE
*
fp
,
bool
with_hits
);
int
machine__load_kallsyms
(
struct
machine
*
self
,
const
char
*
filename
,
enum
map_type
type
,
symbol_filter_t
filter
);
int
machine__load_vmlinux_path
(
struct
machine
*
self
,
enum
map_type
type
,
symbol_filter_t
filter
);
size_t
machines__fprintf_dsos
(
struct
rb_root
*
self
,
FILE
*
fp
);
size_t
machines__fprintf_dsos_buildid
(
struct
rb_root
*
self
,
FILE
*
fp
,
bool
with_hits
);
size_t
dso__fprintf_buildid
(
struct
dso
*
self
,
FILE
*
fp
);
size_t
dso__fprintf
(
struct
dso
*
self
,
enum
map_type
type
,
FILE
*
fp
);
...
...
@@ -186,8 +190,7 @@ enum dso_origin {
char
dso__symtab_origin
(
const
struct
dso
*
self
);
void
dso__set_long_name
(
struct
dso
*
self
,
char
*
name
);
void
dso__set_build_id
(
struct
dso
*
self
,
void
*
build_id
);
void
dso__read_running_kernel_build_id
(
struct
dso
*
self
,
struct
kernel_info
*
kerninfo
);
void
dso__read_running_kernel_build_id
(
struct
dso
*
self
,
struct
machine
*
machine
);
struct
symbol
*
dso__find_symbol
(
struct
dso
*
self
,
enum
map_type
type
,
u64
addr
);
struct
symbol
*
dso__find_symbol_by_name
(
struct
dso
*
self
,
enum
map_type
type
,
const
char
*
name
);
...
...
@@ -200,11 +203,11 @@ int kallsyms__parse(const char *filename, void *arg,
int
(
*
process_symbol
)(
void
*
arg
,
const
char
*
name
,
char
type
,
u64
start
));
int
__ma
p_groups__create_kernel_maps
(
struct
map_groups
*
self
,
struct
map
*
vmlinux_maps
[
MAP__NR_TYPES
],
struct
dso
*
kernel
);
int
ma
p_groups__create_kernel_maps
(
struct
rb_root
*
kerninfo_root
,
pid_t
pid
);
int
ma
p_groups__create_guest_kernel_maps
(
struct
rb_root
*
kerninfo_root
);
int
__ma
chine__create_kernel_maps
(
struct
machine
*
self
,
struct
dso
*
kernel
);
int
machine__create_kernel_maps
(
struct
machine
*
self
);
int
ma
chines__create_kernel_maps
(
struct
rb_root
*
self
,
pid_t
pid
);
int
ma
chines__create_guest_kernel_maps
(
struct
rb_root
*
self
);
int
symbol__init
(
void
);
bool
symbol_type__is_a
(
char
symbol_type
,
enum
map_type
map_type
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment