Skip to content

Commit 91a03e2

Browse files
authored
Merge branch 'vbpf:main' into sanitizer
2 parents e8e6ec9 + edf88e2 commit 91a03e2

27 files changed

+1167
-274
lines changed

.clang-format

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ AlwaysBreakTemplateDeclarations: Yes
44
AllowShortCaseLabelsOnASingleLine: true
55
PointerAlignment: Left
66
AlignEscapedNewlines: Left
7-
#BreakAfterAttributes: Always
7+
BreakAfterAttributes: Always
88
PenaltyReturnTypeOnItsOwnLine: 60
99
AlwaysBreakAfterReturnType: None

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
3030
FORCE)
3131
set(CMAKE_EXE_LINKER_FLAGS_FUZZERDEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG}")
3232
set(CMAKE_SHARED_LINKER_FLAGS_FUZZERDEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}")
33-
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")
34-
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")
33+
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")
34+
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")
3535

3636
find_program(NUGET nuget)
3737
if (NOT NUGET)

src/asm_cfg.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ static std::string instype(Instruction ins) {
178178
return "callx";
179179
} else if (std::holds_alternative<Mem>(ins)) {
180180
return std::get<Mem>(ins).is_load ? "load" : "store";
181-
} else if (std::holds_alternative<LockAdd>(ins)) {
181+
} else if (std::holds_alternative<Atomic>(ins)) {
182182
return "load_store";
183183
} else if (std::holds_alternative<Packet>(ins)) {
184184
return "packet_access";

src/asm_marshal.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ struct MarshalVisitor {
219219
vector<ebpf_inst> operator()(Mem const& b) {
220220
Deref access = b.access;
221221
ebpf_inst res{
222-
.opcode = static_cast<uint8_t>((INST_MEM << 5) | width_to_opcode(access.width)),
222+
.opcode = static_cast<uint8_t>(INST_MODE_MEM | width_to_opcode(access.width)),
223223
.dst = 0,
224224
.src = 0,
225225
.offset = static_cast<int16_t>(access.offset),
@@ -253,21 +253,24 @@ struct MarshalVisitor {
253253
.imm = static_cast<int32_t>(b.offset),
254254
};
255255
if (b.regoffset) {
256-
res.opcode |= (INST_IND << 5);
256+
res.opcode |= INST_MODE_IND;
257257
res.src = b.regoffset->v;
258258
} else {
259-
res.opcode |= (INST_ABS << 5);
259+
res.opcode |= INST_MODE_ABS;
260260
}
261261
return {res};
262262
}
263263

264-
vector<ebpf_inst> operator()(LockAdd const& b) {
264+
vector<ebpf_inst> operator()(Atomic const& b) {
265+
int32_t imm = (int32_t)b.op;
266+
if (b.fetch)
267+
imm |= INST_FETCH;
265268
return {ebpf_inst{
266-
.opcode = static_cast<uint8_t>(INST_CLS_ST | 0x1 | (INST_XADD << 5) | width_to_opcode(b.access.width)),
269+
.opcode = static_cast<uint8_t>(INST_CLS_STX | INST_MODE_ATOMIC | width_to_opcode(b.access.width)),
267270
.dst = b.access.basereg.v,
268271
.src = b.valreg.v,
269272
.offset = static_cast<int16_t>(b.access.offset),
270-
.imm = 0}};
273+
.imm = imm}};
271274
}
272275

273276
vector<ebpf_inst> operator()(IncrementLoopCounter const& ins) {

src/asm_ostream.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,10 +328,24 @@ struct InstructionPrinterVisitor {
328328
}
329329
}
330330

331-
void operator()(LockAdd const& b) {
331+
void operator()(Atomic const& b) {
332332
os_ << "lock ";
333333
print(b.access);
334-
os_ << " += " << b.valreg;
334+
os_ << " ";
335+
bool showfetch = true;
336+
switch (b.op) {
337+
case Atomic::Op::ADD: os_ << "+"; break;
338+
case Atomic::Op::OR : os_ << "|"; break;
339+
case Atomic::Op::AND: os_ << "&"; break;
340+
case Atomic::Op::XOR: os_ << "^"; break;
341+
case Atomic::Op::XCHG: os_ << "x"; showfetch = false; break;
342+
case Atomic::Op::CMPXCHG: os_ << "cx"; showfetch = false; break;
343+
}
344+
os_ << "= " << b.valreg;
345+
346+
if (showfetch && b.fetch) {
347+
os_ << " fetch";
348+
}
335349
}
336350

337351
void operator()(Assume const& b) {

src/asm_ostream.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ inline std::ostream& operator<<(std::ostream& os, Exit const& a) { return os <<
5959
inline std::ostream& operator<<(std::ostream& os, Jmp const& a) { return os << (Instruction)a; }
6060
inline std::ostream& operator<<(std::ostream& os, Packet const& a) { return os << (Instruction)a; }
6161
inline std::ostream& operator<<(std::ostream& os, Mem const& a) { return os << (Instruction)a; }
62-
inline std::ostream& operator<<(std::ostream& os, LockAdd const& a) { return os << (Instruction)a; }
62+
inline std::ostream& operator<<(std::ostream& os, Atomic const& a) { return os << (Instruction)a; }
6363
inline std::ostream& operator<<(std::ostream& os, Assume const& a) { return os << (Instruction)a; }
6464
inline std::ostream& operator<<(std::ostream& os, Assert const& a) { return os << (Instruction)a; }
6565
inline std::ostream& operator<<(std::ostream& os, IncrementLoopCounter const& a) { return os << (Instruction)a; }

src/asm_parse.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ using crab::linear_expression_t;
3434
#define ASSIGN R"_(\s*=\s*)_"
3535
#define LONGLONG R"_(\s*(ll|)\s*)_"
3636
#define UNOP R"_((-|be16|be32|be64|le16|le32|le64|swap16|swap32|swap64))_"
37+
#define ATOMICOP R"_((\+|\||&|\^|x|cx)=)_"
3738

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

85+
static const std::map<std::string, Atomic::Op> str_to_atomicop = {
86+
{"+", Atomic::Op::ADD},
87+
{"|", Atomic::Op::OR},
88+
{"&", Atomic::Op::AND},
89+
{"^", Atomic::Op::XOR},
90+
{"x", Atomic::Op::XCHG},
91+
{"cx", Atomic::Op::CMPXCHG}};
92+
8493
static const std::map<std::string, int> str_to_width = {
8594
{"8", 1},
8695
{"16", 2},
@@ -182,8 +191,13 @@ Instruction parse_instruction(const std::string& line, const std::map<std::strin
182191
.is_load = false,
183192
};
184193
}
185-
if (regex_match(text, m, regex("lock " DEREF PAREN(REG PLUSMINUS IMM) " [+]= " REG))) {
186-
return LockAdd{.access = deref(m[1], m[2], m[3], m[4]), .valreg = reg(m[5])};
194+
if (regex_match(text, m, regex("lock " DEREF PAREN(REG PLUSMINUS IMM) " " ATOMICOP " " REG "( fetch)?"))) {
195+
Atomic::Op op = str_to_atomicop.at(m[5]);
196+
return Atomic{
197+
.op = op,
198+
.fetch = m[7].matched || op == Atomic::Op::XCHG || op == Atomic::Op::CMPXCHG,
199+
.access = deref(m[1], m[2], m[3], m[4]),
200+
.valreg = reg(m[6])};
187201
}
188202
if (regex_match(text, m, regex("r0 = " DEREF "skb\\[(.*)\\]"))) {
189203
auto width = str_to_width.at(m[1]);

src/asm_syntax.hpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -235,11 +235,24 @@ struct Packet {
235235
constexpr bool operator==(const Packet&) const = default;
236236
};
237237

238-
/// Special instruction for incrementing values inside shared memory.
239-
struct LockAdd {
238+
/// Special instruction for atomically updating values inside shared memory.
239+
/// The analysis just treats an atomic operation as a series of consecutive
240+
/// operations, and the atomicity itself is not significant.
241+
struct Atomic {
242+
enum class Op {
243+
ADD = 0x00,
244+
OR = 0x40,
245+
AND = 0x50,
246+
XOR = 0xa0,
247+
XCHG = 0xe0, // Only valid with fetch=true.
248+
CMPXCHG = 0xf0, // Only valid with fetch=true.
249+
};
250+
251+
Op op;
252+
bool fetch{};
240253
Deref access;
241254
Reg valreg;
242-
constexpr bool operator==(const LockAdd&) const = default;
255+
constexpr bool operator==(const Atomic&) const = default;
243256
};
244257

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

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

370383
using LabeledInstruction = std::tuple<label_t, Instruction, std::optional<btf_line_info_t>>;
371384
using InstructionSeq = std::vector<LabeledInstruction>;

0 commit comments

Comments
 (0)