Skip to content

Commit

Permalink
Tracewrap 8.1 hexagon (#38)
Browse files Browse the repository at this point in the history
* Rest of unfinished hexagon work.

* Add trace function defintions to helper.h

* Add trace helper functions.

* Remove any tracing code from original files for now.

* Log trace events

* Fix defintions

* Fix several build errors.

* Add first logging of register reads.

* Trace frame begins and ends

* Log register read and writes

* Log traps with endframe

* Generate register reads, instead of having them in get_result_gpr.

Otherwise too many reads get logged and would lead to conflicts when comparing the traces.

* Add load_reg tracing only for rw regs. Not also w regs.

* Generate load traces

* Trace memory stores.

* Rework and add some register logging

* Emit register names instead of numbers

* Set actually passed parameter type.

* Trace gpr/ctrl load/store

* Trace register pair load/store

* Trace predicate reg load/stores

* Rename hexagon_regnames -> hex_regnames (use our names)

* Pass size in bytes, not in bits.

* Move vector trace functions to bottom of file for order.

* Clean up comments

* Remove unused function.

* Pass complete size of packet, not just number of instructions.

* 1byte = 8bits -.-

* Trace register writes during packet commit.

* Always log prediate reads.

* Remove tracing of double register.

* Fix: call correct helper

* Add many more traces of reg loads and stores of new/normal

* Add several traces of PC stores.

* Trace write to PC for end of packet

* Add initial load of PC.

* Check for new or old pred write

* Remove loggin of PC

* Determine num of instructions for fram ends by packet size. Since num_insn omits immext.

* Log all loads at the beginning of a packet to prevent incorrect Pre-Operand setting

* Fix: Pass MemOps to tracing functions. Not byte numbers.

* Check needs_commit falg before writing the .new or the non new reg

* Fix logging of endframe.

* Set the .new register as Pre-Operands the non-tmp registers.

* Trace USR writes

* Track the LC0 decrement writes properly.

* Fix: hex_gpr doesn't track the PC always reliable. remove tracking of it.

* Trace correct register C5 insteaed of C4

* Dont use get_gpr since it messes up the execution.

* Fix tracking of LC0

* Add build job for Hexagon

* Update .github/workflows/build.yaml

Co-authored-by: Ivan Gotovchits <[email protected]>

* Use checkout action to clone BAP repos.

* Add missing libprotobuf-c-dev dep

* Remove ref from checkout action.

---------

Co-authored-by: Ivan Gotovchits <[email protected]>
  • Loading branch information
Rot127 and ivg authored Dec 14, 2023
1 parent ccecd89 commit 3ab48d3
Show file tree
Hide file tree
Showing 13 changed files with 431 additions and 14 deletions.
20 changes: 13 additions & 7 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
run: |
sudo apt-get update
sudo apt-get --no-install-recommends -y build-dep qemu
sudo apt-get install -y autoconf libtool protobuf-c-compiler
sudo apt-get install -y autoconf libtool protobuf-c-compiler libprotobuf-c-dev
pip3 install --user ninja
- name: Install OCaml
uses: ocaml/setup-ocaml@v2
Expand All @@ -30,12 +30,18 @@ jobs:
- name: Install piqi
run: |
opam install piqi
- name: Clone qemu and bap-frames
run: |
git clone --depth 1 http://github.com/BinaryAnalysisPlatform/bap-frames.git
git clone --depth 1 http://github.com/BinaryAnalysisPlatform/qemu.git
- name: Build without tracewrap
- name: Checkout bap-frames
uses: actions/checkout@v4
with:
repository: BinaryAnalysisPlatform/bap-frames
path: bap-frames
- name: Checkout qemu
uses: actions/checkout@v4
with:
repository: BinaryAnalysisPlatform/qemu
path: qemu
- name: Build for Hexagon
run: |
cd qemu
./configure --prefix=$HOME --target-list=arm-linux-user
opam exec -- ./configure --prefix=$HOME --with-tracewrap="$GITHUB_WORKSPACE"/bap-frames --target-list=hexagon-linux-user
ninja -C build
6 changes: 6 additions & 0 deletions linux-user/hexagon/trace_info.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#pragma once

#include "frame_arch.h"

const uint64_t frame_arch = frame_arch_hexagon;
const uint64_t frame_mach = frame_mach_hexagon_V6;
5 changes: 5 additions & 0 deletions scripts/meson-buildoptions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ meson_options_help() {
printf "%s\n" ' Set available tracing backends [log] (choices:'
printf "%s\n" ' dtrace/ftrace/log/nop/simple/syslog/ust)'
printf "%s\n" ' --enable-tsan enable thread sanitizer'
printf "%s\n" ' --enable-tracewrap tracewrap (bap-frames) compression support'
printf "%s\n" ' --firmwarepath=VALUES search PATH for firmware files [share/qemu-'
printf "%s\n" ' firmware]'
printf "%s\n" ' --iasl=VALUE Path to ACPI disassembler'
Expand All @@ -66,6 +67,7 @@ meson_options_help() {
printf "%s\n" ' [NORMAL]'
printf "%s\n" ' --with-coroutine=CHOICE coroutine backend to use (choices:'
printf "%s\n" ' auto/sigaltstack/ucontext/windows)'
printf "%s\n" ' --tracewrap-dir=VALUE path to bap-frames'
printf "%s\n" ' --with-pkgversion=VALUE use specified string as sub-version of the'
printf "%s\n" ' package'
printf "%s\n" ' --with-trace-file=VALUE Trace file prefix for simple backend [trace]'
Expand Down Expand Up @@ -468,6 +470,9 @@ _meson_option_parse() {
--with-trace-file=*) quote_sh "-Dtrace_file=$2" ;;
--enable-tsan) printf "%s" -Dtsan=true ;;
--disable-tsan) printf "%s" -Dtsan=false ;;
--enable-tracewrap) printf "%s" -Dtracewrap=true ;;
--disable-tracewrap) printf "%s" -Dtracewrap=false ;;
--tracewrap-dir=*) quote_sh "-Dtracewrap_dir=$2" ;;
--enable-u2f) printf "%s" -Du2f=enabled ;;
--disable-u2f) printf "%s" -Du2f=disabled ;;
--enable-usb-redir) printf "%s" -Dusb_redir=enabled ;;
Expand Down
1 change: 1 addition & 0 deletions target/hexagon/gen_tcg.h
Original file line number Diff line number Diff line change
Expand Up @@ -1367,6 +1367,7 @@
uiV = uiV; \
tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], ctx->pkt->pc); \
TCGv excp = tcg_constant_tl(HEX_EXCP_TRAP0); \
gen_helper_trace_endframe(cpu_env, hex_gpr[HEX_REG_PC], tcg_constant_i32(1)); \
gen_helper_raise_exception(cpu_env, excp); \
} while (0)
#endif
3 changes: 2 additions & 1 deletion target/hexagon/gen_tcg_funcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ def genptr_decl_pair_writable(f, tag, regtype, regid, regno):
hex_common.bad_register(regtype, regid)
f.write(f" TCGv_i64 {regtype}{regid}V = " f"get_result_gpr_pair(ctx, {regN});\n")


