freedreno/decode: try harder to not crash in disasm
authorRob Clark <robdclark@chromium.org>
Mon, 10 Aug 2020 15:47:40 +0000 (08:47 -0700)
committerMarge Bot <eric+marge@anholt.net>
Tue, 11 Aug 2020 03:13:42 +0000 (03:13 +0000)
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>

src/freedreno/common/disasm.h
src/freedreno/decode/cffdec.c
src/freedreno/decode/crashdec.c
src/freedreno/ir3/disasm-a3xx.c

index 0e1d8502ed763a5a0c7bcc18e864ca2e8850ed5f..00b6e7979be64bc2ebb1d8af315d77f07a12da89 100644 (file)
@@ -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 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);
 
 void disasm_a2xx_set_debug(enum debug_t debug);
 void disasm_a3xx_set_debug(enum debug_t debug);
index afa1fb82f80d4f8ae6bee9ef021277747e7f7a45..a790ca216ee5b1de96d9e01feb74449347668dc3 100644 (file)
@@ -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);
                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")) {
 
                /* 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)
                }
 
                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)
 
                /* dump raw shader: */
                if (ext)
index 933da0ddec06849f21237939888aafdae5d76a3b..fcb4c154191f9282312f28542f3fcd41bde15284 100644 (file)
@@ -40,7 +40,6 @@
 #include <assert.h>
 #include <getopt.h>
 #include <inttypes.h>
 #include <assert.h>
 #include <getopt.h>
 #include <inttypes.h>
-#include <setjmp.h>
 #include <stdarg.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdarg.h>
 #include <stdbool.h>
 #include <stdint.h>
@@ -231,34 +230,6 @@ parseline(const char *line, const char *fmt, ...)
                        break;                                                \
                } else
 
                        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:
  */
 /*
  * 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?
                                 */
                                 * (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)
                        }
 
                        if (dump)
index 2555c739082fd3613c7c8205009af5719d0872ca..29c78ad5e18c28b9bde573eafd7756fa3c591f38 100644 (file)
@@ -1635,12 +1635,6 @@ static bool print_instr(struct disasm_ctx *ctx, uint32_t *dwords, int n)
                ((opc == OPC_END) || (opc == OPC_CHSH));
 }
 
                ((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)
 {
 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;
 }
 {
        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;
+}