Commit c0e96c15 authored by Alastair Robertson's avatar Alastair Robertson

Add str() function

parent 1e30b834
......@@ -59,7 +59,9 @@ Variables:
- `uid` - User ID
- `gid` - Group ID
- `nsecs` - Nanosecond timestamp
- `comm` - Process name
- `stack` - Kernel stack trace
- `ustack` - User stack trace
- `arg0`, `arg1`, ... etc. - Arguments to the function being traced
- `retval` - Return value from function being traced
......@@ -67,6 +69,7 @@ Functions:
- `quantize(int n)` - produce a log2 histogram of values of `n`
- `count()` - count the number of times this function is called
- `delete()` - delete the map element this is assigned to
- `str(char *s)` - returns the string pointed to by `s`
# Building
......
......@@ -124,6 +124,14 @@ void CodegenLLVM::visit(Call &call)
b_.CreateMapDeleteElem(map, key);
expr_ = nullptr;
}
else if (call.func == "str")
{
AllocaInst *buf = b_.CreateAllocaBPF(call.type, "str");
b_.CreateMemset(buf, b_.getInt8(0), b_.getInt64(call.type.size));
call.vargs->front()->accept(*this);
b_.CreateProbeReadStr(buf, b_.getInt64(call.type.size), expr_);
expr_ = buf;
}
else
{
abort();
......
......@@ -33,6 +33,16 @@ IRBuilderBPF::IRBuilderBPF(LLVMContext &context,
GlobalValue::ExternalLinkage,
"llvm.memcpy.p0i8.p0i8.i64",
&module_);
FunctionType *memset_func_type = FunctionType::get(
getVoidTy(),
{getInt8PtrTy(), getInt8Ty(), getInt64Ty(), getInt32Ty(), getInt1Ty()},
false);
Function::Create(
memset_func_type,
GlobalValue::ExternalLinkage,
"llvm.memset.p0i8.i64",
&module_);
}
AllocaInst *IRBuilderBPF::CreateAllocaBPF(const SizedType &stype, const std::string &name)
......@@ -82,6 +92,12 @@ void IRBuilderBPF::CreateMemcpy(Value *dst, Value *src, Value *len)
CreateCall(memcpy_func, {dst, src, len, getInt32(1), getInt1(0)}, "memcpy");
}
void IRBuilderBPF::CreateMemset(Value *dst, Value *val, Value *len)
{
Function *memset_func = module_.getFunction("llvm.memset.p0i8.i64");
CreateCall(memset_func, {dst, val, len, getInt32(1), getInt1(0)}, "memset");
}
CallInst *IRBuilderBPF::CreateBpfPseudoCall(int mapfd)
{
Function *pseudo_func = module_.getFunction("llvm.bpf.pseudo");
......@@ -188,6 +204,21 @@ void IRBuilderBPF::CreateProbeRead(AllocaInst *dst, Value *size, Value *src)
CallInst *call = CreateCall(proberead_func, {dst, size, src}, "probe_read");
}
void IRBuilderBPF::CreateProbeReadStr(AllocaInst *dst, Value *size, Value *src)
{
// int bpf_probe_read_str(void *dst, int size, const void *unsafe_ptr)
FunctionType *probereadstr_func_type = FunctionType::get(
getInt64Ty(),
{getInt8PtrTy(), getInt64Ty(), getInt8PtrTy()},
false);
PointerType *probereadstr_func_ptr_type = PointerType::get(probereadstr_func_type, 0);
Constant *probereadstr_func = ConstantExpr::getCast(
Instruction::IntToPtr,
getInt64(BPF_FUNC_probe_read_str),
probereadstr_func_ptr_type);
CallInst *call = CreateCall(probereadstr_func, {dst, size, src}, "probe_read_str");
}
CallInst *IRBuilderBPF::CreateGetNs()
{
// u64 ktime_get_ns()
......
......@@ -21,12 +21,14 @@ public:
AllocaInst *CreateAllocaBPF(const SizedType &stype, const std::string &name="");
AllocaInst *CreateAllocaMapKey(int bytes, const std::string &name="");
void CreateMemcpy(Value *dst, Value *src, Value *len);
void CreateMemset(Value *dst, Value *val, Value *len);
CallInst *CreateBpfPseudoCall(int mapfd);
CallInst *CreateBpfPseudoCall(Map &map);
LoadInst *CreateMapLookupElem(Map &map, AllocaInst *key);
void CreateMapUpdateElem(Map &map, AllocaInst *key, Value *val);
void CreateMapDeleteElem(Map &map, AllocaInst *key);
void CreateProbeRead(AllocaInst *dst, Value *size, Value *src);
void CreateProbeReadStr(AllocaInst *dst, Value *size, Value *src);
CallInst *CreateGetNs();
CallInst *CreateGetPidTgid();
CallInst *CreateGetUidGid();
......
......@@ -99,6 +99,13 @@ void SemanticAnalyser::visit(Call &call)
}
call.type = SizedType(Type::del, 0);
}
else if (call.func == "str") {
if (nargs != 1) {
err_ << "str() should take 1 arguments (";
err_ << nargs << " provided)" << std::endl;
}
call.type = SizedType(Type::string, STRING_SIZE);
}
else {
err_ << "Unknown function: '" << call.func << "'" << std::endl;
call.type = SizedType(Type::none, 0);
......
......@@ -9,7 +9,7 @@
namespace bpftrace {
const int MAX_STACK_SIZE = 32;
const int STRING_SIZE = 32;
const int STRING_SIZE = 64;
enum class Type
{
......
......@@ -83,4 +83,11 @@ TEST(semantic_analyser, call_delete)
test("kprobe:f { delete(); }", 1);
}
TEST(semantic_analyser, call_str)
{
test("kprobe:f { str(arg0); }", 0);
test("kprobe:f { @x = str(arg0); }", 0);
test("kprobe:f { str(); }", 1);
}
} // namespace bpftrace
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment