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>
This commit is contained in:
Rob Clark
2020-08-10 08:47:40 -07:00
committed by Marge Bot
parent cbfce486f2
commit 3d6e4a201a
4 changed files with 43 additions and 38 deletions

View 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 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);

View 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);
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)

View File

@@ -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>
@@ -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)

View File

@@ -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;
}