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
3d1d8358
Commit
3d1d8358
authored
May 10, 2015
by
4ast
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #11 from plumgrid/clang_dev
Use clang as a lib to parse the helper file live
parents
ba97c279
25245bfa
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
312 additions
and
87 deletions
+312
-87
CMakeLists.txt
CMakeLists.txt
+15
-14
src/cc/CMakeLists.txt
src/cc/CMakeLists.txt
+7
-19
src/cc/bitops.c
src/cc/bitops.c
+30
-30
src/cc/bpf_program.cc
src/cc/bpf_program.cc
+249
-18
src/cc/bpf_program.h
src/cc/bpf_program.h
+4
-1
src/cc/parser.yy
src/cc/parser.yy
+7
-5
No files found.
CMakeLists.txt
View file @
3d1d8358
...
...
@@ -9,20 +9,21 @@ find_package(BISON)
find_package
(
FLEX
)
find_package
(
LLVM REQUIRED CONFIG
)
message
(
STATUS
"Found LLVM:
${
LLVM_INCLUDE_DIRS
}
"
)
find_program
(
XXD xxd
)
if
(
${
XXD
}
STREQUAL
"XXD-NOTFOUND"
)
message
(
FATAL_ERROR
"program xxd not found, install vim-common"
)
endif
()
find_program
(
CLANG clang
)
if
(
${
CLANG
}
STREQUAL
"CLANG-NOTFOUND"
)
message
(
FATAL_ERROR
"program clang not found, install clang with bpf support"
)
endif
()
execute_process
(
COMMAND
${
CLANG
}
--version OUTPUT_VARIABLE CLANG_VERSION_RAW
)
string
(
REGEX MATCH
"[0-9]+[.][0-9]+[.][0-9]+"
CLANG_VERSION
${
CLANG_VERSION_RAW
}
)
message
(
STATUS
"Found CLANG:
${
CLANG
}
(found version
\"
${
CLANG_VERSION
}
\"
)"
)
if
(
CLANG_VERSION VERSION_LESS 3.0.0
)
message
(
FATAL_ERROR
"requires clang version >= 3.0.0,
${
CLANG_VERSION
}
found"
)
endif
()
# clang is linked as a library, but the library path searching is
# primitively supported, unlike libLLVM
set
(
CLANG_SEARCH
"/opt/local/llvm/lib"
)
find_library
(
libclangAnalysis NAMES clangAnalysis HINTS
${
CLANG_SEARCH
}
)
find_library
(
libclangAST NAMES clangAST HINTS
${
CLANG_SEARCH
}
)
find_library
(
libclangBasic NAMES clangBasic HINTS
${
CLANG_SEARCH
}
)
find_library
(
libclangCodeGen NAMES clangCodeGen HINTS
${
CLANG_SEARCH
}
)
find_library
(
libclangDriver NAMES clangDriver HINTS
${
CLANG_SEARCH
}
)
find_library
(
libclangEdit NAMES clangEdit HINTS
${
CLANG_SEARCH
}
)
find_library
(
libclangFrontend NAMES clangFrontend HINTS
${
CLANG_SEARCH
}
)
find_library
(
libclangLex NAMES clangLex HINTS
${
CLANG_SEARCH
}
)
find_library
(
libclangParse NAMES clangParse HINTS
${
CLANG_SEARCH
}
)
find_library
(
libclangSema NAMES clangSema HINTS
${
CLANG_SEARCH
}
)
find_library
(
libclangSerialization NAMES clangSerialization HINTS
${
CLANG_SEARCH
}
)
set
(
CMAKE_C_FLAGS
"-Wall"
)
set
(
CMAKE_CXX_FLAGS
"-std=c++11 -Wall"
)
...
...
src/cc/CMakeLists.txt
View file @
3d1d8358
...
...
@@ -7,31 +7,19 @@ BISON_TARGET(Parser parser.yy ${CMAKE_CURRENT_BINARY_DIR}/parser.yy.cc COMPILE_F
FLEX_TARGET
(
Lexer lexer.ll
${
CMAKE_CURRENT_BINARY_DIR
}
/lexer.ll.cc COMPILE_FLAGS
"--c++ --o lexer.ll.cc"
)
ADD_FLEX_BISON_DEPENDENCY
(
Lexer Parser
)
add_custom_command
(
OUTPUT
${
CMAKE_CURRENT_BINARY_DIR
}
/bitops.bc
COMMAND
${
CLANG
}
ARGS -O3 -emit-llvm -o bitops.bc -I
${
CMAKE_SOURCE_DIR
}
/jit/compat/include
-c
${
CMAKE_CURRENT_SOURCE_DIR
}
/bitops.c
DEPENDS
${
CMAKE_CURRENT_SOURCE_DIR
}
/bitops.c
${
CMAKE_CURRENT_SOURCE_DIR
}
/bpf_helpers.h
WORKING_DIRECTORY
${
CMAKE_CURRENT_BINARY_DIR
}
COMMENT
"Generating bitops IR"
)
add_custom_command
(
OUTPUT
${
CMAKE_CURRENT_BINARY_DIR
}
/bitops.h
COMMAND
${
XXD
}
ARGS -i bitops.bc bitops.h
DEPENDS
${
CMAKE_CURRENT_BINARY_DIR
}
/bitops.bc
WORKING_DIRECTORY
${
CMAKE_CURRENT_BINARY_DIR
}
COMMENT
"Generating bitops.h"
)
add_custom_target
(
bitops DEPENDS
${
CMAKE_CURRENT_BINARY_DIR
}
/bitops.h
)
set
(
CMAKE_SHARED_LINKER_FLAGS
"-static-libstdc++ -Wl,--exclude-libs=ALL"
)
add_library
(
bpfprog SHARED bpf_common.cc bpf_program.cc codegen_llvm.cc
node.cc parser.cc printer.cc type_check.cc libbpf.c
${
BISON_Parser_OUTPUTS
}
${
FLEX_Lexer_OUTPUTS
}
${
CMAKE_CURRENT_BINARY_DIR
}
/bitops.h
)
${
BISON_Parser_OUTPUTS
}
${
FLEX_Lexer_OUTPUTS
}
)
# BPF is still experimental otherwise it should be available
#llvm_map_components_to_libnames(llvm_libs bpf mcjit irreader passes)
llvm_map_components_to_libnames
(
llvm_libs mcjit irreader passes
)
llvm_map_components_to_libnames
(
llvm_libs mcjit irreader passes linker instrumentation objcarcopts bitwriter option
)
# order is important
set
(
clang_libs
${
libclangFrontend
}
${
libclangParse
}
${
libclangSema
}
${
libclangCodeGen
}
${
libclangDriver
}
${
libclangAnalysis
}
${
libclangSerialization
}
${
libclangEdit
}
${
libclangLex
}
${
libclangAST
}
${
libclangBasic
}
)
# Link against LLVM libraries
target_link_libraries
(
bpfprog
${
llvm_libs
}
LLVMBPFCodeGen mnl
)
target_link_libraries
(
bpfprog
${
clang_libs
}
${
llvm_libs
}
LLVMBPFCodeGen mnl
)
src/cc/bitops.c
View file @
3d1d8358
...
...
@@ -16,57 +16,57 @@
* ====================================================================
*/
#include <
stdint
.h>
#include
"linux/bpf.h"
#include <
linux/skbuff
.h>
#include
<linux/bpf.h>
#include "bpf_helpers.h"
#define assert(v)
static
inline
u
int16_t
bpf_ntohs
(
uint16_t
val
)
{
static
inline
u
16
bpf_ntohs
(
u16
val
)
{
/* will be recognized by gcc into rotate insn and eventually rolw 8 */
return
(
val
<<
8
)
|
(
val
>>
8
);
}
static
inline
u
int32_t
bpf_ntohl
(
uint32_t
val
)
{
static
inline
u
32
bpf_ntohl
(
u32
val
)
{
/* gcc will use bswapsi2 insn */
return
__builtin_bswap32
(
val
);
}
static
inline
u
int64_t
bpf_ntohll
(
uint64_t
val
)
{
static
inline
u
64
bpf_ntohll
(
u64
val
)
{
/* gcc will use bswapdi2 insn */
return
__builtin_bswap64
(
val
);
}
static
inline
unsigned
__int128
bpf_ntoh128
(
unsigned
__int128
val
)
{
return
(((
unsigned
__int128
)
bpf_ntohll
(
val
)
<<
64
)
|
(
u
int64_t
)
bpf_ntohll
(
val
>>
64
));
return
(((
unsigned
__int128
)
bpf_ntohll
(
val
)
<<
64
)
|
(
u
64
)
bpf_ntohll
(
val
>>
64
));
}
static
inline
u
int16_t
bpf_htons
(
uint16_t
val
)
{
static
inline
u
16
bpf_htons
(
u16
val
)
{
return
bpf_ntohs
(
val
);
}
static
inline
u
int32_t
bpf_htonl
(
uint32_t
val
)
{
static
inline
u
32
bpf_htonl
(
u32
val
)
{
return
bpf_ntohl
(
val
);
}
static
inline
u
int64_t
bpf_htonll
(
uint64_t
val
)
{
static
inline
u
64
bpf_htonll
(
u64
val
)
{
return
bpf_ntohll
(
val
);
}
static
inline
unsigned
__int128
bpf_hton128
(
unsigned
__int128
val
)
{
return
bpf_ntoh128
(
val
);
}
static
inline
u
int64_t
load_dword
(
void
*
skb
,
uint64_t
off
)
{
return
((
u
int64_t
)
load_word
(
skb
,
off
)
<<
4
)
|
load_word
(
skb
,
off
+
4
);
static
inline
u
64
load_dword
(
void
*
skb
,
u64
off
)
{
return
((
u
64
)
load_word
(
skb
,
off
)
<<
4
)
|
load_word
(
skb
,
off
+
4
);
}
void
bpf_store_byte
(
void
*
skb
,
u
int64_t
off
,
uint64_t
val
)
asm
(
"llvm.bpf.store.byte"
);
void
bpf_store_half
(
void
*
skb
,
u
int64_t
off
,
uint64_t
val
)
asm
(
"llvm.bpf.store.half"
);
void
bpf_store_word
(
void
*
skb
,
u
int64_t
off
,
uint64_t
val
)
asm
(
"llvm.bpf.store.word"
);
static
inline
void
bpf_store_dword
(
void
*
skb
,
u
int64_t
off
,
uint64_t
val
)
{
bpf_store_word
(
skb
,
off
,
(
u
int32_t
)
val
);
void
bpf_store_byte
(
void
*
skb
,
u
64
off
,
u64
val
)
asm
(
"llvm.bpf.store.byte"
);
void
bpf_store_half
(
void
*
skb
,
u
64
off
,
u64
val
)
asm
(
"llvm.bpf.store.half"
);
void
bpf_store_word
(
void
*
skb
,
u
64
off
,
u64
val
)
asm
(
"llvm.bpf.store.word"
);
static
inline
void
bpf_store_dword
(
void
*
skb
,
u
64
off
,
u64
val
)
{
bpf_store_word
(
skb
,
off
,
(
u
32
)
val
);
bpf_store_word
(
skb
,
off
+
4
,
val
>>
32
);
}
#define MASK(_n) ((_n) < 64 ? (1ull << (_n)) - 1 : ((u
int64_t
)-1LL))
#define MASK(_n) ((_n) < 64 ? (1ull << (_n)) - 1 : ((u
64
)-1LL))
#define MASK128(_n) ((_n) < 128 ? ((unsigned __int128)1 << (_n)) - 1 : ((unsigned __int128)-1))
struct
_skbuff
;
...
...
@@ -74,7 +74,7 @@ struct bpf_context;
//static inline __attribute__((always_inline))
SEC
(
"helpers"
)
u
int64_t
bpf_dext_pkt
(
void
*
pkt
,
uint64_t
off
,
uint64_t
bofs
,
uint64_t
bsz
)
{
u
64
bpf_dext_pkt
(
void
*
pkt
,
u64
off
,
u64
bofs
,
u64
bsz
)
{
if
(
bofs
==
0
&&
bsz
==
8
)
{
return
load_byte
(
pkt
,
off
);
}
else
if
(
bofs
+
bsz
<=
8
)
{
...
...
@@ -97,40 +97,40 @@ uint64_t bpf_dext_pkt(void *pkt, uint64_t off, uint64_t bofs, uint64_t bsz) {
//static inline __attribute__((always_inline))
SEC
(
"helpers"
)
void
bpf_dins_pkt
(
void
*
pkt
,
u
int64_t
off
,
uint64_t
bofs
,
uint64_t
bsz
,
uint64_t
val
)
{
void
bpf_dins_pkt
(
void
*
pkt
,
u
64
off
,
u64
bofs
,
u64
bsz
,
u64
val
)
{
// The load_xxx function does a bswap before returning the short/word/dword,
// so the value in register will always be host endian. However, the bytes
// written back need to be in network order.
if
(
bofs
==
0
&&
bsz
==
8
)
{
bpf_skb_store_bytes
(
pkt
,
off
,
&
val
,
1
,
0
);
}
else
if
(
bofs
+
bsz
<=
8
)
{
u
int8_t
v
=
load_byte
(
pkt
,
off
);
u
8
v
=
load_byte
(
pkt
,
off
);
v
&=
~
(
MASK
(
bsz
)
<<
(
8
-
(
bofs
+
bsz
)));
v
|=
((
val
&
MASK
(
bsz
))
<<
(
8
-
(
bofs
+
bsz
)));
bpf_skb_store_bytes
(
pkt
,
off
,
&
v
,
1
,
0
);
}
else
if
(
bofs
==
0
&&
bsz
==
16
)
{
u
int16_t
v
=
bpf_htons
(
val
);
u
16
v
=
bpf_htons
(
val
);
bpf_skb_store_bytes
(
pkt
,
off
,
&
v
,
2
,
0
);
}
else
if
(
bofs
+
bsz
<=
16
)
{
u
int16_t
v
=
load_half
(
pkt
,
off
);
u
16
v
=
load_half
(
pkt
,
off
);
v
&=
~
(
MASK
(
bsz
)
<<
(
16
-
(
bofs
+
bsz
)));
v
|=
((
val
&
MASK
(
bsz
))
<<
(
16
-
(
bofs
+
bsz
)));
v
=
bpf_htons
(
v
);
bpf_skb_store_bytes
(
pkt
,
off
,
&
v
,
2
,
0
);
}
else
if
(
bofs
==
0
&&
bsz
==
32
)
{
u
int32_t
v
=
bpf_htonl
(
val
);
u
32
v
=
bpf_htonl
(
val
);
bpf_skb_store_bytes
(
pkt
,
off
,
&
v
,
4
,
0
);
}
else
if
(
bofs
+
bsz
<=
32
)
{
u
int32_t
v
=
load_word
(
pkt
,
off
);
u
32
v
=
load_word
(
pkt
,
off
);
v
&=
~
(
MASK
(
bsz
)
<<
(
32
-
(
bofs
+
bsz
)));
v
|=
((
val
&
MASK
(
bsz
))
<<
(
32
-
(
bofs
+
bsz
)));
v
=
bpf_htonl
(
v
);
bpf_skb_store_bytes
(
pkt
,
off
,
&
v
,
4
,
0
);
}
else
if
(
bofs
==
0
&&
bsz
==
64
)
{
u
int64_t
v
=
bpf_htonll
(
val
);
u
64
v
=
bpf_htonll
(
val
);
bpf_skb_store_bytes
(
pkt
,
off
,
&
v
,
8
,
0
);
}
else
if
(
bofs
+
bsz
<=
64
)
{
u
int64_t
v
=
load_dword
(
pkt
,
off
);
u
64
v
=
load_dword
(
pkt
,
off
);
v
&=
~
(
MASK
(
bsz
)
<<
(
64
-
(
bofs
+
bsz
)));
v
|=
((
val
&
MASK
(
bsz
))
<<
(
64
-
(
bofs
+
bsz
)));
v
=
bpf_htonll
(
v
);
...
...
@@ -150,7 +150,7 @@ void * bpf_map_lookup_elem_(uintptr_t map, void *key) {
}
SEC
(
"helpers"
)
int
bpf_map_update_elem_
(
uintptr_t
map
,
void
*
key
,
void
*
value
,
u
int64_t
flags
)
{
int
bpf_map_update_elem_
(
uintptr_t
map
,
void
*
key
,
void
*
value
,
u
64
flags
)
{
return
bpf_map_update_elem
((
void
*
)
map
,
key
,
value
,
flags
);
}
...
...
@@ -160,12 +160,12 @@ int bpf_map_delete_elem_(uintptr_t map, void *key) {
}
SEC
(
"helpers"
)
int
bpf_skb_store_bytes_
(
void
*
ctx
,
u
int64_t
off
,
void
*
from
,
uint64_t
len
,
uint64_t
flags
)
{
int
bpf_skb_store_bytes_
(
void
*
ctx
,
u
64
off
,
void
*
from
,
u64
len
,
u64
flags
)
{
return
bpf_skb_store_bytes
(
ctx
,
off
,
from
,
len
,
flags
);
}
SEC
(
"helpers"
)
int
bpf_l3_csum_replace_
(
void
*
ctx
,
u
int64_t
off
,
uint64_t
from
,
uint64_t
to
,
uint64_t
flags
)
{
int
bpf_l3_csum_replace_
(
void
*
ctx
,
u
64
off
,
u64
from
,
u64
to
,
u64
flags
)
{
switch
(
flags
&
0xf
)
{
case
2
:
return
bpf_l3_csum_replace
(
ctx
,
off
,
bpf_htons
(
from
),
bpf_htons
(
to
),
flags
);
...
...
@@ -180,7 +180,7 @@ int bpf_l3_csum_replace_(void *ctx, uint64_t off, uint64_t from, uint64_t to, ui
}
SEC
(
"helpers"
)
int
bpf_l4_csum_replace_
(
void
*
ctx
,
u
int64_t
off
,
uint64_t
from
,
uint64_t
to
,
uint64_t
flags
)
{
int
bpf_l4_csum_replace_
(
void
*
ctx
,
u
64
off
,
u64
from
,
u64
to
,
u64
flags
)
{
switch
(
flags
&
0xf
)
{
case
2
:
return
bpf_l4_csum_replace
(
ctx
,
off
,
bpf_htons
(
from
),
bpf_htons
(
to
),
flags
);
...
...
src/cc/bpf_program.cc
View file @
3d1d8358
// Generated by llvm2cpp - DO NOT MODIFY!
#include <algorithm>
#include <fcntl.h>
#include <ftw.h>
#include <map>
#include <stdio.h>
#include <string>
#include <sys/stat.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <vector>
#include <clang/Basic/FileManager.h>
#include <clang/Basic/TargetInfo.h>
#include <clang/CodeGen/BackendUtil.h>
#include <clang/CodeGen/CodeGenAction.h>
#include <clang/CodeGen/ModuleBuilder.h>
#include <clang/Driver/Compilation.h>
#include <clang/Driver/Driver.h>
#include <clang/Driver/Job.h>
#include <clang/Driver/Tool.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Frontend/CompilerInvocation.h>
#include <clang/Frontend/FrontendDiagnostic.h>
#include <clang/Frontend/TextDiagnosticPrinter.h>
#include <clang/FrontendTool/Utils.h>
#include "clang/Parse/ParseAST.h"
#include <llvm/ADT/STLExtras.h>
#include <llvm/ExecutionEngine/MCJIT.h>
...
...
@@ -15,6 +36,7 @@
#include <llvm/IR/Verifier.h>
#include <llvm/Object/ObjectFile.h>
#include <llvm/Support/FormattedStream.h>
#include <llvm/Support/Host.h>
#include <llvm/Support/SourceMgr.h>
#include <llvm/Transforms/IPO.h>
#include <llvm/Transforms/IPO/PassManagerBuilder.h>
...
...
@@ -25,6 +47,11 @@
#include "codegen_llvm.h"
#include "bpf_program.h"
#define KERNEL_MODULES_DIR "/lib/modules"
// This is temporary, to be removed in the next commit
#define HELPER_FILE "../../src/cc/bitops.c"
namespace
ebpf
{
using
std
::
get
;
...
...
@@ -34,6 +61,7 @@ using std::move;
using
std
::
string
;
using
std
::
tuple
;
using
std
::
unique_ptr
;
using
std
::
vector
;
using
namespace
llvm
;
// Snooping class to remember the sections as the JIT creates them
...
...
@@ -67,7 +95,7 @@ class MyMemoryManager : public SectionMemoryManager {
};
BPFProgram
::
BPFProgram
(
unsigned
flags
)
:
flags_
(
flags
)
{
:
flags_
(
flags
)
,
ctx_
(
new
LLVMContext
)
{
LLVMInitializeBPFTarget
();
LLVMInitializeBPFTargetMC
();
LLVMInitializeBPFTargetInfo
();
...
...
@@ -77,7 +105,7 @@ BPFProgram::BPFProgram(unsigned flags)
BPFProgram
::~
BPFProgram
()
{
engine_
.
reset
();
LLVMShutdown
();
ctx_
.
reset
();
}
int
BPFProgram
::
parse
()
{
...
...
@@ -117,27 +145,230 @@ int BPFProgram::parse() {
return
0
;
}
string
BPFProgram
::
load_helper
()
const
{
// generated from bitops.cc -> bitops.bc -> hexdump -> bitops.h
#include "cc/bitops.h"
return
string
((
const
char
*
)
bitops_bc
,
bitops_bc_len
);
// Helper with pushd/popd semantics
class
DirStack
{
public:
explicit
DirStack
(
const
char
*
dst
)
:
ok_
(
false
)
{
if
(
getcwd
(
cwd_
,
sizeof
(
cwd_
))
==
NULL
)
{
::
perror
(
"getcwd"
);
return
;
}
if
(
::
chdir
(
dst
))
{
fprintf
(
stderr
,
"chdir(%s): %s
\n
"
,
dst
,
strerror
(
errno
));
return
;
}
ok_
=
true
;
}
~
DirStack
()
{
if
(
!
ok_
)
return
;
if
(
::
chdir
(
cwd_
))
{
fprintf
(
stderr
,
"chdir(%s): %s
\n
"
,
cwd_
,
strerror
(
errno
));
}
}
bool
ok
()
const
{
return
ok_
;
}
const
char
*
cwd
()
const
{
return
cwd_
;
}
private:
bool
ok_
;
char
cwd_
[
256
];
};
struct
FileDeleter
{
void
operator
()
(
FILE
*
fp
)
{
fclose
(
fp
);
}
};
typedef
std
::
unique_ptr
<
FILE
,
FileDeleter
>
FILEPtr
;
// Scoped class to manage the creation/deletion of tmpdirs
class
TmpDir
{
public:
explicit
TmpDir
(
const
string
&
prefix
=
"/tmp/bcc-"
)
:
ok_
(
false
),
prefix_
(
prefix
)
{
prefix_
+=
"XXXXXX"
;
if
(
::
mkdtemp
((
char
*
)
prefix
.
data
())
==
NULL
)
::
perror
(
"mkdtemp"
);
else
ok_
=
true
;
}
~
TmpDir
()
{
auto
fn
=
[]
(
const
char
*
path
,
const
struct
stat
*
,
int
)
->
int
{
return
::
remove
(
path
);
};
if
(
::
ftw
(
prefix_
.
c_str
(),
fn
,
20
)
<
0
)
::
perror
(
"ftw"
);
else
::
remove
(
prefix_
.
c_str
());
}
bool
ok
()
const
{
return
ok_
;
}
const
string
&
str
()
const
{
return
prefix_
;
}
private:
bool
ok_
;
string
prefix_
;
};
// Compute the kbuild flags for the currently running kernel
// Do this by:
// 1. Create temp Makefile with stub dummy.c
// 2. Run module build on that makefile, saving the computed flags to a file
// 3. Cache the file for fast flag lookup in subsequent runs
// Note: Depending on environment, different cache locations may be desired. In
// case we eventually support non-root user programs, cache in $HOME.
// Makefile helper for kbuild_flags
static
int
learn_flags
(
const
string
&
tmpdir
,
const
char
*
uname_release
,
const
char
*
cachefile
)
{
{
// Create a kbuild file to generate the flags
string
makefile
=
tmpdir
+
"/Makefile"
;
FILEPtr
mf
(
::
fopen
(
makefile
.
c_str
(),
"w"
));
if
(
!
mf
)
return
-
1
;
fprintf
(
&*
mf
,
"obj-y := dummy.o
\n
"
);
fprintf
(
&*
mf
,
"CACHEDIR=$(dir %s)
\n
"
,
cachefile
);
fprintf
(
&*
mf
,
"$(CACHEDIR):
\n
"
);
fprintf
(
&*
mf
,
"
\t
@mkdir -p $(CACHEDIR)
\n
"
);
fprintf
(
&*
mf
,
"$(obj)/%%.o: $(src)/%%.c $(CACHEDIR)
\n
"
);
fprintf
(
&*
mf
,
"
\t
@echo -n
\"
$(NOSTDINC_FLAGS) $(LINUXINCLUDE) $(EXTRA_CFLAGS) "
"-D__KERNEL__ -Wno-unused-value -Wno-pointer-sign
\"
> %s
\n
"
,
cachefile
);
}
{
string
cfile
=
tmpdir
+
"/dummy.c"
;
FILEPtr
cf
(
::
fopen
(
cfile
.
c_str
(),
"w"
));
if
(
!
cf
)
return
-
1
;
}
string
cmd
=
"make -s"
;
cmd
+=
" -C "
KERNEL_MODULES_DIR
"/"
+
string
(
uname_release
)
+
"/build"
;
cmd
+=
" M="
+
tmpdir
+
" dummy.o"
;
int
rc
=
::
system
(
cmd
.
c_str
());
if
(
rc
<
0
)
{
::
perror
(
"system"
);
return
-
1
;
}
return
::
open
(
cachefile
,
O_RDONLY
);
}
// read the flags from cache or learn
int
BPFProgram
::
kbuild_flags
(
const
char
*
uname_release
,
vector
<
string
>
*
cflags
)
{
char
cachefile
[
256
];
char
*
home
=
::
getenv
(
"HOME"
);
if
(
home
)
snprintf
(
cachefile
,
sizeof
(
cachefile
),
"%s/.cache/bcc/%s.flags"
,
home
,
uname_release
);
else
snprintf
(
cachefile
,
sizeof
(
cachefile
),
"/var/run/bcc/%s.flags"
,
uname_release
);
int
cachefd
=
::
open
(
cachefile
,
O_RDONLY
);
if
(
cachefd
<
0
)
{
TmpDir
tmpdir
;
if
(
!
tmpdir
.
ok
())
return
-
1
;
cachefd
=
learn_flags
(
tmpdir
.
str
(),
uname_release
,
cachefile
);
if
(
cachefd
<
0
)
return
-
1
;
}
FILEPtr
f
(
::
fdopen
(
cachefd
,
"r"
));
size_t
len
=
0
;
char
*
line
=
NULL
;
ssize_t
nread
;
while
((
nread
=
getdelim
(
&
line
,
&
len
,
' '
,
&*
f
))
>=
0
)
{
if
(
nread
==
0
||
(
nread
==
1
&&
line
[
0
]
==
' '
))
continue
;
if
(
line
[
nread
-
1
]
==
' '
)
--
nread
;
cflags
->
push_back
(
string
(
line
,
nread
));
}
free
(
line
);
return
0
;
}
int
BPFProgram
::
load_helper
(
unique_ptr
<
llvm
::
Module
>
*
mod
)
{
using
namespace
clang
;
struct
utsname
un
;
uname
(
&
un
);
char
kdir
[
256
];
snprintf
(
kdir
,
sizeof
(
kdir
),
"%s/%s/build"
,
KERNEL_MODULES_DIR
,
un
.
release
);
DirStack
dstack
(
kdir
);
if
(
!
dstack
.
ok
())
return
-
1
;
string
file
=
string
(
dstack
.
cwd
())
+
"/"
HELPER_FILE
;
vector
<
const
char
*>
flags_cstr
({
"-fsyntax-only"
,
"-emit-llvm"
,
"-o"
,
"/dev/null"
,
"-c"
,
file
.
c_str
()});
vector
<
string
>
kflags
;
if
(
kbuild_flags
(
un
.
release
,
&
kflags
))
return
-
1
;
for
(
auto
it
=
kflags
.
begin
();
it
!=
kflags
.
end
();
++
it
)
flags_cstr
.
push_back
(
it
->
c_str
());
IntrusiveRefCntPtr
<
DiagnosticOptions
>
diag_opts
(
new
DiagnosticOptions
());
auto
diag_client
=
new
TextDiagnosticPrinter
(
llvm
::
errs
(),
&*
diag_opts
);
IntrusiveRefCntPtr
<
DiagnosticIDs
>
DiagID
(
new
DiagnosticIDs
());
DiagnosticsEngine
diags
(
DiagID
,
&*
diag_opts
,
diag_client
);
driver
::
Driver
drv
(
""
,
"x86_64-unknown-linux-gnu"
,
diags
);
drv
.
setTitle
(
"bcc-clang-driver"
);
drv
.
setCheckInputsExist
(
false
);
unique_ptr
<
driver
::
Compilation
>
compilation
(
drv
.
BuildCompilation
(
flags_cstr
));
if
(
!
compilation
)
return
0
;
// expect exactly 1 job, otherwise error
const
driver
::
JobList
&
jobs
=
compilation
->
getJobs
();
if
(
jobs
.
size
()
!=
1
||
!
isa
<
driver
::
Command
>
(
*
jobs
.
begin
()))
{
SmallString
<
256
>
msg
;
llvm
::
raw_svector_ostream
os
(
msg
);
jobs
.
Print
(
os
,
"; "
,
true
);
diags
.
Report
(
diag
::
err_fe_expected_compiler_job
)
<<
os
.
str
();
return
-
1
;
}
const
driver
::
Command
&
cmd
=
cast
<
driver
::
Command
>
(
*
jobs
.
begin
());
if
(
llvm
::
StringRef
(
cmd
.
getCreator
().
getName
())
!=
"clang"
)
{
diags
.
Report
(
diag
::
err_fe_expected_clang_command
);
return
-
1
;
}
// Initialize a compiler invocation object from the clang (-cc1) arguments.
const
driver
::
ArgStringList
&
ccargs
=
cmd
.
getArguments
();
auto
invocation
=
make_unique
<
CompilerInvocation
>
();
CompilerInvocation
::
CreateFromArgs
(
*
invocation
,
const_cast
<
const
char
**>
(
ccargs
.
data
()),
const_cast
<
const
char
**>
(
ccargs
.
data
())
+
ccargs
.
size
(),
diags
);
// Show the invocation, with -v.
if
(
invocation
->
getHeaderSearchOpts
().
Verbose
)
jobs
.
Print
(
llvm
::
errs
(),
"
\n
"
,
true
);
// Create a compiler instance to handle the actual work.
CompilerInstance
compiler
;
compiler
.
setInvocation
(
invocation
.
release
());
// Create the compilers actual diagnostics engine.
compiler
.
createDiagnostics
();
if
(
!
compiler
.
hasDiagnostics
())
return
-
1
;
// Create and execute the frontend to generate an LLVM bitcode module.
EmitLLVMOnlyAction
act
(
&*
ctx_
);
if
(
!
compiler
.
ExecuteAction
(
act
))
return
-
1
;
*
mod
=
act
.
takeModule
();
return
0
;
}
// Load in a pre-built list of functions into the initial Module object, then
// build an ExecutionEngine.
int
BPFProgram
::
init_engine
()
{
SMDiagnostic
diag
;
string
helper
=
load_helper
();
MemoryBufferRef
helper_mem
(
helper
,
"helper"
);
unique_ptr
<
Module
>
mod
=
parseIR
(
helper_mem
,
diag
,
getGlobalContext
());
if
(
!
mod
)
{
diag
.
print
(
"bitops"
,
errs
());
exit
(
1
);
}
mod_
=
mod
.
get
();
unique_ptr
<
Module
>
mod
;
if
(
load_helper
(
&
mod
))
return
-
1
;
mod_
=
&*
mod
;
mod_
->
setDataLayout
(
"e-m:e-i64:64-f80:128-n8:16:32:64-S128"
);
mod_
->
setTargetTriple
(
"bpf"
);
mod_
->
setTargetTriple
(
"bpf
-pc-linux
"
);
for
(
auto
fn
=
mod_
->
getFunctionList
().
begin
();
fn
!=
mod_
->
getFunctionList
().
end
();
++
fn
)
fn
->
addFnAttr
(
Attribute
::
AlwaysInline
);
...
...
src/cc/bpf_program.h
View file @
3d1d8358
...
...
@@ -26,6 +26,7 @@
namespace
llvm
{
class
ExecutionEngine
;
class
LLVMContext
;
class
Module
;
}
...
...
@@ -42,7 +43,8 @@ class BPFProgram {
int
parse
();
int
finalize
();
void
dump_ir
();
std
::
string
load_helper
()
const
;
int
load_helper
(
std
::
unique_ptr
<
llvm
::
Module
>
*
mod
);
int
kbuild_flags
(
const
char
*
uname_release
,
std
::
vector
<
std
::
string
>
*
cflags
);
public:
BPFProgram
(
unsigned
flags
);
~
BPFProgram
();
...
...
@@ -55,6 +57,7 @@ class BPFProgram {
unsigned
flags_
;
// 0x1 for printing
std
::
string
filename_
;
std
::
string
proto_filename_
;
std
::
unique_ptr
<
llvm
::
LLVMContext
>
ctx_
;
std
::
unique_ptr
<
llvm
::
ExecutionEngine
>
engine_
;
llvm
::
Module
*
mod_
;
std
::
unique_ptr
<
ebpf
::
cc
::
Parser
>
parser_
;
...
...
src/cc/parser.yy
View file @
3d1d8358
...
...
@@ -440,15 +440,17 @@ numeric
;
assign_expr
: dotted_ident TEQUAL expr
: expr TEQUAL expr
{ $$ = new AssignExprNode(ExprNode::Ptr($1), ExprNode::Ptr($3));
parser.set_loc($$, @$); }
/* The below has a reduce/reduce conflict.
TODO: ensure the above is handled in the type check properly */
/*| dotted_ident TEQUAL expr
{ $$ = new AssignExprNode(IdentExprNode::Ptr($1), ExprNode::Ptr($3));
parser.set_loc($$, @$); }
| dotted_ident bitop TEQUAL expr
{ $$ = new AssignExprNode(IdentExprNode::Ptr($1), ExprNode::Ptr($4)); $$->bitop_ = BitopExprNode::Ptr($2);
parser.set_loc($$, @$); }
| expr TEQUAL expr
{ $$ = new AssignExprNode(ExprNode::Ptr($1), ExprNode::Ptr($3));
parser.set_loc($$, @$); }
parser.set_loc($$, @$); }*/
;
return_expr
...
...
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