Skip to content

Commit

Permalink
Merge branch 'vbpf:main' into sanitizer
Browse files Browse the repository at this point in the history
  • Loading branch information
Alan-Jowett committed May 8, 2024
2 parents e8e6ec9 + edf88e2 commit 91a03e2
Show file tree
Hide file tree
Showing 27 changed files with 1,167 additions and 274 deletions.
2 changes: 1 addition & 1 deletion .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ AlwaysBreakTemplateDeclarations: Yes
AllowShortCaseLabelsOnASingleLine: true
PointerAlignment: Left
AlignEscapedNewlines: Left
#BreakAfterAttributes: Always
BreakAfterAttributes: Always
PenaltyReturnTypeOnItsOwnLine: 60
AlwaysBreakAfterReturnType: None
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
FORCE)
set(CMAKE_EXE_LINKER_FLAGS_FUZZERDEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG}")
set(CMAKE_SHARED_LINKER_FLAGS_FUZZERDEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}")
set(CMAKE_C_FLAGS_FUZZERDEBUG "${CMAKE_C_FLAGS_DEBUG} /fsanitize-coverage=inline-bool-flag /fsanitize-coverage=edge /fsanitize-coverage=trace-cmp /fsanitize-coverage=trace-div /ZH:SHA_256")
set(CMAKE_CXX_FLAGS_FUZZERDEBUG "${CMAKE_CXX_FLAGS_DEBUG} /fsanitize-coverage=inline-bool-flag /fsanitize-coverage=edge /fsanitize-coverage=trace-cmp /fsanitize-coverage=trace-div /ZH:SHA_256")
set(CMAKE_C_FLAGS_FUZZERDEBUG "${CMAKE_C_FLAGS_DEBUG} /fsanitize=address /fsanitize=fuzzer /fsanitize-coverage=inline-bool-flag /fsanitize-coverage=edge /fsanitize-coverage=trace-cmp /fsanitize-coverage=trace-div /ZH:SHA_256")
set(CMAKE_CXX_FLAGS_FUZZERDEBUG "${CMAKE_CXX_FLAGS_DEBUG} /fsanitize=address /fsanitize=fuzzer /fsanitize-coverage=inline-bool-flag /fsanitize-coverage=edge /fsanitize-coverage=trace-cmp /fsanitize-coverage=trace-div /ZH:SHA_256")

