About debugging

If you have any questions on programming, this is the place to ask them, whether you're a newbie or an experienced programmer. Discussion on programming in general is also welcome. We will help you with programming homework, but we will not do your work for you! Any porting requests must be made in Developmental Ideas.
Post Reply
User avatar
Newbie
Insane DCEmu
Insane DCEmu
Posts: 171
https://www.artistsworkshop.eu/meble-kuchenne-na-wymiar-warszawa-gdzie-zamowic/
Joined: Sat Jul 27, 2013 1:16 pm
Has thanked: 0
Been thanked: 0

About debugging

Post by Newbie »

Hello everybody,

I know about TRAP #N instruction in SH4 (N between 0-255).
But is there something in SH4 like "Single Step (Trace) Exception (INT 1)" in X86 ?

To Clarify :

The single step exception occurs after every instruction if the trace bit in the flags register is equal to one. Debuggers and other programs will often set this flag so they can trace the execution of a program.

When this exception occurs, the return address on the stack is the address of the next instruction to execute. The trap handler can decode this opcode and decide how to proceed. Most debuggers use the trace exception to check for watchpoints and other events that change dynamically during program execution. Debuggers that use the trace exception for single stepping often disassemble the next instruction using the return address on the stack as a pointer to that instruction's opcode bytes.

Generally, a single step exception handler should preserve all 80x86 registers and other state information. However, you will see an interesting use of the trace exception later in this text where we will purposely modify register values to make one instruction behave like another.
Thanks.
User avatar
bogglez
Moderator
Moderator
Posts: 578
Joined: Sun Apr 20, 2014 9:45 am
Has thanked: 0
Been thanked: 0

Re: About debugging

Post by bogglez »

I have read that the development kit made extensive use of single stepping, but if I remember correctly it was not documented in the non-SEGA manual.. I'm not quite sure. I have never used it myself.
Wiki & tutorials: http://dcemulation.org/?title=Development
Wiki feedback: viewtopic.php?f=29&t=103940
My libgl playground (not for production): https://bitbucket.org/bogglez/libgl15
My lxdream fork (with small fixes): https://bitbucket.org/bogglez/lxdream
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5666
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has thanked: 9 times
Been thanked: 69 times
Contact:

Re: About debugging

Post by BlueCrab »

The User Break Controller on the SH4 would probably be able to do what you want, as you can effectively set it to break on every single instruction.

KOS provides some very basic functionality using it to set individual instructions as breakpoints, but you could certainly extend that. Look it up in the SH4 Hardware Manual if you want to use it.
User avatar
Newbie
Insane DCEmu
Insane DCEmu
Posts: 171
Joined: Sat Jul 27, 2013 1:16 pm
Has thanked: 0
Been thanked: 0

Re: About debugging

Post by Newbie »

Thanks for your answers.

I just want to be sure there' s no kind of special interrupt in SH4 like in X86.

Effectively, I found three way of doing so : the UBC, JTAG and some kind of trick using TRAPA.

On this subject, I suspect KOS using some TRAPA instructions.

Is there some number (TRAPA #N) that could be used along with KOS (in own assembly code) without making trouble and disruption ?

Thanks for your help.
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5666
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has thanked: 9 times
Been thanked: 69 times
Contact:

Re: About debugging

Post by BlueCrab »

The UBC gives you your "special" interrupt. That's really the only way to sensibly set the CPU up to interrupt every instruction, if you really want it to do that. You can use the UBC with KOS already, it's just there's not a function in KOS to do exactly what you want -- it shouldn't be hard to do if you just look it up in the SH4 hardware manual, though.

Your only other option would be to effectively overwrite instructions as you go with trapa, which is just plain ugly to do (you have to deal with flushing the cache every instruction, which, well, is a lot of extra work to be doing).
User avatar
Newbie
Insane DCEmu
Insane DCEmu
Posts: 171
Joined: Sat Jul 27, 2013 1:16 pm
Has thanked: 0
Been thanked: 0

Re: About debugging

Post by Newbie »


Your only other option would be to effectively overwrite instructions as you go with trapa, which is just plain ugly to do (you have to deal with flushing the cache every instruction, which, well, is a lot of extra work to be doing).
I agree with you, it's painful and ugly :)

By the way, I read the UBC hardware documentation.
Assuming I know what registers to handle and how to set up them to trigger a special "event".

I do not see anything about how to "redirect" to my own routine.

I saw a bit that could be set to define a UBC function in control register.
I saw too a nice flow chart that speak about a "debug" program but nothing about how to set up own handle routine when a UBC break is made.

All I found is that when UBC break is made registers and PC are saved.
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5666
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has thanked: 9 times
Been thanked: 69 times
Contact:

Re: About debugging

Post by BlueCrab »

When a UBC break is made, an interrupt is generated. If you leave the UBDE bit of the BRCR unset, then you can register a handler for the interrupt with the normal irq_set_handler() function in KOS (use EXC_USER_BREAK_POST as the source and a C function following the appropriate typedef as your handler). Look at kernel/arch/dreamcast/include/arch/irq.h for more information.

If you set the UBDE bit, then your work is a bit more difficult, but the gist is that you make a piece of assembly that handles the interrupt (which, like every interrupt handler has to return with the rte instruction) and put the address of the function in the DBR register on the CPU. You also have to deal with all the stuff that the normal IRQ handler would deal with (saving registers and the like), so it's probably for the best to just leave that bit unset. :wink:
User avatar
Newbie
Insane DCEmu
Insane DCEmu
Posts: 171
Joined: Sat Jul 27, 2013 1:16 pm
Has thanked: 0
Been thanked: 0

Re: About debugging

Post by Newbie »

Sorry for the late answer. I try to test a "minimal" debug scenario with UBC.

Scenario:

The story is to execute a handler function that prints the PC value of each instructions one by one
each time before those instructions are executed. It' a a mean of test for accuracy of code behavior.

Condition :

I use only channel A in a case of reading instruction.
I don' t care about operand size.
Channel B is off.
Channel A and B are independent (I mean not sequential).
I trigger a Pre execution.


Code :

I use some code from sh-stub.c to retrieve easily the PC value from context parameter in handler.
I use the KOS registering function for my handler function, set up only channel A as instruction read :
I do not set the "User Break Debug Support Function" bit, it's already very complicated thing :)
I post a source code as a start point to discussion on why it does not work.
The source is compiled with just a warning on printf use, it runs but the event seems to not be triggered.

Questions :

First, why it does not work ? Something I miss ?

I do not know if I must change the address value after each match in channel A condition to trigger next instruction :
if yes, it would mean change a register channel A value in UBC and then make 11 nops in handler function.

Also I do not know if I must reset bit 15 to 0 in BRCR register each time to force Channel A break condition to "false" :
if yes, it would mean change BCR value in UBC and then make 11 nops in handler function.

Again, a very interesting study / topic :)

