pvr: debug: Enhancements to hex dumps
Contains the following enhancements & fixes: - Increase (decrease?) the granularity to single bytes rather than using an arbitrary word size, - Remove some spurious semicolons at the end of macros, and - Do not collapse sections of zero bytes that consist of only a single line. Signed-off-by: Matt Coster <matt.coster@imgtec.com> Reviewed-by: Karmjit Mahil <Karmjit.Mahil@imgtec.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20040>
This commit is contained in:
@@ -23,10 +23,12 @@
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "pvr_dump.h"
|
||||
#include "pvr_util.h"
|
||||
#include "util/u_math.h"
|
||||
|
||||
const struct pvr_dump_ctx __pvr_dump_ctx_invalid = {
|
||||
.active_child = &__pvr_dump_ctx_invalid,
|
||||
@@ -37,56 +39,51 @@ const struct pvr_dump_ctx __pvr_dump_ctx_invalid = {
|
||||
*****************************************************************************/
|
||||
|
||||
#define HEX_WORD_SIZE ((unsigned)sizeof(uint32_t))
|
||||
#define HEX_WORD_FMT "%08" PRIx32
|
||||
#define HEX_BYTE_FMT "%02" PRIx8
|
||||
|
||||
/* This must be even, and should probably always be a power of 2. */
|
||||
#define HEX_LINE_SIZE UINT32_C(8)
|
||||
#define HEX_LINE_SIZE (HEX_WORD_SIZE * 8)
|
||||
|
||||
struct pvr_dump_hex_ctx {
|
||||
struct pvr_dump_ctx base;
|
||||
|
||||
const uint32_t *start_ptr;
|
||||
const uint32_t *end_ptr;
|
||||
|
||||
uint64_t nr_words;
|
||||
const uint8_t *start_ptr;
|
||||
const uint8_t *end_ptr;
|
||||
uint64_t nr_bytes;
|
||||
uint32_t offset_digits;
|
||||
|
||||
/* User-modifiable values */
|
||||
const uint32_t *line_ptr;
|
||||
const uint8_t *line_ptr;
|
||||
|
||||
uint32_t prev_non_zero_trailing_zero_words;
|
||||
uint32_t prev_non_zero_trailing_zero_bytes;
|
||||
uint64_t prev_non_zero_leading_zero_lines;
|
||||
const uint32_t *prev_non_zero_line;
|
||||
const uint8_t *prev_non_zero_line;
|
||||
uint64_t zero_lines;
|
||||
};
|
||||
|
||||
static bool pvr_dump_hex_ctx_push(struct pvr_dump_hex_ctx *const ctx,
|
||||
struct pvr_dump_buffer_ctx *const parent_ctx,
|
||||
const uint64_t nr_words)
|
||||
const uint64_t nr_bytes)
|
||||
{
|
||||
const uint64_t real_nr_words =
|
||||
nr_words ? nr_words : parent_ctx->remaining_size / HEX_WORD_SIZE;
|
||||
const uint64_t nr_bytes = real_nr_words * HEX_WORD_SIZE;
|
||||
const uint64_t real_nr_bytes = nr_bytes ? nr_bytes
|
||||
: parent_ctx->remaining_size;
|
||||
bool ret;
|
||||
|
||||
if (parent_ctx->remaining_size < nr_bytes ||
|
||||
(!nr_words && nr_bytes != parent_ctx->remaining_size) ||
|
||||
!ptr_is_aligned(parent_ctx->ptr, HEX_WORD_SIZE)) {
|
||||
if (parent_ctx->remaining_size < nr_bytes)
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = pvr_dump_ctx_push(&ctx->base, &parent_ctx->base);
|
||||
if (!ret)
|
||||
return false;
|
||||
|
||||
ctx->start_ptr = parent_ctx->ptr;
|
||||
ctx->end_ptr = ctx->start_ptr + real_nr_words;
|
||||
ctx->nr_words = real_nr_words;
|
||||
ctx->offset_digits = u64_hex_digits(nr_bytes);
|
||||
ctx->end_ptr = ctx->start_ptr + real_nr_bytes;
|
||||
ctx->nr_bytes = real_nr_bytes;
|
||||
ctx->offset_digits = u64_hex_digits(real_nr_bytes);
|
||||
|
||||
ctx->line_ptr = ctx->start_ptr;
|
||||
|
||||
ctx->prev_non_zero_trailing_zero_words = 0;
|
||||
ctx->prev_non_zero_trailing_zero_bytes = 0;
|
||||
ctx->prev_non_zero_leading_zero_lines = 0;
|
||||
ctx->prev_non_zero_line = NULL;
|
||||
ctx->zero_lines = 0;
|
||||
@@ -111,7 +108,7 @@ pvr_dump_hex_ctx_pop(struct pvr_dump_hex_ctx *const ctx)
|
||||
|
||||
parent = container_of(parent_base, struct pvr_dump_buffer_ctx, base);
|
||||
|
||||
pvr_dump_buffer_advance(parent, ctx->nr_words * HEX_WORD_SIZE);
|
||||
pvr_dump_buffer_advance(parent, ctx->nr_bytes);
|
||||
|
||||
return parent;
|
||||
}
|
||||
@@ -122,7 +119,7 @@ static inline void pvr_dump_hex_print_prefix(const struct pvr_dump_hex_ctx *ctx,
|
||||
pvr_dump_printf(&ctx->base,
|
||||
PVR_DUMP_OFFSET_PREFIX,
|
||||
ctx->offset_digits,
|
||||
offset * HEX_WORD_SIZE);
|
||||
offset);
|
||||
}
|
||||
|
||||
#define pvr_dump_hex_println(ctx, offset, format, args...) \
|
||||
@@ -130,31 +127,62 @@ static inline void pvr_dump_hex_print_prefix(const struct pvr_dump_hex_ctx *ctx,
|
||||
PVR_DUMP_OFFSET_PREFIX format, \
|
||||
(ctx)->offset_digits, \
|
||||
offset, \
|
||||
##args);
|
||||
##args)
|
||||
|
||||
#define pvr_dump_hex_println_no_prefix(ctx, format, args...) \
|
||||
pvr_dump_println(&(ctx)->base, \
|
||||
"%*c" format, \
|
||||
(ctx)->offset_digits + 3, \
|
||||
' ', \
|
||||
##args);
|
||||
##args)
|
||||
|
||||
static void pvr_dump_hex_print_line(const struct pvr_dump_hex_ctx *ctx,
|
||||
const uint8_t *const line_ptr,
|
||||
const uint32_t truncate)
|
||||
{
|
||||
const uint32_t nr_bytes =
|
||||
MIN2(HEX_LINE_SIZE - truncate, ctx->end_ptr - line_ptr);
|
||||
|
||||
pvr_dump_hex_print_prefix(ctx, line_ptr - ctx->start_ptr);
|
||||
|
||||
for (uint32_t i = 0; i < nr_bytes; i++) {
|
||||
if (i == HEX_LINE_SIZE / 2)
|
||||
pvr_dump_printf_cont(&ctx->base, " ");
|
||||
|
||||
if (i % HEX_WORD_SIZE == 0)
|
||||
pvr_dump_printf_cont(&ctx->base, " ");
|
||||
|
||||
if (line_ptr[i])
|
||||
pvr_dump_printf_cont(&ctx->base, HEX_BYTE_FMT, line_ptr[i]);
|
||||
else
|
||||
pvr_dump_printf_cont(&ctx->base, "..");
|
||||
}
|
||||
|
||||
pvr_dump_print_eol(&ctx->base);
|
||||
}
|
||||
|
||||
static void
|
||||
pvr_dump_hex_print_zero_lines(const struct pvr_dump_hex_ctx *const ctx,
|
||||
const uint64_t zero_lines)
|
||||
{
|
||||
const uint64_t zero_words = zero_lines * HEX_LINE_SIZE;
|
||||
const uint64_t zero_bytes = zero_words * HEX_WORD_SIZE;
|
||||
const uint64_t zero_bytes = zero_lines * HEX_LINE_SIZE;
|
||||
|
||||
if (zero_lines == 0)
|
||||
if (!zero_lines)
|
||||
return;
|
||||
|
||||
/* If we've only buffered a single zero line, print it normally. We don't
|
||||
* save any space by folding it, and it's more readable this way.
|
||||
*/
|
||||
if (zero_lines == 1) {
|
||||
pvr_dump_hex_print_line(ctx, ctx->prev_non_zero_line + HEX_LINE_SIZE, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
pvr_dump_hex_println_no_prefix(ctx,
|
||||
" + %" PRIu64 " zero line%s (%" PRIu64
|
||||
" words; %" PRIu64 "/0x%" PRIx64 " bytes)",
|
||||
"/0x%" PRIx64 " bytes)",
|
||||
zero_lines,
|
||||
zero_lines == 1 ? "" : "s",
|
||||
zero_words,
|
||||
zero_bytes,
|
||||
zero_bytes);
|
||||
}
|
||||
@@ -162,11 +190,10 @@ pvr_dump_hex_print_zero_lines(const struct pvr_dump_hex_ctx *const ctx,
|
||||
static void
|
||||
pvr_dump_hex_print_trailing_zeroes(const struct pvr_dump_hex_ctx *const ctx)
|
||||
{
|
||||
const uint64_t zero_words =
|
||||
ctx->zero_lines * HEX_LINE_SIZE + ctx->prev_non_zero_trailing_zero_words;
|
||||
const uint64_t zero_bytes = zero_words * HEX_WORD_SIZE;
|
||||
const uint64_t zero_bytes =
|
||||
ctx->zero_lines * HEX_LINE_SIZE + ctx->prev_non_zero_trailing_zero_bytes;
|
||||
|
||||
if (!ctx->prev_non_zero_trailing_zero_words)
|
||||
if (!ctx->prev_non_zero_trailing_zero_bytes)
|
||||
return pvr_dump_hex_print_zero_lines(ctx, ctx->zero_lines);
|
||||
|
||||
if (!ctx->zero_lines)
|
||||
@@ -174,46 +201,29 @@ pvr_dump_hex_print_trailing_zeroes(const struct pvr_dump_hex_ctx *const ctx)
|
||||
|
||||
pvr_dump_hex_println_no_prefix(ctx,
|
||||
" + %" PRIu64 "+%" PRIu32
|
||||
" zero lines (%" PRIu64 " words; %" PRIu64
|
||||
"/0x%" PRIx64 " bytes)",
|
||||
" zero lines (%" PRIu64 "/0x%" PRIx64
|
||||
" bytes)",
|
||||
ctx->zero_lines,
|
||||
ctx->prev_non_zero_trailing_zero_words,
|
||||
zero_words,
|
||||
ctx->prev_non_zero_trailing_zero_bytes,
|
||||
zero_bytes,
|
||||
zero_bytes);
|
||||
}
|
||||
|
||||
static void pvr_dump_hex_print_line(struct pvr_dump_hex_ctx *ctx,
|
||||
const uint32_t *const line_ptr,
|
||||
const uint32_t truncate)
|
||||
static void pvr_dump_hex_process_line(struct pvr_dump_hex_ctx *const ctx,
|
||||
uint32_t truncate)
|
||||
{
|
||||
const uint32_t nr_words =
|
||||
MIN2(HEX_LINE_SIZE - truncate, ctx->end_ptr - line_ptr);
|
||||
const uint32_t max_bytes = HEX_LINE_SIZE - truncate;
|
||||
|
||||
pvr_dump_hex_print_prefix(ctx, line_ptr - ctx->start_ptr);
|
||||
uint32_t trailing_zero_bytes = max_bytes;
|
||||
|
||||
for (uint32_t i = 0; i < nr_words; i++) {
|
||||
if (i == HEX_LINE_SIZE / 2)
|
||||
pvr_dump_printf_cont(&ctx->base, " ");
|
||||
|
||||
pvr_dump_printf_cont(&ctx->base, " " HEX_WORD_FMT, line_ptr[i]);
|
||||
}
|
||||
|
||||
pvr_dump_print_eol(&ctx->base);
|
||||
}
|
||||
|
||||
static void pvr_dump_hex_process_line(struct pvr_dump_hex_ctx *const ctx)
|
||||
{
|
||||
uint32_t trailing_zero_words = HEX_LINE_SIZE;
|
||||
|
||||
for (uint32_t i = HEX_LINE_SIZE; i > 0; i--) {
|
||||
for (uint32_t i = max_bytes; i > 0; i--) {
|
||||
if (ctx->line_ptr[i - 1]) {
|
||||
trailing_zero_words = HEX_LINE_SIZE - i;
|
||||
trailing_zero_bytes = HEX_LINE_SIZE - i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (trailing_zero_words == HEX_LINE_SIZE) {
|
||||
if (trailing_zero_bytes == max_bytes) {
|
||||
/* No non-zero words were found in this line; mark it and move on. */
|
||||
ctx->zero_lines++;
|
||||
return;
|
||||
@@ -225,7 +235,7 @@ static void pvr_dump_hex_process_line(struct pvr_dump_hex_ctx *const ctx)
|
||||
*/
|
||||
if (ctx->prev_non_zero_line) {
|
||||
pvr_dump_hex_print_zero_lines(ctx, ctx->prev_non_zero_leading_zero_lines);
|
||||
pvr_dump_hex_print_line(ctx, ctx->prev_non_zero_line, 0);
|
||||
pvr_dump_hex_print_line(ctx, ctx->prev_non_zero_line, truncate);
|
||||
}
|
||||
|
||||
/* Now we store the current non-zero line for printing later. This way we
|
||||
@@ -233,25 +243,38 @@ static void pvr_dump_hex_process_line(struct pvr_dump_hex_ctx *const ctx)
|
||||
*/
|
||||
ctx->prev_non_zero_line = ctx->line_ptr;
|
||||
ctx->prev_non_zero_leading_zero_lines = ctx->zero_lines;
|
||||
ctx->prev_non_zero_trailing_zero_words = trailing_zero_words;
|
||||
ctx->prev_non_zero_trailing_zero_bytes = trailing_zero_bytes;
|
||||
ctx->zero_lines = 0;
|
||||
}
|
||||
|
||||
static void pvr_dump_hex(struct pvr_dump_hex_ctx *const ctx)
|
||||
{
|
||||
while (ctx->end_ptr - ctx->line_ptr > 0) {
|
||||
pvr_dump_hex_process_line(ctx);
|
||||
while (ctx->line_ptr < (ctx->end_ptr - HEX_LINE_SIZE)) {
|
||||
pvr_dump_hex_process_line(ctx, 0);
|
||||
ctx->line_ptr += HEX_LINE_SIZE;
|
||||
}
|
||||
|
||||
if (ctx->prev_non_zero_line) {
|
||||
pvr_dump_hex_print_zero_lines(ctx, ctx->prev_non_zero_leading_zero_lines);
|
||||
pvr_dump_hex_print_line(ctx,
|
||||
ctx->prev_non_zero_line,
|
||||
ctx->prev_non_zero_trailing_zero_words);
|
||||
pvr_dump_hex_process_line(ctx,
|
||||
HEX_LINE_SIZE - (ctx->end_ptr - ctx->line_ptr));
|
||||
ctx->line_ptr = ctx->end_ptr;
|
||||
|
||||
/* Collapse and print any trailing zeroes. */
|
||||
pvr_dump_hex_print_trailing_zeroes(ctx);
|
||||
if (ctx->prev_non_zero_line) {
|
||||
/* If we don't have any zero lines to collapse, print the trailing zeroes
|
||||
* on the last line.
|
||||
*/
|
||||
if (!ctx->zero_lines) {
|
||||
pvr_dump_hex_print_line(ctx, ctx->prev_non_zero_line, 0);
|
||||
} else {
|
||||
pvr_dump_hex_print_zero_lines(ctx,
|
||||
ctx->prev_non_zero_leading_zero_lines);
|
||||
|
||||
pvr_dump_hex_print_line(ctx,
|
||||
ctx->prev_non_zero_line,
|
||||
ctx->prev_non_zero_trailing_zero_bytes);
|
||||
|
||||
/* Collapse and print any trailing zeroes. */
|
||||
pvr_dump_hex_print_trailing_zeroes(ctx);
|
||||
}
|
||||
} else {
|
||||
/* We made it to the end of the buffer without ever encountering a
|
||||
* non-zero word. Make this known.
|
||||
@@ -259,15 +282,15 @@ static void pvr_dump_hex(struct pvr_dump_hex_ctx *const ctx)
|
||||
pvr_dump_hex_println(ctx, UINT64_C(0), " <empty buffer>");
|
||||
}
|
||||
|
||||
pvr_dump_hex_println(ctx, ctx->nr_words, " <end of buffer>");
|
||||
pvr_dump_hex_println(ctx, ctx->nr_bytes, " <end of buffer>");
|
||||
}
|
||||
|
||||
bool pvr_dump_buffer_hex(struct pvr_dump_buffer_ctx *const ctx,
|
||||
const uint64_t nr_words)
|
||||
const uint64_t nr_bytes)
|
||||
{
|
||||
struct pvr_dump_hex_ctx hex_ctx;
|
||||
|
||||
if (!pvr_dump_hex_ctx_push(&hex_ctx, ctx, nr_words))
|
||||
if (!pvr_dump_hex_ctx_push(&hex_ctx, ctx, nr_bytes))
|
||||
return false;
|
||||
|
||||
pvr_dump_hex(&hex_ctx);
|
||||
|
||||
@@ -287,7 +287,7 @@ pvr_dump_buffer_ctx_pop(struct pvr_dump_buffer_ctx *const ctx)
|
||||
return pvr_dump_ctx_pop(&ctx->base);
|
||||
}
|
||||
|
||||
bool pvr_dump_buffer_hex(struct pvr_dump_buffer_ctx *ctx, uint64_t nr_words);
|
||||
bool pvr_dump_buffer_hex(struct pvr_dump_buffer_ctx *ctx, uint64_t nr_bytes);
|
||||
|
||||
static inline void __pvr_dump_buffer_advance(struct pvr_dump_buffer_ctx *ctx,
|
||||
const uint64_t nr_bytes)
|
||||
|
||||
@@ -452,7 +452,7 @@ print_block_vdmctrl_ppp_state_update(struct pvr_dump_csb_ctx *const csb_ctx,
|
||||
device,
|
||||
BUFFER_TYPE_PPP,
|
||||
ppp_addr,
|
||||
ppp_size,
|
||||
ppp_size * PVR_DUMP_CSB_WORD_SIZE,
|
||||
"word_count");
|
||||
|
||||
end_pop_ctx:
|
||||
@@ -1882,28 +1882,23 @@ static bool print_sub_buffer(struct pvr_dump_ctx *const ctx,
|
||||
if (!expected_size) {
|
||||
pvr_dump_field(base_ctx,
|
||||
"<buffer size>",
|
||||
"%" PRIu64 " words (%" PRIu64 " bytes) mapped",
|
||||
real_size,
|
||||
real_size * PVR_DUMP_CSB_WORD_SIZE);
|
||||
"%" PRIu64 " bytes mapped",
|
||||
real_size);
|
||||
} else if (expected_size > real_size) {
|
||||
pvr_dump_field(base_ctx,
|
||||
"<buffer size>",
|
||||
"%" PRIu64 " (%" PRIu64 " bytes) mapped, expected %" PRIu64
|
||||
" (%" PRIu64 " bytes) from %s",
|
||||
"%" PRIu64 " bytes mapped, expected %" PRIu64
|
||||
" bytes (from %s)",
|
||||
real_size,
|
||||
real_size * PVR_DUMP_CSB_WORD_SIZE,
|
||||
expected_size,
|
||||
expected_size * PVR_DUMP_CSB_WORD_SIZE,
|
||||
size_src);
|
||||
} else {
|
||||
pvr_dump_field(base_ctx,
|
||||
"<buffer size>",
|
||||
"%" PRIu64 " (%" PRIu64 " bytes; from %s)",
|
||||
"%" PRIu64 " bytes (from %s)",
|
||||
expected_size,
|
||||
expected_size * PVR_DUMP_CSB_WORD_SIZE,
|
||||
size_src);
|
||||
pvr_dump_buffer_truncate(&sub_ctx.base,
|
||||
expected_size * PVR_DUMP_CSB_WORD_SIZE);
|
||||
pvr_dump_buffer_truncate(&sub_ctx.base, expected_size);
|
||||
}
|
||||
|
||||
if (sub_ctx.bo_mapped_in_ctx)
|
||||
|
||||
Reference in New Issue
Block a user