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
Show 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,11 +5,10 @@
...
@@ -5,11 +5,10 @@
#include <string.h>
#include <string.h>
#include <gelf.h>
#include <gelf.h>
#include "bcc_
helpers
.h"
#include "bcc_
elf
.h"
#define NT_STAPSDT 3
#define NT_STAPSDT 3
static
int
openelf
(
const
char
*
path
,
Elf
**
elf_out
,
int
*
fd_out
)
static
int
openelf
(
const
char
*
path
,
Elf
**
elf_out
,
int
*
fd_out
)
{
{
if
(
elf_version
(
EV_CURRENT
)
==
EV_NONE
)
if
(
elf_version
(
EV_CURRENT
)
==
EV_NONE
)
return
-
1
;
return
-
1
;
...
@@ -26,9 +25,8 @@ static int openelf(const char *path, Elf **elf_out, int *fd_out)
...
@@ -26,9 +25,8 @@ static int openelf(const char *path, Elf **elf_out, int *fd_out)
return
0
;
return
0
;
}
}
static
const
char
*
static
const
char
*
parse_stapsdt_note
(
struct
bcc_elf_usdt
*
probe
,
parse_stapsdt_note
(
struct
bcc_elf_usdt
*
probe
,
const
char
*
desc
,
int
elf_class
)
const
char
*
desc
,
int
elf_class
)
{
{
if
(
elf_class
==
ELFCLASS32
)
{
if
(
elf_class
==
ELFCLASS32
)
{
probe
->
pc
=
*
((
uint32_t
*
)(
desc
));
probe
->
pc
=
*
((
uint32_t
*
)(
desc
));
probe
->
base_addr
=
*
((
uint32_t
*
)(
desc
+
4
));
probe
->
base_addr
=
*
((
uint32_t
*
)(
desc
+
4
));
...
@@ -53,10 +51,9 @@ parse_stapsdt_note(struct bcc_elf_usdt *probe, const char *desc, int elf_class)
...
@@ -53,10 +51,9 @@ parse_stapsdt_note(struct bcc_elf_usdt *probe, const char *desc, int elf_class)
return
desc
;
return
desc
;
}
}
static
int
do_note_segment
(
static
int
do_note_segment
(
Elf_Scn
*
section
,
int
elf_class
,
Elf_Scn
*
section
,
int
elf_class
,
bcc_elf_probecb
callback
,
const
char
*
binpath
,
bcc_elf_probecb
callback
,
const
char
*
binpath
,
void
*
payload
)
void
*
payload
)
{
{
Elf_Data
*
data
=
NULL
;
Elf_Data
*
data
=
NULL
;
while
((
data
=
elf_getdata
(
section
,
data
))
!=
0
)
{
while
((
data
=
elf_getdata
(
section
,
data
))
!=
0
)
{
...
@@ -64,7 +61,8 @@ static int do_note_segment(
...
@@ -64,7 +61,8 @@ static int do_note_segment(
GElf_Nhdr
hdr
;
GElf_Nhdr
hdr
;
size_t
name_off
,
desc_off
;
size_t
name_off
,
desc_off
;
while
((
offset
=
gelf_getnote
(
data
,
offset
,
&
hdr
,
&
name_off
,
&
desc_off
))
!=
0
)
{
while
((
offset
=
gelf_getnote
(
data
,
offset
,
&
hdr
,
&
name_off
,
&
desc_off
))
!=
0
)
{
const
char
*
desc
,
*
desc_end
;
const
char
*
desc
,
*
desc_end
;
struct
bcc_elf_usdt
probe
;
struct
bcc_elf_usdt
probe
;
...
@@ -87,8 +85,8 @@ static int do_note_segment(
...
@@ -87,8 +85,8 @@ static int do_note_segment(
return
0
;
return
0
;
}
}
static
int
listprobes
(
Elf
*
e
,
bcc_elf_probecb
callback
,
const
char
*
binpath
,
void
*
payload
)
static
int
listprobes
(
Elf
*
e
,
bcc_elf_probecb
callback
,
const
char
*
binpath
,
{
void
*
payload
)
{
Elf_Scn
*
section
=
NULL
;
Elf_Scn
*
section
=
NULL
;
size_t
stridx
;
size_t
stridx
;
int
elf_class
=
gelf_getclass
(
e
);
int
elf_class
=
gelf_getclass
(
e
);
...
@@ -116,8 +114,8 @@ static int listprobes(Elf *e, bcc_elf_probecb callback, const char *binpath, voi
...
@@ -116,8 +114,8 @@ static int listprobes(Elf *e, bcc_elf_probecb callback, const char *binpath, voi
return
0
;
return
0
;
}
}
int
bcc_elf_foreach_usdt
(
const
char
*
path
,
bcc_elf_probecb
callback
,
void
*
payload
)
int
bcc_elf_foreach_usdt
(
const
char
*
path
,
bcc_elf_probecb
callback
,
{
void
*
payload
)
{
Elf
*
e
;
Elf
*
e
;
int
fd
,
res
;
int
fd
,
res
;
...
@@ -131,12 +129,8 @@ int bcc_elf_foreach_usdt(const char *path, bcc_elf_probecb callback, void *paylo
...
@@ -131,12 +129,8 @@ int bcc_elf_foreach_usdt(const char *path, bcc_elf_probecb callback, void *paylo
return
res
;
return
res
;
}
}
static
int
list_in_scn
(
Elf
*
e
,
Elf_Scn
*
section
,
size_t
stridx
,
size_t
symsize
,
static
int
list_in_scn
(
bcc_elf_symcb
callback
,
void
*
payload
)
{
Elf
*
e
,
Elf_Scn
*
section
,
size_t
stridx
,
size_t
symsize
,
bcc_elf_symcb
callback
,
void
*
payload
)
{
Elf_Data
*
data
=
NULL
;
Elf_Data
*
data
=
NULL
;
while
((
data
=
elf_getdata
(
section
,
data
))
!=
0
)
{
while
((
data
=
elf_getdata
(
section
,
data
))
!=
0
)
{
...
@@ -163,8 +157,7 @@ static int list_in_scn(
...
@@ -163,8 +157,7 @@ static int list_in_scn(
return
0
;
return
0
;
}
}
static
int
listsymbols
(
Elf
*
e
,
bcc_elf_symcb
callback
,
void
*
payload
)
static
int
listsymbols
(
Elf
*
e
,
bcc_elf_symcb
callback
,
void
*
payload
)
{
{
Elf_Scn
*
section
=
NULL
;
Elf_Scn
*
section
=
NULL
;
while
((
section
=
elf_nextscn
(
e
,
section
))
!=
0
)
{
while
((
section
=
elf_nextscn
(
e
,
section
))
!=
0
)
{
...
@@ -176,16 +169,16 @@ static int listsymbols(Elf *e, bcc_elf_symcb callback, void *payload)
...
@@ -176,16 +169,16 @@ static int listsymbols(Elf *e, bcc_elf_symcb callback, void *payload)
if
(
header
.
sh_type
!=
SHT_SYMTAB
&&
header
.
sh_type
!=
SHT_DYNSYM
)
if
(
header
.
sh_type
!=
SHT_SYMTAB
&&
header
.
sh_type
!=
SHT_DYNSYM
)
continue
;
continue
;
if
(
list_in_scn
(
e
,
section
,
if
(
list_in_scn
(
e
,
section
,
header
.
sh_link
,
header
.
sh_entsize
,
callback
,
header
.
sh_link
,
header
.
sh_entsize
,
callback
,
payload
)
<
0
)
payload
)
<
0
)
return
-
1
;
return
-
1
;
}
}
return
0
;
return
0
;
}
}
int
bcc_elf_foreach_sym
(
const
char
*
path
,
bcc_elf_symcb
callback
,
void
*
payload
)
int
bcc_elf_foreach_sym
(
const
char
*
path
,
bcc_elf_symcb
callback
,
{
void
*
payload
)
{
Elf
*
e
;
Elf
*
e
;
int
fd
,
res
;
int
fd
,
res
;
...
@@ -198,8 +191,7 @@ int bcc_elf_foreach_sym(const char *path, bcc_elf_symcb callback, void *payload)
...
@@ -198,8 +191,7 @@ int bcc_elf_foreach_sym(const char *path, bcc_elf_symcb callback, void *payload)
return
res
;
return
res
;
}
}
static
int
loadaddr
(
Elf
*
e
,
uint64_t
*
addr
)
static
int
loadaddr
(
Elf
*
e
,
uint64_t
*
addr
)
{
{
size_t
phnum
,
i
;
size_t
phnum
,
i
;
if
(
elf_getphdrnum
(
e
,
&
phnum
)
!=
0
)
if
(
elf_getphdrnum
(
e
,
&
phnum
)
!=
0
)
...
@@ -221,8 +213,7 @@ static int loadaddr(Elf *e, uint64_t *addr)
...
@@ -221,8 +213,7 @@ static int loadaddr(Elf *e, uint64_t *addr)
return
-
1
;
return
-
1
;
}
}
int
bcc_elf_loadaddr
(
const
char
*
path
,
uint64_t
*
address
)
int
bcc_elf_loadaddr
(
const
char
*
path
,
uint64_t
*
address
)
{
{
Elf
*
e
;
Elf
*
e
;
int
fd
,
res
;
int
fd
,
res
;
...
@@ -236,8 +227,7 @@ int bcc_elf_loadaddr(const char *path, uint64_t *address)
...
@@ -236,8 +227,7 @@ int bcc_elf_loadaddr(const char *path, uint64_t *address)
return
res
;
return
res
;
}
}
int
bcc_elf_is_shared_obj
(
const
char
*
path
)
int
bcc_elf_is_shared_obj
(
const
char
*
path
)
{
{
Elf
*
e
;
Elf
*
e
;
GElf_Ehdr
hdr
;
GElf_Ehdr
hdr
;
int
fd
,
res
=
-
1
;
int
fd
,
res
=
-
1
;
...
...
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,10 +10,10 @@
...
@@ -10,10 +10,10 @@
#include <ctype.h>
#include <ctype.h>
#include <stdio.h>
#include <stdio.h>
#include "bcc_helpers.h"
#include "bcc_proc.h"
#include "bcc_elf.h"
static
bool
is_exe
(
const
char
*
path
)
static
bool
is_exe
(
const
char
*
path
)
{
{
struct
stat
s
;
struct
stat
s
;
if
(
access
(
path
,
X_OK
)
<
0
)
if
(
access
(
path
,
X_OK
)
<
0
)
return
false
;
return
false
;
...
@@ -24,8 +24,7 @@ static bool is_exe(const char *path)
...
@@ -24,8 +24,7 @@ static bool is_exe(const char *path)
return
S_ISREG
(
s
.
st_mode
);
return
S_ISREG
(
s
.
st_mode
);
}
}
char
*
bcc_procutils_which
(
const
char
*
binpath
)
char
*
bcc_procutils_which
(
const
char
*
binpath
)
{
{
char
buffer
[
4096
];
char
buffer
[
4096
];
const
char
*
PATH
;
const
char
*
PATH
;
...
@@ -54,8 +53,8 @@ char *bcc_procutils_which(const char *binpath)
...
@@ -54,8 +53,8 @@ char *bcc_procutils_which(const char *binpath)
return
0
;
return
0
;
}
}
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
)
{
char
procmap_filename
[
128
];
char
procmap_filename
[
128
];
FILE
*
procmap
;
FILE
*
procmap
;
int
ret
;
int
ret
;
...
@@ -71,8 +70,8 @@ int bcc_procutils_each_module(int pid, bcc_procutils_modulecb callback, void *pa
...
@@ -71,8 +70,8 @@ int bcc_procutils_each_module(int pid, bcc_procutils_modulecb callback, void *pa
char
perm
[
8
],
dev
[
8
];
char
perm
[
8
],
dev
[
8
];
long
long
begin
,
end
,
size
,
inode
;
long
long
begin
,
end
,
size
,
inode
;
ret
=
fscanf
(
procmap
,
"%llx-%llx %s %llx %s %llx"
,
ret
=
fscanf
(
procmap
,
"%llx-%llx %s %llx %s %llx"
,
&
begin
,
&
end
,
perm
,
&
begin
,
&
end
,
perm
,
&
size
,
dev
,
&
inode
);
&
size
,
dev
,
&
inode
);
if
(
!
fgets
(
endline
,
sizeof
(
endline
),
procmap
))
if
(
!
fgets
(
endline
,
sizeof
(
endline
),
procmap
))
break
;
break
;
...
@@ -84,8 +83,7 @@ int bcc_procutils_each_module(int pid, bcc_procutils_modulecb callback, void *pa
...
@@ -84,8 +83,7 @@ int bcc_procutils_each_module(int pid, bcc_procutils_modulecb callback, void *pa
if
(
newline
)
if
(
newline
)
newline
[
0
]
=
'\0'
;
newline
[
0
]
=
'\0'
;
while
(
isspace
(
mapname
[
0
]))
while
(
isspace
(
mapname
[
0
]))
mapname
++
;
mapname
++
;
if
(
strchr
(
perm
,
'x'
)
&&
mapname
[
0
]
&&
mapname
[
0
]
!=
'['
)
if
(
strchr
(
perm
,
'x'
)
&&
mapname
[
0
]
&&
mapname
[
0
]
!=
'['
)
callback
(
mapname
,
(
uint64_t
)
begin
,
(
uint64_t
)
end
,
payload
);
callback
(
mapname
,
(
uint64_t
)
begin
,
(
uint64_t
)
end
,
payload
);
...
@@ -96,8 +94,7 @@ int bcc_procutils_each_module(int pid, bcc_procutils_modulecb callback, void *pa
...
@@ -96,8 +94,7 @@ int bcc_procutils_each_module(int pid, bcc_procutils_modulecb callback, void *pa
return
0
;
return
0
;
}
}
int
bcc_procutils_each_ksym
(
bcc_procutils_ksymcb
callback
,
void
*
payload
)
int
bcc_procutils_each_ksym
(
bcc_procutils_ksymcb
callback
,
void
*
payload
)
{
{
char
line
[
2048
];
char
line
[
2048
];
FILE
*
kallsyms
=
fopen
(
"/proc/kallsyms"
,
"r"
);
FILE
*
kallsyms
=
fopen
(
"/proc/kallsyms"
,
"r"
);
...
@@ -116,8 +113,7 @@ int bcc_procutils_each_ksym(bcc_procutils_ksymcb callback, void *payload)
...
@@ -116,8 +113,7 @@ int bcc_procutils_each_ksym(bcc_procutils_ksymcb callback, void *payload)
addr
=
strtoull
(
line
,
&
symname
,
16
);
addr
=
strtoull
(
line
,
&
symname
,
16
);
endsym
=
symname
=
symname
+
3
;
endsym
=
symname
=
symname
+
3
;
while
(
*
endsym
&&
!
isspace
(
*
endsym
))
while
(
*
endsym
&&
!
isspace
(
*
endsym
))
endsym
++
;
endsym
++
;
*
endsym
=
'\0'
;
*
endsym
=
'\0'
;
callback
(
symname
,
addr
,
payload
);
callback
(
symname
,
addr
,
payload
);
...
@@ -168,15 +164,16 @@ static struct ld_lib {
...
@@ -168,15 +164,16 @@ static struct ld_lib {
char
*
libname
;
char
*
libname
;
char
*
path
;
char
*
path
;
int
flags
;
int
flags
;
}
*
lib_cache
;
}
*
lib_cache
;
static
int
read_cache1
(
const
char
*
ld_map
)
static
int
read_cache1
(
const
char
*
ld_map
)
{
{
struct
ld_cache1
*
ldcache
=
(
struct
ld_cache1
*
)
ld_map
;
struct
ld_cache1
*
ldcache
=
(
struct
ld_cache1
*
)
ld_map
;
const
char
*
ldstrings
=
(
const
char
*
)(
ldcache
->
entries
+
ldcache
->
entry_count
);
const
char
*
ldstrings
=
(
const
char
*
)(
ldcache
->
entries
+
ldcache
->
entry_count
);
uint32_t
i
;
uint32_t
i
;
lib_cache
=
(
struct
ld_lib
*
)
malloc
(
ldcache
->
entry_count
*
sizeof
(
struct
ld_lib
));
lib_cache
=
(
struct
ld_lib
*
)
malloc
(
ldcache
->
entry_count
*
sizeof
(
struct
ld_lib
));
lib_cache_count
=
(
int
)
ldcache
->
entry_count
;
lib_cache_count
=
(
int
)
ldcache
->
entry_count
;
for
(
i
=
0
;
i
<
ldcache
->
entry_count
;
++
i
)
{
for
(
i
=
0
;
i
<
ldcache
->
entry_count
;
++
i
)
{
...
@@ -191,15 +188,15 @@ static int read_cache1(const char *ld_map)
...
@@ -191,15 +188,15 @@ static int read_cache1(const char *ld_map)
return
0
;
return
0
;
}
}
static
int
read_cache2
(
const
char
*
ld_map
)
static
int
read_cache2
(
const
char
*
ld_map
)
{
{
struct
ld_cache2
*
ldcache
=
(
struct
ld_cache2
*
)
ld_map
;
struct
ld_cache2
*
ldcache
=
(
struct
ld_cache2
*
)
ld_map
;
uint32_t
i
;
uint32_t
i
;
if
(
memcmp
(
ld_map
,
CACHE2_HEADER
,
CACHE2_HEADER_LEN
))
if
(
memcmp
(
ld_map
,
CACHE2_HEADER
,
CACHE2_HEADER_LEN
))
return
-
1
;
return
-
1
;
lib_cache
=
(
struct
ld_lib
*
)
malloc
(
ldcache
->
entry_count
*
sizeof
(
struct
ld_lib
));
lib_cache
=
(
struct
ld_lib
*
)
malloc
(
ldcache
->
entry_count
*
sizeof
(
struct
ld_lib
));
lib_cache_count
=
(
int
)
ldcache
->
entry_count
;
lib_cache_count
=
(
int
)
ldcache
->
entry_count
;
for
(
i
=
0
;
i
<
ldcache
->
entry_count
;
++
i
)
{
for
(
i
=
0
;
i
<
ldcache
->
entry_count
;
++
i
)
{
...
@@ -214,8 +211,7 @@ static int read_cache2(const char *ld_map)
...
@@ -214,8 +211,7 @@ static int read_cache2(const char *ld_map)
return
0
;
return
0
;
}
}
static
int
load_ld_cache
(
const
char
*
cache_path
)
static
int
load_ld_cache
(
const
char
*
cache_path
)
{
{
struct
stat
st
;
struct
stat
st
;
size_t
ld_size
;
size_t
ld_size
;
const
char
*
ld_map
;
const
char
*
ld_map
;
...
@@ -265,8 +261,7 @@ static int load_ld_cache(const char *cache_path)
...
@@ -265,8 +261,7 @@ static int load_ld_cache(const char *cache_path)
#define ABI_S390_LIB64 0x0400
#define ABI_S390_LIB64 0x0400
#define ABI_POWERPC_LIB64 0x0500
#define ABI_POWERPC_LIB64 0x0500
static
bool
match_so_flags
(
int
flags
)
static
bool
match_so_flags
(
int
flags
)
{
{
if
((
flags
&
FLAG_TYPE_MASK
)
!=
TYPE_ELF_LIBC6
)
if
((
flags
&
FLAG_TYPE_MASK
)
!=
TYPE_ELF_LIBC6
)
return
false
;
return
false
;
...
@@ -282,8 +277,7 @@ static bool match_so_flags(int flags)
...
@@ -282,8 +277,7 @@ static bool match_so_flags(int flags)
return
true
;
return
true
;
}
}
const
char
*
bcc_procutils_which_so
(
const
char
*
libname
)
const
char
*
bcc_procutils_which_so
(
const
char
*
libname
)
{
{
const
size_t
soname_len
=
strlen
(
libname
)
+
strlen
(
"lib.so"
);
const
size_t
soname_len
=
strlen
(
libname
)
+
strlen
(
"lib.so"
);
char
soname
[
soname_len
+
1
];
char
soname
[
soname_len
+
1
];
int
i
;
int
i
;
...
@@ -308,53 +302,3 @@ const char *bcc_procutils_which_so(const char *libname)
...
@@ -308,53 +302,3 @@ const char *bcc_procutils_which_so(const char *libname)
}
}
return
NULL
;
return
NULL
;
}
}
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_
helpers
.h
→
src/cc/bcc_
proc
.h
View file @
c1c2373f
#ifndef LIBBCC_
ELF
_H
#ifndef LIBBCC_
PROC
_H
#define LIBBCC_
ELF
_H
#define LIBBCC_
PROC
_H
#ifdef __cplusplus
#ifdef __cplusplus
extern
"C"
{
extern
"C"
{
#endif
#endif
#include <stdint.h>
typedef
void
(
*
bcc_procutils_modulecb
)(
const
char
*
,
uint64_t
,
uint64_t
,
void
*
);
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_ksymcb
)(
const
char
*
,
uint64_t
,
void
*
);
typedef
void
(
*
bcc_procutils_ksymcb
)(
const
char
*
,
uint64_t
,
void
*
);
const
char
*
bcc_procutils_which_so
(
const
char
*
libname
);
const
char
*
bcc_procutils_which_so
(
const
char
*
libname
);
char
*
bcc_procutils_which
(
const
char
*
binpath
);
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_procutils_each_ksym
(
bcc_procutils_ksymcb
callback
,
void
*
payload
);
int
bcc_resolve_symname
(
const
char
*
module
,
const
char
*
symname
,
const
uint64_t
addr
,
int
bcc_resolve_symname
(
const
char
*
module
,
const
char
*
symname
,
struct
bcc_symbol
*
sym
);
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
);
#ifdef __cplusplus
#ifdef __cplusplus
}
}
...
...
src/cc/bcc_syms.cc
View file @
c1c2373f
...
@@ -6,11 +6,14 @@
...
@@ -6,11 +6,14 @@
#include <sys/types.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/stat.h>
#include <unistd.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
{
class
SymbolCache
{
public:
public:
virtual
void
refresh
()
=
0
;
virtual
void
refresh
()
=
0
;
virtual
bool
resolve_addr
(
uint64_t
addr
,
struct
bcc_symbol
*
sym
)
=
0
;
virtual
bool
resolve_addr
(
uint64_t
addr
,
struct
bcc_symbol
*
sym
)
=
0
;
virtual
bool
resolve_name
(
const
char
*
name
,
uint64_t
*
addr
)
=
0
;
virtual
bool
resolve_name
(
const
char
*
name
,
uint64_t
*
addr
)
=
0
;
...
@@ -18,67 +21,62 @@ public:
...
@@ -18,67 +21,62 @@ public:
class
KSyms
:
SymbolCache
{
class
KSyms
:
SymbolCache
{
struct
Symbol
{
struct
Symbol
{
Symbol
(
const
char
*
name
,
uint64_t
addr
)
:
Symbol
(
const
char
*
name
,
uint64_t
addr
)
:
name
(
name
),
addr
(
addr
)
{}
name
(
name
),
addr
(
addr
)
{}
std
::
string
name
;
std
::
string
name
;
uint64_t
addr
;
uint64_t
addr
;
bool
operator
<
(
const
Symbol
&
rhs
)
const
{
return
addr
<
rhs
.
addr
;
}
bool
operator
<
(
const
Symbol
&
rhs
)
const
{
return
addr
<
rhs
.
addr
;
}
};
};
std
::
vector
<
Symbol
>
_syms
;
std
::
vector
<
Symbol
>
syms_
;
std
::
unordered_map
<
std
::
string
,
uint64_t
>
_sym_names
;
std
::
unordered_map
<
std
::
string
,
uint64_t
>
symnames_
;
static
void
_add_symbol
(
const
char
*
,
uint64_t
,
void
*
);
static
void
_add_symbol
(
const
char
*
,
uint64_t
,
void
*
);
public:
public:
virtual
bool
resolve_addr
(
uint64_t
addr
,
struct
bcc_symbol
*
sym
);
virtual
bool
resolve_addr
(
uint64_t
addr
,
struct
bcc_symbol
*
sym
);
virtual
bool
resolve_name
(
const
char
*
name
,
uint64_t
*
addr
);
virtual
bool
resolve_name
(
const
char
*
name
,
uint64_t
*
addr
);
virtual
void
refresh
()
virtual
void
refresh
()
{
{
if
(
syms_
.
empty
())
{
if
(
_syms
.
empty
())
{
bcc_procutils_each_ksym
(
_add_symbol
,
this
);
bcc_procutils_each_ksym
(
_add_symbol
,
this
);
std
::
sort
(
_syms
.
begin
(),
_syms
.
end
());
std
::
sort
(
syms_
.
begin
(),
syms_
.
end
());
}
}
}
}
};
};
void
KSyms
::
_add_symbol
(
const
char
*
symname
,
uint64_t
addr
,
void
*
p
)
void
KSyms
::
_add_symbol
(
const
char
*
symname
,
uint64_t
addr
,
void
*
p
)
{
{
KSyms
*
ks
=
static_cast
<
KSyms
*>
(
p
);
KSyms
*
ks
=
static_cast
<
KSyms
*>
(
p
);
ks
->
_syms
.
emplace_back
(
symname
,
addr
);
ks
->
syms_
.
emplace_back
(
symname
,
addr
);
}
}
bool
KSyms
::
resolve_addr
(
uint64_t
addr
,
struct
bcc_symbol
*
sym
)
bool
KSyms
::
resolve_addr
(
uint64_t
addr
,
struct
bcc_symbol
*
sym
)
{
{
refresh
();
refresh
();
if
(
_syms
.
empty
())
{
if
(
syms_
.
empty
())
{
sym
->
name
=
nullptr
;
sym
->
name
=
nullptr
;
sym
->
module
=
nullptr
;
sym
->
module
=
nullptr
;
sym
->
offset
=
0x0
;
sym
->
offset
=
0x0
;
return
false
;
return
false
;
}
}
auto
it
=
std
::
upper_bound
(
_syms
.
begin
(),
_syms
.
end
(),
Symbol
(
""
,
addr
))
-
1
;
auto
it
=
std
::
upper_bound
(
syms_
.
begin
(),
syms_
.
end
(),
Symbol
(
""
,
addr
))
-
1
;
sym
->
name
=
(
*
it
).
name
.
c_str
();
sym
->
name
=
(
*
it
).
name
.
c_str
();
sym
->
module
=
"[kernel]"
;
sym
->
module
=
"[kernel]"
;
sym
->
offset
=
addr
-
(
*
it
).
addr
;
sym
->
offset
=
addr
-
(
*
it
).
addr
;
return
true
;
return
true
;
}
}
bool
KSyms
::
resolve_name
(
const
char
*
name
,
uint64_t
*
addr
)
bool
KSyms
::
resolve_name
(
const
char
*
name
,
uint64_t
*
addr
)
{
{
refresh
();
refresh
();
if
(
_syms
.
size
()
!=
_sym_names
.
size
())
{
if
(
syms_
.
size
()
!=
symnames_
.
size
())
{
_sym_names
.
clear
();
symnames_
.
clear
();
for
(
Symbol
&
sym
:
_syms
)
{
for
(
Symbol
&
sym
:
syms_
)
{
_sym_names
[
sym
.
name
]
=
sym
.
addr
;
symnames_
[
sym
.
name
]
=
sym
.
addr
;
}
}
}
}
auto
it
=
_sym_names
.
find
(
name
);
auto
it
=
symnames_
.
find
(
name
);
if
(
it
==
_sym_names
.
end
())
if
(
it
==
symnames_
.
end
())
return
false
;
return
false
;
*
addr
=
it
->
second
;
*
addr
=
it
->
second
;
...
@@ -86,37 +84,34 @@ bool KSyms::resolve_name(const char *name, uint64_t *addr)
...
@@ -86,37 +84,34 @@ bool KSyms::resolve_name(const char *name, uint64_t *addr)
}
}
class
ProcStat
{
class
ProcStat
{
std
::
string
_procfs
;
std
::
string
procfs_
;
ino_t
_inode
;
ino_t
inode_
;
ino_t
get_inode
()
ino_t
getinode_
()
{
{
struct
stat
s
;
struct
stat
s
;
return
(
!
stat
(
_procfs
.
c_str
(),
&
s
))
?
s
.
st_ino
:
-
1
;
return
(
!
stat
(
procfs_
.
c_str
(),
&
s
))
?
s
.
st_ino
:
-
1
;
}
}
public:
public:
ProcStat
(
int
pid
)
:
_inode
(
-
1
)
ProcStat
(
int
pid
)
:
inode_
(
-
1
)
{
{
char
buffer
[
128
];
char
buffer
[
128
];
snprintf
(
buffer
,
sizeof
(
buffer
),
"/proc/%d/exe"
,
pid
);
snprintf
(
buffer
,
sizeof
(
buffer
),
"/proc/%d/exe"
,
pid
);
_procfs
=
buffer
;
procfs_
=
buffer
;
}
}
bool
is_stale
()
{
return
_inode
!=
get_inode
();
}
bool
is_stale
()
{
return
inode_
!=
getinode_
();
}
void
reset
()
{
_inode
=
get_inode
();
}
void
reset
()
{
inode_
=
getinode_
();
}
};
};
static
bool
has_suffix
(
const
std
::
string
&
str
,
const
std
::
string
&
suffix
)
static
bool
has_suffix
(
const
std
::
string
&
str
,
const
std
::
string
&
suffix
)
{
{
return
str
.
size
()
>=
suffix
.
size
()
&&
return
str
.
size
()
>=
suffix
.
size
()
&&
str
.
compare
(
str
.
size
()
-
suffix
.
size
(),
suffix
.
size
(),
suffix
)
==
0
;
str
.
compare
(
str
.
size
()
-
suffix
.
size
(),
suffix
.
size
(),
suffix
)
==
0
;
}
}
class
ProcSyms
:
SymbolCache
{
class
ProcSyms
:
SymbolCache
{
struct
Symbol
{
struct
Symbol
{
Symbol
(
const
char
*
name
,
uint64_t
start
,
uint64_t
size
,
int
flags
=
0
)
:
Symbol
(
const
char
*
name
,
uint64_t
start
,
uint64_t
size
,
int
flags
=
0
)
name
(
name
),
start
(
start
),
size
(
size
),
flags
(
flags
)
{}
:
name
(
name
),
start
(
start
),
size
(
size
),
flags
(
flags
)
{}
std
::
string
name
;
std
::
string
name
;
uint64_t
start
;
uint64_t
start
;
uint64_t
size
;
uint64_t
size
;
...
@@ -124,101 +119,91 @@ class ProcSyms : SymbolCache {
...
@@ -124,101 +119,91 @@ class ProcSyms : SymbolCache {
};
};
struct
Module
{
struct
Module
{
Module
(
const
char
*
name
,
uint64_t
start
,
uint64_t
end
)
:
Module
(
const
char
*
name
,
uint64_t
start
,
uint64_t
end
)
_name
(
name
),
_start
(
start
),
_end
(
end
)
{}
:
name_
(
name
),
start_
(
start
),
end_
(
end
)
{}
std
::
string
_name
;
std
::
string
name_
;
uint64_t
_start
;
uint64_t
start_
;
uint64_t
_end
;
uint64_t
end_
;
std
::
vector
<
Symbol
>
_syms
;
std
::
vector
<
Symbol
>
syms_
;
void
load_sym_table
();
void
load_sym_table
();
bool
decode_sym
(
uint64_t
addr
,
struct
bcc_symbol
*
sym
);
bool
decode_sym
(
uint64_t
addr
,
struct
bcc_symbol
*
sym
);
bool
is_so
()
{
return
has_suffix
(
_name
,
".so"
);
}
bool
is_so
()
{
return
has_suffix
(
name_
,
".so"
);
}
static
int
_add_symbol
(
const
char
*
symname
,
static
int
_add_symbol
(
const
char
*
symname
,
uint64_t
start
,
uint64_t
end
,
uint64_t
start
,
uint64_t
end
,
int
flags
,
void
*
p
);
int
flags
,
void
*
p
);
};
};
int
_pid
;
int
pid_
;
std
::
vector
<
Module
>
_modules
;
std
::
vector
<
Module
>
modules_
;
ProcStat
_procstat
;
ProcStat
procstat_
;
static
void
_add_module
(
const
char
*
,
uint64_t
,
uint64_t
,
void
*
);
static
void
_add_module
(
const
char
*
,
uint64_t
,
uint64_t
,
void
*
);
public:
public:
ProcSyms
(
int
pid
);
ProcSyms
(
int
pid
);
virtual
void
refresh
();
virtual
void
refresh
();
virtual
bool
resolve_addr
(
uint64_t
addr
,
struct
bcc_symbol
*
sym
);
virtual
bool
resolve_addr
(
uint64_t
addr
,
struct
bcc_symbol
*
sym
);
virtual
bool
resolve_name
(
const
char
*
name
,
uint64_t
*
addr
);
virtual
bool
resolve_name
(
const
char
*
name
,
uint64_t
*
addr
);
};
};
ProcSyms
::
ProcSyms
(
int
pid
)
:
_pid
(
pid
),
_procstat
(
pid
)
ProcSyms
::
ProcSyms
(
int
pid
)
:
pid_
(
pid
),
procstat_
(
pid
)
{
refresh
();
}
{
refresh
();
}
void
ProcSyms
::
refresh
()
void
ProcSyms
::
refresh
()
{
{
modules_
.
clear
();
_modules
.
clear
();
bcc_procutils_each_module
(
pid_
,
_add_module
,
this
);
bcc_procutils_each_module
(
_pid
,
_add_module
,
this
);
procstat_
.
reset
();
_procstat
.
reset
();
}
}
void
ProcSyms
::
_add_module
(
void
ProcSyms
::
_add_module
(
const
char
*
modname
,
uint64_t
start
,
uint64_t
end
,
const
char
*
modname
,
uint64_t
start
,
uint64_t
end
,
void
*
payload
)
void
*
payload
)
{
{
ProcSyms
*
ps
=
static_cast
<
ProcSyms
*>
(
payload
);
ProcSyms
*
ps
=
static_cast
<
ProcSyms
*>
(
payload
);
ps
->
_modules
.
emplace_back
(
modname
,
start
,
end
);
ps
->
modules_
.
emplace_back
(
modname
,
start
,
end
);
}
}
bool
ProcSyms
::
resolve_addr
(
uint64_t
addr
,
struct
bcc_symbol
*
sym
)
bool
ProcSyms
::
resolve_addr
(
uint64_t
addr
,
struct
bcc_symbol
*
sym
)
{
{
if
(
procstat_
.
is_stale
())
if
(
_procstat
.
is_stale
())
refresh
();
refresh
();
sym
->
module
=
nullptr
;
sym
->
module
=
nullptr
;
sym
->
name
=
nullptr
;
sym
->
name
=
nullptr
;
sym
->
offset
=
0x0
;
sym
->
offset
=
0x0
;
for
(
Module
&
mod
:
_modules
)
{
for
(
Module
&
mod
:
modules_
)
{
if
(
addr
>=
mod
.
_start
&&
addr
<=
mod
.
_end
)
if
(
addr
>=
mod
.
start_
&&
addr
<=
mod
.
end_
)
return
mod
.
decode_sym
(
addr
,
sym
);
return
mod
.
decode_sym
(
addr
,
sym
);
}
}
return
false
;
return
false
;
}
}
bool
ProcSyms
::
resolve_name
(
const
char
*
name
,
uint64_t
*
addr
)
bool
ProcSyms
::
resolve_name
(
const
char
*
name
,
uint64_t
*
addr
)
{
{
*
addr
=
0x0
;
*
addr
=
0x0
;
return
false
;
return
false
;
}
}
int
ProcSyms
::
Module
::
_add_symbol
(
const
char
*
symname
,
int
ProcSyms
::
Module
::
_add_symbol
(
const
char
*
symname
,
uint64_t
start
,
uint64_t
start
,
uint64_t
end
,
int
flags
,
void
*
p
)
uint64_t
end
,
int
flags
,
void
*
p
)
{
{
Module
*
m
=
static_cast
<
Module
*>
(
p
);
Module
*
m
=
static_cast
<
Module
*>
(
p
);
m
->
_syms
.
emplace_back
(
symname
,
start
,
end
,
flags
);
m
->
syms_
.
emplace_back
(
symname
,
start
,
end
,
flags
);
return
0
;
return
0
;
}
}
void
ProcSyms
::
Module
::
load_sym_table
()
void
ProcSyms
::
Module
::
load_sym_table
()
{
{
if
(
syms_
.
size
())
if
(
_syms
.
size
())
return
;
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
)
bool
ProcSyms
::
Module
::
decode_sym
(
uint64_t
addr
,
struct
bcc_symbol
*
sym
)
{
{
uint64_t
offset
=
is_so
()
?
(
addr
-
start_
)
:
addr
;
uint64_t
offset
=
is_so
()
?
(
addr
-
_start
)
:
addr
;
load_sym_table
();
load_sym_table
();
sym
->
module
=
_name
.
c_str
();
sym
->
module
=
name_
.
c_str
();
sym
->
offset
=
offset
;
sym
->
offset
=
offset
;
for
(
Symbol
&
s
:
_syms
)
{
for
(
Symbol
&
s
:
syms_
)
{
if
(
offset
>=
s
.
start
&&
offset
<=
(
s
.
start
+
s
.
size
))
{
if
(
offset
>=
s
.
start
&&
offset
<=
(
s
.
start
+
s
.
size
))
{
sym
->
name
=
s
.
name
.
c_str
();
sym
->
name
=
s
.
name
.
c_str
();
sym
->
offset
=
(
offset
-
s
.
start
);
sym
->
offset
=
(
offset
-
s
.
start
);
...
@@ -230,29 +215,74 @@ bool ProcSyms::Module::decode_sym(uint64_t addr, struct bcc_symbol *sym)
...
@@ -230,29 +215,74 @@ bool ProcSyms::Module::decode_sym(uint64_t addr, struct bcc_symbol *sym)
extern
"C"
{
extern
"C"
{
void
*
bcc_symcache_new
(
int
pid
)
void
*
bcc_symcache_new
(
int
pid
)
{
{
if
(
pid
<
0
)
if
(
pid
<
0
)
return
static_cast
<
void
*>
(
new
KSyms
());
return
static_cast
<
void
*>
(
new
KSyms
());
return
static_cast
<
void
*>
(
new
ProcSyms
(
pid
));
return
static_cast
<
void
*>
(
new
ProcSyms
(
pid
));
}
}
int
bcc_symcache_resolve
(
void
*
resolver
,
uint64_t
addr
,
struct
bcc_symbol
*
sym
)
int
bcc_symcache_resolve
(
void
*
resolver
,
uint64_t
addr
,
{
struct
bcc_symbol
*
sym
)
{
SymbolCache
*
cache
=
static_cast
<
SymbolCache
*>
(
resolver
);
SymbolCache
*
cache
=
static_cast
<
SymbolCache
*>
(
resolver
);
return
cache
->
resolve_addr
(
addr
,
sym
)
?
0
:
-
1
;
return
cache
->
resolve_addr
(
addr
,
sym
)
?
0
:
-
1
;
}
}
int
bcc_symcache_resolve_name
(
void
*
resolver
,
const
char
*
name
,
uint64_t
*
addr
)
int
bcc_symcache_resolve_name
(
void
*
resolver
,
const
char
*
name
,
{
uint64_t
*
addr
)
{
SymbolCache
*
cache
=
static_cast
<
SymbolCache
*>
(
resolver
);
SymbolCache
*
cache
=
static_cast
<
SymbolCache
*>
(
resolver
);
return
cache
->
resolve_name
(
name
,
addr
)
?
0
:
-
1
;
return
cache
->
resolve_name
(
name
,
addr
)
?
0
:
-
1
;
}
}
void
bcc_symcache_refresh
(
void
*
resolver
)
void
bcc_symcache_refresh
(
void
*
resolver
)
{
{
SymbolCache
*
cache
=
static_cast
<
SymbolCache
*>
(
resolver
);
SymbolCache
*
cache
=
static_cast
<
SymbolCache
*>
(
resolver
);
cache
->
refresh
();
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