summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuyang Huang <yuyanghuang@google.com>2023-10-17 07:10:30 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2023-10-17 07:10:30 +0000
commitc725c0ddc73d6a41d0d627f084288191c85a0d6b (patch)
tree7dc0db68be407bfdd80f1bc04a997726fcc46b41
parentd371c27d80eb389a929f743f23a9c29a2942a95e (diff)
parenta57fefba56ff96ae0295b2285c9e553b02818ef9 (diff)
downloadapf-c725c0ddc73d6a41d0d627f084288191c85a0d6b.tar.gz
Update apf_disassemble() to print to buffer am: a57fefba56
Original change: https://android-review.googlesource.com/c/platform/hardware/google/apf/+/2788872 Change-Id: Ie94882be898dc29da37983336e1b62e51462ebd6 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--apf_disassembler.c5
-rw-r--r--apf_run.c6
-rw-r--r--disassembler.c272
-rw-r--r--disassembler.h4
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);
}
}
diff --git a/apf_run.c b/apf_run.c
index 95de667..116c5ff 100644
--- a/apf_run.c
+++ b/apf_run.c
@@ -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);