Permalink
Browse files

bcc/cc: Make kernel building more configurable

Using bcc for cross development requires ability to set a custom
kernel source path and architecture, further such changes needed to
be propogated to bcc helpers so that the bpf program is built
properly. This patches does all this.

Signed-off-by: Joel Fernandes <joelaf@google.com>
  • Loading branch information...
Joel Fernandes
Joel Fernandes committed Jan 7, 2018
1 parent 76cef27 commit 2a2f9d41c336d8aa058338ae536bd93d31dbb1ef
@@ -543,7 +543,37 @@ struct pt_regs;
int bpf_usdt_readarg(int argc, struct pt_regs *ctx, void *arg) asm("llvm.bpf.extra");
int bpf_usdt_readarg_p(int argc, struct pt_regs *ctx, void *buf, u64 len) asm("llvm.bpf.extra");
#ifdef __powerpc__
/* Scan the ARCH passed in from ARCH env variable (see Makefile) */
#if defined(__TARGET_ARCH_x86)
#define bpf_target_x86
#define bpf_target_defined
#elif defined(__TARGET_ARCH_s930x)
#define bpf_target_s930x
#define bpf_target_defined
#elif defined(__TARGET_ARCH_arm64)
#define bpf_target_arm64
#define bpf_target_defined
#elif defined(__TARGET_ARCH_powerpc)
#define bpf_target_powerpc
#define bpf_target_defined
#else
#undef bpf_target_defined
#endif
/* Fall back to what the compiler says */
#ifndef bpf_target_defined
#if defined(__x86_64__)
#define bpf_target_x86
#elif defined(__s390x__)
#define bpf_target_s930x
#elif defined(__aarch64__)
#define bpf_target_arm64
#elif defined(__powerpc__)
#define bpf_target_powerpc
#endif
#endif
#if defined(bpf_target_powerpc)
#define PT_REGS_PARM1(ctx) ((ctx)->gpr[3])
#define PT_REGS_PARM2(ctx) ((ctx)->gpr[4])
#define PT_REGS_PARM3(ctx) ((ctx)->gpr[5])
@@ -553,7 +583,7 @@ int bpf_usdt_readarg_p(int argc, struct pt_regs *ctx, void *buf, u64 len) asm("l
#define PT_REGS_RC(ctx) ((ctx)->gpr[3])
#define PT_REGS_IP(ctx) ((ctx)->nip)
#define PT_REGS_SP(ctx) ((ctx)->gpr[1])
#elif defined(__s390x__)
#elif defined(bpf_target_s930x)
#define PT_REGS_PARM1(x) ((x)->gprs[2])
#define PT_REGS_PARM2(x) ((x)->gprs[3])
#define PT_REGS_PARM3(x) ((x)->gprs[4])
@@ -564,7 +594,7 @@ int bpf_usdt_readarg_p(int argc, struct pt_regs *ctx, void *buf, u64 len) asm("l
#define PT_REGS_RC(x) ((x)->gprs[2])
#define PT_REGS_SP(x) ((x)->gprs[15])
#define PT_REGS_IP(x) ((x)->psw.addr)
#elif defined(__x86_64__)
#elif defined(bpf_target_x86)
#define PT_REGS_PARM1(ctx) ((ctx)->di)
#define PT_REGS_PARM2(ctx) ((ctx)->si)
#define PT_REGS_PARM3(ctx) ((ctx)->dx)
@@ -575,7 +605,7 @@ int bpf_usdt_readarg_p(int argc, struct pt_regs *ctx, void *buf, u64 len) asm("l
#define PT_REGS_RC(ctx) ((ctx)->ax)
#define PT_REGS_IP(ctx) ((ctx)->ip)
#define PT_REGS_SP(ctx) ((ctx)->sp)
#elif defined(__aarch64__)
#elif defined(bpf_target_arm64)
#define PT_REGS_PARM1(x) ((x)->regs[0])
#define PT_REGS_PARM2(x) ((x)->regs[1])
#define PT_REGS_PARM3(x) ((x)->regs[2])
@@ -587,6 +617,7 @@ int bpf_usdt_readarg_p(int argc, struct pt_regs *ctx, void *buf, u64 len) asm("l
#define PT_REGS_RC(x) ((x)->regs[0])
#define PT_REGS_SP(x) ((x)->sp)
#define PT_REGS_IP(x) ((x)->pc)
#else
#error "bcc does not support this platform yet"
#endif
@@ -47,16 +47,33 @@ const char *calling_conv_regs_s390x[] = {"gprs[2]", "gprs[3]", "gprs[4]",
const char *calling_conv_regs_arm64[] = {"regs[0]", "regs[1]", "regs[2]",
"regs[3]", "regs[4]", "regs[5]"};
const char **get_call_conv(void) {
const char *archenv = ::getenv("ARCH");
if (!archenv) {
// todo: support more archs
#if defined(__powerpc__)
const char **calling_conv_regs = calling_conv_regs_ppc;
#if defined(__powerpc64__)
return calling_conv_regs_ppc;
#elif defined(__s390x__)
const char **calling_conv_regs = calling_conv_regs_s390x;
return calling_conv_regs_s390x;
#elif defined(__aarch64__)
const char **calling_conv_regs = calling_conv_regs_arm64;
return calling_conv_regs_arm64;
#else
const char **calling_conv_regs = calling_conv_regs_x86;
return calling_conv_regs_x86;
#endif
} else {
if (!strcmp(archenv, "powerpc")) {
return calling_conv_regs_ppc;
} else if (!strcmp(archenv, "s390x")) {
return calling_conv_regs_s390x;
} else if (!strcmp(archenv, "arm64")) {
return calling_conv_regs_arm64;
} else {
return calling_conv_regs_x86;
}
}
}
using std::map;
using std::move;
@@ -256,6 +273,8 @@ BTypeVisitor::BTypeVisitor(ASTContext &C, BFrontendAction &fe)
: C(C), diag_(C.getDiagnostics()), fe_(fe), rewriter_(fe.rewriter()), out_(llvm::errs()) {}
bool BTypeVisitor::VisitFunctionDecl(FunctionDecl *D) {
const char **calling_conv_regs = get_call_conv();
// put each non-static non-inline function decl in its own section, to be
// extracted by the MemoryManager
auto real_start_loc = rewriter_.getSourceMgr().getFileLoc(D->getLocStart());
@@ -14,6 +14,8 @@
* limitations under the License.
*/
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <ftw.h>
#include "kbuild_helper.h"
@@ -34,6 +36,8 @@ int KBuildHelper::get_flags(const char *uname_machine, vector<string> *cflags) {
// -e s/aarch64.*/arm64/
string arch = uname_machine;
const char *archenv;
if (!strncmp(uname_machine, "x86_64", 6)) {
arch = "x86";
} else if (uname_machine[0] == 'i' && !strncmp(&uname_machine[2], "86", 2)) {
@@ -56,6 +60,15 @@ int KBuildHelper::get_flags(const char *uname_machine, vector<string> *cflags) {
arch = "arm64";
}
// If ARCH env is defined, use it over uname
archenv = getenv("ARCH");
if (archenv) {
if (getenv("BCC_KBUILD_DEBUG"))
printf("Using archiecture %s from env instead of uname\n", archenv);
arch = string(archenv);
}
cflags->push_back("-nostdinc");
cflags->push_back("-isystem");
cflags->push_back("/virtual/lib/clang/include");
@@ -87,6 +100,11 @@ int KBuildHelper::get_flags(const char *uname_machine, vector<string> *cflags) {
cflags->push_back("-D__HAVE_BUILTIN_BSWAP16__");
cflags->push_back("-D__HAVE_BUILTIN_BSWAP32__");
cflags->push_back("-D__HAVE_BUILTIN_BSWAP64__");
// If ARCH env variable is set, pass this along.
if (archenv)
cflags->push_back("-D__TARGET_ARCH_" + arch);
cflags->push_back("-Wno-unused-value");
cflags->push_back("-Wno-pointer-sign");
cflags->push_back("-fno-stack-protector");
@@ -20,6 +20,7 @@
#include <fcntl.h>
#include <ftw.h>
#include <map>
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string>
@@ -108,11 +109,26 @@ int ClangLoader::parse(unique_ptr<llvm::Module> *mod, TableStorage &ts,
unique_ptr<llvm::MemoryBuffer> main_buf;
struct utsname un;
uname(&un);
string kdir = string(KERNEL_MODULES_DIR) + "/" + un.release;
auto kernel_path_info = get_kernel_path_info (kdir);
string kdir, kpath;
const char *kpath_env = ::getenv("BCC_KERNEL_SOURCE");
bool has_kpath_source = false;
if (kpath_env) {
kpath = string(kpath_env);
} else {
kdir = string(KERNEL_MODULES_DIR) + "/" + un.release;
auto kernel_path_info = get_kernel_path_info (kdir);
has_kpath_source = kernel_path_info.first;
kpath = kdir + "/" + kernel_path_info.second;
}
if (getenv("BCC_KBUILD_DEBUG"))
printf("Using kernel directory at: %s\n", kpath.c_str());
// clang needs to run inside the kernel dir
DirStack dstack(kdir + "/" + kernel_path_info.second);
DirStack dstack(kpath);
if (!dstack.ok())
return -1;
@@ -143,7 +159,9 @@ int ClangLoader::parse(unique_ptr<llvm::Module> *mod, TableStorage &ts,
"-fno-asynchronous-unwind-tables",
"-x", "c", "-c", abs_file.c_str()});
KBuildHelper kbuild_helper(kdir, kernel_path_info.first);
KBuildHelper kbuild_helper(kpath_env ? kpath : kdir, has_kpath_source);
vector<string> kflags;
if (kbuild_helper.get_flags(un.machine, &kflags))
return -1;
@@ -186,6 +204,40 @@ int ClangLoader::parse(unique_ptr<llvm::Module> *mod, TableStorage &ts,
return 0;
}
string get_clang_target(void) {
const char *archenv = ::getenv("ARCH");
if (!archenv) {
#if defined(__powerpc64__)
#if defined(_CALL_ELF) && _CALL_ELF == 2
return "powerpc64le-unknown-linux-gnu";
#else
return "powerpc64-unknown-linux-gnu";
#endif
#elif defined(__s390x__)
return "s390x-ibm-linux-gnu";
#elif defined(__aarch64__)
return "aarch64-unknown-linux-gnu";
#else
return "x86_64-unknown-linux-gnu";
#endif
} else {
if (!strcmp(archenv, "powerpc")) {
#if defined(_CALL_ELF) && _CALL_ELF == 2
return "powerpc64le-unknown-linux-gnu";
#else
return "powerpc64-unknown-linux-gnu";
#endif
} else if (!strcmp(archenv, "s390x")) {
return "s390x-ibm-linux-gnu";
} else if (!strcmp(archenv, "arm64")) {
return "aarch64-unknown-linux-gnu";
} else {
return "x86_64-unknown-linux-gnu";
}
}
}
int ClangLoader::do_compile(unique_ptr<llvm::Module> *mod, TableStorage &ts,
bool in_memory,
const vector<const char *> &flags_cstr_in,
@@ -211,20 +263,19 @@ int ClangLoader::do_compile(unique_ptr<llvm::Module> *mod, TableStorage &ts,
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
DiagnosticsEngine diags(DiagID, &*diag_opts, diag_client);
if (getenv("BCC_KBUILD_DEBUG")) {
printf("Kernel flags for the build are set to:\n");

This comment has been minimized.

@josefbacik

josefbacik Jan 25, 2018

We are in c++ land, maybe we should use std::cout everywhere?

This comment has been minimized.

@joelagnel

joelagnel Jan 25, 2018

Owner

Ok, will fix.

for (const auto& value : flags_cstr) {
std::cout << value << '\n';
}
std::cout << "\n";
}
// set up the command line argument wrapper
#if defined(__powerpc64__)
#if defined(_CALL_ELF) && _CALL_ELF == 2
driver::Driver drv("", "powerpc64le-unknown-linux-gnu", diags);
#else
driver::Driver drv("", "powerpc64-unknown-linux-gnu", diags);
#endif
#elif defined(__s390x__)
driver::Driver drv("", "s390x-ibm-linux-gnu", diags);
#elif defined(__aarch64__)
driver::Driver drv("", "aarch64-unknown-linux-gnu", diags);
#else
driver::Driver drv("", "x86_64-unknown-linux-gnu", diags);
#endif
string target_triple = get_clang_target();
driver::Driver drv("", target_triple, diags);
drv.setTitle("bcc-clang-driver");
drv.setCheckInputsExist(false);

0 comments on commit 2a2f9d4

Please sign in to comment.