From 3d6e4a201af04018f18c413dead488c3c5565e1a Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Mon, 10 Aug 2020 08:47:40 -0700 Subject: [PATCH] freedreno/decode: try harder to not crash in disasm Move the handling for catching asserts when we start decoding garbage into disasm-a3xx. This way it can also cover other cases where cffdec tries to disassemble memory, such as SP_xS_OBJ_START. Signed-off-by: Rob Clark Part-of: --- src/freedreno/common/disasm.h | 1 + src/freedreno/decode/cffdec.c | 4 +-- src/freedreno/decode/crashdec.c | 31 +---------------------- src/freedreno/ir3/disasm-a3xx.c | 45 ++++++++++++++++++++++++++++----- 4 files changed, 43 insertions(+), 38 deletions(-) diff --git a/src/freedreno/common/disasm.h b/src/freedreno/common/disasm.h index 0e1d8502ed7..00b6e7979be 100644 --- a/src/freedreno/common/disasm.h +++ b/src/freedreno/common/disasm.h @@ -54,6 +54,7 @@ int disasm_a2xx(uint32_t *dwords, int sizedwords, int level, gl_shader_stage typ int disasm_a3xx(uint32_t *dwords, int sizedwords, int level, FILE *out, unsigned gpu_id); int disasm_a3xx_stat(uint32_t *dwords, int sizedwords, int level, FILE *out, unsigned gpu_id, struct shader_stats *stats); +int try_disasm_a3xx(uint32_t *dwords, int sizedwords, int level, FILE *out, unsigned gpu_id); void disasm_a2xx_set_debug(enum debug_t debug); void disasm_a3xx_set_debug(enum debug_t debug); diff --git a/src/freedreno/decode/cffdec.c b/src/freedreno/decode/cffdec.c index afa1fb82f80..a790ca216ee 100644 --- a/src/freedreno/decode/cffdec.c +++ b/src/freedreno/decode/cffdec.c @@ -424,7 +424,7 @@ disasm_gpuaddr(const char *name, uint64_t gpuaddr, int level) const char *ext; dump_hex(buf, min(64, sizedwords), level+1); - disasm_a3xx(buf, sizedwords, level+2, stdout, options->gpu_id); + try_disasm_a3xx(buf, sizedwords, level+2, stdout, options->gpu_id); /* this is a bit ugly way, but oh well.. */ if (strstr(name, "SP_VS_OBJ")) { @@ -1491,7 +1491,7 @@ cp_load_state(uint32_t *dwords, uint32_t sizedwords, int level) } if (contents) - disasm_a3xx(contents, num_unit * 2, level+2, stdout, options->gpu_id); + try_disasm_a3xx(contents, num_unit * 2, level+2, stdout, options->gpu_id); /* dump raw shader: */ if (ext) diff --git a/src/freedreno/decode/crashdec.c b/src/freedreno/decode/crashdec.c index 933da0ddec0..fcb4c154191 100644 --- a/src/freedreno/decode/crashdec.c +++ b/src/freedreno/decode/crashdec.c @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include @@ -231,34 +230,6 @@ parseline(const char *line, const char *fmt, ...) break; \ } else -/* - * Provide our own disasm assert() handler, so that we can recover - * after attempting to disassemble things that might not be valid - * instructions: - */ - -static bool jmp_env_valid; -static jmp_buf jmp_env; - -void -ir3_assert_handler(const char *expr, const char *file, int line, - const char *func) -{ - printf("\n%s:%u: %s: Assertion `%s' failed.\n", file, line, func, expr); - if (jmp_env_valid) - longjmp(jmp_env, 1); - abort(); -} - -#define TRY(x) do { \ - assert(!jmp_env_valid); \ - if (setjmp(jmp_env) == 0) { \ - jmp_env_valid = true; \ - x; \ - } \ - jmp_env_valid = false; \ - } while (0) - /* * Decode ringbuffer section: */ @@ -930,7 +901,7 @@ decode_shader_blocks(void) * (or parts of shaders?), so perhaps we should search * for ends of shaders and decode each? */ - TRY(disasm_a3xx(buf, sizedwords, 1, stdout, options.gpu_id)); + try_disasm_a3xx(buf, sizedwords, 1, stdout, options.gpu_id); } if (dump) diff --git a/src/freedreno/ir3/disasm-a3xx.c b/src/freedreno/ir3/disasm-a3xx.c index 2555c739082..29c78ad5e18 100644 --- a/src/freedreno/ir3/disasm-a3xx.c +++ b/src/freedreno/ir3/disasm-a3xx.c @@ -1635,12 +1635,6 @@ static bool print_instr(struct disasm_ctx *ctx, uint32_t *dwords, int n) ((opc == OPC_END) || (opc == OPC_CHSH)); } -int disasm_a3xx(uint32_t *dwords, int sizedwords, int level, FILE *out, unsigned gpu_id) -{ - struct shader_stats stats; - return disasm_a3xx_stat(dwords, sizedwords, level, out, gpu_id, &stats); -} - int disasm_a3xx_stat(uint32_t *dwords, int sizedwords, int level, FILE *out, unsigned gpu_id, struct shader_stats *stats) { @@ -1680,3 +1674,42 @@ void disasm_a3xx_set_debug(enum debug_t d) { debug = d; } + +#include + +static bool jmp_env_valid; +static jmp_buf jmp_env; + +void +ir3_assert_handler(const char *expr, const char *file, int line, + const char *func) +{ + fprintf(stdout, "\n%s:%u: %s: Assertion `%s' failed.\n", file, line, func, expr); + if (jmp_env_valid) + longjmp(jmp_env, 1); + abort(); +} + +#define TRY(x) do { \ + assert(!jmp_env_valid); \ + if (setjmp(jmp_env) == 0) { \ + jmp_env_valid = true; \ + x; \ + } \ + jmp_env_valid = false; \ + } while (0) + + +int disasm_a3xx(uint32_t *dwords, int sizedwords, int level, FILE *out, unsigned gpu_id) +{ + struct shader_stats stats; + return disasm_a3xx_stat(dwords, sizedwords, level, out, gpu_id, &stats); +} + +int try_disasm_a3xx(uint32_t *dwords, int sizedwords, int level, FILE *out, unsigned gpu_id) +{ + struct shader_stats stats; + int ret; + TRY(ret = disasm_a3xx_stat(dwords, sizedwords, level, out, gpu_id, &stats)); + return ret; +} -- 2.30.2