Thanks for your help and attention.
Attachments
TEST.c
(4.57 KiB) Downloaded 54 times
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5666
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has thanked: 9 times
Been thanked: 69 times
Contact:

Re: About debugging

Post by BlueCrab »

Well, I can't really comment too much on the code (I haven't actually had a chance to read/digest it)... I don't know why you pulled code from the GDB stub though for getting the registers, since irq_context_t is actually a type in KOS. Now, what you're doing may well work (because KOS' type matches how GDB handles it up to that point), but it's really not the right way to do it.

Look at KOS' UBC code (kernel/arch/dreamcast/include/dc/ubc.h), because I don't think you're quite setting the registers up correctly. For instance, you probably want to set BASRA to 0x00, not 0x80 (since KOS doesn't use any ASIDs by default other than 0). Also, that file has handy defines for all the registers, so that you don't just have address constants sitting around like you do now...
User avatar
Newbie
Insane DCEmu
Insane DCEmu
Posts: 171
Joined: Sat Jul 27, 2013 1:16 pm
Has thanked: 0
Been thanked: 0

Re: About debugging

Post by Newbie »

Well, I can't really comment too much on the code (I haven't actually had a chance to read/digest it)...
Sad, but thanks to give me some clues.
I don't know why you pulled code from the GDB stub though for getting the registers, since irq_context_t is actually a type in KOS. Now, what you're doing may well work (because KOS' type matches how GDB handles it up to that point), but it's really not the right way to do it.
It's a bit chaotic, but when it will run correctly, I will clean it up.
My goal is just to obtain a break and a call to handler ...
Look at KOS' UBC code (kernel/arch/dreamcast/include/dc/ubc.h), because I don't think you're quite setting the registers up correctly.
Ok, I try to stick around UBC.h. I agree with you, I miss something somewhere ...
For instance, you probably want to set BASRA to 0x00, not 0x80 (since KOS doesn't use any ASIDs by default other than 0).
I use the same value as in the hardware manual examples : big lack of information.
I imagine it depends on what kind of OS the code should be executed : memory virtualization, allocation, paging etc ...

Hard to find people who know about UBC or detailed documentation.

We are so many to be interested in this subject that we could easily set up a convention in a phone booth :)

Thanks again !
User avatar
Newbie
Insane DCEmu
Insane DCEmu
Posts: 171
Joined: Sat Jul 27, 2013 1:16 pm
Has thanked: 0
Been thanked: 0

Re: About debugging

Post by Newbie »

Hi,

When using irq_set_handler() function in KOS and provide a C function following the appropriate type def as handler, I could use context structure to retrieve registers values.

It seems that the registers after leaving handler are restored so no need to save them at all in the handler before using them ...

But for PR, it seems to not be preserved as if I do not save (at start) and restore (at end) it in my handler, it screw up the execution.

Must I make a stack save of all registers I use in my handler ?

Thanks.
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5666
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has thanked: 9 times
Been thanked: 69 times
Contact:

Re: About debugging

Post by BlueCrab »

Newbie wrote:Hi,

When using irq_set_handler() function in KOS and provide a C function following the appropriate type def as handler, I could use context structure to retrieve registers values.

It seems that the registers after leaving handler are restored so no need to save them at all in the handler before using them ...

But for PR, it seems to not be preserved as if I do not save (at start) and restore (at end) it in my handler, it screw up the execution.

Must I make a stack save of all registers I use in my handler ?

Thanks.
PR is definitely saved by the register storing code (look at kernel/arch/dreamcast/kernel/entry.s, specifically the functions _irq_save_regs and _save_regs_finish). If PR is getting corrupted, you've got a problem somewhere in your code, somehow...

And no, you don't have to save the registers, as long as you don't change them in the context that's passed to your function. If you change registers in that, you are going to mess up the state of the program when it returns. The function is called just like any other IRQ handler in KOS, which means it goes through that _irq_save_regs/_save_regs_finish to save/restore registers for you.
User avatar
Newbie
Insane DCEmu
Insane DCEmu
Posts: 171
Joined: Sat Jul 27, 2013 1:16 pm
Has thanked: 0
Been thanked: 0

Re: About debugging

Post by Newbie »

Thanks for all : it ends my questions about debugging :)
Post Reply