summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Clark <robdclark@chromium.org>2020-08-10 08:47:40 -0700
committerMarge Bot <eric+marge@anholt.net>2020-08-11 03:13:42 +0000
commit3d6e4a201af04018f18c413dead488c3c5565e1a (patch)
treeb36dbd76d47b451538dada36596f8d7a58f687b1
parentcbfce486f2cea8ace3bda5d2d93d28952ad2944d (diff)
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 <robdclark@chromium.org> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6242>
-rw-r--r--src/freedreno/common/disasm.h1
-rw-r--r--src/freedreno/decode/cffdec.c4
-rw-r--r--src/freedreno/decode/crashdec.c31
-rw-r--r--src/freedreno/ir3/disasm-a3xx.c45
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 <assert.h>
#include <getopt.h>
#include <inttypes.h>
-#include <setjmp.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
@@ -232,34 +231,6 @@ parseline(const char *line, const char *fmt, ...)
} 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 <setjmp.h>
+
+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;
+}