mtdbg: Backtrace implemented (#315)

Added support for backtrace/stacktrace output.
This is useful for high-level languages ​​like C and Oberon07.
If a debug file is provided, searches for the nearest debug symbol.

Reviewed-on: KolibriOS/kolibrios#315
Reviewed-by: Mikhail Frolov <mixa.frolov2003@gmail.com>
Reviewed-by: Burer <burer@noreply.localhost>
This commit is contained in:
2026-01-18 13:08:02 +00:00
parent f065cc6e69
commit ccd0c183ec
2 changed files with 192 additions and 4 deletions

View File

@@ -2,7 +2,10 @@
COLOR_THEME fix MOVIEOS COLOR_THEME fix MOVIEOS
format binary as "" format binary as ""
include '../../macros.inc' include '../../macros.inc'
include '../../KOSfuncs.inc'
use32 use32
db 'MENUET01' db 'MENUET01'
dd 1 dd 1
@@ -1145,6 +1148,105 @@ OnDump:
.ret: .ret:
ret ret
;-----------------------------------------------------------------------------
; Print Backtrace
struct STACK_FRAME
prev_frame rd 1
ret_addr rd 1
ends
OnBacktrace:
push ebp
; Set max depth counter
xor eax, eax
dec eax
mov esi, [curarg]
cmp byte [esi], 0
jz .save_depth
call get_hex_number
mov esi, aParseError
jc .exit
; If depth 0
test eax, eax
jz .done
.save_depth:
mov [bt_depth], eax
; Get start frame addres
mov ebp, [_ebp]
test ebp, ebp
jz .done
mov edi, stack_frame_dump
.next:
mcall SF_DEBUG, SSF_READ_MEMORY, [debuggee_pid], sizeof.STACK_FRAME, ebp
cmp eax, -1
mov esi, read_mem_err
jz .exit
; The address of the previous frame must be less than the current one
mov eax, [edi + STACK_FRAME.prev_frame]
test eax, eax
jz .done
; Save stack_frame_dump
push edi
; Save previous frame
push ebp
; Save return address
mov eax, [edi + STACK_FRAME.ret_addr]
push eax
; Print frame address and return address
push eax ; pop in put_message_nodraw
push ebp ; pop in put_message_nodraw
mov esi, aBacktraceFmt
call put_message_nodraw
; Restore return address
pop eax
; Find symbol by return address
call find_near_symbol
test esi, esi
jnz .print_sym
mov esi, aBacktraceSymStub
.print_sym:
call put_message_nodraw
mov esi, newline
call put_message_nodraw
; Restore previous frame
pop ebp
; Restore stack_frame_dump
pop edi
; The address of the previous frame must be greater than the current one.
cmp [edi + STACK_FRAME.prev_frame], ebp
jna .done
; Set previous frame
mov ebp, [edi + STACK_FRAME.prev_frame]
dec [bt_depth]
jnz .next
.done:
mov esi, newline
.exit:
call put_message
pop ebp
ret
;----------------------------------------------------------------------------- ;-----------------------------------------------------------------------------
; Dissassemble block of executable event ; Dissassemble block of executable event
@@ -1864,7 +1966,7 @@ include 'disasm.inc'
caption_str db 'Kolibri Debugger',0 caption_str db 'Kolibri Debugger',0
begin_str db 'Kolibri Debugger, version 0.35',10 begin_str db 'Kolibri Debugger, version 0.36',10
db 'Hint: type "help" for help, "quit" to quit' db 'Hint: type "help" for help, "quit" to quit'
newline db 10,0 newline db 10,0
prompt db '> ',0 prompt db '> ',0
@@ -1920,6 +2022,9 @@ commands:
dd aDump, OnDump, DumpSyntax, DumpHelp dd aDump, OnDump, DumpSyntax, DumpHelp
db CMD_WITHOUT_PARAM or CMD_WITH_PARAM or CMD_WITH_LOADED_APP db CMD_WITHOUT_PARAM or CMD_WITH_PARAM or CMD_WITH_LOADED_APP
dd aBacktrace, OnBacktrace, BacktraceSyntax, BacktraceHelp
db CMD_WITHOUT_PARAM or CMD_WITH_PARAM or CMD_WITH_LOADED_APP
dd aUnassemble, OnUnassemble, UnassembleSyntax, UnassembleHelp dd aUnassemble, OnUnassemble, UnassembleSyntax, UnassembleHelp
db CMD_WITHOUT_PARAM or CMD_WITH_PARAM or CMD_WITH_LOADED_APP db CMD_WITHOUT_PARAM or CMD_WITH_PARAM or CMD_WITH_LOADED_APP
@@ -1999,7 +2104,8 @@ help_data_msg db 'List of data commands:',10
db 'd [<expression>] - dump data at given address',10 db 'd [<expression>] - dump data at given address',10
db 'u [<expression>] - unassemble instructions at given address',10 db 'u [<expression>] - unassemble instructions at given address',10
db 'r <register> <expression> or',10 db 'r <register> <expression> or',10
db 'r <register>=<expression> - set register value',10,0 db 'r <register>=<expression> - set register value',10
db 'bt [<number>] - display backtrace / stacktrace',10,0
; Breakpoints commands group ; Breakpoints commands group
@@ -2057,6 +2163,11 @@ DumpHelp db 'Dump data of debugged program',10
DumpSyntax db 'Usage: d <expression> - dump data at specified address',10 DumpSyntax db 'Usage: d <expression> - dump data at specified address',10
db ' or: d - continue current dump',10,0 db ' or: d - continue current dump',10,0
aBacktrace db 3,'bt',0
BacktraceHelp db 'Display backtrace / stacktrace',10
BacktraceSyntax db 'Usage: bt <number> - display backtrace with depth',10
db ' or: bt display all backtrace',10,0
aCalc db 2,'?',0 aCalc db 2,'?',0
CalcHelp db 'Calculate value of expression',10 CalcHelp db 'Calculate value of expression',10
CalcSyntax db 'Usage: ? <expression>',10,0 CalcSyntax db 'Usage: ? <expression>',10,0
@@ -2121,6 +2232,11 @@ LoadSymbolsSyntax db 'Usage: load-symbols <symbols-file-name>',10,0
aUnknownCommand db 'Unknown command',10,0 aUnknownCommand db 'Unknown command',10,0
;-----------------------------------------------------------------------------
; Info messages
aBacktraceSymStub db '??',0
aBacktraceFmt db '[0x%8X] 0x%8X in ',0
;----------------------------------------------------------------------------- ;-----------------------------------------------------------------------------
; Error messages ; Error messages
@@ -2493,11 +2609,13 @@ disasm_cur_pos dd ?
disasm_cur_str dd ? disasm_cur_str dd ?
disasm_string rb 256 disasm_string rb 256
thread_info process_information stack_frame_dump rb sizeof.STACK_FRAME
bt_depth rd 1
;----------------------------------------------------------------------------- ;-----------------------------------------------------------------------------
; Coordinates and sizes for GUI ; Coordinates and sizes for GUI
thread_info process_information
data_x_size_dd dd ?, ? data_x_size_dd dd ?, ?
messages_x_size_dd dd ?, ? messages_x_size_dd dd ?, ?
registers_x_pos_dd dd ?, ? registers_x_pos_dd dd ?, ?

View File

@@ -4,6 +4,11 @@
include 'sort.inc' include 'sort.inc'
struct DEBUG_SYMBOL
addr rd 1
string rd 0
ends
; compare proc for sorter ; compare proc for sorter
compare: compare:
cmpsd cmpsd
@@ -459,4 +464,69 @@ find_symbol_name:
@@: @@:
pop esi pop esi
ret ret
;-----------------------------------------------------------------------------
;
; Find the nearest symol using binary search
;
; in: eax - target addres
; out: esi - symbol name
; destroys: ebx, ecx, edx, edi, ebp
;
find_near_symbol:
mov edi, [symbols]
xor esi, esi ; Result
mov ecx, esi ; Left
mov edx, [num_symbols] ; Right
dec edx
js .end
; If the first address is already greater than the target
mov ebp, [edi + ecx * sizeof.DEBUG_SYMBOL]
cmp [ebp + DEBUG_SYMBOL.addr], eax
ja .end
; If the last address is less than or equal to the target
mov ebp, [edi + edx * sizeof.DEBUG_SYMBOL]
cmp [ebp + DEBUG_SYMBOL.addr], eax
jbe .found
.loop:
cmp ecx, edx
ja .end
; Calc middle:
mov ebx, edx ; Middle
sub ebx, ecx ; (right - left)
shr ebx, 1 ; / 2
add ebx, ecx ; + left
; Equal
mov ebp, [edi + ebx * sizeof.DEBUG_SYMBOL]
cmp [ebp + DEBUG_SYMBOL.addr], eax
jz .found
jb .update_left
; Update right
mov edx, ebx
dec edx
jmp .loop
.update_left:
; Save potential result
mov esi, ebp
add esi, DEBUG_SYMBOL.string
; Update left
mov ecx, ebx
inc ecx
jmp .loop
.found:
mov esi, ebp
add esi, DEBUG_SYMBOL.string
.end:
ret