VOGONS


First post, by llm

User metadata
Rank Member
Rank
Member

years ago i've added a feature for break point on memory read(write) ranges, slow and only available in heavy-debug mode

something likes these commands
BSMR seg:ofs range // detect reads
BSMW seg:ofs range // detect writes
BSRMW seg:ofs range // detect reads and writes

but i've accidentally deleted the very old dosbox svn repo containing the stuff years ago while cleaning up my backups/moveing to a new system 😒

now i want to reimplement this feature again - and im totaly lost - i need to understand which part of the code is reading, writing parts of data
so can give me anyone of the devs a tip how to cleanly introduce such feature and what parts of the code could be relevant

Writing:
the range write BP is just an extension of the current BPM with a range of values

Reading:
the reading bp needs to hook reading (i think i've done it that way before??)

are these the functions i need to hook? is there a better place to check for hitting the bp range?
dosbox\include\mem.h
host_readb
host_readw
host_readd

or dosbox\include\paging.h
mem_readb_inline
mem_readw_inline
mem_readd_inline

or all of them?

is there a chance to get something like this into mainline, so it won't get lost another time?

Reply 1 of 18, by llm

User metadata
Rank Member
Rank
Member

what i think so far what is needed

dosbox\include\mem.h

extend the host_reads like this (also for word,dword and WORDS_BIGENDIAN/C_UNALIGNED_MEMORY)

static INLINE Bit8u host_readb( HostPt off )
{
#ifdef C_HEAVY_DEBUG
// check for mem-read-bp in range and activate bp if hit
#endif
return off[0];
}

i also need to extend some PageHandler::readb

static INLINE Bit8u mem_readb_inline(PhysPt address) {
HostPt tlb_addr=get_tlb_read(address);
if (tlb_addr) return host_readb(tlb_addr+address);
else return (Bit8u)(get_tlb_readhandler(address))->readb(address); // <-----
}

to get the mem_readX_inline functions into the bp detection

the other unaligned read using mem_readb_inline

Bit16u mem_unalignedreadw(PhysPt address) {
Bit16u ret = mem_readb_inline(address);
ret |= mem_readb_inline(address+1) << 8;
return ret;
}

and some of the PageHandler using direct memory access - without using the above backend functions - is that correct?

Reply 2 of 18, by llm

User metadata
Rank Member
Rank
Member

and i think it will be only available for normal core mode

Reply 3 of 18, by llm

User metadata
Rank Member
Rank
Member

seeking for help:

attached is a WIP/Compilable but not working patch based on svn 4447
that shows my ideas how to hopefully cleanly add a memory read breakpoint feature to heavy-debug mode

there is a new function DEBUG_CheckMemReadBreakpoint that gets called from (nearly) every memory reading function (host_readX, ...)
that searches for BKPNT_MEMORY_READ breakpoints that are in the range of the read, if so the read-happend flag is set in the breakpoint
and CBreakpoint::CheckBreakpoint checks for BKPNT_MEMORY_READ bps with active read-happend

Questions:

1. in CBreakpoint::FindMemReadBreakpoint: how to detect if my host memory read was in the bp range?
2. is the idea with the read-happend flag sensible this way?
3. overall: its not clear to me if i should only implement seg:ofs or also a linear variant and if real or protected-mode memory read bps detection needs to be different
4. should that feature be limited to normal-core - or does the dynamic core also uses the host_readX and the others functions?

Todo:

-Parsing of Command
...

Reply 4 of 18, by llm

User metadata
Rank Member
Rank
Member

i think i've found a way to get a host ptr from the location in my Find-Routine - but is that always the correct way or do i need to work with the get_tlb_read stuff like in the mem_readX_inline functions?

CBreakpoint* CBreakpoint::FindMemReadBreakpoint(Bit8u const* const addr, Bit32u range)
{
std::list<CBreakpoint*>::iterator i;
for (i = BPoints.begin(); i != BPoints.end(); ++i) {
CBreakpoint* bp = (*i);
if ((bp->GetType() == BKPNT_MEMORY_READ) && bp->IsActive())
{
Bit8u const* const bp_host_begin = addr;
Bit8u const* const bp_host_end = addr + range;

PhysPt location = bp->GetLocation();
Bit8u const* const host_location = MemBase + location;

if ((host_location >= bp_host_begin) && (host_location < bp_host_end))
{
return bp;
}
}
}
return 0;
}

Reply 5 of 18, by llm

User metadata
Rank Member
Rank
Member

my second patch to svn 4448

added brakepoint at the hello world string with "BPMR 1dd:108 1"

but it seems that my read-checks do not reach the string bytes - do i still miss some read functions?

core=normal

Reply 6 of 18, by llm

User metadata
Rank Member
Rank
Member

just to be clear: i know that tracking memory reads can be very very very ... slow and that it will work only for core=normal

Reply 7 of 18, by llm

User metadata
Rank Member
Rank
Member

btw: i've got massive problems under VS2019 to debug the debugger itself - the dosbox or windows at whole is blocking very hard, mouse is invisble, etc. any tips to handle that?

Reply 8 of 18, by jmarsh

User metadata
Rank Oldbie
Rank
Oldbie

Edit the project configuration and add "SDL_VIDEODRIVER=windib" to the environment settings for running the debug build. Otherwise the directx backend is used by default and it uses global system locks that trigger the UI blocking you mentioned.

Reply 9 of 18, by llm

User metadata
Rank Member
Rank
Member
jmarsh wrote on 2021-04-26, 17:48:

Edit the project configuration and add "SDL_VIDEODRIVER=windib" to the environment settings for running the debug build. Otherwise the directx backend is used by default and it uses global system locks that trigger the UI blocking you mentioned.

thank you!

any tip how i can my read bp to work?

Reply 10 of 18, by llm

User metadata
Rank Member
Rank
Member

it seems that my finding code is ok but my understanding of when/how breakpoints get activated is wrong

Reply 11 of 18, by Qbix

User metadata
Rank DOSBox Author
Rank
DOSBox Author

Are you calling
DEBUG_EnableDebugger
somewhere when you encounter the memory location that you want to stop execution (will probably be after the read though)

Water flows down the stream
How to ask questions the smart way!

Reply 12 of 18, by llm

User metadata
Rank Member
Rank
Member
Qbix wrote on 2021-04-29, 08:50:

Are you calling
DEBUG_EnableDebugger
somewhere when you encounter the memory location that you want to stop execution (will probably be after the read though)

i thought that gets already set when i start "debug readb.com"

currently its unclear to me:

1. how to detect if the debug command is running - so im not testing memory reads like hell

my idea is to use the pDebugcom+pDebugcom->Active check for that

class DEBUG : public Program {
public:
DEBUG() { pDebugcom = this; active = false; };
~DEBUG() { pDebugcom = 0; };
...

but im a little but confused that the pDebugcom static gets nulled on DEBUG_CheckExecuteBreakpoint?

void DEBUG_CheckExecuteBreakpoint(Bit16u seg, Bit32u off)
{
if (pDebugcom && pDebugcom->IsActive()) {
CBreakpoint::AddBreakpoint(seg,off,true);
CBreakpoint::ActivateBreakpointsExceptAt(SegPhys(cs)+reg_eip);
pDebugcom = 0;
};
};

2. the next thing is that i don't understand when CBreakpoint::IsActive is true or of that changed sometimes

so im uncertain if the activation of breakpoints comes currently too late for my memory read bps

Reply 13 of 18, by Qbix

User metadata
Rank DOSBox Author
Rank
DOSBox Author

debug.com active shouldn't matter.
What you should check is whether the debugger prompt is active or not (where you type in the commands)
Debug_enableDebugger is what causes the debugger to enable when you are running code

Water flows down the stream
How to ask questions the smart way!

Reply 14 of 18, by llm

User metadata
Rank Member
Rank
Member
Qbix wrote on 2021-04-29, 12:38:

debug.com active shouldn't matter.

that means, i must run the debug command - but its not needed to check for these vars to dectect if the debugger is present
and i think its the static bool debugging flag in debug.cpp (that gets set by DEBUG_Enable)

Reply 15 of 18, by Qbix

User metadata
Rank DOSBox Author
Rank
DOSBox Author

Alt-pause starts the debugger. I don't use debug.com very often. It's a convenient way to break at the start of a program.

Water flows down the stream
How to ask questions the smart way!

Reply 16 of 18, by llm

User metadata
Rank Member
Rank
Member
Qbix wrote on 2021-04-29, 12:48:

Alt-pause starts the debugger. I don't use debug.com very often. It's a convenient way to break at the start of a program.

didn't know that

watching the debugging flag does not work because its get set to false as soon as i hit F5 and reanabled when reaching another code bp

		case KEY_F(5):	// Run Program
debugging=false;
DrawCode(); // update code window to show "running" status

my memry read checks run in between so that seems not to be enough for my case

Reply 17 of 18, by llm

User metadata
Rank Member
Rank
Member

my third patchagainst current svn 4450

what works so far:

read detection seems to work now - the breakpoint is getting activate on the next instruction but that is ok for now

problems:
i can't distinguish between dos program and debugger memory reads

debug.cpp/AnalyzeInstruction and others also reading the memory using the mem_read... functions so for example the disassembler view triggers my breakpoint 🙁
and the debugging-flag is false at this point so my check is active

any idea how to get around that?
-i could add a bool from_debugger to all the read-functions
-wrap the reads in the debugger with debugger=true (read) debugger=false (but only works for F5)

what is the exact purpose of the debugging flag? F5 sets it to false, F10 doesn't touch the flag?

all in all - its not as easy as i hoped 😀

Reply 18 of 18, by quadpixels

User metadata
Rank Newbie
Rank
Newbie

Hello,
A reply for a previous question on

is there a reason why you only extended the mem_readX/writeX_inline methods for your memory visualization?
https://github.com/quadpixels/dosbox/commit/f … 4c2e0d4af27d573

(due to my not being able to reply a PM)

I actually found the histogram in the memory visualizer is not very accurate, it was written about 1 year ago, and I have to refresh my memory to correct it.
I think the reason for only extending those mem_readX/writeX_inline is because this is they use physical addresses and are what memory-mapped read/write operations end up reading (but I may be wrong..)