2
* Copyright (c) 2012 Rob Clark <robdclark@gmail.com>
4
* Permission is hereby granted, free of charge, to any person obtaining a
5
* copy of this software and associated documentation files (the "Software"),
6
* to deal in the Software without restriction, including without limitation
7
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
* and/or sell copies of the Software, and to permit persons to whom the
9
* Software is furnished to do so, subject to the following conditions:
11
* The above copyright notice and this permission notice (including the next
12
* paragraph) shall be included in all copies or substantial portions of the
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39
#include <sys/types.h>
51
static struct cffdec_options options = {
55
static bool needs_wfi = false;
56
static bool is_blob = false;
57
static int show_comp = false;
58
static int interactive;
60
static const char *exename;
62
static int handle_file(const char *filename, int start, int end, int draw);
65
print_usage(const char *name)
67
/* clang-format off */
68
fprintf(stderr, "Usage:\n\n"
69
"\t%s [OPTSIONS]... FILE...\n\n"
71
"\t-v, --verbose - more verbose disassembly\n"
72
"\t--dump-shaders - dump each shader to a raw file\n"
73
"\t--no-color - disable colorized output (default for non-console\n"
75
"\t--color - enable colorized output (default for tty output)\n"
76
"\t--no-pager - disable pager (default for non-console output)\n"
77
"\t--pager - enable pager (default for tty output)\n"
78
"\t-s, --summary - don't show individual register writes, but just\n"
79
"\t register values on draws\n"
80
"\t-a, --allregs - show all registers (including ones not written\n"
81
"\t since previous draw) on each draw\n"
82
"\t-S, --start=N - start decoding from frame N\n"
83
"\t-E, --end=N - stop decoding after frame N\n"
84
"\t-F, --frame=N - decode only frame N\n"
85
"\t-D, --draw=N - decode only draw N\n"
86
"\t-e, --exe=NAME - only decode cmdstream from named process\n"
87
"\t--textures - dump texture contents (if possible)\n"
88
"\t-L, --script=LUA - run specified lua script to analyze state\n"
89
"\t-q, --query=REG - query mode, dump only specified query registers on\n"
90
"\t each draw; multiple --query/-q args can be given to\n"
91
"\t dump multiple registers; register can be specified\n"
92
"\t either by name or numeric offset\n"
93
"\t--query-all - in query mode, show all queried regs on each draw\n"
94
"\t (default query mode)\n"
95
"\t--query-written - in query mode, show queried regs on draws if any of\n"
96
"\t them have been written since previous draw\n"
97
"\t--query-delta - in query mode, show queried regs on draws if any of\n"
98
"\t them have changed since previous draw\n"
99
"\t--query-compare - dump registers for BINNING vs GMEM/BYPASS per draw;\n"
100
"\t only applicable for regs set via SDS group (a6xx+),\n"
101
"\t implies --once, can be combined with --query-all,\n"
102
"\t --query-written, or --query-delta\n"
103
"\t--once - decode cmdstream only once (per draw mode); if same\n"
104
"\t cmdstream is executed for each tile, this will decode\n"
105
"\t it only for the first tile and skip the remainder,\n"
106
"\t which can be useful when looking at state that does\n"
107
"\t not change per tile\n"
108
"\t--not-once - decode cmdstream for each IB (default)\n"
109
"\t--unit-test - make reproducible output for unit testing\n"
110
"\t-h, --help - show this message\n"
112
/* clang-format on */
116
/* clang-format off */
117
static const struct option opts[] = {
118
/* Long opts that simply set a flag (no corresponding short alias: */
119
{ "dump-shaders", no_argument, &options.dump_shaders, 1 },
120
{ "no-color", no_argument, &options.color, 0 },
121
{ "color", no_argument, &options.color, 1 },
122
{ "no-pager", no_argument, &interactive, 0 },
123
{ "pager", no_argument, &interactive, 1 },
124
{ "textures", no_argument, &options.dump_textures, 1 },
125
{ "show-compositor", no_argument, &show_comp, 1 },
126
{ "query-all", no_argument, &options.query_mode, QUERY_ALL },
127
{ "query-written", no_argument, &options.query_mode, QUERY_WRITTEN },
128
{ "query-delta", no_argument, &options.query_mode, QUERY_DELTA },
129
{ "query-compare", no_argument, &options.query_compare, 1 },
130
{ "once", no_argument, &options.once, 1 },
131
{ "not-once", no_argument, &options.once, 0 },
132
{ "unit-test", no_argument, &options.unit_test, 1 },
134
/* Long opts with short alias: */
135
{ "verbose", no_argument, 0, 'v' },
136
{ "summary", no_argument, 0, 's' },
137
{ "allregs", no_argument, 0, 'a' },
138
{ "start", required_argument, 0, 'S' },
139
{ "end", required_argument, 0, 'E' },
140
{ "frame", required_argument, 0, 'F' },
141
{ "draw", required_argument, 0, 'D' },
142
{ "exe", required_argument, 0, 'e' },
143
{ "script", required_argument, 0, 'L' },
144
{ "query", required_argument, 0, 'q' },
145
{ "help", no_argument, 0, 'h' },
147
/* clang-format on */
150
main(int argc, char **argv)
152
enum debug_t debug = PRINT_RAW | PRINT_STATS;
154
int start = 0, end = 0x7ffffff, draw = -1;
157
interactive = isatty(STDOUT_FILENO);
159
options.color = interactive;
161
while ((c = getopt_long(argc, argv, "vsaS:E:F:D:e:L:q:h", opts, NULL)) !=
165
/* option that set a flag, nothing to do */
168
debug |= (PRINT_RAW | EXPAND_REPEAT | PRINT_VERBOSE);
171
options.summary = true;
174
options.allregs = true;
177
start = atoi(optarg);
183
start = end = atoi(optarg);
192
options.script = optarg;
193
if (script_load(options.script)) {
194
errx(-1, "error loading %s\n", options.script);
199
realloc(options.querystrs,
200
(options.nquery + 1) * sizeof(*options.querystrs));
201
options.querystrs[options.nquery] = optarg;
207
print_usage(argv[0]);
211
disasm_a2xx_set_debug(debug);
212
disasm_a3xx_set_debug(debug);
218
while (optind < argc) {
219
ret = handle_file(argv[optind], start, end, draw);
221
fprintf(stderr, "error reading: %s\n", argv[optind]);
222
fprintf(stderr, "continuing..\n");
228
print_usage(argv[0]);
230
if ((options.query_mode || options.query_compare) && !options.nquery) {
231
fprintf(stderr, "query options only valid in query mode!\n");
232
print_usage(argv[0]);
245
parse_addr(uint32_t *buf, int sz, unsigned int *len, uint64_t *gpuaddr)
250
*gpuaddr |= ((uint64_t)(buf[2])) << 32;
254
handle_file(const char *filename, int start, int end, int draw)
256
enum rd_sect_type type = RD_NONE;
259
int submit = 0, got_gpu_id = 0;
261
bool needs_reset = false;
264
options.draw_filter = draw;
266
cffdec_init(&options);
268
if (!options.unit_test)
269
printf("Reading %s...\n", filename);
271
script_start_cmdstream(filename);
273
if (!strcmp(filename, "-"))
276
io = io_open(filename);
279
fprintf(stderr, "could not open: %s\n", filename);
291
ret = io_readn(io, arr, 8);
295
while ((arr[0] == 0xffffffff) && (arr[1] == 0xffffffff)) {
296
ret = io_readn(io, arr, 8);
313
buf = malloc(sz + 1);
314
((char *)buf)[sz] = '\0';
315
ret = io_readn(io, buf, sz);
321
printl(1, "test: %s\n", (char *)buf);
325
printl(2, "cmd: %s\n", (char *)buf);
328
skip |= (strstr(buf, exename) != buf);
329
} else if (!show_comp) {
330
skip |= (strstr(buf, "fdperf") == buf);
331
skip |= (strstr(buf, "chrome") == buf);
332
skip |= (strstr(buf, "surfaceflinger") == buf);
333
skip |= ((char *)buf)[0] == 'X';
337
printl(2, "vertex shader:\n%s\n", (char *)buf);
340
printl(2, "fragment shader:\n%s\n", (char *)buf);
347
parse_addr(buf, sz, &gpuaddr.len, &gpuaddr.gpuaddr);
349
case RD_BUFFER_CONTENTS:
350
add_buffer(gpuaddr.gpuaddr, gpuaddr.len, buf);
353
case RD_CMDSTREAM_ADDR:
354
if ((start <= submit) && (submit <= end)) {
355
unsigned int sizedwords;
357
parse_addr(buf, sz, &sizedwords, &gpuaddr);
358
printl(2, "############################################################\n");
359
printl(2, "cmdstream: %d dwords\n", sizedwords);
361
script_start_submit();
362
dump_commands(hostptr(gpuaddr), sizedwords, 0);
365
printl(2, "############################################################\n");
366
printl(2, "vertices: %d\n", vertices);
373
uint32_t gpu_id = *((unsigned int *)buf);
376
options.gpu_id = gpu_id;
377
printl(2, "gpu_id: %d\n", options.gpu_id);
378
cffdec_init(&options);
384
uint64_t chip_id = *((uint64_t *)buf);
385
options.gpu_id = 100 * ((chip_id >> 24) & 0xff) +
386
10 * ((chip_id >> 16) & 0xff) +
387
((chip_id >> 8) & 0xff);
388
printl(2, "gpu_id: %d\n", options.gpu_id);
389
cffdec_init(&options);
399
script_end_cmdstream();
405
printf("corrupt file\n");