diff options
author | Yuyang Huang <yuyanghuang@google.com> | 2023-10-13 17:59:51 +0900 |
---|---|---|
committer | Yuyang Huang <yuyanghuang@google.com> | 2023-10-17 14:41:50 +0900 |
commit | a57fefba56ff96ae0295b2285c9e553b02818ef9 (patch) | |
tree | 7dc0db68be407bfdd80f1bc04a997726fcc46b41 | |
parent | da5fa76889ac458e1b9f18f4e63049ca41ef32e4 (diff) | |
download | apf-a57fefba56ff96ae0295b2285c9e553b02818ef9.tar.gz |
Update apf_disassemble() to print to buffer
Update apf_disassemble() to print to buffer instead of directly print to
STDOUT. It will make the apf_disassemble() reusable in ApfTest.java
through JNI.
Bug: 293811969
Test: TH
Change-Id: I224bbd32d26eb3becc33ae634a8f396f41138877
-rw-r--r-- | apf_disassembler.c | 5 | ||||
-rw-r--r-- | apf_run.c | 6 | ||||
-rw-r--r-- | disassembler.c | 272 | ||||
-rw-r--r-- | disassembler.h | 4 |
4 files changed, 229 insertions, 58 deletions
diff --git a/apf_disassembler.c b/apf_disassembler.c index a7401f3..738079a 100644 --- a/apf_disassembler.c +++ b/apf_disassembler.c @@ -29,6 +29,7 @@ int main(void) { uint32_t program_len = 0; uint8_t program[10000]; + char output_buffer[512]; // Read in hex program bytes int byte; @@ -37,6 +38,8 @@ int main(void) { } for (uint32_t pc = 0; pc < program_len;) { - pc = apf_disassemble(program, program_len, pc); + pc = apf_disassemble(program, program_len, pc, output_buffer, + sizeof(output_buffer) / sizeof(output_buffer[0])); + printf("%s\n", output_buffer); } } @@ -171,13 +171,17 @@ void packet_handler(uint8_t* program, uint32_t program_len, uint32_t ram_len, free(packet); } +static char output_buffer[512]; + void apf_trace_hook(uint32_t pc, const uint32_t* regs, const uint8_t* program, uint32_t program_len, const uint8_t* packet __unused, uint32_t packet_len __unused, const uint32_t* memory __unused, uint32_t memory_len __unused) { if (!tracing_enabled) return; printf("%8" PRIx32 " %8" PRIx32 " ", regs[0], regs[1]); - apf_disassemble(program, program_len, pc); + apf_disassemble(program, program_len, pc, output_buffer, + sizeof(output_buffer) / sizeof(output_buffer[0])); + printf("%s\n", output_buffer); } // Process pcap file through APF filter and generate output files diff --git a/disassembler.c b/disassembler.c index 47f45d9..830e621 100644 --- a/disassembler.c +++ b/disassembler.c @@ -24,8 +24,11 @@ // superfluous ">= 0" with unsigned expressions generates compile warnings. #define ENFORCE_UNSIGNED(c) ((c)==(uint32_t)(c)) -static void print_opcode(const char* opcode) { - printf("%-6s", opcode); +static int print_opcode(const char* opcode, char* output_buffer, + int output_buffer_len, int offset) { + int ret = snprintf(output_buffer + offset, output_buffer_len - offset, + "%-6s", opcode); + return ret; } // Mapping from opcode number to opcode name. @@ -54,32 +57,61 @@ static const char* opcode_names [] = { [STDW_OPCODE] = "stdw", }; -static void print_jump_target(uint32_t target, uint32_t program_len) { +static int print_jump_target(uint32_t target, uint32_t program_len, + char* output_buffer, int output_buffer_len, + int offset) { + int ret; if (target == program_len) { - printf("PASS"); + ret = snprintf(output_buffer + offset, output_buffer_len - offset, + "PASS"); } else if (target == program_len + 1) { - printf("DROP"); + ret = snprintf(output_buffer + offset, output_buffer_len - offset, + "DROP"); } else { - printf("%u", target); + ret = snprintf(output_buffer + offset, output_buffer_len - offset, + "%u", target); } + return ret; } -uint32_t apf_disassemble(const uint8_t* program, uint32_t program_len, uint32_t pc) { - printf("%8u: ", pc); +uint32_t apf_disassemble(const uint8_t* program, uint32_t program_len, + uint32_t pc, char* output_buffer, + int output_buffer_len) { + if (pc > program_len + 1) { + fprintf(stderr, "pc is overflow: pc %d, program_len: %d", pc, + program_len); + return pc; + } +#define ASSERT_RET_INBOUND(x) \ + if ((x) < 0 || (x) >= (output_buffer_len - offset)) return pc + 2 + + int offset = 0; + int ret; + ret = snprintf(output_buffer + offset, output_buffer_len - offset, + "%8u: ", pc); + ASSERT_RET_INBOUND(ret); + offset += ret; if (pc == program_len) { - printf("PASS\n"); + ret = snprintf(output_buffer + offset, output_buffer_len - offset, + "PASS"); + ASSERT_RET_INBOUND(ret); + offset += ret; return ++pc; } if (pc == program_len + 1) { - printf("DROP\n"); + ret = snprintf(output_buffer + offset, output_buffer_len - offset, + "DROP"); + ASSERT_RET_INBOUND(ret); + offset += ret; return ++pc; } const uint8_t bytecode = program[pc++]; const uint32_t opcode = EXTRACT_OPCODE(bytecode); -#define PRINT_OPCODE() print_opcode(opcode_names[opcode]) +#define PRINT_OPCODE() \ + print_opcode(opcode_names[opcode], output_buffer, output_buffer_len, offset) const uint32_t reg_num = EXTRACT_REGISTER(bytecode); // All instructions have immediate fields, so load them now. const uint32_t len_field = EXTRACT_IMM_LENGTH(bytecode); @@ -97,22 +129,42 @@ uint32_t apf_disassemble(const uint8_t* program, uint32_t program_len, uint32_t case LDB_OPCODE: case LDH_OPCODE: case LDW_OPCODE: - PRINT_OPCODE(); - printf("r%d, [%u]", reg_num, imm); + ret = PRINT_OPCODE(); + ASSERT_RET_INBOUND(ret); + offset += ret; + ret = snprintf(output_buffer + offset, output_buffer_len - offset, + "r%d, [%u]", reg_num, imm); + ASSERT_RET_INBOUND(ret); + offset += ret; break; case LDBX_OPCODE: case LDHX_OPCODE: case LDWX_OPCODE: - PRINT_OPCODE(); + ret = PRINT_OPCODE(); + ASSERT_RET_INBOUND(ret); + offset += ret; if (imm) { - printf("r%d, [r1+%u]", reg_num, imm); + ret = + snprintf(output_buffer + offset, output_buffer_len - offset, + "r%d, [r1+%u]", reg_num, imm); + ASSERT_RET_INBOUND(ret); + offset += ret; } else { - printf("r%d, [r1]", reg_num); + ret = + snprintf(output_buffer + offset, output_buffer_len - offset, + "r%d, [r1]", reg_num); + ASSERT_RET_INBOUND(ret); + offset += ret; } break; case JMP_OPCODE: - PRINT_OPCODE(); - print_jump_target(pc + imm, program_len); + ret = PRINT_OPCODE(); + ASSERT_RET_INBOUND(ret); + offset += ret; + ret = print_jump_target(pc + imm, program_len, output_buffer, + output_buffer_len, offset); + ASSERT_RET_INBOUND(ret); + offset += ret; break; case JEQ_OPCODE: case JNE_OPCODE: @@ -120,37 +172,74 @@ uint32_t apf_disassemble(const uint8_t* program, uint32_t program_len, uint32_t case JLT_OPCODE: case JSET_OPCODE: case JNEBS_OPCODE: { - PRINT_OPCODE(); - printf("r0, "); + ret = PRINT_OPCODE(); + ASSERT_RET_INBOUND(ret); + offset += ret; + ret = snprintf(output_buffer + offset, output_buffer_len - offset, + "r0, "); + ASSERT_RET_INBOUND(ret); + offset += ret; // Load second immediate field. uint32_t cmp_imm = 0; if (reg_num == 1) { - printf("r1, "); + ret = snprintf(output_buffer + offset, + output_buffer_len - offset, "r1, "); + ASSERT_RET_INBOUND(ret); + offset += ret; } else if (len_field == 0) { - printf("0, "); + ret = snprintf(output_buffer + offset, + output_buffer_len - offset, "0, "); + ASSERT_RET_INBOUND(ret); + offset += ret; } else { uint32_t cmp_imm_len = 1 << (len_field - 1); uint32_t i; for (i = 0; i < cmp_imm_len && pc < program_len; i++) cmp_imm = (cmp_imm << 8) | program[pc++]; - printf("0x%x, ", cmp_imm); + ret = snprintf(output_buffer + offset, + output_buffer_len - offset, "0x%x, ", cmp_imm); + ASSERT_RET_INBOUND(ret); + offset += ret; } if (opcode == JNEBS_OPCODE) { - print_jump_target(pc + imm + cmp_imm, program_len); - printf(", "); - while (cmp_imm--) - printf("%02x", program[pc++]); + ret = print_jump_target(pc + imm + cmp_imm, program_len, + output_buffer, output_buffer_len, offset); + ASSERT_RET_INBOUND(ret); + offset += ret; + ret = snprintf(output_buffer + offset, + output_buffer_len - offset, ", "); + ASSERT_RET_INBOUND(ret); + offset += ret; + while (cmp_imm--) { + uint8_t byte = program[pc++]; + ret = snprintf(output_buffer + offset, + output_buffer_len - offset, "%02x", byte); + ASSERT_RET_INBOUND(ret); + offset += ret; + } } else { - print_jump_target(pc + imm, program_len); + ret = print_jump_target(pc + imm, program_len, output_buffer, + output_buffer_len, offset); + ASSERT_RET_INBOUND(ret); + offset += ret; } break; } case SH_OPCODE: - PRINT_OPCODE(); + ret = PRINT_OPCODE(); + ASSERT_RET_INBOUND(ret); + offset += ret; if (reg_num) { - printf("r0, r1"); + ret = snprintf(output_buffer + offset, + output_buffer_len - offset, "r0, r1"); + ASSERT_RET_INBOUND(ret); + offset += ret; } else { - printf("r0, %d", signed_imm); + ret = + snprintf(output_buffer + offset, output_buffer_len - offset, + "r0, %d", signed_imm); + ASSERT_RET_INBOUND(ret); + offset += ret; } break; case ADD_OPCODE: @@ -158,18 +247,34 @@ uint32_t apf_disassemble(const uint8_t* program, uint32_t program_len, uint32_t case DIV_OPCODE: case AND_OPCODE: case OR_OPCODE: - PRINT_OPCODE(); + ret = PRINT_OPCODE(); + ASSERT_RET_INBOUND(ret); + offset += ret; if (reg_num) { - printf("r0, r1"); + ret = snprintf(output_buffer + offset, + output_buffer_len - offset, "r0, r1"); + ASSERT_RET_INBOUND(ret); + offset += ret; } else if (!imm && opcode == DIV_OPCODE) { - printf("pass (div 0)"); + ret = snprintf(output_buffer + offset, + output_buffer_len - offset, "pass (div 0)"); + ASSERT_RET_INBOUND(ret); + offset += ret; } else { - printf("r0, %u", imm); + ret = snprintf(output_buffer + offset, + output_buffer_len - offset, "r0, %u", imm); + ASSERT_RET_INBOUND(ret); + offset += ret; } break; case LI_OPCODE: - PRINT_OPCODE(); - printf("r%d, %d", reg_num, signed_imm); + ret = PRINT_OPCODE(); + ASSERT_RET_INBOUND(ret); + offset += ret; + ret = snprintf(output_buffer + offset, output_buffer_len - offset, + "r%d, %d", reg_num, signed_imm); + ASSERT_RET_INBOUND(ret); + offset += ret; break; case EXT_OPCODE: if ( @@ -181,49 +286,106 @@ uint32_t apf_disassemble(const uint8_t* program, uint32_t program_len, uint32_t imm >= LDM_EXT_OPCODE && #endif imm < (LDM_EXT_OPCODE + MEMORY_ITEMS)) { - print_opcode("ldm"); - printf("r%d, m[%u]", reg_num, imm - LDM_EXT_OPCODE); + ret = print_opcode("ldm", output_buffer, output_buffer_len, + offset); + ASSERT_RET_INBOUND(ret); + offset += ret; + ret = + snprintf(output_buffer + offset, output_buffer_len - offset, + "r%d, m[%u]", reg_num, imm - LDM_EXT_OPCODE); + ASSERT_RET_INBOUND(ret); + offset += ret; } else if (imm >= STM_EXT_OPCODE && imm < (STM_EXT_OPCODE + MEMORY_ITEMS)) { - print_opcode("stm"); - printf("r%d, m[%u]", reg_num, imm - STM_EXT_OPCODE); + ret = print_opcode("stm", output_buffer, output_buffer_len, + offset); + ASSERT_RET_INBOUND(ret); + offset += ret; + ret = + snprintf(output_buffer + offset, output_buffer_len - offset, + "r%d, m[%u]", reg_num, imm - STM_EXT_OPCODE); + ASSERT_RET_INBOUND(ret); + offset += ret; } else switch (imm) { case NOT_EXT_OPCODE: - print_opcode("not"); - printf("r%d", reg_num); + ret = print_opcode("not", output_buffer, + output_buffer_len, offset); + ASSERT_RET_INBOUND(ret); + offset += ret; + ret = snprintf(output_buffer + offset, + output_buffer_len - offset, "r%d", + reg_num); + ASSERT_RET_INBOUND(ret); + offset += ret; break; case NEG_EXT_OPCODE: - print_opcode("neg"); - printf("r%d", reg_num); + ret = print_opcode("neg", output_buffer, output_buffer_len, + offset); + ASSERT_RET_INBOUND(ret); + offset += ret; + ret = snprintf(output_buffer + offset, + output_buffer_len - offset, "r%d", reg_num); + ASSERT_RET_INBOUND(ret); + offset += ret; break; case SWAP_EXT_OPCODE: - print_opcode("swap"); + ret = print_opcode("swap", output_buffer, output_buffer_len, + offset); + ASSERT_RET_INBOUND(ret); + offset += ret; break; case MOV_EXT_OPCODE: - print_opcode("mov"); - printf("r%d, r%d", reg_num, reg_num ^ 1); + ret = print_opcode("mov", output_buffer, output_buffer_len, + offset); + ASSERT_RET_INBOUND(ret); + offset += ret; + ret = snprintf(output_buffer + offset, + output_buffer_len - offset, "r%d, r%d", + reg_num, reg_num ^ 1); + ASSERT_RET_INBOUND(ret); + offset += ret; break; default: - printf("unknown_ext %u", imm); + ret = snprintf(output_buffer + offset, + output_buffer_len - offset, "unknown_ext %u", + imm); + ASSERT_RET_INBOUND(ret); + offset += ret; break; } break; case LDDW_OPCODE: case STDW_OPCODE: - PRINT_OPCODE(); + ret = PRINT_OPCODE(); + ASSERT_RET_INBOUND(ret); + offset += ret; if (signed_imm > 0) { - printf("r%u, [r%u+%d]", reg_num, reg_num ^ 1, signed_imm); + ret = snprintf(output_buffer + offset, + output_buffer_len - offset, "r%u, [r%u+%d]", reg_num, + reg_num ^ 1, signed_imm); + ASSERT_RET_INBOUND(ret); + offset += ret; } else if (signed_imm < 0) { - printf("r%u, [r%u-%d]", reg_num, reg_num ^ 1, -signed_imm); + ret = snprintf(output_buffer + offset, + output_buffer_len - offset, "r%u, [r%u-%d]", + reg_num, reg_num ^ 1, -signed_imm); + ASSERT_RET_INBOUND(ret); + offset += ret; } else { - printf("r%u, [r%u]", reg_num, reg_num ^ 1); + ret = snprintf(output_buffer + offset, + output_buffer_len - offset, "r%u, [r%u]", reg_num, + reg_num ^ 1); + ASSERT_RET_INBOUND(ret); + offset += ret; } break; // Unknown opcode default: - printf("unknown %u", opcode); + ret = snprintf(output_buffer + offset, output_buffer_len - offset, + "unknown %u", opcode); + ASSERT_RET_INBOUND(ret); + offset += ret; break; } - printf("\n"); return pc; } diff --git a/disassembler.h b/disassembler.h index c13320e..f4c36f6 100644 --- a/disassembler.h +++ b/disassembler.h @@ -18,4 +18,6 @@ #include <stdint.h> -uint32_t apf_disassemble(const uint8_t* program, uint32_t program_len, uint32_t pc); +uint32_t apf_disassemble(const uint8_t* program, uint32_t program_len, + uint32_t pc, char* output_buffer, + int output_buffer_len); |