def genptr_decl_writable(f, tag, regtype, regid, regno):
regN = f"{regtype}{regid}N"
if regtype == "R":
Expand Down Expand Up @@ -276,6 +275,7 @@ def genptr_src_read(f, tag, regtype, regid):
elif regid not in {"s", "t", "u", "v"}:
hex_common.bad_register(regtype, regid)
elif regtype == "C":
# BAP tracing: Done in gen_read_ctrl_reg_...
if regid == "ss":
f.write(
f" gen_read_ctrl_reg_pair(ctx, {regtype}{regid}N, "
Expand Down Expand Up @@ -387,6 +387,7 @@ def gen_helper_call_imm(f, immlett):


def genptr_dst_write_pair(f, tag, regtype, regid):
# BAP tracing: Done in gen_log_reg_write_pair
f.write(f" gen_log_reg_write_pair(ctx, {regtype}{regid}N, "
f"{regtype}{regid}V);\n")

Expand Down
49 changes: 49 additions & 0 deletions target/hexagon/genptr.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,13 @@ void gen_log_reg_write(DisasContext *ctx, int rnum, TCGv val)
/* Do this so HELPER(debug_commit_end) will know */
tcg_gen_movi_tl(hex_reg_written[rnum], 1);
}
if (rnum != HEX_REG_PC) {
if (ctx->need_commit && rnum != HEX_REG_LC0) {
gen_helper_trace_store_reg_new(tcg_constant_i32(rnum), val);
} else {
gen_helper_trace_store_reg(tcg_constant_i32(rnum), val);
}
}
}