find_program(NUGET nuget)
if (NOT NUGET)
Expand Down
2 changes: 1 addition & 1 deletion ebpf-samples
2 changes: 1 addition & 1 deletion src/asm_cfg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ static std::string instype(Instruction ins) {
return "callx";
} else if (std::holds_alternative<Mem>(ins)) {
return std::get<Mem>(ins).is_load ? "load" : "store";
} else if (std::holds_alternative<LockAdd>(ins)) {
} else if (std::holds_alternative<Atomic>(ins)) {
return "load_store";
} else if (std::holds_alternative<Packet>(ins)) {
return "packet_access";
Expand Down
15 changes: 9 additions & 6 deletions src/asm_marshal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ struct MarshalVisitor {
vector<ebpf_inst> operator()(Mem const& b) {
Deref access = b.access;
ebpf_inst res{
.opcode = static_cast<uint8_t>((INST_MEM << 5) | width_to_opcode(access.width)),
.opcode = static_cast<uint8_t>(INST_MODE_MEM | width_to_opcode(access.width)),
.dst = 0,
.src = 0,
.offset = static_cast<int16_t>(access.offset),
Expand Down Expand Up @@ -253,21 +253,24 @@ struct MarshalVisitor {
.imm = static_cast<int32_t>(b.offset),
};
if (b.regoffset) {
res.opcode |= (INST_IND << 5);
res.opcode |= INST_MODE_IND;
res.src = b.regoffset->v;
} else {
res.opcode |= (INST_ABS << 5);
res.opcode |= INST_MODE_ABS;
}
return {res};
}

vector<ebpf_inst> operator()(LockAdd const& b) {
vector<ebpf_inst> operator()(Atomic const& b) {
int32_t imm = (int32_t)b.op;
if (b.fetch)
imm |= INST_FETCH;
return {ebpf_inst{
.opcode = static_cast<uint8_t>(INST_CLS_ST | 0x1 | (INST_XADD << 5) | width_to_opcode(b.access.width)),
.opcode = static_cast<uint8_t>(INST_CLS_STX | INST_MODE_ATOMIC | width_to_opcode(b.access.width)),
.dst = b.access.basereg.v,
.src = b.valreg.v,
.offset = static_cast<int16_t>(b.access.offset),
.imm = 0}};
.imm = imm}};
}

vector<ebpf_inst> operator()(IncrementLoopCounter const& ins) {
Expand Down
18 changes: 16 additions & 2 deletions src/asm_ostream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,10 +328,24 @@ struct InstructionPrinterVisitor {
}
}

void operator()(LockAdd const& b) {
void operator()(Atomic const& b) {
os_ << "lock ";
print(b.access);
os_ << " += " << b.valreg;
os_ << " ";
bool showfetch = true;
switch (b.op) {
case Atomic::Op::ADD: os_ << "+"; break;
case Atomic::Op::OR : os_ << "|"; break;
case Atomic::Op::AND: os_ << "&"; break;
case Atomic::Op::XOR: os_ << "^"; break;
case Atomic::Op::XCHG: os_ << "x"; showfetch = false; break;
case Atomic::Op::CMPXCHG: os_ << "cx"; showfetch = false; break;
}
os_ << "= " << b.valreg;

if (showfetch && b.fetch) {
os_ << " fetch";
}
}

void operator()(Assume const& b) {
Expand Down
2 changes: 1 addition & 1 deletion src/asm_ostream.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ inline std::ostream& operator<<(std::ostream& os, Exit const& a) { return os <<
inline std::ostream& operator<<(std::ostream& os, Jmp const& a) { return os << (Instruction)a; }
inline std::ostream& operator<<(std::ostream& os, Packet const& a) { return os << (Instruction)a; }
inline std::ostream& operator<<(std::ostream& os, Mem const& a) { return os << (Instruction)a; }
inline std::ostream& operator<<(std::ostream& os, LockAdd const& a) { return os << (Instruction)a; }
inline std::ostream& operator<<(std::ostream& os, Atomic const& a) { return os << (Instruction)a; }
inline std::ostream& operator<<(std::ostream& os, Assume const& a) { return os << (Instruction)a; }
inline std::ostream& operator<<(std::ostream& os, Assert const& a) { return os << (Instruction)a; }
inline std::ostream& operator<<(std::ostream& os, IncrementLoopCounter const& a) { return os << (Instruction)a; }
Expand Down
18 changes: 16 additions & 2 deletions src/asm_parse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ using crab::linear_expression_t;
#define ASSIGN R"_(\s*=\s*)_"
#define LONGLONG R"_(\s*(ll|)\s*)_"
#define UNOP R"_((-|be16|be32|be64|le16|le32|le64|swap16|swap32|swap64))_"
#define ATOMICOP R"_((\+|\||&|\^|x|cx)=)_"

#define PLUSMINUS R"_((\s*[+-])\s*)_"
#define LPAREN R"_(\s*\(\s*)_"
Expand Down Expand Up @@ -81,6 +82,14 @@ static const std::map<std::string, Condition::Op> str_to_cmpop = {
{"s<", Condition::Op::SLT}, {"s<=", Condition::Op::SLE}, {"s>", Condition::Op::SGT}, {"s>=", Condition::Op::SGE},
};

static const std::map<std::string, Atomic::Op> str_to_atomicop = {
{"+", Atomic::Op::ADD},
{"|", Atomic::Op::OR},
{"&", Atomic::Op::AND},
{"^", Atomic::Op::XOR},
{"x", Atomic::Op::XCHG},
{"cx", Atomic::Op::CMPXCHG}};

static const std::map<std::string, int> str_to_width = {
{"8", 1},
{"16", 2},
Expand Down Expand Up @@ -182,8 +191,13 @@ Instruction parse_instruction(const std::string& line, const std::map<std::strin
.is_load = false,
};
}
if (regex_match(text, m, regex("lock " DEREF PAREN(REG PLUSMINUS IMM) " [+]= " REG))) {
return LockAdd{.access = deref(m[1], m[2], m[3], m[4]), .valreg = reg(m[5])};
if (regex_match(text, m, regex("lock " DEREF PAREN(REG PLUSMINUS IMM) " " ATOMICOP " " REG "( fetch)?"))) {
Atomic::Op op = str_to_atomicop.at(m[5]);
return Atomic{
.op = op,
.fetch = m[7].matched || op == Atomic::Op::XCHG || op == Atomic::Op::CMPXCHG,
.access = deref(m[1], m[2], m[3], m[4]),
.valreg = reg(m[6])};
}
if (regex_match(text, m, regex("r0 = " DEREF "skb\\[(.*)\\]"))) {
auto width = str_to_width.at(m[1]);
Expand Down
21 changes: 17 additions & 4 deletions src/asm_syntax.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,11 +235,24 @@ struct Packet {
constexpr bool operator==(const Packet&) const = default;
};

/// Special instruction for incrementing values inside shared memory.
struct LockAdd {
/// Special instruction for atomically updating values inside shared memory.
/// The analysis just treats an atomic operation as a series of consecutive
/// operations, and the atomicity itself is not significant.
struct Atomic {
enum class Op {
ADD = 0x00,
OR = 0x40,
AND = 0x50,
XOR = 0xa0,
XCHG = 0xe0, // Only valid with fetch=true.
CMPXCHG = 0xf0, // Only valid with fetch=true.
};

Op op;
bool fetch{};
Deref access;
Reg valreg;
constexpr bool operator==(const LockAdd&) const = default;
constexpr bool operator==(const Atomic&) const = default;
};

/// Not an instruction, just used for failure cases.
Expand Down Expand Up @@ -365,7 +378,7 @@ struct IncrementLoopCounter {
constexpr bool operator==(const IncrementLoopCounter&) const = default;
};

using Instruction = std::variant<Undefined, Bin, Un, LoadMapFd, Call, Callx, Exit, Jmp, Mem, Packet, LockAdd, Assume, Assert, IncrementLoopCounter>;
using Instruction = std::variant<Undefined, Bin, Un, LoadMapFd, Call, Callx, Exit, Jmp, Mem, Packet, Atomic, Assume, Assert, IncrementLoopCounter>;

using LabeledInstruction = std::tuple<label_t, Instruction, std::optional<btf_line_info_t>>;
using InstructionSeq = std::vector<LabeledInstruction>;
Expand Down
Loading

0 comments on commit 91a03e2

Please sign in to comment.