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:
@@ -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);
|
||||
|
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user