static void gen_log_reg_write_pair(DisasContext *ctx, int rnum, TCGv_i64 val)
Expand Down Expand Up @@ -155,6 +162,11 @@ void gen_log_pred_write(DisasContext *ctx, int pnum, TCGv val)
tcg_gen_ori_tl(ctx->pred_written, ctx->pred_written, 1 << pnum);
}
set_bit(pnum, ctx->pregs_written);
if (ctx->need_commit) {
gen_helper_trace_store_pred_new(tcg_constant_i32(pnum), pred);
} else {
gen_helper_trace_store_pred(tcg_constant_i32(pnum), pred);
}
}

static inline void gen_read_p3_0(TCGv control_reg)
Expand Down Expand Up @@ -202,6 +214,7 @@ static inline void gen_read_ctrl_reg_pair(DisasContext *ctx, const int reg_num,
TCGv p3_0 = tcg_temp_new();
gen_read_p3_0(p3_0);
tcg_gen_concat_i32_i64(dest, p3_0, hex_gpr[reg_num + 1]);
// p3_0 already read in gen_read_p3_0
} else if (reg_num == HEX_REG_PC - 1) {
TCGv pc = tcg_constant_tl(ctx->base.pc_next);
tcg_gen_concat_i32_i64(dest, hex_gpr[reg_num], pc);
Expand Down Expand Up @@ -270,6 +283,12 @@ static inline void gen_write_ctrl_reg_pair(DisasContext *ctx, int reg_num,
gen_write_p3_0(ctx, val32);
tcg_gen_extrh_i64_i32(val32, val);
tcg_gen_mov_tl(result, val32);
// p3_0 already written in gen_write_p3_0
if (ctx->need_commit) {
gen_helper_trace_store_reg_new(tcg_constant_i32(reg_num + 1), val32);
} else {
gen_helper_trace_store_reg(tcg_constant_i32(reg_num + 1), val32);
}
} else {
gen_log_reg_write_pair(ctx, reg_num, val);
if (reg_num == HEX_REG_QEMU_PKT_CNT) {
Expand Down Expand Up @@ -412,6 +431,7 @@ void gen_store32(TCGv vaddr, TCGv src, int width, uint32_t slot)
tcg_gen_mov_tl(hex_store_addr[slot], vaddr);
tcg_gen_movi_tl(hex_store_width[slot], width);
tcg_gen_mov_tl(hex_store_val32[slot], src);
gen_helper_trace_store_mem(vaddr, src, tcg_constant_i32(size_memop(width)));
}

void gen_store1(TCGv_env cpu_env, TCGv vaddr, TCGv src, uint32_t slot)
Expand Down Expand Up @@ -452,6 +472,7 @@ void gen_store8(TCGv_env cpu_env, TCGv vaddr, TCGv_i64 src, uint32_t slot)
tcg_gen_mov_tl(hex_store_addr[slot], vaddr);
tcg_gen_movi_tl(hex_store_width[slot], 8);
tcg_gen_mov_i64(hex_store_val64[slot], src);
gen_helper_trace_store_mem_64(vaddr, src, tcg_constant_i32(size_memop(8)));
}

void gen_store8i(TCGv_env cpu_env, TCGv vaddr, int64_t src, uint32_t slot)
Expand Down Expand Up @@ -516,6 +537,7 @@ void gen_set_usr_field(DisasContext *ctx, int field, TCGv val)
tcg_gen_deposit_tl(usr, usr, val,
reg_field_info[field].offset,
reg_field_info[field].width);
gen_helper_trace_store_reg(tcg_constant_i32(HEX_REG_USR), usr);
}

