Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
B
bpftrace
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
bpftrace
Commits
e1960e9a
Commit
e1960e9a
authored
Dec 24, 2018
by
Brendan Gregg
Committed by
GitHub
Dec 24, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #282 from dw/master
Extract LINUX_VERSION_CODE from running kernel via vDSO.
parents
2ae2a53f
7c61605f
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
61 additions
and
6 deletions
+61
-6
src/attached_probe.cpp
src/attached_probe.cpp
+61
-6
No files found.
src/attached_probe.cpp
View file @
e1960e9a
#include <cstring>
#include <elf.h>
#include <fcntl.h>
#include <fcntl.h>
#include <fstream>
#include <fstream>
#include <iostream>
#include <iostream>
#include <link.h>
#include <regex>
#include <regex>
#include <sys/auxv.h>
#include <sys/utsname.h>
#include <sys/utsname.h>
#include <tuple>
#include <tuple>
#include <unistd.h>
#include <unistd.h>
...
@@ -193,12 +197,67 @@ uint64_t AttachedProbe::offset() const
...
@@ -193,12 +197,67 @@ uint64_t AttachedProbe::offset() const
return
sym
.
offset
;
return
sym
.
offset
;
}
}
/**
* Search for LINUX_VERSION_CODE in the vDSO, returning 0 if it can't be found.
*/
static
unsigned
_find_version_note
(
unsigned
long
base
)
{
auto
ehdr
=
reinterpret_cast
<
const
ElfW
(
Ehdr
)
*>
(
base
);
for
(
int
i
=
0
;
i
<
ehdr
->
e_shnum
;
i
++
)
{
auto
shdr
=
reinterpret_cast
<
const
ElfW
(
Shdr
)
*>
(
base
+
ehdr
->
e_shoff
+
(
i
*
ehdr
->
e_shentsize
)
);
if
(
shdr
->
sh_type
==
SHT_NOTE
)
{
auto
ptr
=
reinterpret_cast
<
const
char
*>
(
base
+
shdr
->
sh_offset
);
auto
end
=
ptr
+
shdr
->
sh_size
;
while
(
ptr
<
end
)
{
auto
nhdr
=
reinterpret_cast
<
const
ElfW
(
Nhdr
)
*>
(
ptr
);
ptr
+=
sizeof
*
nhdr
;
auto
name
=
ptr
;
ptr
+=
(
nhdr
->
n_namesz
+
sizeof
(
ElfW
(
Word
))
-
1
)
&
-
sizeof
(
ElfW
(
Word
));
auto
desc
=
ptr
;
ptr
+=
(
nhdr
->
n_descsz
+
sizeof
(
ElfW
(
Word
))
-
1
)
&
-
sizeof
(
ElfW
(
Word
));
if
((
nhdr
->
n_namesz
>
5
&&
!
memcmp
(
name
,
"Linux"
,
5
))
&&
nhdr
->
n_descsz
==
4
&&
!
nhdr
->
n_type
)
return
*
reinterpret_cast
<
const
uint32_t
*>
(
desc
);
}
}
}
return
0
;
}
/**
* Find a LINUX_VERSION_CODE matching the host kernel. The build-time constant
* may not match if bpftrace is compiled on a different Linux version than it's
* used on, e.g. if built with Docker.
*/
static
unsigned
kernel_version
(
int
attempt
)
static
unsigned
kernel_version
(
int
attempt
)
{
{
switch
(
attempt
)
switch
(
attempt
)
{
{
case
0
:
case
0
:
return
LINUX_VERSION_CODE
;
{
// Fetch LINUX_VERSION_CODE from the vDSO .note section, falling back on
// the build-time constant if unavailable. This always matches the
// running kernel, but is not supported on arm32.
unsigned
code
=
0
;
unsigned
long
base
=
getauxval
(
AT_SYSINFO_EHDR
);
if
(
base
&&
!
memcmp
(
reinterpret_cast
<
void
*>
(
base
),
ELFMAG
,
4
))
code
=
_find_version_note
(
base
);
if
(
!
code
)
code
=
LINUX_VERSION_CODE
;
return
code
;
}
case
1
:
case
1
:
struct
utsname
utsname
;
struct
utsname
utsname
;
if
(
uname
(
&
utsname
)
<
0
)
if
(
uname
(
&
utsname
)
<
0
)
...
@@ -208,11 +267,7 @@ static unsigned kernel_version(int attempt)
...
@@ -208,11 +267,7 @@ static unsigned kernel_version(int attempt)
return
0
;
return
0
;
return
KERNEL_VERSION
(
x
,
y
,
z
);
return
KERNEL_VERSION
(
x
,
y
,
z
);
case
2
:
case
2
:
// try to get the definition of LINUX_VERSION_CODE at runtime.
// Try to get the definition of LINUX_VERSION_CODE at runtime.
// needed if bpftrace is compiled on a different linux version than it's used on.
// e.g. if built with docker.
// the reason case 0 doesn't work for this is because it uses the preprocessor directive,
// which is by definition a compile-time constant
std
::
ifstream
linux_version_header
{
"/usr/include/linux/version.h"
};
std
::
ifstream
linux_version_header
{
"/usr/include/linux/version.h"
};
const
std
::
string
content
{
std
::
istreambuf_iterator
<
char
>
(
linux_version_header
),
const
std
::
string
content
{
std
::
istreambuf_iterator
<
char
>
(
linux_version_header
),
std
::
istreambuf_iterator
<
char
>
()};
std
::
istreambuf_iterator
<
char
>
()};
...
...
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