From d69e0de92fe6152ccbb520093f13124c91f3c4ef Mon Sep 17 00:00:00 2001 From: Yatis Date: Wed, 24 Feb 2021 11:46:05 +0100 Subject: [PATCH] Gintracer: v0.2.0 - Update disasembler menu @add * Improve performance on the disasm menu * fix centering error on the disasm menu --- gintrace.g3a | Bin 110256 -> 110656 bytes include/gintrace/menu/disasm.h | 18 +- src/main.c | 3 +- src/menu/disassembler/disasm.c | 382 +++++++++++++++++++++++---------- 4 files changed, 280 insertions(+), 123 deletions(-) diff --git a/gintrace.g3a b/gintrace.g3a index dd7a3bf612ced9e375a48b5dbc625e5327bf55e1..295c273b6e731ca4676f8079ff1864d1df71ae2b 100644 GIT binary patch delta 18560 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 XmfPtg7VSRmWbtddg}N~QPlf&;?KPQ8 delta 18159 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 Pj_o%rGz9VgVe|h0xy2J( diff --git a/include/gintrace/menu/disasm.h b/include/gintrace/menu/disasm.h index 6654cf3..917a292 100644 --- a/include/gintrace/menu/disasm.h +++ b/include/gintrace/menu/disasm.h @@ -12,8 +12,8 @@ /* define font information */ #ifdef FXCG50 -#define FWIDTH 8 -#define FHEIGHT 9 +#define FWIDTH 9 +#define FHEIGHT 10 #endif #ifdef FX9860G #define FWIDTH 5 @@ -24,6 +24,13 @@ #define DISASM_NB_COLUMN (DWIDTH / (FWIDTH + 1)) #define DISASM_NB_ROW (DHEIGHT / (FHEIGHT + 1)) + +/* buffcursor: buffer cursor (line + note) */ +struct buffcursor { + int line_idx; + int note_idx; +}; + /* tracer: internal information used to display disassembly view */ struct tracer { /* circular buffer information. @@ -38,8 +45,11 @@ struct tracer { size_t width; size_t height; } size; - off_t cursor; - uint16_t *anchor; + struct { + off_t line_idx; + uint16_t *addr; + } anchor; + struct buffcursor cursor; } buffer; /* display offset */ diff --git a/src/main.c b/src/main.c index 853880d..f5ddce1 100644 --- a/src/main.c +++ b/src/main.c @@ -35,7 +35,8 @@ int main(void) /* intialize UBC information */ ubc_install(); ubc_set_handler(&gintrace_handler); - ubc_set_breakpoint(0, (void*)0x80358a6c, NULL); + //ubc_set_breakpoint(0, (void*)0x80358a6c, NULL); + ubc_set_breakpoint(0, (void*)0x80358a7e, NULL); /* try to trace the function */ gint_switch((void *)0x80358a6c); diff --git a/src/menu/disassembler/disasm.c b/src/menu/disassembler/disasm.c index a893873..ecd793c 100644 --- a/src/menu/disassembler/disasm.c +++ b/src/menu/disassembler/disasm.c @@ -10,13 +10,13 @@ #include /* define the menu information */ -/* TODO: find way to have local information */ +/* TODO: find a way to have local information (session) */ struct tracer tracer; //--- // Internal disassembler processing //--- -/* dhreverse(): Reverse horizotal area (TODO: move me !!) */ +/* dhreverse(): Reverse pixels color on a horizontal area (TODO: move me !!) */ static void dhreverse(int ypos, size_t size) { #ifdef FXCG50 @@ -34,39 +34,56 @@ static void dhreverse(int ypos, size_t size) } -/* disasm_update_index(): Little helper to update the circular index */ -static int disasm_update_index(int index, int direction) +/* disasm_util_line_update(): Little helper to update the line index + * @nte: + * This function will update the given line circular index based on the given + * direction. This is a dirty way to avoid use of modulo. + * + * @arg + * - line_idx The line index + * - direction The direction: upward (negative) and downward (positive) + * + * @return + * - the new line index */ +static int disasm_util_line_update(int line_idx, int direction) { - /* update the counter */ - if (direction > 0) - index = index - 1; - if (direction < 0) - index = index + 1; - - /* check border */ - if (index < 0) - index = (int)tracer.buffer.size.height - 1; - if (index >= (int)tracer.buffer.size.height) - index = 0; + line_idx = line_idx + direction; + while (1) { + if (line_idx < 0) { + line_idx += (int)tracer.buffer.size.height; + continue; + } + if (line_idx >= (int)tracer.buffer.size.height) { + line_idx -= (int)tracer.buffer.size.height; + continue; + } + break; + } /* return the index */ - return (index); + return (line_idx); } -/* disasm_check_special_addr(): Check if the address is special - * +/* disasm_check_special_addr(): Check if the address is special. * @note: - * mode & 1 -> check hardware module register - * mode & 2 -> check syscall address */ -static void disasm_check_special_addr(char *buffer, void *address, int mode) + * This function will check if the given address is special (like a syscall or + * a register) and generate a string which content all information. + * + * @arg: + * - buffer Buffer to store the string information + * - address Address to check + * - type Type of check: + * type & 1 -> check hardware module register + * type & 2 -> check syscall address */ +static void disasm_check_special_addr(char *buffer, void *address, int type) { extern struct tracer tracer; const char *addrname; addrname = NULL; - if ((mode & 1) != 0) + if ((type & 1) != 0) addrname = disasm_dictionary_check_peripheral(address); - if (addrname == NULL && (mode & 2) != 0) + if (addrname == NULL && (type & 2) != 0) addrname = disasm_dictionary_check_syscalls(address); if (addrname == NULL) return; @@ -77,16 +94,23 @@ static void disasm_check_special_addr(char *buffer, void *address, int mode) /* disasm_get_mnemonic_info(): Get mnemonic information * * @note: - * line[0] -> "address opcode opcode_name" - * line[1] -> opcode address note - * line[2] -> first note (arg0) - * line[3] -> first note (arg1) - * line[4] -> first note (arg2) */ + * This function will analyze the given instruction's address. All of its + * information will be stored in a buffer "line". A line is constituted of: + * - line[0] -> "address opcode opcode_name" + * - line[1] -> address note (syscall, register, ...) + * - line[2] -> note (arg0) + * - line[3] -> note (arg1) + * - line[4] -> note (arg2) + * + * @arg: + * - line Line index, used to find the buffer line to store information + * - pc Current Program Counter which store the instruction address */ static void disasm_get_mnemonic_info(int line, uint16_t *pc) { const struct opcode *opcode_info; uint16_t opcode; uintptr_t arg[3]; + int note; /* Wipe note */ tracer.buffer.raw[line][0][0] = '\0'; @@ -96,9 +120,12 @@ static void disasm_get_mnemonic_info(int line, uint16_t *pc) tracer.buffer.raw[line][4][0] = '\0'; /* check special address (register, syscall, ...) */ - disasm_check_special_addr(tracer.buffer.raw[line][1], pc, 2); + note = 1; + disasm_check_special_addr(tracer.buffer.raw[line][note], pc, 2); + if (tracer.buffer.raw[line][note][0] != '\0') + note += 1; - /* generate the "default" information (only the address and word) */ + /* generate the "default" string info (only the address and word) */ snprintf(&tracer.buffer.raw[line][0][0], tracer.buffer.size.width, "%.8lx %.4x ", (uintptr_t)pc, (unsigned int)pc[0]); @@ -119,62 +146,147 @@ static void disasm_get_mnemonic_info(int line, uint16_t *pc) opcode, i, pc); if (arg[i] == 0x00000000) continue; - disasm_check_special_addr( - tracer.buffer.raw[line][2 + i], - (void*)arg[i], 3 - ); + disasm_check_special_addr(tracer.buffer.raw[line][note++], + (void*)arg[i], 3); } - /* generate the complet mnemonic information */ + /* generate the complete mnemonic information */ snprintf(&tracer.buffer.raw[line][0][14], tracer.buffer.size.width - 14, opcode_info->name, arg[0], arg[1], arg[2]); } -/* disasm_buffer_update(): Update the internal display buffer information */ -static void disasm_buffer_update(void) +/* disasm_util_note_counter(): Retrun the index max of a line + * @note + * This function will return the maximum index for a given line. That line + * contains one instruction information and four possible notes. So, the index + * that will be returned can be set in this range [0;4]. + * + * @arg + * - line_idx Line index + * + * @return + * The note index max of the line_idx */ +static int disasm_util_note_counter(int line_idx) { - int direction; - size_t gap; - int line; - int pc; + int note_idx; - /* first, we need to calculate the gaps between the current buffer's - * based anchor and the new memory information, then determine the - * direction */ - direction = (intptr_t)(tracer.buffer.anchor - tracer.memory); - gap = (direction < 0) ? 0 - direction : direction; - if (gap > tracer.buffer.size.height) { - gap = tracer.buffer.size.height; - direction = -tracer.buffer.size.height; + note_idx = 0; + while (++note_idx < 5) { + if (tracer.buffer.raw[line_idx][note_idx][0] == '\0') + break; } - if (gap == 0) - return; - - /* update the virtual PC, used with the internal memory information. - * Note that we reach */ - pc = gap - 1; - if (direction < 0) - pc = tracer.buffer.size.height - gap; - - /* get the start line index */ - line = tracer.buffer.cursor; - if (direction > 0) - line = disasm_update_index(tracer.buffer.cursor, direction); - - /* update the internal buffer */ - tracer.buffer.anchor = tracer.memory; - while ((signed)--gap >= 0) { - disasm_get_mnemonic_info(line, &tracer.buffer.anchor[pc]); - if (direction > 0) - tracer.buffer.cursor = line; - line = disasm_update_index(line, direction); - pc = (direction < 0) ? pc + 1 : pc - 1; - } - if (direction < 0) - tracer.buffer.cursor = line; + return (note_idx - 1); } +/* disasm_util_row_update(): Update the row counter and return true if OOB + * @note: + * This function will update the row counter, used to display one line of + * information. If the row counter exits the screen, true is returned + * + * @arg: + * - row The row counter + * - direction The direction: upward (-1), downward (1) + * + * @return + * 0 The row is always visible + * 1 The row is out of screen */ +static int disasm_util_row_update(int *row, int direction) +{ + *row = *row + direction; + return(*row < 0 || *row >= DISASM_NB_ROW); +} + +/* disasm_util_line_fetch(): Generate all information for the given line. + * + * @arg: + * - line_idx Line index + * - pc Memory address + * - direction Direction to push the limit */ +static void disasm_util_line_fetch(int line_idx, uint16_t *pc, int direction) +{ + if (tracer.buffer.raw[line_idx][0][0] == '\0') { + disasm_get_mnemonic_info(line_idx, pc); + line_idx = disasm_util_line_update(line_idx, direction); + tracer.buffer.raw[line_idx][0][0] = '\0'; + } +} + +/* disasm_display_addr_info(): Display entiere line information + * @note + * This function is a bit complex. It will display, if available, one entire + * line's information like address, opcode name and notes. If the line is not + * available, it will be generated and cached into a circular buffer. + * + * The process to get one instruction information (opcode + notes) cost a lot + * of time because of the amount of data to check. This is why a part of the + * display is cached into an internal circular buffer to avoid display lags + * during the displacement. + * + * @args: + * - row current row id (used to display information) + * - line_idx buffer line index + * - context context information + * - direction display upward (negative) or downward (positive) + * + * @return + * - 0 Row is still on the screen + * - 1 Row is out-of-screen */ +int disasm_display_addr_info(int *row, struct buffcursor *cursor, + struct ucontext *context, int direction, int pc) +{ + int note_max_idx; + void *ptr; + + /* generate the line if missing and move the limit */ + disasm_util_line_fetch(cursor->line_idx, + &tracer.buffer.anchor.addr[pc], direction); + + /* get the last note index if downward */ + note_max_idx = 5; + if (direction == 1) + note_max_idx = disasm_util_note_counter(cursor->line_idx); + + /* walk trough the notes */ + while (cursor->note_idx <= note_max_idx && cursor->note_idx >= 0) { + /* check loop condition */ + ptr = tracer.buffer.raw[cursor->line_idx][cursor->note_idx]; + if (((char*)ptr)[0] == '\0') + break; + + /* check note */ + if (cursor->note_idx != 0) { + drect(0, (*row) * (FHEIGHT + 1) - 1, DWIDTH, + ((*row) * (FHEIGHT + 1) - 1) + (FHEIGHT + 2), + 0x556655); + dtext(tracer.disp.hoffset * (FWIDTH + 1), + (*row) * (FHEIGHT + 1), C_WHITE, ptr); + } else { + /* check instruction */ + dtext(tracer.disp.hoffset * (FWIDTH + 1), + (*row) * (FHEIGHT + 1), C_BLACK, ptr); + + /* highlight SPC if possible */ + ptr = &tracer.buffer.anchor.addr[pc]; + if ((uintptr_t)ptr == context->spc) + dhreverse((*row) * (FHEIGHT + 1) - 1, + FHEIGHT + 2); + /* draw next break / instruction */ + if (tracer.next_break != context->spc + && ptr == (void*)tracer.next_break) { + dhline((*row) * (FHEIGHT + 1) - 1, C_BLACK); + dhline( ((*row) + 1) * (FHEIGHT + 1) - 1, + C_BLACK); + } + } + + /* update internal information */ + if (disasm_util_row_update(row, direction) == 1) + return (1); + cursor->note_idx -= direction; + } + return (0); +} @@ -186,7 +298,7 @@ static void disasm_ctor(void) { memset(&tracer, 0x00, sizeof(struct tracer)); tracer.buffer.size.width = DISASM_NB_COLUMN * 2; - tracer.buffer.size.height = DISASM_NB_ROW * 2; + tracer.buffer.size.height = DISASM_NB_ROW * 2 + 2; tracer.buffer.raw = calloc(sizeof(void*), tracer.buffer.size.height); for (size_t i = 0; i < tracer.buffer.size.height; ++i) { tracer.buffer.raw[i] = calloc(sizeof(char*), 5); @@ -196,7 +308,8 @@ static void disasm_ctor(void) tracer.buffer.raw[i][3] = calloc(tracer.buffer.size.width, 1); tracer.buffer.raw[i][4] = calloc(tracer.buffer.size.width, 1); } - tracer.buffer.cursor = 0; + tracer.buffer.cursor.line_idx = 0; + tracer.buffer.cursor.note_idx = 0; tracer.disp.hoffset = 0; tracer.disp.voffset = 0; } @@ -220,65 +333,79 @@ static void disasm_dtor(void) memset(&tracer, 0x00, sizeof(struct tracer)); } -/* disasm_init(): Called each breakpoint, update the internal buffer */ +/* disasm_init(): Called at each breakpoint, update the internal buffer */ static void disasm_init(struct ucontext *context) { - tracer.memory = (void*)(uintptr_t)((context->spc + 3) & ~3); + int a; + + tracer.buffer.anchor.addr = (void*)(uintptr_t)((context->spc + 1) & ~1); tracer.next_break = context->spc; tracer.next_instruction = context->spc; tracer.spc = context->spc; - disasm_buffer_update(); + + tracer.buffer.cursor.note_idx = 0; + tracer.buffer.cursor.line_idx = 0; + a = disasm_util_line_update(tracer.buffer.cursor.line_idx, -1); + tracer.buffer.raw[a][0][0] = '\0'; + tracer.buffer.raw[tracer.buffer.cursor.line_idx][0][0] = '\0'; + disasm_util_line_fetch(tracer.buffer.cursor.line_idx, + &tracer.buffer.anchor.addr[0], 1); } /* disasm_display(); Display trace information */ static void disasm_display(struct ucontext *context) { - int line; + struct buffcursor cursor; + int row; int pc; + /* display the first part (current middle line and before, upward) */ pc = 0; - line = tracer.buffer.cursor; - for (int row = 0; row < DISASM_NB_ROW; ++row) { - /* display notes and opcode information */ - for (int i = 0; i < 4; ++i) { - if (tracer.buffer.raw[line][i + 1][0] == '\0') - continue; - drect(0, row * (FHEIGHT + 1) - 1, DWIDTH, - (row * (FHEIGHT + 1) - 1) + (FHEIGHT + 2), - 0x556655); - dtext(tracer.disp.hoffset * (FWIDTH + 1), - row * (FHEIGHT + 1), C_WHITE, - tracer.buffer.raw[line][i + 1]); - row = row + 1; - if (row >= DISASM_NB_ROW) - return; - } - dtext(tracer.disp.hoffset * (FWIDTH + 1), - row * (FHEIGHT + 1), C_BLACK, - tracer.buffer.raw[line][0]); + row = DISASM_NB_ROW / 2; + cursor.line_idx = tracer.buffer.cursor.line_idx; + cursor.note_idx = tracer.buffer.cursor.note_idx; + disasm_display_addr_info(&row, &cursor, context, -1, pc); + while (row >= 0) { + disasm_display_addr_info(&row, &cursor, context, -1, pc); + cursor.line_idx = disasm_util_line_update(cursor.line_idx, -1); + cursor.note_idx = 0; + pc = pc - 1; + } - /* highlight SPC if possible */ - if ((uintptr_t)&tracer.buffer.anchor[pc] == context->spc) - dhreverse(row * (FHEIGHT + 1) - 1, FHEIGHT + 2); - - /* draw next break / instruction */ - if (tracer.next_break != context->spc - && (uintptr_t)&tracer.buffer.anchor[pc] == tracer.next_break) { - dhline(row * (FHEIGHT + 1) - 1, C_BLACK); - dhline((row + 1) * (FHEIGHT + 1) - 1, C_BLACK); - } - - /* update line position (circular buffer) */ - line = line + 1; - if (line >= (int)tracer.buffer.size.height) - line = 0; + /* display the second part (after the current middle line, downward) + * @note: + * I use a huge dirty workaround to skip the current middle line + * because all the instruction is generated at the display_addr() + * function. So, if the line is not generated, its notes will not be + * displayed and skipped. So, we need to update the line, fetch + * information, get the note index max then start displaying lines. */ + pc = 0; + row = (DISASM_NB_ROW / 2) + 1; + cursor.line_idx = tracer.buffer.cursor.line_idx; + cursor.note_idx = tracer.buffer.cursor.note_idx - 1; + if (cursor.note_idx < 0) { + pc = 1; + cursor.line_idx = disasm_util_line_update(cursor.line_idx, 1); + disasm_util_line_fetch(cursor.line_idx, + &tracer.buffer.anchor.addr[pc], 1); + cursor.note_idx = disasm_util_note_counter(cursor.line_idx); + } + while (row <= DISASM_NB_ROW) { + disasm_display_addr_info(&row, &cursor, context, 1, pc); pc = pc + 1; + cursor.line_idx = disasm_util_line_update(cursor.line_idx, 1); + disasm_util_line_fetch(cursor.line_idx, + &tracer.buffer.anchor.addr[pc], 1); + cursor.note_idx = disasm_util_note_counter(cursor.line_idx); } } /* disasm_keyboard(): Handle one key event */ static int disasm_keyboard(struct ucontext *context, int key) { + int note_idx; + int line_idx; + /* horizontal update */ if (key == KEY_LEFT) tracer.disp.hoffset += 1; @@ -287,12 +414,31 @@ static int disasm_keyboard(struct ucontext *context, int key) /* vertical update */ if (key == KEY_UP) { - tracer.memory = &tracer.memory[-1]; - disasm_buffer_update(); + tracer.buffer.cursor.note_idx += 1; + note_idx = tracer.buffer.cursor.note_idx; + line_idx = tracer.buffer.cursor.line_idx; + if (note_idx >= 5 + || tracer.buffer.raw[line_idx][note_idx][0] == '\0') { + tracer.buffer.anchor.addr = + &tracer.buffer.anchor.addr[-1]; + line_idx = disasm_util_line_update(line_idx, -1); + tracer.buffer.cursor.line_idx = line_idx; + tracer.buffer.cursor.note_idx = 0; + } } if (key == KEY_DOWN) { - tracer.memory = &tracer.memory[1]; - disasm_buffer_update(); + tracer.buffer.cursor.note_idx -= 1; + note_idx = tracer.buffer.cursor.note_idx; + line_idx = tracer.buffer.cursor.line_idx; + if (note_idx < 0) { + tracer.buffer.anchor.addr = + &tracer.buffer.anchor.addr[1]; + line_idx = disasm_util_line_update(line_idx, 1); + disasm_util_line_fetch(line_idx, tracer.memory, 1); + note_idx = disasm_util_note_counter(line_idx); + tracer.buffer.cursor.line_idx = line_idx; + tracer.buffer.cursor.note_idx = note_idx; + } } /* move break point */