void gen_set_usr_fieldi(DisasContext *ctx, int field, int x)
Expand All @@ -528,6 +550,7 @@ void gen_set_usr_fieldi(DisasContext *ctx, int field, int x)
} else {
tcg_gen_andi_tl(usr, usr, ~bit);
}
gen_helper_trace_store_reg(tcg_constant_i32(HEX_REG_USR), usr);
} else {
TCGv val = tcg_constant_tl(x);
gen_set_usr_field(ctx, field, val);
Expand Down Expand Up @@ -704,13 +727,23 @@ static void gen_call(DisasContext *ctx, int pc_off)
{
TCGv lr = get_result_gpr(ctx, HEX_REG_LR);
tcg_gen_movi_tl(lr, ctx->next_PC);
if (ctx->need_commit) {
gen_helper_trace_store_reg_new(tcg_constant_i32(HEX_REG_LR), lr);
} else {
gen_helper_trace_store_reg(tcg_constant_i32(HEX_REG_LR), lr);
}
gen_write_new_pc_pcrel(ctx, pc_off, TCG_COND_ALWAYS, NULL);
}

static void gen_callr(DisasContext *ctx, TCGv new_pc)
{
TCGv lr = get_result_gpr(ctx, HEX_REG_LR);
tcg_gen_movi_tl(lr, ctx->next_PC);
if (ctx->need_commit) {
gen_helper_trace_store_reg_new(tcg_constant_i32(HEX_REG_LR), lr);
} else {
gen_helper_trace_store_reg(tcg_constant_i32(HEX_REG_LR), lr);
}
gen_write_new_pc_addr(ctx, new_pc, TCG_COND_ALWAYS, NULL);
}

Expand All @@ -724,6 +757,11 @@ static void gen_cond_call(DisasContext *ctx, TCGv pred,
gen_write_new_pc_pcrel(ctx, pc_off, cond, lsb);
tcg_gen_brcondi_tl(cond, lsb, 0, skip);
tcg_gen_movi_tl(lr, ctx->next_PC);
if (ctx->need_commit) {
gen_helper_trace_store_reg_new(tcg_constant_i32(HEX_REG_LR), lr);
} else {
gen_helper_trace_store_reg(tcg_constant_i32(HEX_REG_LR), lr);
}
gen_set_label(skip);
}

Expand Down Expand Up @@ -764,6 +802,7 @@ static void gen_load_frame(DisasContext *ctx, TCGv_i64 frame, TCGv EA)
Insn *insn = ctx->insn; /* Needed for CHECK_NOSHUF */
CHECK_NOSHUF(EA, 8);
tcg_gen_qemu_ld_i64(frame, EA, ctx->mem_idx, MO_TEUQ);
gen_helper_trace_load_mem_64(EA, frame, tcg_constant_i32(MO_TEUQ));
}

#ifndef CONFIG_HEXAGON_IDEF_PARSER
Expand Down Expand Up @@ -873,6 +912,13 @@ static void gen_endloop0(DisasContext *ctx)
}
gen_set_label(label2);

TCGLabel *label_lc0_decr = gen_new_label();
tcg_gen_brcondi_tl(TCG_COND_LEU, hex_gpr[HEX_REG_LC0], 1, label_lc0_decr);
TCGv lc0_tmp = tcg_temp_new();
tcg_gen_subi_tl(lc0_tmp, hex_gpr[HEX_REG_LC0], 1);
gen_helper_trace_store_reg(tcg_constant_i32(HEX_REG_LC0), lc0_tmp);
gen_set_label(label_lc0_decr);

