Skip to content

Commit

Permalink
Byteswap fixes
Browse files Browse the repository at this point in the history
* Add byteswap test cases
* Fix asm_parse.cpp to allow le* operations

Signed-off-by: Dave Thaler <[email protected]>
  • Loading branch information
dthaler committed Dec 28, 2023
1 parent 81a834d commit 2d83ab9
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 8 deletions.
2 changes: 1 addition & 1 deletion src/asm_parse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ using crab::linear_expression_t;
#define OPASSIGN R"_(\s*(\S*)=\s*)_"
#define ASSIGN R"_(\s*=\s*)_"
#define LONGLONG R"_(\s*(ll|)\s*)_"
#define UNOP R"_((-|be16|be32|be64))_"
#define UNOP R"_((-|be16|be32|be64|le16|le32|le64))_"

#define PLUSMINUS R"_((\s*[+-])\s*)_"
#define LPAREN R"_(\s*\(\s*)_"
Expand Down
13 changes: 7 additions & 6 deletions src/asm_unmarshal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,15 @@ struct Unmarshaller {
note("arsh32 is not allowed");
return Bin::Op::ARSH;
case INST_ALU_OP_END:
if ((inst.opcode & INST_CLS_MASK) == INST_CLS_ALU64) {
std::string error_message =
"invalid endian immediate " + std::to_string(inst.imm) + " for 64 bit instruction";
throw InvalidInstruction(pc, error_message.c_str());
}
switch (inst.imm) {
case 16: return (inst.opcode & INST_END_BE) ? Un::Op::BE16 : Un::Op::LE16;
case 32:
if ((inst.opcode & INST_CLS_MASK) == INST_CLS_ALU64)
throw InvalidInstruction(pc, "invalid endian immediate 32 for 64 bit instruction");
return (inst.opcode & INST_END_BE) ? Un::Op::BE32 : Un::Op::LE32;
case 64:
return (inst.opcode & INST_END_BE) ? Un::Op::BE64 : Un::Op::LE64;
case 32: return (inst.opcode & INST_END_BE) ? Un::Op::BE32 : Un::Op::LE32;
case 64: return (inst.opcode & INST_END_BE) ? Un::Op::BE64 : Un::Op::LE64;
default:
throw InvalidInstruction(pc, "invalid endian immediate");
}
Expand Down
6 changes: 5 additions & 1 deletion src/test/test_marshal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ static void check_unmarshal_fail(ebpf_inst inst, std::string expected_error_mess
program_info info{.platform = &g_ebpf_platform_linux,
.type = g_ebpf_platform_linux.get_program_type("unspec", "unspec")};
std::vector<ebpf_inst> insns = {inst};
std::string error_message = std::get<std::string>(unmarshal(raw_program{"", "", insns, info}));
auto result = unmarshal(raw_program{"", "", insns, info});
REQUIRE(std::holds_alternative<std::string>(result));
std::string error_message = std::get<std::string>(result);
REQUIRE(error_message == expected_error_message);
}

Expand Down Expand Up @@ -270,4 +272,6 @@ TEST_CASE("fail unmarshal", "[disasm][marshal]") {
check_unmarshal_fail(ebpf_inst{.opcode = INST_CLS_JMP32}, "0: jump out of bounds\n");
check_unmarshal_fail(ebpf_inst{.opcode = 0x90 | INST_CLS_JMP32}, "0: Bad instruction\n");
check_unmarshal_fail(ebpf_inst{.opcode = 0x10 | INST_CLS_JMP32}, "0: jump out of bounds\n");
check_unmarshal_fail(ebpf_inst{.opcode = INST_ALU_OP_END | INST_CLS_ALU64, .imm = 0}, "0: invalid endian immediate 0 for 64 bit instruction\n");
check_unmarshal_fail(ebpf_inst{.opcode = INST_ALU_OP_END | INST_CLS_ALU64, .imm = 16}, "0: invalid endian immediate 16 for 64 bit instruction\n");
}
80 changes: 80 additions & 0 deletions test-data/unop.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,83 @@ code:
r1 = -r1
post: ["r1.type=number", "r1.svalue=[-5, 5]"]
---
test-case: be16 singleton

pre: ["r1.type=number", "r1.svalue=6636321", "r1.uvalue=6636321"]

code:
<start>: |
r1 = be16 r1 ; 0x654321 -> 0x2143
post: ["r1.type=number", "r1.svalue=8515", "r1.uvalue=8515"]
---
test-case: be32 singleton

pre: ["r1.type=number", "r1.svalue=40926266145", "r1.uvalue=40926266145"]

code:
<start>: |
r1 = be32 r1 ; 0x0987654321 -> 0x21436587
post: ["r1.type=number", "r1.svalue=558065031", "r1.uvalue=558065031"]
---
test-case: be64 singleton

pre: ["r1.type=number", "r1.svalue=40926266145", "r1.uvalue=40926266145"]

code:
<start>: |
r1 = be64 r1 ; 0x0987654321 -> 0x2143658709000000
post: ["r1.type=number", "r1.svalue=2396871057337221120", "r1.uvalue=2396871057337221120"]
---
test-case: le16 singleton

pre: ["r1.type=number", "r1.svalue=6636321", "r1.uvalue=6636321"]

code:
<start>: |
r1 = le16 r1 ; 0x654321 -> 0x4321
post: ["r1.type=number", "r1.svalue=17185", "r1.uvalue=17185"]
---
test-case: le32 singleton

pre: ["r1.type=number", "r1.svalue=40926266145", "r1.uvalue=40926266145"]

code:
<start>: |
r1 = le32 r1 ; 0x0987654321 -> 0x87654321
post: ["r1.type=number", "r1.svalue=2271560481", "r1.uvalue=2271560481"]
---
test-case: le64 singleton

pre: ["r1.type=number", "r1.svalue=40926266145", "r1.uvalue=40926266145"]

code:
<start>: |
r1 = le64 r1 ; 0x0987654321 -> 0x2143658709000000
post: ["r1.type=number", "r1.svalue=40926266145", "r1.uvalue=40926266145"]
---
test-case: le16 range

pre: ["r1.type=number", "r1.svalue=[0, 2]", "r1.uvalue=[0, 2]", "r1.svalue=r1.uvalue"]

code:
<start>: |
r1 = le16 r1 ; this could preserve the range but we don't support that yet
post: ["r1.type=number"]
---
test-case: be16 range

pre: ["r1.type=number", "r1.svalue=[0, 2]", "r1.uvalue=[0, 2]", "r1.svalue=r1.uvalue"]

code:
<start>: |
r1 = be16 r1 ; [0x0000, 0x0002] -> [0x0000, 0x2000] but currently we just lose the range
post: ["r1.type=number"]

0 comments on commit 2d83ab9

Please sign in to comment.