Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
B
bcc
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
bcc
Commits
c1c2373f
Commit
c1c2373f
authored
Apr 20, 2016
by
Vicent Marti
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
cc: Format C and C++ code according to Google's styleguide
parent
1ad2cef6
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
676 additions
and
634 deletions
+676
-634
src/cc/bcc_elf.c
src/cc/bcc_elf.c
+169
-179
src/cc/bcc_elf.h
src/cc/bcc_elf.h
+32
-0
src/cc/bcc_proc.c
src/cc/bcc_proc.c
+206
-262
src/cc/bcc_proc.h
src/cc/bcc_proc.h
+24
-0
src/cc/bcc_syms.cc
src/cc/bcc_syms.cc
+223
-193
src/cc/bcc_syms.h
src/cc/bcc_syms.h
+22
-0
No files found.
src/cc/bcc_elf.c
View file @
c1c2373f
...
...
@@ -5,253 +5,243 @@
#include <string.h>
#include <gelf.h>
#include "bcc_
helpers
.h"
#include "bcc_
elf
.h"
#define NT_STAPSDT 3
static
int
openelf
(
const
char
*
path
,
Elf
**
elf_out
,
int
*
fd_out
)
{
if
(
elf_version
(
EV_CURRENT
)
==
EV_NONE
)
return
-
1
;
static
int
openelf
(
const
char
*
path
,
Elf
**
elf_out
,
int
*
fd_out
)
{
if
(
elf_version
(
EV_CURRENT
)
==
EV_NONE
)
return
-
1
;
*
fd_out
=
open
(
path
,
O_RDONLY
);
if
(
*
fd_out
<
0
)
return
-
1
;
*
fd_out
=
open
(
path
,
O_RDONLY
);
if
(
*
fd_out
<
0
)
return
-
1
;
*
elf_out
=
elf_begin
(
*
fd_out
,
ELF_C_READ
,
0
);
if
(
*
elf_out
==
0
)
{
close
(
*
fd_out
);
return
-
1
;
}
*
elf_out
=
elf_begin
(
*
fd_out
,
ELF_C_READ
,
0
);
if
(
*
elf_out
==
0
)
{
close
(
*
fd_out
);
return
-
1
;
}
return
0
;
return
0
;
}
static
const
char
*
parse_stapsdt_note
(
struct
bcc_elf_usdt
*
probe
,
const
char
*
desc
,
int
elf_class
)
{
if
(
elf_class
==
ELFCLASS32
)
{
probe
->
pc
=
*
((
uint32_t
*
)(
desc
));
probe
->
base_addr
=
*
((
uint32_t
*
)(
desc
+
4
));
probe
->
semaphore
=
*
((
uint32_t
*
)(
desc
+
8
));
desc
=
desc
+
12
;
}
else
{
probe
->
pc
=
*
((
uint64_t
*
)(
desc
));
probe
->
base_addr
=
*
((
uint64_t
*
)(
desc
+
8
));
probe
->
semaphore
=
*
((
uint64_t
*
)(
desc
+
16
));
desc
=
desc
+
24
;
}
probe
->
provider
=
desc
;
desc
+=
strlen
(
desc
)
+
1
;
probe
->
name
=
desc
;
desc
+=
strlen
(
desc
)
+
1
;
probe
->
arg_fmt
=
desc
;
desc
+=
strlen
(
desc
)
+
1
;
return
desc
;
static
const
char
*
parse_stapsdt_note
(
struct
bcc_elf_usdt
*
probe
,
const
char
*
desc
,
int
elf_class
)
{
if
(
elf_class
==
ELFCLASS32
)
{
probe
->
pc
=
*
((
uint32_t
*
)(
desc
));
probe
->
base_addr
=
*
((
uint32_t
*
)(
desc
+
4
));
probe
->
semaphore
=
*
((
uint32_t
*
)(
desc
+
8
));
desc
=
desc
+
12
;
}
else
{
probe
->
pc
=
*
((
uint64_t
*
)(
desc
));
probe
->
base_addr
=
*
((
uint64_t
*
)(
desc
+
8
));
probe
->
semaphore
=
*
((
uint64_t
*
)(
desc
+
16
));
desc
=
desc
+
24
;
}
probe
->
provider
=
desc
;
desc
+=
strlen
(
desc
)
+
1
;
probe
->
name
=
desc
;
desc
+=
strlen
(
desc
)
+
1
;
probe
->
arg_fmt
=
desc
;
desc
+=
strlen
(
desc
)
+
1
;
return
desc
;
}
static
int
do_note_segment
(
Elf_Scn
*
section
,
int
elf_class
,
bcc_elf_probecb
callback
,
const
char
*
binpath
,
void
*
payload
)
{
Elf_Data
*
data
=
NULL
;
static
int
do_note_segment
(
Elf_Scn
*
section
,
int
elf_class
,
bcc_elf_probecb
callback
,
const
char
*
binpath
,
void
*
payload
)
{
Elf_Data
*
data
=
NULL
;
while
((
data
=
elf_getdata
(
section
,
data
))
!=
0
)
{
size_t
offset
=
0
;
GElf_Nhdr
hdr
;
size_t
name_off
,
desc_off
;
while
((
data
=
elf_getdata
(
section
,
data
))
!=
0
)
{
size_t
offset
=
0
;
GElf_Nhdr
hdr
;
size_t
name_off
,
desc_off
;
while
((
offset
=
gelf_getnote
(
data
,
offset
,
&
hdr
,
&
name_off
,
&
desc_off
))
!=
0
)
{
const
char
*
desc
,
*
desc_end
;
struct
bcc_elf_usdt
probe
;
while
((
offset
=
gelf_getnote
(
data
,
offset
,
&
hdr
,
&
name_off
,
&
desc_off
))
!=
0
)
{
const
char
*
desc
,
*
desc_end
;
struct
bcc_elf_usdt
probe
;
if
(
hdr
.
n_type
!=
NT_STAPSDT
)
continue
;
if
(
hdr
.
n_type
!=
NT_STAPSDT
)
continue
;
if
(
hdr
.
n_namesz
!=
8
)
continue
;
if
(
hdr
.
n_namesz
!=
8
)
continue
;
if
(
memcmp
((
const
char
*
)
data
->
d_buf
+
name_off
,
"stapsdt"
,
8
)
!=
0
)
continue
;
if
(
memcmp
((
const
char
*
)
data
->
d_buf
+
name_off
,
"stapsdt"
,
8
)
!=
0
)
continue
;
desc
=
(
const
char
*
)
data
->
d_buf
+
desc_off
;
desc_end
=
desc
+
hdr
.
n_descsz
;
desc
=
(
const
char
*
)
data
->
d_buf
+
desc_off
;
desc_end
=
desc
+
hdr
.
n_descsz
;
if
(
parse_stapsdt_note
(
&
probe
,
desc
,
elf_class
)
==
desc_end
)
callback
(
binpath
,
&
probe
,
payload
);
}
}
return
0
;
if
(
parse_stapsdt_note
(
&
probe
,
desc
,
elf_class
)
==
desc_end
)
callback
(
binpath
,
&
probe
,
payload
);
}
}
return
0
;
}
static
int
listprobes
(
Elf
*
e
,
bcc_elf_probecb
callback
,
const
char
*
binpath
,
void
*
payload
)
{
Elf_Scn
*
section
=
NULL
;
size_t
stridx
;
int
elf_class
=
gelf_getclass
(
e
);
static
int
listprobes
(
Elf
*
e
,
bcc_elf_probecb
callback
,
const
char
*
binpath
,
void
*
payload
)
{
Elf_Scn
*
section
=
NULL
;
size_t
stridx
;
int
elf_class
=
gelf_getclass
(
e
);
if
(
elf_getshdrstrndx
(
e
,
&
stridx
)
!=
0
)
return
-
1
;
if
(
elf_getshdrstrndx
(
e
,
&
stridx
)
!=
0
)
return
-
1
;
while
((
section
=
elf_nextscn
(
e
,
section
))
!=
0
)
{
GElf_Shdr
header
;
char
*
name
;
while
((
section
=
elf_nextscn
(
e
,
section
))
!=
0
)
{
GElf_Shdr
header
;
char
*
name
;
if
(
!
gelf_getshdr
(
section
,
&
header
))
continue
;
if
(
!
gelf_getshdr
(
section
,
&
header
))
continue
;
if
(
header
.
sh_type
!=
SHT_NOTE
)
continue
;
if
(
header
.
sh_type
!=
SHT_NOTE
)
continue
;
name
=
elf_strptr
(
e
,
stridx
,
header
.
sh_name
);
if
(
name
&&
!
strcmp
(
name
,
".note.stapsdt"
))
{
if
(
do_note_segment
(
section
,
elf_class
,
callback
,
binpath
,
payload
)
<
0
)
return
-
1
;
}
}
name
=
elf_strptr
(
e
,
stridx
,
header
.
sh_name
);
if
(
name
&&
!
strcmp
(
name
,
".note.stapsdt"
))
{
if
(
do_note_segment
(
section
,
elf_class
,
callback
,
binpath
,
payload
)
<
0
)
return
-
1
;
}
}
return
0
;
return
0
;
}
int
bcc_elf_foreach_usdt
(
const
char
*
path
,
bcc_elf_probecb
callback
,
void
*
payload
)
{
Elf
*
e
;
int
fd
,
res
;
int
bcc_elf_foreach_usdt
(
const
char
*
path
,
bcc_elf_probecb
callback
,
void
*
payload
)
{
Elf
*
e
;
int
fd
,
res
;
if
(
openelf
(
path
,
&
e
,
&
fd
)
<
0
)
return
-
1
;
if
(
openelf
(
path
,
&
e
,
&
fd
)
<
0
)
return
-
1
;
res
=
listprobes
(
e
,
callback
,
path
,
payload
);
elf_end
(
e
);
close
(
fd
);
res
=
listprobes
(
e
,
callback
,
path
,
payload
);
elf_end
(
e
);
close
(
fd
);
return
res
;
return
res
;
}
static
int
list_in_scn
(
Elf
*
e
,
Elf_Scn
*
section
,
size_t
stridx
,
size_t
symsize
,
bcc_elf_symcb
callback
,
void
*
payload
)
{
Elf_Data
*
data
=
NULL
;
static
int
list_in_scn
(
Elf
*
e
,
Elf_Scn
*
section
,
size_t
stridx
,
size_t
symsize
,
bcc_elf_symcb
callback
,
void
*
payload
)
{
Elf_Data
*
data
=
NULL
;
while
((
data
=
elf_getdata
(
section
,
data
))
!=
0
)
{
size_t
i
,
symcount
=
data
->
d_size
/
symsize
;
while
((
data
=
elf_getdata
(
section
,
data
))
!=
0
)
{
size_t
i
,
symcount
=
data
->
d_size
/
symsize
;
if
(
data
->
d_size
%
symsize
)
return
-
1
;
if
(
data
->
d_size
%
symsize
)
return
-
1
;
for
(
i
=
0
;
i
<
symcount
;
++
i
)
{
GElf_Sym
sym
;
const
char
*
name
;
for
(
i
=
0
;
i
<
symcount
;
++
i
)
{
GElf_Sym
sym
;
const
char
*
name
;
if
(
!
gelf_getsym
(
data
,
(
int
)
i
,
&
sym
))
continue
;
if
(
!
gelf_getsym
(
data
,
(
int
)
i
,
&
sym
))
continue
;
if
((
name
=
elf_strptr
(
e
,
stridx
,
sym
.
st_name
))
==
NULL
)
continue
;
if
((
name
=
elf_strptr
(
e
,
stridx
,
sym
.
st_name
))
==
NULL
)
continue
;
if
(
callback
(
name
,
sym
.
st_value
,
sym
.
st_size
,
sym
.
st_info
,
payload
)
<
0
)
break
;
}
}
if
(
callback
(
name
,
sym
.
st_value
,
sym
.
st_size
,
sym
.
st_info
,
payload
)
<
0
)
break
;
}
}
return
0
;
return
0
;
}
static
int
listsymbols
(
Elf
*
e
,
bcc_elf_symcb
callback
,
void
*
payload
)
{
Elf_Scn
*
section
=
NULL
;
static
int
listsymbols
(
Elf
*
e
,
bcc_elf_symcb
callback
,
void
*
payload
)
{
Elf_Scn
*
section
=
NULL
;
while
((
section
=
elf_nextscn
(
e
,
section
))
!=
0
)
{
GElf_Shdr
header
;
while
((
section
=
elf_nextscn
(
e
,
section
))
!=
0
)
{
GElf_Shdr
header
;
if
(
!
gelf_getshdr
(
section
,
&
header
))
continue
;
if
(
!
gelf_getshdr
(
section
,
&
header
))
continue
;
if
(
header
.
sh_type
!=
SHT_SYMTAB
&&
header
.
sh_type
!=
SHT_DYNSYM
)
continue
;
if
(
header
.
sh_type
!=
SHT_SYMTAB
&&
header
.
sh_type
!=
SHT_DYNSYM
)
continue
;
if
(
list_in_scn
(
e
,
section
,
header
.
sh_link
,
header
.
sh_entsize
,
callback
,
payload
)
<
0
)
return
-
1
;
}
if
(
list_in_scn
(
e
,
section
,
header
.
sh_link
,
header
.
sh_entsize
,
callback
,
payload
)
<
0
)
return
-
1
;
}
return
0
;
return
0
;
}
int
bcc_elf_foreach_sym
(
const
char
*
path
,
bcc_elf_symcb
callback
,
void
*
payload
)
{
Elf
*
e
;
int
fd
,
res
;
int
bcc_elf_foreach_sym
(
const
char
*
path
,
bcc_elf_symcb
callback
,
void
*
payload
)
{
Elf
*
e
;
int
fd
,
res
;
if
(
openelf
(
path
,
&
e
,
&
fd
)
<
0
)
return
-
1
;
if
(
openelf
(
path
,
&
e
,
&
fd
)
<
0
)
return
-
1
;
res
=
listsymbols
(
e
,
callback
,
payload
);
elf_end
(
e
);
close
(
fd
);
return
res
;
res
=
listsymbols
(
e
,
callback
,
payload
);
elf_end
(
e
);
close
(
fd
);
return
res
;
}
static
int
loadaddr
(
Elf
*
e
,
uint64_t
*
addr
)
{
size_t
phnum
,
i
;
static
int
loadaddr
(
Elf
*
e
,
uint64_t
*
addr
)
{
size_t
phnum
,
i
;
if
(
elf_getphdrnum
(
e
,
&
phnum
)
!=
0
)
return
-
1
;
if
(
elf_getphdrnum
(
e
,
&
phnum
)
!=
0
)
return
-
1
;
for
(
i
=
0
;
i
<
phnum
;
++
i
)
{
GElf_Phdr
header
;
for
(
i
=
0
;
i
<
phnum
;
++
i
)
{
GElf_Phdr
header
;
if
(
!
gelf_getphdr
(
e
,
(
int
)
i
,
&
header
))
continue
;
if
(
!
gelf_getphdr
(
e
,
(
int
)
i
,
&
header
))
continue
;
if
(
header
.
p_type
!=
PT_LOAD
)
continue
;
if
(
header
.
p_type
!=
PT_LOAD
)
continue
;
*
addr
=
(
uint64_t
)
header
.
p_vaddr
;
return
0
;
}
*
addr
=
(
uint64_t
)
header
.
p_vaddr
;
return
0
;
}
return
-
1
;
return
-
1
;
}
int
bcc_elf_loadaddr
(
const
char
*
path
,
uint64_t
*
address
)
{
Elf
*
e
;
int
fd
,
res
;
int
bcc_elf_loadaddr
(
const
char
*
path
,
uint64_t
*
address
)
{
Elf
*
e
;
int
fd
,
res
;
if
(
openelf
(
path
,
&
e
,
&
fd
)
<
0
)
return
-
1
;
if
(
openelf
(
path
,
&
e
,
&
fd
)
<
0
)
return
-
1
;
res
=
loadaddr
(
e
,
address
);
elf_end
(
e
);
close
(
fd
);
res
=
loadaddr
(
e
,
address
);
elf_end
(
e
);
close
(
fd
);
return
res
;
return
res
;
}
int
bcc_elf_is_shared_obj
(
const
char
*
path
)
{
Elf
*
e
;
GElf_Ehdr
hdr
;
int
fd
,
res
=
-
1
;
int
bcc_elf_is_shared_obj
(
const
char
*
path
)
{
Elf
*
e
;
GElf_Ehdr
hdr
;
int
fd
,
res
=
-
1
;
if
(
openelf
(
path
,
&
e
,
&
fd
)
<
0
)
return
-
1
;
if
(
openelf
(
path
,
&
e
,
&
fd
)
<
0
)
return
-
1
;
if
(
gelf_getehdr
(
e
,
&
hdr
))
res
=
(
hdr
.
e_type
==
ET_DYN
);
if
(
gelf_getehdr
(
e
,
&
hdr
))
res
=
(
hdr
.
e_type
==
ET_DYN
);
elf_end
(
e
);
close
(
fd
);
elf_end
(
e
);
close
(
fd
);
return
res
;
return
res
;
}
#if 0
...
...
src/cc/bcc_elf.h
0 → 100644
View file @
c1c2373f
#ifndef LIBBCC_ELF_H
#define LIBBCC_ELF_H
#ifdef __cplusplus
extern
"C"
{
#endif
struct
bcc_elf_usdt
{
uint64_t
pc
;
uint64_t
base_addr
;
uint64_t
semaphore
;
const
char
*
provider
;
const
char
*
name
;
const
char
*
arg_fmt
;
};
typedef
void
(
*
bcc_elf_probecb
)(
const
char
*
,
const
struct
bcc_elf_usdt
*
,
void
*
);
typedef
int
(
*
bcc_elf_symcb
)(
const
char
*
,
uint64_t
,
uint64_t
,
int
,
void
*
);
int
bcc_elf_foreach_usdt
(
const
char
*
path
,
bcc_elf_probecb
callback
,
void
*
payload
);
int
bcc_elf_loadaddr
(
const
char
*
path
,
uint64_t
*
address
);
int
bcc_elf_foreach_sym
(
const
char
*
path
,
bcc_elf_symcb
callback
,
void
*
payload
);
int
bcc_elf_is_shared_obj
(
const
char
*
path
);
#ifdef __cplusplus
}
#endif
#endif
src/cc/bcc_proc.c
View file @
c1c2373f
...
...
@@ -10,121 +10,117 @@
#include <ctype.h>
#include <stdio.h>
#include "bcc_helpers.h"
#include "bcc_proc.h"
#include "bcc_elf.h"
static
bool
is_exe
(
const
char
*
path
)
{
struct
stat
s
;
if
(
access
(
path
,
X_OK
)
<
0
)
return
false
;
static
bool
is_exe
(
const
char
*
path
)
{
struct
stat
s
;
if
(
access
(
path
,
X_OK
)
<
0
)
return
false
;
if
(
stat
(
path
,
&
s
)
<
0
)
return
false
;
if
(
stat
(
path
,
&
s
)
<
0
)
return
false
;
return
S_ISREG
(
s
.
st_mode
);
return
S_ISREG
(
s
.
st_mode
);
}
char
*
bcc_procutils_which
(
const
char
*
binpath
)
{
char
buffer
[
4096
];
const
char
*
PATH
;
char
*
bcc_procutils_which
(
const
char
*
binpath
)
{
char
buffer
[
4096
];
const
char
*
PATH
;
if
(
strchr
(
binpath
,
'/'
))
return
is_exe
(
binpath
)
?
strdup
(
binpath
)
:
0
;
if
(
strchr
(
binpath
,
'/'
))
return
is_exe
(
binpath
)
?
strdup
(
binpath
)
:
0
;
if
(
!
(
PATH
=
getenv
(
"PATH"
)))
return
0
;
if
(
!
(
PATH
=
getenv
(
"PATH"
)))
return
0
;
while
(
PATH
)
{
const
char
*
next
=
strchr
(
PATH
,
':'
)
?:
strchr
(
PATH
,
'\0'
);
const
size_t
path_len
=
next
-
PATH
;
while
(
PATH
)
{
const
char
*
next
=
strchr
(
PATH
,
':'
)
?:
strchr
(
PATH
,
'\0'
);
const
size_t
path_len
=
next
-
PATH
;
if
(
path_len
)
{
memcpy
(
buffer
,
PATH
,
path_len
);
buffer
[
path_len
]
=
'/'
;
strcpy
(
buffer
+
path_len
+
1
,
binpath
);
if
(
path_len
)
{
memcpy
(
buffer
,
PATH
,
path_len
);
buffer
[
path_len
]
=
'/'
;
strcpy
(
buffer
+
path_len
+
1
,
binpath
);
if
(
is_exe
(
buffer
))
return
strdup
(
buffer
);
}
if
(
is_exe
(
buffer
))
return
strdup
(
buffer
);
}
PATH
=
*
next
?
(
next
+
1
)
:
0
;
}
PATH
=
*
next
?
(
next
+
1
)
:
0
;
}
return
0
;
return
0
;
}
int
bcc_procutils_each_module
(
int
pid
,
bcc_procutils_modulecb
callback
,
void
*
payload
)
{
char
procmap_filename
[
128
];
FILE
*
procmap
;
int
ret
;
int
bcc_procutils_each_module
(
int
pid
,
bcc_procutils_modulecb
callback
,
void
*
payload
)
{
char
procmap_filename
[
128
];
FILE
*
procmap
;
int
ret
;
sprintf
(
procmap_filename
,
"/proc/%ld/maps"
,
(
long
)
pid
);
procmap
=
fopen
(
procmap_filename
,
"r"
);
sprintf
(
procmap_filename
,
"/proc/%ld/maps"
,
(
long
)
pid
);
procmap
=
fopen
(
procmap_filename
,
"r"
);
if
(
!
procmap
)
return
-
1
;
if
(
!
procmap
)
return
-
1
;
do
{
char
endline
[
4096
];
char
perm
[
8
],
dev
[
8
];
long
long
begin
,
end
,
size
,
inode
;
do
{
char
endline
[
4096
];
char
perm
[
8
],
dev
[
8
];
long
long
begin
,
end
,
size
,
inode
;
ret
=
fscanf
(
procmap
,
"%llx-%llx %s %llx %s %llx"
,
&
begin
,
&
end
,
perm
,
&
size
,
dev
,
&
inode
);
ret
=
fscanf
(
procmap
,
"%llx-%llx %s %llx %s %llx"
,
&
begin
,
&
end
,
perm
,
&
size
,
dev
,
&
inode
);
if
(
!
fgets
(
endline
,
sizeof
(
endline
),
procmap
))
break
;
if
(
!
fgets
(
endline
,
sizeof
(
endline
),
procmap
))
break
;
if
(
ret
==
6
)
{
char
*
mapname
=
endline
;
char
*
newline
=
strchr
(
endline
,
'\n'
);
if
(
ret
==
6
)
{
char
*
mapname
=
endline
;
char
*
newline
=
strchr
(
endline
,
'\n'
);
if
(
newline
)
newline
[
0
]
=
'\0'
;
if
(
newline
)
newline
[
0
]
=
'\0'
;
while
(
isspace
(
mapname
[
0
]))
mapname
++
;
while
(
isspace
(
mapname
[
0
]))
mapname
++
;
if
(
strchr
(
perm
,
'x'
)
&&
mapname
[
0
]
&&
mapname
[
0
]
!=
'['
)
callback
(
mapname
,
(
uint64_t
)
begin
,
(
uint64_t
)
end
,
payload
);
}
}
while
(
ret
&&
ret
!=
EOF
);
if
(
strchr
(
perm
,
'x'
)
&&
mapname
[
0
]
&&
mapname
[
0
]
!=
'['
)
callback
(
mapname
,
(
uint64_t
)
begin
,
(
uint64_t
)
end
,
payload
);
}
}
while
(
ret
&&
ret
!=
EOF
);
fclose
(
procmap
);
return
0
;
fclose
(
procmap
);
return
0
;
}
int
bcc_procutils_each_ksym
(
bcc_procutils_ksymcb
callback
,
void
*
payload
)
{
char
line
[
2048
];
FILE
*
kallsyms
=
fopen
(
"/proc/kallsyms"
,
"r"
);
int
bcc_procutils_each_ksym
(
bcc_procutils_ksymcb
callback
,
void
*
payload
)
{
char
line
[
2048
];
FILE
*
kallsyms
=
fopen
(
"/proc/kallsyms"
,
"r"
);
if
(
!
kallsyms
)
return
-
1
;
if
(
!
kallsyms
)
return
-
1
;
if
(
!
fgets
(
line
,
sizeof
(
line
),
kallsyms
))
{
fclose
(
kallsyms
);
return
-
1
;
}
if
(
!
fgets
(
line
,
sizeof
(
line
),
kallsyms
))
{
fclose
(
kallsyms
);
return
-
1
;
}
while
(
fgets
(
line
,
sizeof
(
line
),
kallsyms
))
{
char
*
symname
,
*
endsym
;
unsigned
long
long
addr
;
while
(
fgets
(
line
,
sizeof
(
line
),
kallsyms
))
{
char
*
symname
,
*
endsym
;
unsigned
long
long
addr
;
addr
=
strtoull
(
line
,
&
symname
,
16
);
endsym
=
symname
=
symname
+
3
;
addr
=
strtoull
(
line
,
&
symname
,
16
);
endsym
=
symname
=
symname
+
3
;
while
(
*
endsym
&&
!
isspace
(
*
endsym
))
endsym
++
;
while
(
*
endsym
&&
!
isspace
(
*
endsym
))
endsym
++
;
*
endsym
=
'\0'
;
callback
(
symname
,
addr
,
payload
);
}
*
endsym
=
'\0'
;
callback
(
symname
,
addr
,
payload
);
}
fclose
(
kallsyms
);
return
0
;
fclose
(
kallsyms
);
return
0
;
}
#define CACHE1_HEADER "ld.so-1.7.0"
...
...
@@ -135,124 +131,124 @@ int bcc_procutils_each_ksym(bcc_procutils_ksymcb callback, void *payload)
#define CACHE2_VERSION "1.1"
struct
ld_cache1_entry
{
int32_t
flags
;
uint32_t
key
;
uint32_t
value
;
int32_t
flags
;
uint32_t
key
;
uint32_t
value
;
};
struct
ld_cache1
{
char
header
[
CACHE1_HEADER_LEN
];
uint32_t
entry_count
;
struct
ld_cache1_entry
entries
[
0
];
char
header
[
CACHE1_HEADER_LEN
];
uint32_t
entry_count
;
struct
ld_cache1_entry
entries
[
0
];
};
struct
ld_cache2_entry
{
int32_t
flags
;
uint32_t
key
;
uint32_t
value
;
uint32_t
pad1_
;
uint64_t
pad2_
;
int32_t
flags
;
uint32_t
key
;
uint32_t
value
;
uint32_t
pad1_
;
uint64_t
pad2_
;
};
struct
ld_cache2
{
char
header
[
CACHE2_HEADER_LEN
];
char
version
[
3
];
uint32_t
entry_count
;
uint32_t
string_table_len
;
uint32_t
pad_
[
5
];
struct
ld_cache2_entry
entries
[
0
];
char
header
[
CACHE2_HEADER_LEN
];
char
version
[
3
];
uint32_t
entry_count
;
uint32_t
string_table_len
;
uint32_t
pad_
[
5
];
struct
ld_cache2_entry
entries
[
0
];
};
static
int
lib_cache_count
;
static
struct
ld_lib
{
char
*
libname
;
char
*
path
;
int
flags
;
}
*
lib_cache
;
static
int
read_cache1
(
const
char
*
ld_map
)
{
struct
ld_cache1
*
ldcache
=
(
struct
ld_cache1
*
)
ld_map
;
const
char
*
ldstrings
=
(
const
char
*
)(
ldcache
->
entries
+
ldcache
->
entry_count
);
uint32_t
i
;
lib_cache
=
(
struct
ld_lib
*
)
malloc
(
ldcache
->
entry_count
*
sizeof
(
struct
ld_lib
));
lib_cache_count
=
(
int
)
ldcache
->
entry_count
;
for
(
i
=
0
;
i
<
ldcache
->
entry_count
;
++
i
)
{
const
char
*
key
=
ldstrings
+
ldcache
->
entries
[
i
].
key
;
const
char
*
val
=
ldstrings
+
ldcache
->
entries
[
i
].
value
;
const
int
flags
=
ldcache
->
entries
[
i
].
flags
;
lib_cache
[
i
].
libname
=
strdup
(
key
);
lib_cache
[
i
].
path
=
strdup
(
val
);
lib_cache
[
i
].
flags
=
flags
;
}
return
0
;
char
*
libname
;
char
*
path
;
int
flags
;
}
*
lib_cache
;
static
int
read_cache1
(
const
char
*
ld_map
)
{
struct
ld_cache1
*
ldcache
=
(
struct
ld_cache1
*
)
ld_map
;
const
char
*
ldstrings
=
(
const
char
*
)(
ldcache
->
entries
+
ldcache
->
entry_count
);
uint32_t
i
;
lib_cache
=
(
struct
ld_lib
*
)
malloc
(
ldcache
->
entry_count
*
sizeof
(
struct
ld_lib
));
lib_cache_count
=
(
int
)
ldcache
->
entry_count
;
for
(
i
=
0
;
i
<
ldcache
->
entry_count
;
++
i
)
{
const
char
*
key
=
ldstrings
+
ldcache
->
entries
[
i
].
key
;
const
char
*
val
=
ldstrings
+
ldcache
->
entries
[
i
].
value
;
const
int
flags
=
ldcache
->
entries
[
i
].
flags
;
lib_cache
[
i
].
libname
=
strdup
(
key
);
lib_cache
[
i
].
path
=
strdup
(
val
);
lib_cache
[
i
].
flags
=
flags
;
}
return
0
;
}
static
int
read_cache2
(
const
char
*
ld_map
)
{
struct
ld_cache2
*
ldcache
=
(
struct
ld_cache2
*
)
ld_map
;
uint32_t
i
;
static
int
read_cache2
(
const
char
*
ld_map
)
{
struct
ld_cache2
*
ldcache
=
(
struct
ld_cache2
*
)
ld_map
;
uint32_t
i
;
if
(
memcmp
(
ld_map
,
CACHE2_HEADER
,
CACHE2_HEADER_LEN
))
return
-
1
;
if
(
memcmp
(
ld_map
,
CACHE2_HEADER
,
CACHE2_HEADER_LEN
))
return
-
1
;
lib_cache
=
(
struct
ld_lib
*
)
malloc
(
ldcache
->
entry_count
*
sizeof
(
struct
ld_lib
));
lib_cache_count
=
(
int
)
ldcache
->
entry_count
;
lib_cache
=
(
struct
ld_lib
*
)
malloc
(
ldcache
->
entry_count
*
sizeof
(
struct
ld_lib
));
lib_cache_count
=
(
int
)
ldcache
->
entry_count
;
for
(
i
=
0
;
i
<
ldcache
->
entry_count
;
++
i
)
{
const
char
*
key
=
ld_map
+
ldcache
->
entries
[
i
].
key
;
const
char
*
val
=
ld_map
+
ldcache
->
entries
[
i
].
value
;
const
int
flags
=
ldcache
->
entries
[
i
].
flags
;
for
(
i
=
0
;
i
<
ldcache
->
entry_count
;
++
i
)
{
const
char
*
key
=
ld_map
+
ldcache
->
entries
[
i
].
key
;
const
char
*
val
=
ld_map
+
ldcache
->
entries
[
i
].
value
;
const
int
flags
=
ldcache
->
entries
[
i
].
flags
;
lib_cache
[
i
].
libname
=
strdup
(
key
);
lib_cache
[
i
].
path
=
strdup
(
val
);
lib_cache
[
i
].
flags
=
flags
;
}
return
0
;
lib_cache
[
i
].
libname
=
strdup
(
key
);
lib_cache
[
i
].
path
=
strdup
(
val
);
lib_cache
[
i
].
flags
=
flags
;
}
return
0
;
}
static
int
load_ld_cache
(
const
char
*
cache_path
)
{
struct
stat
st
;
size_t
ld_size
;
const
char
*
ld_map
;
int
ret
,
fd
=
open
(
cache_path
,
O_RDONLY
);
if
(
fd
<
0
)
return
-
1
;
if
(
fstat
(
fd
,
&
st
)
<
0
||
st
.
st_size
<
sizeof
(
struct
ld_cache1
))
{
close
(
fd
);
return
-
1
;
}
ld_size
=
st
.
st_size
;
ld_map
=
(
const
char
*
)
mmap
(
NULL
,
ld_size
,
PROT_READ
,
MAP_PRIVATE
,
fd
,
0
);
if
(
ld_map
==
MAP_FAILED
)
{
close
(
fd
);
return
-
1
;
}
if
(
memcmp
(
ld_map
,
CACHE1_HEADER
,
CACHE1_HEADER_LEN
)
==
0
)
{
const
struct
ld_cache1
*
cache1
=
(
struct
ld_cache1
*
)
ld_map
;
size_t
cache1_len
=
sizeof
(
struct
ld_cache1
)
+
(
cache1
->
entry_count
*
sizeof
(
struct
ld_cache1_entry
));
cache1_len
=
(
cache1_len
+
0x7
)
&
~
0x7ULL
;
if
(
ld_size
>
(
cache1_len
+
sizeof
(
struct
ld_cache2
)))
ret
=
read_cache2
(
ld_map
+
cache1_len
);
else
ret
=
read_cache1
(
ld_map
);
}
else
{
ret
=
read_cache2
(
ld_map
);
}
munmap
((
void
*
)
ld_map
,
ld_size
);
close
(
fd
);
return
ret
;
static
int
load_ld_cache
(
const
char
*
cache_path
)
{
struct
stat
st
;
size_t
ld_size
;
const
char
*
ld_map
;
int
ret
,
fd
=
open
(
cache_path
,
O_RDONLY
);
if
(
fd
<
0
)
return
-
1
;
if
(
fstat
(
fd
,
&
st
)
<
0
||
st
.
st_size
<
sizeof
(
struct
ld_cache1
))
{
close
(
fd
);
return
-
1
;
}
ld_size
=
st
.
st_size
;
ld_map
=
(
const
char
*
)
mmap
(
NULL
,
ld_size
,
PROT_READ
,
MAP_PRIVATE
,
fd
,
0
);
if
(
ld_map
==
MAP_FAILED
)
{
close
(
fd
);
return
-
1
;
}
if
(
memcmp
(
ld_map
,
CACHE1_HEADER
,
CACHE1_HEADER_LEN
)
==
0
)
{
const
struct
ld_cache1
*
cache1
=
(
struct
ld_cache1
*
)
ld_map
;
size_t
cache1_len
=
sizeof
(
struct
ld_cache1
)
+
(
cache1
->
entry_count
*
sizeof
(
struct
ld_cache1_entry
));
cache1_len
=
(
cache1_len
+
0x7
)
&
~
0x7ULL
;
if
(
ld_size
>
(
cache1_len
+
sizeof
(
struct
ld_cache2
)))
ret
=
read_cache2
(
ld_map
+
cache1_len
);
else
ret
=
read_cache1
(
ld_map
);
}
else
{
ret
=
read_cache2
(
ld_map
);
}
munmap
((
void
*
)
ld_map
,
ld_size
);
close
(
fd
);
return
ret
;
}
#define LD_SO_CACHE "/etc/ld.so.cache"
...
...
@@ -265,96 +261,44 @@ static int load_ld_cache(const char *cache_path)
#define ABI_S390_LIB64 0x0400
#define ABI_POWERPC_LIB64 0x0500
static
bool
match_so_flags
(
int
flags
)
{
if
((
flags
&
FLAG_TYPE_MASK
)
!=
TYPE_ELF_LIBC6
)
return
false
;
switch
(
flags
&
FLAG_ABI_MASK
)
{
case
ABI_SPARC_LIB64
:
case
ABI_IA64_LIB64
:
case
ABI_X8664_LIB64
:
case
ABI_S390_LIB64
:
case
ABI_POWERPC_LIB64
:
return
(
sizeof
(
void
*
)
==
8
);
}
return
true
;
}
const
char
*
bcc_procutils_which_so
(
const
char
*
libname
)
{
const
size_t
soname_len
=
strlen
(
libname
)
+
strlen
(
"lib.so"
);
char
soname
[
soname_len
+
1
];
int
i
;
if
(
strchr
(
libname
,
'/'
))
return
libname
;
static
bool
match_so_flags
(
int
flags
)
{
if
((
flags
&
FLAG_TYPE_MASK
)
!=
TYPE_ELF_LIBC6
)
return
false
;
if
(
lib_cache_count
<
0
)
return
NULL
;
switch
(
flags
&
FLAG_ABI_MASK
)
{
case
ABI_SPARC_LIB64
:
case
ABI_IA64_LIB64
:
case
ABI_X8664_LIB64
:
case
ABI_S390_LIB64
:
case
ABI_POWERPC_LIB64
:
return
(
sizeof
(
void
*
)
==
8
);
}
if
(
!
lib_cache_count
&&
load_ld_cache
(
LD_SO_CACHE
)
<
0
)
{
lib_cache_count
=
-
1
;
return
NULL
;
}
snprintf
(
soname
,
soname_len
+
1
,
"lib%s.so"
,
libname
);
for
(
i
=
0
;
i
<
lib_cache_count
;
++
i
)
{
if
(
!
strncmp
(
lib_cache
[
i
].
libname
,
soname
,
soname_len
)
&&
match_so_flags
(
lib_cache
[
i
].
flags
))
return
lib_cache
[
i
].
path
;
}
return
NULL
;
return
true
;
}
static
int
_find_sym
(
const
char
*
symname
,
uint64_t
addr
,
uint64_t
end
,
int
flags
,
void
*
payload
)
{
struct
bcc_symbol
*
sym
=
(
struct
bcc_symbol
*
)
payload
;
if
(
!
strcmp
(
sym
->
name
,
symname
))
{
sym
->
offset
=
addr
;
return
-
1
;
}
return
0
;
}
int
bcc_resolve_symname
(
const
char
*
module
,
const
char
*
symname
,
const
uint64_t
addr
,
struct
bcc_symbol
*
sym
)
{
uint64_t
load_addr
;
sym
->
module
=
NULL
;
sym
->
name
=
NULL
;
sym
->
offset
=
0x0
;
if
(
module
==
NULL
)
return
-
1
;
if
(
strchr
(
module
,
'/'
))
{
sym
->
module
=
module
;
}
else
{
sym
->
module
=
bcc_procutils_which_so
(
module
);
}
if
(
sym
->
module
==
NULL
)
return
-
1
;
const
char
*
bcc_procutils_which_so
(
const
char
*
libname
)
{
const
size_t
soname_len
=
strlen
(
libname
)
+
strlen
(
"lib.so"
);
char
soname
[
soname_len
+
1
];
int
i
;
if
(
bcc_elf_loadaddr
(
sym
->
module
,
&
load_addr
)
<
0
)
{
sym
->
module
=
NULL
;
return
-
1
;
}
if
(
strchr
(
libname
,
'/'
))
return
libname
;
sym
->
name
=
symname
;
sym
->
offset
=
addr
;
if
(
lib_cache_count
<
0
)
return
NULL
;
if
(
sym
->
name
&&
sym
->
offset
==
0x0
)
bcc_elf_foreach_sym
(
sym
->
module
,
_find_sym
,
sym
);
if
(
!
lib_cache_count
&&
load_ld_cache
(
LD_SO_CACHE
)
<
0
)
{
lib_cache_count
=
-
1
;
return
NULL
;
}
if
(
sym
->
offset
==
0x0
)
return
-
1
;
snprintf
(
soname
,
soname_len
+
1
,
"lib%s.so"
,
libname
);
sym
->
offset
=
(
sym
->
offset
-
load_addr
);
return
0
;
for
(
i
=
0
;
i
<
lib_cache_count
;
++
i
)
{
if
(
!
strncmp
(
lib_cache
[
i
].
libname
,
soname
,
soname_len
)
&&
match_so_flags
(
lib_cache
[
i
].
flags
))
return
lib_cache
[
i
].
path
;
}
return
NULL
;
}
src/cc/bcc_
helpers
.h
→
src/cc/bcc_
proc
.h
View file @
c1c2373f
#ifndef LIBBCC_
ELF
_H
#define LIBBCC_
ELF
_H
#ifndef LIBBCC_
PROC
_H
#define LIBBCC_
PROC
_H
#ifdef __cplusplus
extern
"C"
{
#endif
#include <stdint.h>
struct
bcc_symbol
{
const
char
*
name
;
const
char
*
module
;
uint64_t
offset
;
};
struct
bcc_elf_usdt
{
uint64_t
pc
;
uint64_t
base_addr
;
uint64_t
semaphore
;
const
char
*
provider
;
const
char
*
name
;
const
char
*
arg_fmt
;
};
typedef
void
(
*
bcc_elf_probecb
)(
const
char
*
,
const
struct
bcc_elf_usdt
*
,
void
*
);
typedef
int
(
*
bcc_elf_symcb
)(
const
char
*
,
uint64_t
,
uint64_t
,
int
,
void
*
);
int
bcc_elf_foreach_usdt
(
const
char
*
path
,
bcc_elf_probecb
callback
,
void
*
payload
);
int
bcc_elf_loadaddr
(
const
char
*
path
,
uint64_t
*
address
);
int
bcc_elf_foreach_sym
(
const
char
*
path
,
bcc_elf_symcb
callback
,
void
*
payload
);
int
bcc_elf_is_shared_obj
(
const
char
*
path
);
typedef
void
(
*
bcc_procutils_modulecb
)(
const
char
*
,
uint64_t
,
uint64_t
,
void
*
);
typedef
void
(
*
bcc_procutils_modulecb
)(
const
char
*
,
uint64_t
,
uint64_t
,
void
*
);
typedef
void
(
*
bcc_procutils_ksymcb
)(
const
char
*
,
uint64_t
,
void
*
);
const
char
*
bcc_procutils_which_so
(
const
char
*
libname
);
char
*
bcc_procutils_which
(
const
char
*
binpath
);
int
bcc_procutils_each_module
(
int
pid
,
bcc_procutils_modulecb
callback
,
void
*
payload
);
int
bcc_procutils_each_module
(
int
pid
,
bcc_procutils_modulecb
callback
,
void
*
payload
);
int
bcc_procutils_each_ksym
(
bcc_procutils_ksymcb
callback
,
void
*
payload
);
int
bcc_resolve_symname
(
const
char
*
module
,
const
char
*
symname
,
const
uint64_t
addr
,
struct
bcc_symbol
*
sym
);
void
*
bcc_symcache_new
(
int
pid
);
int
bcc_symcache_resolve
(
void
*
symcache
,
uint64_t
addr
,
struct
bcc_symbol
*
sym
);
int
bcc_symcache_resolve_name
(
void
*
resolver
,
const
char
*
name
,
uint64_t
*
addr
);
void
bcc_symcache_refresh
(
void
*
resolver
);
int
bcc_resolve_symname
(
const
char
*
module
,
const
char
*
symname
,
const
uint64_t
addr
,
struct
bcc_symbol
*
sym
);
#ifdef __cplusplus
}
...
...
src/cc/bcc_syms.cc
View file @
c1c2373f
...
...
@@ -6,253 +6,283 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include "bcc_helpers.h"
#include "bcc_syms.h"
#include "bcc_proc.h"
#include "bcc_elf.h"
class
SymbolCache
{
public:
virtual
void
refresh
()
=
0
;
virtual
bool
resolve_addr
(
uint64_t
addr
,
struct
bcc_symbol
*
sym
)
=
0
;
virtual
bool
resolve_name
(
const
char
*
name
,
uint64_t
*
addr
)
=
0
;
public:
virtual
void
refresh
()
=
0
;
virtual
bool
resolve_addr
(
uint64_t
addr
,
struct
bcc_symbol
*
sym
)
=
0
;
virtual
bool
resolve_name
(
const
char
*
name
,
uint64_t
*
addr
)
=
0
;
};
class
KSyms
:
SymbolCache
{
struct
Symbol
{
Symbol
(
const
char
*
name
,
uint64_t
addr
)
:
name
(
name
),
addr
(
addr
)
{}
std
::
string
name
;
uint64_t
addr
;
bool
operator
<
(
const
Symbol
&
rhs
)
const
{
return
addr
<
rhs
.
addr
;
}
};
std
::
vector
<
Symbol
>
_syms
;
std
::
unordered_map
<
std
::
string
,
uint64_t
>
_sym_names
;
static
void
_add_symbol
(
const
char
*
,
uint64_t
,
void
*
);
public:
virtual
bool
resolve_addr
(
uint64_t
addr
,
struct
bcc_symbol
*
sym
);
virtual
bool
resolve_name
(
const
char
*
name
,
uint64_t
*
addr
);
virtual
void
refresh
()
{
if
(
_syms
.
empty
())
{
bcc_procutils_each_ksym
(
_add_symbol
,
this
);
std
::
sort
(
_syms
.
begin
(),
_syms
.
end
());
}
}
struct
Symbol
{
Symbol
(
const
char
*
name
,
uint64_t
addr
)
:
name
(
name
),
addr
(
addr
)
{}
std
::
string
name
;
uint64_t
addr
;
bool
operator
<
(
const
Symbol
&
rhs
)
const
{
return
addr
<
rhs
.
addr
;
}
};
std
::
vector
<
Symbol
>
syms_
;
std
::
unordered_map
<
std
::
string
,
uint64_t
>
symnames_
;
static
void
_add_symbol
(
const
char
*
,
uint64_t
,
void
*
);
public:
virtual
bool
resolve_addr
(
uint64_t
addr
,
struct
bcc_symbol
*
sym
);
virtual
bool
resolve_name
(
const
char
*
name
,
uint64_t
*
addr
);
virtual
void
refresh
()
{
if
(
syms_
.
empty
())
{
bcc_procutils_each_ksym
(
_add_symbol
,
this
);
std
::
sort
(
syms_
.
begin
(),
syms_
.
end
());
}
}
};
void
KSyms
::
_add_symbol
(
const
char
*
symname
,
uint64_t
addr
,
void
*
p
)
{
KSyms
*
ks
=
static_cast
<
KSyms
*>
(
p
);
ks
->
_syms
.
emplace_back
(
symname
,
addr
);
void
KSyms
::
_add_symbol
(
const
char
*
symname
,
uint64_t
addr
,
void
*
p
)
{
KSyms
*
ks
=
static_cast
<
KSyms
*>
(
p
);
ks
->
syms_
.
emplace_back
(
symname
,
addr
);
}
bool
KSyms
::
resolve_addr
(
uint64_t
addr
,
struct
bcc_symbol
*
sym
)
{
refresh
();
if
(
_syms
.
empty
())
{
sym
->
name
=
nullptr
;
sym
->
module
=
nullptr
;
sym
->
offset
=
0x0
;
return
false
;
}
auto
it
=
std
::
upper_bound
(
_syms
.
begin
(),
_syms
.
end
(),
Symbol
(
""
,
addr
))
-
1
;
sym
->
name
=
(
*
it
).
name
.
c_str
();
sym
->
module
=
"[kernel]"
;
sym
->
offset
=
addr
-
(
*
it
).
addr
;
return
true
;
bool
KSyms
::
resolve_addr
(
uint64_t
addr
,
struct
bcc_symbol
*
sym
)
{
refresh
();
if
(
syms_
.
empty
())
{
sym
->
name
=
nullptr
;
sym
->
module
=
nullptr
;
sym
->
offset
=
0x0
;
return
false
;
}
auto
it
=
std
::
upper_bound
(
syms_
.
begin
(),
syms_
.
end
(),
Symbol
(
""
,
addr
))
-
1
;
sym
->
name
=
(
*
it
).
name
.
c_str
();
sym
->
module
=
"[kernel]"
;
sym
->
offset
=
addr
-
(
*
it
).
addr
;
return
true
;
}
bool
KSyms
::
resolve_name
(
const
char
*
name
,
uint64_t
*
addr
)
{
refresh
();
bool
KSyms
::
resolve_name
(
const
char
*
name
,
uint64_t
*
addr
)
{
refresh
();
if
(
_syms
.
size
()
!=
_sym_names
.
size
())
{
_sym_names
.
clear
();
for
(
Symbol
&
sym
:
_syms
)
{
_sym_names
[
sym
.
name
]
=
sym
.
addr
;
}
}
if
(
syms_
.
size
()
!=
symnames_
.
size
())
{
symnames_
.
clear
();
for
(
Symbol
&
sym
:
syms_
)
{
symnames_
[
sym
.
name
]
=
sym
.
addr
;
}
}
auto
it
=
_sym_names
.
find
(
name
);
if
(
it
==
_sym_names
.
end
())
return
false
;
auto
it
=
symnames_
.
find
(
name
);
if
(
it
==
symnames_
.
end
())
return
false
;
*
addr
=
it
->
second
;
return
true
;
*
addr
=
it
->
second
;
return
true
;
}
class
ProcStat
{
std
::
string
_procfs
;
ino_t
_inode
;
ino_t
get_inode
()
{
struct
stat
s
;
return
(
!
stat
(
_procfs
.
c_str
(),
&
s
))
?
s
.
st_ino
:
-
1
;
}
public:
ProcStat
(
int
pid
)
:
_inode
(
-
1
)
{
char
buffer
[
128
];
snprintf
(
buffer
,
sizeof
(
buffer
),
"/proc/%d/exe"
,
pid
);
_procfs
=
buffer
;
}
bool
is_stale
()
{
return
_inode
!=
get_inode
();
}
void
reset
()
{
_inode
=
get_inode
();
}
std
::
string
procfs_
;
ino_t
inode_
;
ino_t
getinode_
()
{
struct
stat
s
;
return
(
!
stat
(
procfs_
.
c_str
(),
&
s
))
?
s
.
st_ino
:
-
1
;
}
public:
ProcStat
(
int
pid
)
:
inode_
(
-
1
)
{
char
buffer
[
128
];
snprintf
(
buffer
,
sizeof
(
buffer
),
"/proc/%d/exe"
,
pid
);
procfs_
=
buffer
;
}
bool
is_stale
()
{
return
inode_
!=
getinode_
();
}
void
reset
()
{
inode_
=
getinode_
();
}
};
static
bool
has_suffix
(
const
std
::
string
&
str
,
const
std
::
string
&
suffix
)
{
return
str
.
size
()
>=
suffix
.
size
()
&&
str
.
compare
(
str
.
size
()
-
suffix
.
size
(),
suffix
.
size
(),
suffix
)
==
0
;
static
bool
has_suffix
(
const
std
::
string
&
str
,
const
std
::
string
&
suffix
)
{
return
str
.
size
()
>=
suffix
.
size
()
&&
str
.
compare
(
str
.
size
()
-
suffix
.
size
(),
suffix
.
size
(),
suffix
)
==
0
;
}
class
ProcSyms
:
SymbolCache
{
struct
Symbol
{
Symbol
(
const
char
*
name
,
uint64_t
start
,
uint64_t
size
,
int
flags
=
0
)
:
name
(
name
),
start
(
start
),
size
(
size
),
flags
(
flags
)
{}
std
::
string
name
;
uint64_t
start
;
uint64_t
size
;
int
flags
;
};
struct
Module
{
Module
(
const
char
*
name
,
uint64_t
start
,
uint64_t
end
)
:
_name
(
name
),
_start
(
start
),
_end
(
end
)
{}
std
::
string
_name
;
uint64_t
_start
;
uint64_t
_end
;
std
::
vector
<
Symbol
>
_syms
;
void
load_sym_table
();
bool
decode_sym
(
uint64_t
addr
,
struct
bcc_symbol
*
sym
);
bool
is_so
()
{
return
has_suffix
(
_name
,
".so"
);
}
static
int
_add_symbol
(
const
char
*
symname
,
uint64_t
start
,
uint64_t
end
,
int
flags
,
void
*
p
);
};
int
_pid
;
std
::
vector
<
Module
>
_modules
;
ProcStat
_procstat
;
static
void
_add_module
(
const
char
*
,
uint64_t
,
uint64_t
,
void
*
);
public:
ProcSyms
(
int
pid
);
virtual
void
refresh
();
virtual
bool
resolve_addr
(
uint64_t
addr
,
struct
bcc_symbol
*
sym
);
virtual
bool
resolve_name
(
const
char
*
name
,
uint64_t
*
addr
);
struct
Symbol
{
Symbol
(
const
char
*
name
,
uint64_t
start
,
uint64_t
size
,
int
flags
=
0
)
:
name
(
name
),
start
(
start
),
size
(
size
),
flags
(
flags
)
{}
std
::
string
name
;
uint64_t
start
;
uint64_t
size
;
int
flags
;
};
struct
Module
{
Module
(
const
char
*
name
,
uint64_t
start
,
uint64_t
end
)
:
name_
(
name
),
start_
(
start
),
end_
(
end
)
{}
std
::
string
name_
;
uint64_t
start_
;
uint64_t
end_
;
std
::
vector
<
Symbol
>
syms_
;
void
load_sym_table
();
bool
decode_sym
(
uint64_t
addr
,
struct
bcc_symbol
*
sym
);
bool
is_so
()
{
return
has_suffix
(
name_
,
".so"
);
}
static
int
_add_symbol
(
const
char
*
symname
,
uint64_t
start
,
uint64_t
end
,
int
flags
,
void
*
p
);
};
int
pid_
;
std
::
vector
<
Module
>
modules_
;
ProcStat
procstat_
;
static
void
_add_module
(
const
char
*
,
uint64_t
,
uint64_t
,
void
*
);
public:
ProcSyms
(
int
pid
);
virtual
void
refresh
();
virtual
bool
resolve_addr
(
uint64_t
addr
,
struct
bcc_symbol
*
sym
);
virtual
bool
resolve_name
(
const
char
*
name
,
uint64_t
*
addr
);
};
ProcSyms
::
ProcSyms
(
int
pid
)
:
_pid
(
pid
),
_procstat
(
pid
)
{
refresh
();
}
ProcSyms
::
ProcSyms
(
int
pid
)
:
pid_
(
pid
),
procstat_
(
pid
)
{
refresh
();
}
void
ProcSyms
::
refresh
()
{
_modules
.
clear
();
bcc_procutils_each_module
(
_pid
,
_add_module
,
this
);
_procstat
.
reset
();
void
ProcSyms
::
refresh
()
{
modules_
.
clear
();
bcc_procutils_each_module
(
pid_
,
_add_module
,
this
);
procstat_
.
reset
();
}
void
ProcSyms
::
_add_module
(
const
char
*
modname
,
uint64_t
start
,
uint64_t
end
,
void
*
payload
)
{
ProcSyms
*
ps
=
static_cast
<
ProcSyms
*>
(
payload
);
ps
->
_modules
.
emplace_back
(
modname
,
start
,
end
);
void
ProcSyms
::
_add_module
(
const
char
*
modname
,
uint64_t
start
,
uint64_t
end
,
void
*
payload
)
{
ProcSyms
*
ps
=
static_cast
<
ProcSyms
*>
(
payload
);
ps
->
modules_
.
emplace_back
(
modname
,
start
,
end
);
}
bool
ProcSyms
::
resolve_addr
(
uint64_t
addr
,
struct
bcc_symbol
*
sym
)
{
if
(
_procstat
.
is_stale
())
refresh
();
bool
ProcSyms
::
resolve_addr
(
uint64_t
addr
,
struct
bcc_symbol
*
sym
)
{
if
(
procstat_
.
is_stale
())
refresh
();
sym
->
module
=
nullptr
;
sym
->
name
=
nullptr
;
sym
->
offset
=
0x0
;
sym
->
module
=
nullptr
;
sym
->
name
=
nullptr
;
sym
->
offset
=
0x0
;
for
(
Module
&
mod
:
_modules
)
{
if
(
addr
>=
mod
.
_start
&&
addr
<=
mod
.
_end
)
return
mod
.
decode_sym
(
addr
,
sym
);
}
return
false
;
for
(
Module
&
mod
:
modules_
)
{
if
(
addr
>=
mod
.
start_
&&
addr
<=
mod
.
end_
)
return
mod
.
decode_sym
(
addr
,
sym
);
}
return
false
;
}
bool
ProcSyms
::
resolve_name
(
const
char
*
name
,
uint64_t
*
addr
)
{
*
addr
=
0x0
;
return
false
;
bool
ProcSyms
::
resolve_name
(
const
char
*
name
,
uint64_t
*
addr
)
{
*
addr
=
0x0
;
return
false
;
}
int
ProcSyms
::
Module
::
_add_symbol
(
const
char
*
symname
,
uint64_t
start
,
uint64_t
end
,
int
flags
,
void
*
p
)
{
Module
*
m
=
static_cast
<
Module
*>
(
p
);
m
->
_syms
.
emplace_back
(
symname
,
start
,
end
,
flags
);
return
0
;
int
ProcSyms
::
Module
::
_add_symbol
(
const
char
*
symname
,
uint64_t
start
,
uint64_t
end
,
int
flags
,
void
*
p
)
{
Module
*
m
=
static_cast
<
Module
*>
(
p
);
m
->
syms_
.
emplace_back
(
symname
,
start
,
end
,
flags
);
return
0
;
}
void
ProcSyms
::
Module
::
load_sym_table
()
{
if
(
_syms
.
size
())
return
;
void
ProcSyms
::
Module
::
load_sym_table
()
{
if
(
syms_
.
size
())
return
;
bcc_elf_foreach_sym
(
_name
.
c_str
(),
_add_symbol
,
this
);
bcc_elf_foreach_sym
(
name_
.
c_str
(),
_add_symbol
,
this
);
}
bool
ProcSyms
::
Module
::
decode_sym
(
uint64_t
addr
,
struct
bcc_symbol
*
sym
)
{
uint64_t
offset
=
is_so
()
?
(
addr
-
_start
)
:
addr
;
bool
ProcSyms
::
Module
::
decode_sym
(
uint64_t
addr
,
struct
bcc_symbol
*
sym
)
{
uint64_t
offset
=
is_so
()
?
(
addr
-
start_
)
:
addr
;
load_sym_table
();
load_sym_table
();
sym
->
module
=
_name
.
c_str
();
sym
->
offset
=
offset
;
sym
->
module
=
name_
.
c_str
();
sym
->
offset
=
offset
;
for
(
Symbol
&
s
:
_syms
)
{
if
(
offset
>=
s
.
start
&&
offset
<=
(
s
.
start
+
s
.
size
))
{
sym
->
name
=
s
.
name
.
c_str
();
sym
->
offset
=
(
offset
-
s
.
start
);
return
true
;
}
}
return
false
;
for
(
Symbol
&
s
:
syms_
)
{
if
(
offset
>=
s
.
start
&&
offset
<=
(
s
.
start
+
s
.
size
))
{
sym
->
name
=
s
.
name
.
c_str
();
sym
->
offset
=
(
offset
-
s
.
start
);
return
true
;
}
}
return
false
;
}
extern
"C"
{
void
*
bcc_symcache_new
(
int
pid
)
{
if
(
pid
<
0
)
return
static_cast
<
void
*>
(
new
KSyms
());
return
static_cast
<
void
*>
(
new
ProcSyms
(
pid
));
void
*
bcc_symcache_new
(
int
pid
)
{
if
(
pid
<
0
)
return
static_cast
<
void
*>
(
new
KSyms
());
return
static_cast
<
void
*>
(
new
ProcSyms
(
pid
));
}
int
bcc_symcache_resolve
(
void
*
resolver
,
uint64_t
addr
,
struct
bcc_symbol
*
sym
)
{
SymbolCache
*
cache
=
static_cast
<
SymbolCache
*>
(
resolver
);
return
cache
->
resolve_addr
(
addr
,
sym
)
?
0
:
-
1
;
}
int
bcc_symcache_resolve
(
void
*
resolver
,
uint64_t
addr
,
struct
bcc_symbol
*
sym
)
{
SymbolCache
*
cache
=
static_cast
<
SymbolCache
*>
(
resolver
);
return
cache
->
resolve_addr
(
addr
,
sym
)
?
0
:
-
1
;
int
bcc_symcache_resolve
_name
(
void
*
resolver
,
const
char
*
name
,
uint64_t
*
addr
)
{
SymbolCache
*
cache
=
static_cast
<
SymbolCache
*>
(
resolver
);
return
cache
->
resolve_name
(
name
,
addr
)
?
0
:
-
1
;
}
int
bcc_symcache_resolve_name
(
void
*
resolver
,
const
char
*
name
,
uint64_t
*
addr
)
{
SymbolCache
*
cache
=
static_cast
<
SymbolCache
*>
(
resolver
);
return
cache
->
resolve_name
(
name
,
addr
)
?
0
:
-
1
;
void
bcc_symcache_refresh
(
void
*
resolver
)
{
SymbolCache
*
cache
=
static_cast
<
SymbolCache
*>
(
resolver
);
cache
->
refresh
();
}
void
bcc_symcache_refresh
(
void
*
resolver
)
{
SymbolCache
*
cache
=
static_cast
<
SymbolCache
*>
(
resolver
);
cache
->
refresh
();
static
int
_find_sym
(
const
char
*
symname
,
uint64_t
addr
,
uint64_t
end
,
int
flags
,
void
*
payload
)
{
struct
bcc_symbol
*
sym
=
(
struct
bcc_symbol
*
)
payload
;
if
(
!
strcmp
(
sym
->
name
,
symname
))
{
sym
->
offset
=
addr
;
return
-
1
;
}
return
0
;
}
int
bcc_resolve_symname
(
const
char
*
module
,
const
char
*
symname
,
const
uint64_t
addr
,
struct
bcc_symbol
*
sym
)
{
uint64_t
load_addr
;
sym
->
module
=
NULL
;
sym
->
name
=
NULL
;
sym
->
offset
=
0x0
;
if
(
module
==
NULL
)
return
-
1
;
if
(
strchr
(
module
,
'/'
))
{
sym
->
module
=
module
;
}
else
{
sym
->
module
=
bcc_procutils_which_so
(
module
);
}
if
(
sym
->
module
==
NULL
)
return
-
1
;
if
(
bcc_elf_loadaddr
(
sym
->
module
,
&
load_addr
)
<
0
)
{
sym
->
module
=
NULL
;
return
-
1
;
}
sym
->
name
=
symname
;
sym
->
offset
=
addr
;
if
(
sym
->
name
&&
sym
->
offset
==
0x0
)
bcc_elf_foreach_sym
(
sym
->
module
,
_find_sym
,
sym
);
if
(
sym
->
offset
==
0x0
)
return
-
1
;
sym
->
offset
=
(
sym
->
offset
-
load_addr
);
return
0
;
}
}
src/cc/bcc_syms.h
0 → 100644
View file @
c1c2373f
#ifndef LIBBCC_SYMS_H
#define LIBBCC_SYMS_H
#ifdef __cplusplus
extern
"C"
{
#endif
struct
bcc_symbol
{
const
char
*
name
;
const
char
*
module
;
uint64_t
offset
;
};
void
*
bcc_symcache_new
(
int
pid
);
int
bcc_symcache_resolve
(
void
*
symcache
,
uint64_t
addr
,
struct
bcc_symbol
*
sym
);
int
bcc_symcache_resolve_name
(
void
*
resolver
,
const
char
*
name
,
uint64_t
*
addr
);
void
bcc_symcache_refresh
(
void
*
resolver
);
#ifdef __cplusplus
}
#endif
#endif
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