/*
* If we're in a tight loop, we'll do this at the end of the TB to take
* advantage of direct block chaining.
Expand Down Expand Up @@ -909,6 +955,7 @@ static void gen_endloop1(DisasContext *ctx)
TCGv lc1 = get_result_gpr(ctx, HEX_REG_LC1);
gen_jumpr(ctx, hex_gpr[HEX_REG_SA1]);
tcg_gen_subi_tl(lc1, hex_gpr[HEX_REG_LC1], 1);
gen_helper_trace_store_reg(tcg_constant_i32(HEX_REG_LC1), lc1);
}
gen_set_label(label);
}
Expand Down Expand Up @@ -960,6 +1007,7 @@ static void gen_endloop01(DisasContext *ctx)
TCGv lc0 = get_result_gpr(ctx, HEX_REG_LC0);
gen_jumpr(ctx, hex_gpr[HEX_REG_SA0]);
tcg_gen_subi_tl(lc0, hex_gpr[HEX_REG_LC0], 1);
gen_helper_trace_store_reg(tcg_constant_i32(HEX_REG_LC0), lc0);
tcg_gen_br(done);
}
gen_set_label(label3);
Expand All @@ -968,6 +1016,7 @@ static void gen_endloop01(DisasContext *ctx)
TCGv lc1 = get_result_gpr(ctx, HEX_REG_LC1);
gen_jumpr(ctx, hex_gpr[HEX_REG_SA1]);
tcg_gen_subi_tl(lc1, hex_gpr[HEX_REG_LC1], 1);
gen_helper_trace_store_reg(tcg_constant_i32(HEX_REG_LC1), lc1);
}
gen_set_label(done);
}
Expand Down
41 changes: 41 additions & 0 deletions target/hexagon/helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,44 @@ DEF_HELPER_4(probe_noshuf_load, void, env, i32, int, int)
DEF_HELPER_2(probe_pkt_scalar_store_s0, void, env, int)
DEF_HELPER_2(probe_hvx_stores, void, env, int)
DEF_HELPER_2(probe_pkt_scalar_hvx_stores, void, env, int)

#ifdef HAS_TRACEWRAP
// Frames
// name, return type, (CPU env), address
DEF_HELPER_1(trace_newframe, void, tl)
DEF_HELPER_3(trace_endframe, void, env, tl, i32)

// Memory
// name, return type, address, val, width
DEF_HELPER_3(trace_load_mem, void, tl, tl, i32)
DEF_HELPER_3(trace_store_mem, void, tl, tl, i32)
DEF_HELPER_3(trace_load_mem_64, void, tl, i64, i32)
DEF_HELPER_3(trace_store_mem_64, void, tl, i64, i32)

// GPRs
// name, return type, reg, val, (load_new)
DEF_HELPER_2(trace_load_reg, void, i32, i32)
DEF_HELPER_2(trace_load_reg_new, void, i32, i32)
DEF_HELPER_2(trace_store_reg, void, i32, i32)
DEF_HELPER_2(trace_store_reg_new, void, i32, i32)

// VRegs
// name, return type, vreg, val, load_new
DEF_HELPER_2(trace_load_vreg, void, i32, ptr)
DEF_HELPER_2(trace_load_vreg_new, void, i32, ptr)
DEF_HELPER_2(trace_store_vreg, void, i32, ptr)
// DEF_HELPER_2(trace_store_vreg_new, void, i32, ptr)

// Predicates
// name, return type, pred reg, val, load_new
DEF_HELPER_2(trace_load_pred, void, i32, tl)
DEF_HELPER_2(trace_load_pred_new, void, i32, tl)
DEF_HELPER_2(trace_store_pred, void, i32, tl)
DEF_HELPER_2(trace_store_pred_new, void, i32, tl)

DEF_HELPER_2(trace_load_vpred, void, i32, ptr)
DEF_HELPER_2(trace_load_vpred_new, void, i32, ptr)
DEF_HELPER_2(trace_store_vpred, void, i32, ptr)
// DEF_HELPER_2(trace_store_vpred_new, void, i32, ptr)

#endif /* HAS_TRACEWRAP */
7 changes: 7 additions & 0 deletions target/hexagon/idef-parser/parser-helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -1762,6 +1762,13 @@ void gen_load(Context *c, YYLTYPE *locp, HexValue *width,
OUT(c, locp, " | MO_SIGN");
}
OUT(c, locp, " | MO_TE);\n");
OUT(c, locp, "gen_helper_trace_load_mem");
OUT(c, locp, (dst_bit_width == 64) ? "_64(" : "(");
OUT(c, locp, ea, ", ", dst, ", tcg_constant_i32(MO_", &src_bit_width);
if (signedness == SIGNED) {
OUT(c, locp, " | MO_SIGN");
}
OUT(c, locp, " | MO_TE));\n");
}

