Commit e20808ff authored by Alastair Robertson's avatar Alastair Robertson

Add support for different sized values

parent 21eb3db3
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "types.h"
namespace bpftrace { namespace bpftrace {
namespace ast { namespace ast {
...@@ -12,6 +14,8 @@ class Node { ...@@ -12,6 +14,8 @@ class Node {
public: public:
virtual ~Node() { } virtual ~Node() { }
virtual void accept(Visitor &v) = 0; virtual void accept(Visitor &v) = 0;
SizedType type;
}; };
class Expression : public Node { class Expression : public Node {
......
...@@ -10,6 +10,31 @@ ...@@ -10,6 +10,31 @@
namespace bpftrace { namespace bpftrace {
bpf_probe_attach_type attachtype(ProbeType t)
{
switch (t)
{
case ProbeType::kprobe: return BPF_PROBE_ENTRY; break;
case ProbeType::kretprobe: return BPF_PROBE_RETURN; break;
case ProbeType::uprobe: return BPF_PROBE_ENTRY; break;
case ProbeType::uretprobe: return BPF_PROBE_RETURN; break;
default: abort();
}
}
bpf_prog_type progtype(ProbeType t)
{
switch (t)
{
case ProbeType::kprobe: return BPF_PROG_TYPE_KPROBE; break;
case ProbeType::kretprobe: return BPF_PROG_TYPE_KPROBE; break;
case ProbeType::uprobe: return BPF_PROG_TYPE_KPROBE; break;
case ProbeType::uretprobe: return BPF_PROG_TYPE_KPROBE; break;
default: abort();
}
}
AttachedProbe::AttachedProbe(Probe &probe, std::tuple<uint8_t *, uintptr_t> &func) AttachedProbe::AttachedProbe(Probe &probe, std::tuple<uint8_t *, uintptr_t> &func)
: probe_(probe), func_(func) : probe_(probe), func_(func)
{ {
......
...@@ -2,8 +2,13 @@ ...@@ -2,8 +2,13 @@
#include "types.h" #include "types.h"
#include "libbpf.h"
namespace bpftrace { namespace bpftrace {
bpf_probe_attach_type attachtype(ProbeType t);
bpf_prog_type progtype(ProbeType t);
class AttachedProbe class AttachedProbe
{ {
public: public:
......
...@@ -64,7 +64,7 @@ int BPFtrace::print_maps() const ...@@ -64,7 +64,7 @@ int BPFtrace::print_maps() const
{ {
Map &map = *mapmap.second.get(); Map &map = *mapmap.second.get();
int err; int err;
if (map.type_ == Type::quantize) if (map.type_.type == Type::quantize)
err = print_map_quantize(map); err = print_map_quantize(map);
else else
err = print_map(map); err = print_map(map);
...@@ -95,19 +95,19 @@ int BPFtrace::print_map(Map &map) const ...@@ -95,19 +95,19 @@ int BPFtrace::print_map(Map &map) const
{ {
std::cout << map.name_ << map.key_.argument_value_list(*this, key) << ": "; std::cout << map.name_ << map.key_.argument_value_list(*this, key) << ": ";
int64_t value; auto value = std::vector<uint8_t>(map.type_.size);
int err = bpf_lookup_elem(map.mapfd_, key.data(), &value); int err = bpf_lookup_elem(map.mapfd_, key.data(), value.data());
if (err) if (err)
{ {
std::cerr << "Error looking up elem: " << err << std::endl; std::cerr << "Error looking up elem: " << err << std::endl;
return -1; return -1;
} }
if (map.type_ == Type::stack) if (map.type_.type == Type::stack)
std::cout << get_stack(value, false, 8); std::cout << get_stack(*(uint32_t*)value.data(), false, 8);
else if (map.type_ == Type::ustack) else if (map.type_.type == Type::ustack)
std::cout << get_stack(value, true, 8); std::cout << get_stack(*(uint32_t*)value.data(), true, 8);
else else
std::cout << value << std::endl; std::cout << *(int64_t*)value.data() << std::endl;
old_key = key; old_key = key;
} }
...@@ -255,17 +255,17 @@ std::vector<uint8_t> BPFtrace::find_empty_key(Map &map, size_t size) const ...@@ -255,17 +255,17 @@ std::vector<uint8_t> BPFtrace::find_empty_key(Map &map, size_t size) const
{ {
if (size == 0) size = 8; if (size == 0) size = 8;
auto key = std::vector<uint8_t>(size); auto key = std::vector<uint8_t>(size);
uint8_t value; auto value = std::vector<uint8_t>(map.type_.size);
if (bpf_lookup_elem(map.mapfd_, key.data(), &value)) if (bpf_lookup_elem(map.mapfd_, key.data(), value.data()))
return key; return key;
for (auto &elem : key) elem = 0xff; for (auto &elem : key) elem = 0xff;
if (bpf_lookup_elem(map.mapfd_, key.data(), &value)) if (bpf_lookup_elem(map.mapfd_, key.data(), value.data()))
return key; return key;
for (auto &elem : key) elem = 0x55; for (auto &elem : key) elem = 0x55;
if (bpf_lookup_elem(map.mapfd_, key.data(), &value)) if (bpf_lookup_elem(map.mapfd_, key.data(), value.data()))
return key; return key;
throw std::runtime_error("Could not find empty key"); throw std::runtime_error("Could not find empty key");
......
...@@ -56,7 +56,7 @@ void CodegenLLVM::visit(Builtin &builtin) ...@@ -56,7 +56,7 @@ void CodegenLLVM::visit(Builtin &builtin)
{ {
int arg_num = atoi(builtin.ident.substr(3).c_str()); int arg_num = atoi(builtin.ident.substr(3).c_str());
AllocaInst *dst = b_.CreateAllocaBPF(builtin.ident); AllocaInst *dst = b_.CreateAllocaBPF(builtin.type, builtin.ident);
int offset = arch::arg_offset(arg_num) * sizeof(uintptr_t); int offset = arch::arg_offset(arg_num) * sizeof(uintptr_t);
Value *src = b_.CreateGEP(ctx_, b_.getInt64(offset)); Value *src = b_.CreateGEP(ctx_, b_.getInt64(offset));
b_.CreateProbeRead(dst, b_.getInt64(8), src); b_.CreateProbeRead(dst, b_.getInt64(8), src);
...@@ -64,7 +64,7 @@ void CodegenLLVM::visit(Builtin &builtin) ...@@ -64,7 +64,7 @@ void CodegenLLVM::visit(Builtin &builtin)
} }
else if (builtin.ident == "retval") else if (builtin.ident == "retval")
{ {
AllocaInst *dst = b_.CreateAllocaBPF(builtin.ident); AllocaInst *dst = b_.CreateAllocaBPF(builtin.type, builtin.ident);
int offset = arch::ret_offset() * sizeof(uintptr_t); int offset = arch::ret_offset() * sizeof(uintptr_t);
Value *src = b_.CreateGEP(ctx_, b_.getInt64(offset)); Value *src = b_.CreateGEP(ctx_, b_.getInt64(offset));
b_.CreateProbeRead(dst, b_.getInt64(8), src); b_.CreateProbeRead(dst, b_.getInt64(8), src);
...@@ -126,7 +126,7 @@ void CodegenLLVM::visit(Unop &unop) ...@@ -126,7 +126,7 @@ void CodegenLLVM::visit(Unop &unop)
case bpftrace::Parser::token::BNOT: expr_ = b_.CreateNeg(expr_); break; case bpftrace::Parser::token::BNOT: expr_ = b_.CreateNeg(expr_); break;
case bpftrace::Parser::token::MUL: case bpftrace::Parser::token::MUL:
{ {
AllocaInst *dst = b_.CreateAllocaBPF("deref"); AllocaInst *dst = b_.CreateAllocaBPF(unop.expr->type, "deref");
b_.CreateProbeRead(dst, b_.getInt64(8), expr_); b_.CreateProbeRead(dst, b_.getInt64(8), expr_);
expr_ = b_.CreateLoad(dst); expr_ = b_.CreateLoad(dst);
break; break;
...@@ -144,12 +144,11 @@ void CodegenLLVM::visit(AssignMapStatement &assignment) ...@@ -144,12 +144,11 @@ void CodegenLLVM::visit(AssignMapStatement &assignment)
{ {
Map &map = *assignment.map; Map &map = *assignment.map;
AllocaInst *val = b_.CreateAllocaBPF(map.ident + "_val");
assignment.expr->accept(*this); assignment.expr->accept(*this);
b_.CreateStore(expr_, val);
AllocaInst *val = b_.CreateAllocaBPF(map.type, map.ident + "_val");
b_.CreateStore(expr_, val);
AllocaInst *key = getMapKey(map); AllocaInst *key = getMapKey(map);
b_.CreateMapUpdateElem(map, key, val); b_.CreateMapUpdateElem(map, key, val);
} }
...@@ -162,7 +161,7 @@ void CodegenLLVM::visit(AssignMapCallStatement &assignment) ...@@ -162,7 +161,7 @@ void CodegenLLVM::visit(AssignMapCallStatement &assignment)
{ {
AllocaInst *key = getMapKey(map); AllocaInst *key = getMapKey(map);
Value *oldval = b_.CreateMapLookupElem(map, key); Value *oldval = b_.CreateMapLookupElem(map, key);
AllocaInst *newval = b_.CreateAllocaBPF(map.ident + "_val"); AllocaInst *newval = b_.CreateAllocaBPF(map.type, map.ident + "_val");
b_.CreateStore(b_.CreateAdd(oldval, b_.getInt64(1)), newval); b_.CreateStore(b_.CreateAdd(oldval, b_.getInt64(1)), newval);
b_.CreateMapUpdateElem(map, key, newval); b_.CreateMapUpdateElem(map, key, newval);
} }
...@@ -174,7 +173,7 @@ void CodegenLLVM::visit(AssignMapCallStatement &assignment) ...@@ -174,7 +173,7 @@ void CodegenLLVM::visit(AssignMapCallStatement &assignment)
AllocaInst *key = getQuantizeMapKey(map, log2); AllocaInst *key = getQuantizeMapKey(map, log2);
Value *oldval = b_.CreateMapLookupElem(map, key); Value *oldval = b_.CreateMapLookupElem(map, key);
AllocaInst *newval = b_.CreateAllocaBPF(map.ident + "_val"); AllocaInst *newval = b_.CreateAllocaBPF(map.type, map.ident + "_val");
b_.CreateStore(b_.CreateAdd(oldval, b_.getInt64(1)), newval); b_.CreateStore(b_.CreateAdd(oldval, b_.getInt64(1)), newval);
b_.CreateMapUpdateElem(map, key, newval); b_.CreateMapUpdateElem(map, key, newval);
} }
...@@ -246,17 +245,24 @@ AllocaInst *CodegenLLVM::getMapKey(Map &map) ...@@ -246,17 +245,24 @@ AllocaInst *CodegenLLVM::getMapKey(Map &map)
{ {
AllocaInst *key; AllocaInst *key;
if (map.vargs) { if (map.vargs) {
key = b_.CreateAllocaBPF(map.ident + "_key", map.vargs->size()); size_t size = 0;
int i = 0; for (Expression *expr : *map.vargs)
{
size += expr->type.size;
}
key = b_.CreateAllocaMapKey(size, map.ident + "_key");
int offset = 0;
for (Expression *expr : *map.vargs) { for (Expression *expr : *map.vargs) {
expr->accept(*this); expr->accept(*this);
Value *offset = b_.CreateGEP(key, b_.getInt64(i++)); Value *offset_val = b_.CreateGEP(key, {b_.getInt64(0), b_.getInt64(offset)});
b_.CreateStore(expr_, offset); b_.CreateStore(expr_, offset_val);
offset += expr->type.size;
} }
} }
else else
{ {
key = b_.CreateAllocaBPF(map.ident + "_key"); key = b_.CreateAllocaBPF(map.type, map.ident + "_key");
b_.CreateStore(b_.getInt64(0), key); b_.CreateStore(b_.getInt64(0), key);
} }
return key; return key;
...@@ -266,19 +272,26 @@ AllocaInst *CodegenLLVM::getQuantizeMapKey(Map &map, Value *log2) ...@@ -266,19 +272,26 @@ AllocaInst *CodegenLLVM::getQuantizeMapKey(Map &map, Value *log2)
{ {
AllocaInst *key; AllocaInst *key;
if (map.vargs) { if (map.vargs) {
key = b_.CreateAllocaBPF(map.ident + "_key", map.vargs->size() + 1); size_t size = 8; // Extra space for the bucket value
int i = 0; for (Expression *expr : *map.vargs)
{
size += expr->type.size;
}
key = b_.CreateAllocaMapKey(size, map.ident + "_key");
int offset = 0;
for (Expression *expr : *map.vargs) { for (Expression *expr : *map.vargs) {
expr->accept(*this); expr->accept(*this);
Value *offset = b_.CreateGEP(key, b_.getInt64(i++)); Value *offset_val = b_.CreateGEP(key, {b_.getInt64(0), b_.getInt64(offset)});
b_.CreateStore(expr_, offset); b_.CreateStore(expr_, offset_val);
offset += expr->type.size;
} }
Value *offset = b_.CreateGEP(key, b_.getInt64(i)); Value *offset_val = b_.CreateGEP(key, {b_.getInt64(0), b_.getInt64(offset)});
b_.CreateStore(log2, offset); b_.CreateStore(log2, offset_val);
} }
else else
{ {
key = b_.CreateAllocaBPF(map.ident + "_key"); key = b_.CreateAllocaBPF(SizedType(Type::integer, 8), map.ident + "_key");
b_.CreateStore(log2, key); b_.CreateStore(log2, key);
} }
return key; return key;
...@@ -330,10 +343,10 @@ void CodegenLLVM::createLog2Function() ...@@ -330,10 +343,10 @@ void CodegenLLVM::createLog2Function()
Value *arg = &log2_func->getArgumentList().front(); Value *arg = &log2_func->getArgumentList().front();
Value *n_alloc = b_.CreateAllocaBPF(); Value *n_alloc = b_.CreateAllocaBPF(SizedType(Type::integer, 8));
b_.CreateStore(arg, n_alloc); b_.CreateStore(arg, n_alloc);
Value *result = b_.CreateAllocaBPF(); Value *result = b_.CreateAllocaBPF(SizedType(Type::integer, 8));
b_.CreateStore(b_.getInt64(0), result); b_.CreateStore(b_.getInt64(0), result);
for (int i = 4; i >= 0; i--) for (int i = 4; i >= 0; i--)
......
...@@ -25,16 +25,38 @@ IRBuilderBPF::IRBuilderBPF(LLVMContext &context, ...@@ -25,16 +25,38 @@ IRBuilderBPF::IRBuilderBPF(LLVMContext &context,
&module_); &module_);
} }
AllocaInst *IRBuilderBPF::CreateAllocaBPF(const std::string &name, int num_items) AllocaInst *IRBuilderBPF::CreateAllocaBPF(const SizedType &stype, const std::string &name)
{ {
llvm::Type *ty = getInt64Ty(); llvm::Type *ty;
Value *array_size = getInt64(num_items); switch (stype.size)
{
case 8:
ty = getInt64Ty();
break;
case 4:
ty = getInt32Ty();
break;
default:
abort();
}
Function *parent = GetInsertBlock()->getParent(); Function *parent = GetInsertBlock()->getParent();
BasicBlock &entry_block = parent->getEntryBlock(); BasicBlock &entry_block = parent->getEntryBlock();
if (entry_block.empty()) if (entry_block.empty())
return new AllocaInst(ty, array_size, name, &entry_block); return new AllocaInst(ty, name, &entry_block);
else else
return new AllocaInst(ty, array_size, name, &entry_block.front()); return new AllocaInst(ty, name, &entry_block.front());
}
AllocaInst *IRBuilderBPF::CreateAllocaMapKey(int bytes, const std::string &name)
{
llvm::Type *ty = ArrayType::get(getInt8Ty(), bytes);
Value *array_size = getInt64(bytes);
Function *parent = GetInsertBlock()->getParent();
BasicBlock &entry_block = parent->getEntryBlock();
if (entry_block.empty())
return new AllocaInst(ty, name, &entry_block);
else
return new AllocaInst(ty, name, &entry_block.front());
} }
CallInst *IRBuilderBPF::CreateBpfPseudoCall(int mapfd) CallInst *IRBuilderBPF::CreateBpfPseudoCall(int mapfd)
...@@ -72,7 +94,7 @@ LoadInst *IRBuilderBPF::CreateMapLookupElem(Map &map, AllocaInst *key) ...@@ -72,7 +94,7 @@ LoadInst *IRBuilderBPF::CreateMapLookupElem(Map &map, AllocaInst *key)
BasicBlock *lookup_failure_block = BasicBlock::Create(module_.getContext(), "lookup_failure", parent); BasicBlock *lookup_failure_block = BasicBlock::Create(module_.getContext(), "lookup_failure", parent);
BasicBlock *lookup_merge_block = BasicBlock::Create(module_.getContext(), "lookup_merge", parent); BasicBlock *lookup_merge_block = BasicBlock::Create(module_.getContext(), "lookup_merge", parent);
Value *value = CreateAllocaBPF("lookup_elem_val"); Value *value = CreateAllocaBPF(SizedType(Type::integer, 8), "lookup_elem_val");
Value *condition = CreateICmpNE( Value *condition = CreateICmpNE(
CreateIntCast(call, getInt8PtrTy(), true), CreateIntCast(call, getInt8PtrTy(), true),
ConstantExpr::getCast(Instruction::IntToPtr, getInt64(0), getInt8PtrTy()), ConstantExpr::getCast(Instruction::IntToPtr, getInt64(0), getInt8PtrTy()),
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include "ast.h" #include "ast.h"
#include "bpftrace.h" #include "bpftrace.h"
#include "types.h"
#include <llvm/IR/IRBuilder.h> #include <llvm/IR/IRBuilder.h>
...@@ -17,7 +18,8 @@ public: ...@@ -17,7 +18,8 @@ public:
Module &module, Module &module,
BPFtrace &bpftrace); BPFtrace &bpftrace);
AllocaInst *CreateAllocaBPF(const std::string &name="", int num_items=1); AllocaInst *CreateAllocaBPF(const SizedType &stype, const std::string &name="");
AllocaInst *CreateAllocaMapKey(int bytes, const std::string &name="");
CallInst *CreateBpfPseudoCall(int mapfd); CallInst *CreateBpfPseudoCall(int mapfd);
CallInst *CreateBpfPseudoCall(Map &map); CallInst *CreateBpfPseudoCall(Map &map);
LoadInst *CreateMapLookupElem(Map &map, AllocaInst *key); LoadInst *CreateMapLookupElem(Map &map, AllocaInst *key);
......
...@@ -6,16 +6,16 @@ ...@@ -6,16 +6,16 @@
namespace bpftrace { namespace bpftrace {
Map::Map(std::string &name, Type type, MapKey key) Map::Map(const std::string &name, const SizedType &type, const MapKey &key)
: name_(name), type_(type), key_(key) : name_(name), type_(type), key_(key)
{ {
int key_size = key.size(); int key_size = key.size();
if (type == Type::quantize) if (type.type == Type::quantize)
key_size += 8; key_size += 8;
if (key_size == 0) if (key_size == 0)
key_size = 8; key_size = 8;
int value_size = 8; int value_size = type.size;
int max_entries = 128; int max_entries = 128;
int flags = 0; int flags = 0;
mapfd_ = bpf_create_map(BPF_MAP_TYPE_HASH, key_size, value_size, max_entries, flags); mapfd_ = bpf_create_map(BPF_MAP_TYPE_HASH, key_size, value_size, max_entries, flags);
...@@ -25,7 +25,7 @@ Map::Map(std::string &name, Type type, MapKey key) ...@@ -25,7 +25,7 @@ Map::Map(std::string &name, Type type, MapKey key)
} }
} }
Map::Map(std::string name) : name_(name) Map::Map(const std::string &name) : name_(name)
{ {
// Only used for creating maps for storing stack IDs // Only used for creating maps for storing stack IDs
int key_size = 4; int key_size = 4;
......
...@@ -11,15 +11,15 @@ namespace bpftrace { ...@@ -11,15 +11,15 @@ namespace bpftrace {
class Map { class Map {
public: public:
Map(std::string &name, Type type, MapKey key); Map(const std::string &name, const SizedType &type, const MapKey &key);
Map(std::string name); Map(const std::string &name);
~Map(); ~Map();
Map(const Map &) = delete; Map(const Map &) = delete;
Map& operator=(const Map &) = delete; Map& operator=(const Map &) = delete;
int mapfd_; int mapfd_;
std::string name_; std::string name_;
Type type_; SizedType type_;
MapKey key_; MapKey key_;
}; };
......
...@@ -42,17 +42,17 @@ std::string MapKey::argument_value_list(const BPFtrace &bpftrace, ...@@ -42,17 +42,17 @@ std::string MapKey::argument_value_list(const BPFtrace &bpftrace,
int offset = 0; int offset = 0;
for (size_t i = 0; i < n-1; i++) for (size_t i = 0; i < n-1; i++)
{ {
const MapKeyArgument &arg = args_.at(i); const SizedType &arg = args_.at(i);
list << argument_value(bpftrace, arg, &data.at(offset)) << ", "; list << argument_value(bpftrace, arg, &data.at(offset)) << ", ";
offset += arg.size; offset += arg.size;
} }
const MapKeyArgument &arg = args_.at(n-1); const SizedType &arg = args_.at(n-1);
list << argument_value(bpftrace, arg, &data.at(offset)) << "]"; list << argument_value(bpftrace, arg, &data.at(offset)) << "]";
return list.str(); return list.str();
} }
std::string MapKey::argument_value(const BPFtrace &bpftrace, std::string MapKey::argument_value(const BPFtrace &bpftrace,
const MapKeyArgument &arg, const SizedType &arg,
const void *data) const void *data)
{ {
switch (arg.type) switch (arg.type)
......
...@@ -12,7 +12,7 @@ class BPFtrace; ...@@ -12,7 +12,7 @@ class BPFtrace;
class MapKey class MapKey
{ {
public: public:
std::vector<MapKeyArgument> args_; std::vector<SizedType> args_;
bool operator!=(const MapKey &k) const; bool operator!=(const MapKey &k) const;
...@@ -23,7 +23,7 @@ public: ...@@ -23,7 +23,7 @@ public:
private: private:
static std::string argument_value(const BPFtrace &bpftrace, static std::string argument_value(const BPFtrace &bpftrace,
const MapKeyArgument &arg, const SizedType &arg,
const void *data); const void *data);
}; };
......
...@@ -8,9 +8,9 @@ ...@@ -8,9 +8,9 @@
namespace bpftrace { namespace bpftrace {
namespace ast { namespace ast {
void SemanticAnalyser::visit(Integer &) void SemanticAnalyser::visit(Integer &integer)
{ {
type_ = Type::integer; integer.type = SizedType(Type::integer, 8);
} }
void SemanticAnalyser::visit(Builtin &builtin) void SemanticAnalyser::visit(Builtin &builtin)
...@@ -21,14 +21,14 @@ void SemanticAnalyser::visit(Builtin &builtin) ...@@ -21,14 +21,14 @@ void SemanticAnalyser::visit(Builtin &builtin)
builtin.ident == "uid" || builtin.ident == "uid" ||
builtin.ident == "gid" || builtin.ident == "gid" ||
builtin.ident == "retval") { builtin.ident == "retval") {
type_ = Type::integer; builtin.type = SizedType(Type::integer, 8);
} }
else if (builtin.ident == "stack") { else if (builtin.ident == "stack") {
type_ = Type::stack; builtin.type = SizedType(Type::stack, 8);
needs_stackid_map_ = true; needs_stackid_map_ = true;
} }
else if (builtin.ident == "ustack") { else if (builtin.ident == "ustack") {
type_ = Type::ustack; builtin.type = SizedType(Type::ustack, 8);
needs_stackid_map_ = true; needs_stackid_map_ = true;
} }
else if (!builtin.ident.compare(0, 3, "arg") && builtin.ident.size() == 4 && else if (!builtin.ident.compare(0, 3, "arg") && builtin.ident.size() == 4 &&
...@@ -36,10 +36,10 @@ void SemanticAnalyser::visit(Builtin &builtin) ...@@ -36,10 +36,10 @@ void SemanticAnalyser::visit(Builtin &builtin)
int arg_num = atoi(builtin.ident.substr(3).c_str()); int arg_num = atoi(builtin.ident.substr(3).c_str());
if (arg_num > arch::max_arg()) if (arg_num > arch::max_arg())
err_ << arch::name() << " doesn't support " << builtin.ident << std::endl; err_ << arch::name() << " doesn't support " << builtin.ident << std::endl;
type_ = Type::integer; builtin.type = SizedType(Type::integer, 8);
} }
else { else {
type_ = Type::none; builtin.type = SizedType(Type::none, 0);
err_ << "Unknown builtin: '" << builtin.ident << "'" << std::endl; err_ << "Unknown builtin: '" << builtin.ident << "'" << std::endl;
} }
} }
...@@ -59,18 +59,18 @@ void SemanticAnalyser::visit(Call &call) ...@@ -59,18 +59,18 @@ void SemanticAnalyser::visit(Call &call)
err_ << "quantize() should take 1 argument ("; err_ << "quantize() should take 1 argument (";
err_ << nargs << " provided)" << std::endl; err_ << nargs << " provided)" << std::endl;
} }
if (type_ != Type::integer) { if (call.vargs->at(0)->type.type != Type::integer) {
err_ << "quantize() only supports integer arguments"; err_ << "quantize() only supports integer arguments";
err_ << " (" << type_ << " provided)" << std::endl; err_ << " (" << call.vargs->at(0)->type.type << " provided)" << std::endl;
} }
type_ = Type::quantize; call.type = SizedType(Type::quantize, 8);
} }
else if (call.func == "count") { else if (call.func == "count") {
if (nargs != 0) { if (nargs != 0) {
err_ << "count() should take 0 arguments ("; err_ << "count() should take 0 arguments (";
err_ << nargs << " provided)" << std::endl; err_ << nargs << " provided)" << std::endl;
} }
type_ = Type::count; call.type = SizedType(Type::count, 8);
} }
else if (call.func == "delete") { else if (call.func == "delete") {
if (nargs != 0) { if (nargs != 0) {
...@@ -80,7 +80,7 @@ void SemanticAnalyser::visit(Call &call) ...@@ -80,7 +80,7 @@ void SemanticAnalyser::visit(Call &call)
// Don't assign a type // Don't assign a type
} }
else { else {
type_ = Type::none; call.type = SizedType(Type::none, 0);
err_ << "Unknown function: '" << call.func << "'" << std::endl; err_ << "Unknown function: '" << call.func << "'" << std::endl;
} }
} }
...@@ -91,7 +91,7 @@ void SemanticAnalyser::visit(Map &map) ...@@ -91,7 +91,7 @@ void SemanticAnalyser::visit(Map &map)
if (map.vargs) { if (map.vargs) {
for (Expression *expr : *map.vargs) { for (Expression *expr : *map.vargs) {
expr->accept(*this); expr->accept(*this);
key.args_.push_back({type_, 8}); key.args_.push_back({expr->type.type, expr->type.size});
} }
} }
...@@ -112,23 +112,22 @@ void SemanticAnalyser::visit(Map &map) ...@@ -112,23 +112,22 @@ void SemanticAnalyser::visit(Map &map)
auto search_val = map_val_.find(map.ident); auto search_val = map_val_.find(map.ident);
if (search_val != map_val_.end()) { if (search_val != map_val_.end()) {
type_ = search_val->second; map.type = search_val->second;
} }
else { else {
if (is_final_pass()) { if (is_final_pass()) {
err_ << "Undefined map: " << map.ident << std::endl; err_ << "Undefined map: " << map.ident << std::endl;
} }
type_ = Type::none; map.type = SizedType(Type::none, 0);
} }
} }
void SemanticAnalyser::visit(Binop &binop) void SemanticAnalyser::visit(Binop &binop)
{ {
Type lhs, rhs;
binop.left->accept(*this); binop.left->accept(*this);
lhs = type_;
binop.right->accept(*this); binop.right->accept(*this);
rhs = type_; Type &lhs = binop.left->type.type;
Type &rhs = binop.right->type.type;
if (is_final_pass() && lhs != rhs) { if (is_final_pass() && lhs != rhs) {
err_ << "Type mismatch for '" << opstr(binop) << "': "; err_ << "Type mismatch for '" << opstr(binop) << "': ";
...@@ -136,18 +135,18 @@ void SemanticAnalyser::visit(Binop &binop) ...@@ -136,18 +135,18 @@ void SemanticAnalyser::visit(Binop &binop)
err_ << "with '" << rhs << "'" << std::endl; err_ << "with '" << rhs << "'" << std::endl;
} }
type_ = Type::integer; binop.type = SizedType(Type::integer, 8);
} }
void SemanticAnalyser::visit(Unop &unop) void SemanticAnalyser::visit(Unop &unop)
{ {
unop.expr->accept(*this); unop.expr->accept(*this);
if (type_ != Type::integer) { if (unop.expr->type.type != Type::integer) {
err_ << "The " << opstr(unop) << " operator can not be used on expressions of type " << type_ << std::endl; err_ << "The " << opstr(unop) << " operator can not be used on expressions of type " << unop.expr->type << std::endl;
} }
type_ = Type::integer; unop.type = SizedType(Type::integer, 8);
} }
void SemanticAnalyser::visit(ExprStatement &expr) void SemanticAnalyser::visit(ExprStatement &expr)
...@@ -163,24 +162,24 @@ void SemanticAnalyser::visit(AssignMapStatement &assignment) ...@@ -163,24 +162,24 @@ void SemanticAnalyser::visit(AssignMapStatement &assignment)
std::string map_ident = assignment.map->ident; std::string map_ident = assignment.map->ident;
auto search = map_val_.find(map_ident); auto search = map_val_.find(map_ident);
if (search != map_val_.end()) { if (search != map_val_.end()) {
if (search->second == Type::none) { if (search->second.type == Type::none) {
if (is_final_pass()) { if (is_final_pass()) {
err_ << "Undefined map: " << map_ident << std::endl; err_ << "Undefined map: " << map_ident << std::endl;
} }
else { else {
search->second = type_; search->second = assignment.expr->type;
} }
} }
else if (search->second != type_) { else if (search->second.type != assignment.expr->type.type) {
err_ << "Type mismatch for " << map_ident << ": "; err_ << "Type mismatch for " << map_ident << ": ";
err_ << "trying to assign value of type '" << type_; err_ << "trying to assign value of type '" << assignment.expr->type;
err_ << "'\n\twhen map already contains a value of type '"; err_ << "'\n\twhen map already contains a value of type '";
err_ << search->second << "'\n" << std::endl; err_ << search->second << "'\n" << std::endl;
} }
} }
else { else {
// This map hasn't been seen before // This map hasn't been seen before
map_val_.insert({map_ident, type_}); map_val_.insert({map_ident, assignment.expr->type});
} }
} }
...@@ -192,15 +191,15 @@ void SemanticAnalyser::visit(AssignMapCallStatement &assignment) ...@@ -192,15 +191,15 @@ void SemanticAnalyser::visit(AssignMapCallStatement &assignment)
std::string map_ident = assignment.map->ident; std::string map_ident = assignment.map->ident;
auto search = map_val_.find(map_ident); auto search = map_val_.find(map_ident);
if (search != map_val_.end()) { if (search != map_val_.end()) {
if (search->second == Type::none) { if (search->second.type == Type::none) {
if (is_final_pass()) { if (is_final_pass()) {
err_ << "Undefined map: " << map_ident << std::endl; err_ << "Undefined map: " << map_ident << std::endl;
} }
else { else {
search->second = type_; search->second = assignment.call->type;
} }
} }
else if (search->second != type_) { else if (search->second.type != assignment.call->type.type) {
err_ << "Type mismatch for " << map_ident << ": "; err_ << "Type mismatch for " << map_ident << ": ";
err_ << "trying to assign result of '" << assignment.call->func; err_ << "trying to assign result of '" << assignment.call->func;
err_ << "()'\n\twhen map already contains a value of type '"; err_ << "()'\n\twhen map already contains a value of type '";
...@@ -209,7 +208,7 @@ void SemanticAnalyser::visit(AssignMapCallStatement &assignment) ...@@ -209,7 +208,7 @@ void SemanticAnalyser::visit(AssignMapCallStatement &assignment)
} }
else { else {
// This map hasn't been seen before // This map hasn't been seen before
map_val_.insert({map_ident, type_}); map_val_.insert({map_ident, assignment.call->type});
} }
} }
...@@ -261,7 +260,7 @@ int SemanticAnalyser::create_maps() ...@@ -261,7 +260,7 @@ int SemanticAnalyser::create_maps()
for (auto &map_val : map_val_) for (auto &map_val : map_val_)
{ {
std::string map_name = map_val.first; std::string map_name = map_val.first;
Type type = map_val.second; SizedType type = map_val.second;
auto search_args = map_key_.find(map_name); auto search_args = map_key_.find(map_name);
if (search_args == map_key_.end()) if (search_args == map_key_.end())
......
...@@ -43,9 +43,7 @@ private: ...@@ -43,9 +43,7 @@ private:
bool is_final_pass() const; bool is_final_pass() const;
using Type = bpftrace::Type; std::map<std::string, SizedType> map_val_;
Type type_;
std::map<std::string, Type> map_val_;
std::map<std::string, MapKey> map_key_; std::map<std::string, MapKey> map_key_;
bool needs_stackid_map_ = false; bool needs_stackid_map_ = false;
}; };
......
...@@ -10,15 +10,15 @@ std::ostream &operator<<(std::ostream &os, Type type) ...@@ -10,15 +10,15 @@ std::ostream &operator<<(std::ostream &os, Type type)
return os; return os;
} }
std::ostream &operator<<(std::ostream &os, MapKeyArgument arg) std::ostream &operator<<(std::ostream &os, const SizedType &type)
{ {
os << arg.type; os << type.type;
return os; return os;
} }
bool MapKeyArgument::operator==(const MapKeyArgument &a) const bool SizedType::operator==(const SizedType &t) const
{ {
return type == a.type && size == a.size; return type == t.type && size == t.size;
} }
std::string typestr(Type t) std::string typestr(Type t)
...@@ -35,28 +35,4 @@ std::string typestr(Type t) ...@@ -35,28 +35,4 @@ std::string typestr(Type t)
} }
} }
bpf_probe_attach_type attachtype(ProbeType t)
{
switch (t)
{
case ProbeType::kprobe: return BPF_PROBE_ENTRY; break;
case ProbeType::kretprobe: return BPF_PROBE_RETURN; break;
case ProbeType::uprobe: return BPF_PROBE_ENTRY; break;
case ProbeType::uretprobe: return BPF_PROBE_RETURN; break;
default: abort();
}
}
bpf_prog_type progtype(ProbeType t)
{
switch (t)
{
case ProbeType::kprobe: return BPF_PROG_TYPE_KPROBE; break;
case ProbeType::kretprobe: return BPF_PROG_TYPE_KPROBE; break;
case ProbeType::uprobe: return BPF_PROG_TYPE_KPROBE; break;
case ProbeType::uretprobe: return BPF_PROG_TYPE_KPROBE; break;
default: abort();
}
}
} // namespace bpftrace } // namespace bpftrace
...@@ -6,8 +6,6 @@ ...@@ -6,8 +6,6 @@
#include <vector> #include <vector>
#include <unistd.h> #include <unistd.h>
#include "libbpf.h"
namespace bpftrace { namespace bpftrace {
const int MAX_STACK_SIZE = 32; const int MAX_STACK_SIZE = 32;
...@@ -20,20 +18,23 @@ enum class Type ...@@ -20,20 +18,23 @@ enum class Type
count, count,
stack, stack,
ustack, ustack,
string,
}; };
std::ostream &operator<<(std::ostream &os, Type type); std::ostream &operator<<(std::ostream &os, Type type);
class MapKeyArgument class SizedType
{ {
public: public:
SizedType() : type(Type::none), size(0) { }
SizedType(Type type, size_t size) : type(type), size(size) { }
Type type; Type type;
size_t size; size_t size;
bool operator==(const MapKeyArgument &a) const; bool operator==(const SizedType &t) const;
}; };
std::ostream &operator<<(std::ostream &os, MapKeyArgument arg); std::ostream &operator<<(std::ostream &os, const SizedType &type);
enum class ProbeType enum class ProbeType
{ {
...@@ -44,8 +45,6 @@ enum class ProbeType ...@@ -44,8 +45,6 @@ enum class ProbeType
}; };
std::string typestr(Type t); std::string typestr(Type t);
bpf_probe_attach_type attachtype(ProbeType t);
bpf_prog_type progtype(ProbeType t);
class Probe class Probe
{ {
......
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