Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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 committed Jan 10, 2018
1 parent 76cef27 commit 2a2f9d4
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 26 deletions.
39 changes: 35 additions & 4 deletions src/cc/export/helpers.h
Expand Up @@ -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])
Expand All @@ -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])
Expand All @@ -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)
Expand All @@ -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])
Expand All @@ -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
Expand Down
29 changes: 24 additions & 5 deletions src/cc/frontends/clang/b_frontend_action.cc
Expand Up @@ -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;
Expand Down Expand Up @@ -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());
Expand Down
18 changes: 18 additions & 0 deletions src/cc/frontends/clang/kbuild_helper.cc
Expand Up @@ -14,6 +14,8 @@
* limitations under the License.
*/
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <ftw.h>
#include "kbuild_helper.h"

Expand All @@ -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)) {
Expand All @@ -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");
Expand Down Expand Up @@ -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");
Expand Down
85 changes: 68 additions & 17 deletions src/cc/frontends/clang/loader.cc
Expand Up @@ -20,6 +20,7 @@
#include <fcntl.h>
#include <ftw.h>
#include <map>
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string>
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand All @@ -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.

Copy link
@josefbacik

josefbacik Jan 25, 2018

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

This comment has been minimized.

Copy link
@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);

Expand Down

0 comments on commit 2a2f9d4

Please sign in to comment.