void gen_store(Context *c, YYLTYPE *locp, HexValue *width, HexValue *ea,
Expand Down
1 change: 1 addition & 0 deletions target/hexagon/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ hexagon_ss.add(files(
'fma_emu.c',
'mmvec/decode_ext_mmvec.c',
'mmvec/system_ext_mmvec.c',
'trace_helper.c'
))

#
Expand Down
20 changes: 16 additions & 4 deletions target/hexagon/op_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,15 +104,19 @@ void HELPER(commit_store)(CPUHexagonState *env, int slot_num)
switch (width) {
case 1:
cpu_stb_data_ra(env, va, env->mem_log_stores[slot_num].data32, ra);
HELPER(trace_store_mem)(va, env->mem_log_stores[slot_num].data32, size_memop(width));
break;
case 2:
cpu_stw_data_ra(env, va, env->mem_log_stores[slot_num].data32, ra);
HELPER(trace_store_mem)(va, env->mem_log_stores[slot_num].data32, size_memop(width));
break;
case 4:
cpu_stl_data_ra(env, va, env->mem_log_stores[slot_num].data32, ra);
HELPER(trace_store_mem)(va, env->mem_log_stores[slot_num].data32, size_memop(width));
break;
case 8:
cpu_stq_data_ra(env, va, env->mem_log_stores[slot_num].data64, ra);
HELPER(trace_store_mem_64)(va, env->mem_log_stores[slot_num].data64, size_memop(width));
break;
default:
g_assert_not_reached();
Expand Down Expand Up @@ -581,31 +585,39 @@ uint8_t mem_load1(CPUHexagonState *env, bool pkt_has_store_s1,
{
uintptr_t ra = GETPC();
check_noshuf(env, pkt_has_store_s1, slot, vaddr, 1);
return cpu_ldub_data_ra(env, vaddr, ra);
uint8_t val = cpu_ldub_data_ra(env, vaddr, ra);
HELPER(trace_load_mem)(vaddr, val, MO_8);
return val;
}

uint16_t mem_load2(CPUHexagonState *env, bool pkt_has_store_s1,
uint32_t slot, target_ulong vaddr)
{
uintptr_t ra = GETPC();
check_noshuf(env, pkt_has_store_s1, slot, vaddr, 2);
return cpu_lduw_data_ra(env, vaddr, ra);
uint16_t val = cpu_lduw_data_ra(env, vaddr, ra);
HELPER(trace_load_mem)(vaddr, val, MO_16);
return val;
}

uint32_t mem_load4(CPUHexagonState *env, bool pkt_has_store_s1,
uint32_t slot, target_ulong vaddr)
{
uintptr_t ra = GETPC();
check_noshuf(env, pkt_has_store_s1, slot, vaddr, 4);
return cpu_ldl_data_ra(env, vaddr, ra);
uint32_t val = cpu_ldl_data_ra(env, vaddr, ra);
HELPER(trace_load_mem)(vaddr, val, MO_32);
return val;
}

uint64_t mem_load8(CPUHexagonState *env, bool pkt_has_store_s1,
uint32_t slot, target_ulong vaddr)
{
uintptr_t ra = GETPC();
check_noshuf(env, pkt_has_store_s1, slot, vaddr, 8);
return cpu_ldq_data_ra(env, vaddr, ra);
uint64_t val = cpu_ldq_data_ra(env, vaddr, ra);
HELPER(trace_load_mem_64)(vaddr, val, size_memop(8));
return val;
}

/* Floating point */
Expand Down
Loading

0 comments on commit 3ab48d3

Please sign in to comment.