Skip to content

Commit

Permalink
use correct arch register for the 4th param of x86_64 syscalls
Browse files Browse the repository at this point in the history
Fix #3150

On x86_64, for syscalls, the calling convension is to use
r10 instead of rcx for the 4th parameter. I have verified this
with disassembling vmlinux codes.
  https://www.systutorials.com/x86-64-calling-convention-by-gcc/

bcc previously used rcx for the 4th parameter for all cases.
This patch fixed the issue by using r10 for syscalls.
A macro PT_REGS_PARM4_SYSCALL() is also introduced in helpers.h
to access the 4th parameter for r10.

Signed-off-by: Yonghong Song <[email protected]>
  • Loading branch information
yonghong-song committed Nov 4, 2020
1 parent ad5b82a commit 12107c6
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 18 deletions.
1 change: 1 addition & 0 deletions src/cc/export/helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -1099,6 +1099,7 @@ int bpf_usdt_readarg_p(int argc, struct pt_regs *ctx, void *buf, u64 len) asm("l
#define PT_REGS_PARM2(ctx) ((ctx)->si)
#define PT_REGS_PARM3(ctx) ((ctx)->dx)
#define PT_REGS_PARM4(ctx) ((ctx)->cx)
#define PT_REGS_PARM4_SYSCALL(ctx) ((ctx)->r10) /* for syscall only */
#define PT_REGS_PARM5(ctx) ((ctx)->r8)
#define PT_REGS_PARM6(ctx) ((ctx)->r9)
#define PT_REGS_RET(ctx) ((ctx)->sp)
Expand Down
24 changes: 12 additions & 12 deletions src/cc/frontends/clang/arch_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,41 +25,41 @@ typedef enum {
BCC_ARCH_X86
} bcc_arch_t;

typedef void *(*arch_callback_t)(bcc_arch_t arch);
typedef void *(*arch_callback_t)(bcc_arch_t arch, bool for_syscall);

static void *run_arch_callback(arch_callback_t fn)
static void *run_arch_callback(arch_callback_t fn, bool for_syscall = false)
{
const char *archenv = getenv("ARCH");

/* If ARCH is not set, detect from local arch clang is running on */
if (!archenv) {
#if defined(__powerpc64__)
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
return fn(BCC_ARCH_PPC_LE);
return fn(BCC_ARCH_PPC_LE, for_syscall);
#else
return fn(BCC_ARCH_PPC);
return fn(BCC_ARCH_PPC, for_syscall);
#endif
#elif defined(__s390x__)
return fn(BCC_ARCH_S390X);
return fn(BCC_ARCH_S390X, for_syscall);
#elif defined(__aarch64__)
return fn(BCC_ARCH_ARM64);
return fn(BCC_ARCH_ARM64, for_syscall);
#else
return fn(BCC_ARCH_X86);
return fn(BCC_ARCH_X86, for_syscall);
#endif
}

/* Otherwise read it from ARCH */
if (!strcmp(archenv, "powerpc")) {
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
return fn(BCC_ARCH_PPC_LE);
return fn(BCC_ARCH_PPC_LE, for_syscall);
#else
return fn(BCC_ARCH_PPC);
return fn(BCC_ARCH_PPC, for_syscall);
#endif
} else if (!strcmp(archenv, "s390x")) {
return fn(BCC_ARCH_S390X);
return fn(BCC_ARCH_S390X, for_syscall);
} else if (!strcmp(archenv, "arm64")) {
return fn(BCC_ARCH_ARM64);
return fn(BCC_ARCH_ARM64, for_syscall);
} else {
return fn(BCC_ARCH_X86);
return fn(BCC_ARCH_X86, for_syscall);
}
}
16 changes: 11 additions & 5 deletions src/cc/frontends/clang/b_frontend_action.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ constexpr int MAX_CALLING_CONV_REGS = 6;
const char *calling_conv_regs_x86[] = {
"di", "si", "dx", "cx", "r8", "r9"
};
const char *calling_conv_syscall_regs_x86[] = {
"di", "si", "dx", "r10", "r8", "r9"
};
const char *calling_conv_regs_ppc[] = {"gpr[3]", "gpr[4]", "gpr[5]",
"gpr[6]", "gpr[7]", "gpr[8]"};

Expand All @@ -54,7 +57,7 @@ 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]"};

void *get_call_conv_cb(bcc_arch_t arch)
void *get_call_conv_cb(bcc_arch_t arch, bool for_syscall)
{
const char **ret;

Expand All @@ -70,16 +73,19 @@ void *get_call_conv_cb(bcc_arch_t arch)
ret = calling_conv_regs_arm64;
break;
default:
ret = calling_conv_regs_x86;
if (for_syscall)
ret = calling_conv_syscall_regs_x86;
else
ret = calling_conv_regs_x86;
}

return (void *)ret;
}

const char **get_call_conv(void) {
const char **get_call_conv(bool for_syscall = false) {
const char **ret;

ret = (const char **)run_arch_callback(get_call_conv_cb);
ret = (const char **)run_arch_callback(get_call_conv_cb, for_syscall);
return ret;
}

Expand Down Expand Up @@ -760,7 +766,7 @@ void BTypeVisitor::genParamIndirectAssign(FunctionDecl *D, string& preamble,
}

void BTypeVisitor::rewriteFuncParam(FunctionDecl *D) {
const char **calling_conv_regs = get_call_conv();
const char **calling_conv_regs = get_call_conv(true);

string preamble = "{\n";
if (D->param_size() > 1) {
Expand Down
2 changes: 1 addition & 1 deletion src/cc/frontends/clang/loader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ int ClangLoader::parse(unique_ptr<llvm::Module> *mod, TableStorage &ts,
return 0;
}

void *get_clang_target_cb(bcc_arch_t arch)
void *get_clang_target_cb(bcc_arch_t arch, bool for_syscall)
{
const char *ret;

Expand Down

0 comments on commit 12107c6

Please sign in to comment.