Run-time debugger in Blackbox Component Builder

Usage of the framework, compiler and tools

Re: Run-time debugger in Blackbox Component Builder

Postby Josef Templ » Tue Feb 07, 2017 8:56 am

Syntax highlighting is an editor feature.
It would require a special editor for module source texts
as opposed to the general purpose text editor of BlackBox.
It has been done in ETH A2 Oberon, for example, and in
more traditional IDEs such as NetBeans and Eclipse.

While such an editor may be helpful indeed, I wouldn't consider
it an alternative for a runtime debugger, which could be
quite helpful in understanding existing complex programs
such as the BlackBox framework itself.

Since ominc did not include it in their original BlackBox distribution,
it is probably more a prototype of such a debugger. That's why I was
asking about known problems or limitations.

- Josef
Josef Templ
 
Posts: 226
Joined: Tue Sep 17, 2013 6:50 am

Re: Run-time debugger in Blackbox Component Builder

Postby X512 » Thu Feb 09, 2017 12:43 pm

Josef Templ wrote:Does this debugger work reliably?
Is it in a shape such that it could be included in the
center distribution?

Any known bugs or limitations?
Anything like a docu?

- Josef

I have managed to run this debugger on BlackBox build 64. Debugger is running in another process. It can show loaded modules of debugged process, show global variables of some module of debugged process and heap objects. Traps are redirected to debugger.
Step debugging are using in following way:
1. Open source code of module to be debugged
2. Put caret to line (do not select anything) and set breakpoint by menu Debug -> Breakpoint 1, 2, 3. Menu item became checked
3. When breakpoint is triggered trap will be shown and stopped position will be selected
4. Step over/into can be used: trap and selected position will be updated
Some documentation is included.
Debugger need to be adapted for Kernel UTF-8 changes. Way of transferring of modList pointer to debugger is not working on Windows 8.1. Following code in Kernel.Init are used for this, but EBX became 0 when debugger handles debug string. Probably this register is used inside of OutputDebugStringW. I changed register to EDI to make it working, but it may also stop working in future Windows versions, another way of transferring modList pointer is required.
Code: Select all
S.PUTREG(ML, S.ADR(modList));
WinApi.OutputDebugStringW("BlackBox started");


I attached my modifications here. It should be installed by unpacking to root of BlackBox 1.7 release, replacing files. Working on another versions is not guaranteed.
Attachments
RemDebug.7z
(151.07 KiB) Downloaded 88 times
X512
 
Posts: 37
Joined: Sat Feb 07, 2015 2:51 pm

Re: Run-time debugger in Blackbox Component Builder

Postby X512 » Thu Feb 09, 2017 12:56 pm

Using RemDebug in theory any BlackBox made application with Kernel linked may be debugged.
X512
 
Posts: 37
Joined: Sat Feb 07, 2015 2:51 pm

Re: Run-time debugger in Blackbox Component Builder

Postby Josef Templ » Mon Feb 13, 2017 2:08 pm

X512 wrote:Debugger need to be adapted for Kernel UTF-8 changes. Way of transferring of modList pointer to debugger is not working on Windows 8.1. Following code in Kernel.Init are used for this, but EBX became 0 when debugger handles debug string. Probably this register is used inside of OutputDebugStringW. I changed register to EDI to make it working, but it may also stop working in future Windows versions, another way of transferring modList pointer is required.
Code: Select all
S.PUTREG(ML, S.ADR(modList));
WinApi.OutputDebugStringW("BlackBox started");



Thanks for uploading the revised RemDebug package
and for the excellent analysis.

Under Win10 I cannot reproduce the problem with EBX,
which is surprising because it should be similar to Win8.1.
Anyway, passing modList via a register is highly questionable indeed.
In addition, I thought that EBX is 'callee' saved, so it should not be changed at all
without restoring it.

A more portable approach may be to pass modList as part of
OutputDebugStringW("BlackBox started"), e.g. "BlackBox started [modList=xxxxxxxxx]"
but it requires an int-to-string conversion in Kernel.
I haven't found any other way of passing an address from the target to
the debugger so far.

- Josef
Josef Templ
 
Posts: 226
Joined: Tue Sep 17, 2013 6:50 am

Re: Run-time debugger in Blackbox Component Builder

Postby Josef Templ » Tue Feb 14, 2017 12:54 pm

I just noticed that EBX is not really changed by setting it to modList
because it already had this value when the module body was started.
It is an implicit parameter passed from the main entry point to the module Kernel.
Since it is not used in code generation by the compiler, except for nested procedures
I think, it is a very natural choice for passing information to the debugger.

@X512: are you sure that it does not work under Win 8.1?

- Josef
Josef Templ
 
Posts: 226
Joined: Tue Sep 17, 2013 6:50 am

Re: Run-time debugger in Blackbox Component Builder

Postby DGDanforth » Wed Feb 15, 2017 6:52 am

I simply change the definition of Ctrl-K to be
"Compile And Unload" "K" "DevCompiler.CompileAndUnload" "TextCmds.FocusGuard"
User avatar
DGDanforth
 
Posts: 59
Joined: Tue Sep 17, 2013 1:16 am
Location: Palo Alto, CA, U.S.A.

Re: Run-time debugger in Blackbox Component Builder

Postby X512 » Thu Feb 16, 2017 2:56 pm

Josef Templ wrote:I just noticed that EBX is not really changed by setting it to modList
because it already had this value when the module body was started.
It is an implicit parameter passed from the main entry point to the module Kernel.

In theory EBX register may be allocated by compiler for expression evaluation. Also value passed to debugger is not modList, but pointer to modList. Global variables modList, root and baseStack are used by debugger as single structure and pointer to modList is pointer to that structure.
Josef Templ wrote:@X512: are you sure that it does not work under Win 8.1?

Yes. I made a simple test to inspect what happens with registers during call of OutputDebugString:
Kernel.Init
Code: Select all
S.PUTREG(0, 12345678H);
S.PUTREG(1, 12345678H);
S.PUTREG(2, 12345678H);
S.PUTREG(3, 12345678H);
S.PUTREG(6, 12345678H);
S.PUTREG(7, 12345678H);
WinApi.OutputDebugStringW("BlackBox started");

DevRemDebug.HandleEvent
Code: Select all
IF string = "BlackBox started" THEN
   context.ContextFlags := WinApi.CONTEXT_INTEGER;
   res := WinApi.GetThreadContext(threadHandle, context); ASSERT(res # 0);
   Log.String("EAX = "); Log.IntForm(context.Eax, 16, 9, "0", FALSE); Log.String("H"); Log.Ln;
   Log.String("ECX = "); Log.IntForm(context.Ecx, 16, 9, "0", FALSE); Log.String("H"); Log.Ln;
   Log.String("EDX = "); Log.IntForm(context.Edx, 16, 9, "0", FALSE); Log.String("H"); Log.Ln;
   Log.String("EBX = "); Log.IntForm(context.Ebx, 16, 9, "0", FALSE); Log.String("H"); Log.Ln;
   Log.String("ESI = "); Log.IntForm(context.Esi, 16, 9, "0", FALSE); Log.String("H"); Log.Ln;
   Log.String("EDI = "); Log.IntForm(context.Edi, 16, 9, "0", FALSE); Log.String("H"); Log.Ln;
   kernelAdr := 0;
END;

Output:
Code: Select all
EAX = 00023FC60H
ECX = 000000002H
EDX = 000000000H
EBX = 000000000H
ESI = 0005C3259H
EDI = 012345678H

Only EDI is unchanged. There is nothing strange in this behavior, because preserved registers may be changed inside procedure. Only guaranteed thing is preserved registers must be changed to their original values at exit of procedure. Calling of debugger callback is technically done inside OutputDebugString procedure.
Tested system is Windows 8.1, 32 bit.
X512
 
Posts: 37
Joined: Sat Feb 07, 2015 2:51 pm

Re: Run-time debugger in Blackbox Component Builder

Postby Josef Templ » Fri Feb 17, 2017 10:31 am

Since EDI is not guaranteed to be unchanged either
the only portable approach would be to
pass kernelAdr as part of the debug string, right?

WinApi.OutputDebugStringW("BlackBox started [kernelAdr=1234567]";

No big problem, but requires some string handling.

- Josef
Josef Templ
 
Posts: 226
Joined: Tue Sep 17, 2013 6:50 am

Re: Run-time debugger in Blackbox Component Builder

Postby Ivan Denisov » Mon Feb 05, 2018 5:03 pm

Is there version of DevRemDebug which works with Windows 10 correctly?
User avatar
Ivan Denisov
 
Posts: 265
Joined: Tue Sep 17, 2013 12:21 am
Location: Krasnoyarsk, Russia

Re: Run-time debugger in Blackbox Component Builder

Postby Ivan Denisov » Mon Feb 05, 2018 7:37 pm

I checked suggested method and it works.

I modified the kernel.
Code: Select all
      S.PUTREG(ML, S.ADR(modList));
      IntToString(S.ADR(modList), trans);
      str := "BlackBox started [-----------------]";
      FOR i:= 0 TO LEN(trans$)-1 DO
         str[18 + i] := trans[i]
      END;
      WinApi.OutputDebugStringW(str);


And in DevRemDebug

Code: Select all
         | WinApi.OUTPUT_DEBUG_STRING_EVENT:
            IF (event.u.DebugString.fUnicode = 0) & (event.dwProcessId = procId) THEN
               GetName(SYSTEM.VAL(INTEGER, event.u.DebugString.lpDebugStringData), string);
               Log.String(string); Log.Ln; (* DIA *)
               string[16] := 0X;
               IF string$ = "BlackBox started" THEN
                  Log.String(string); Log.Ln; (* DIA *)
                  context.ContextFlags := WinApi.CONTEXT_INTEGER;
                  res := WinApi.GetThreadContext(threadHandle, context); ASSERT(res # 0);
                  IF string[17] = "[" THEN
                     i := 18;
                     WHILE (string[i] # "-") & (string[i] # "]") DO
                        kernelAddressString[i - 18] := string[i];
                        INC(i);
                     END;
                     kernelAddressString[i - 18] := 0X;
                     Log.String(kernelAddressString); Log.Ln; (* DIA *)
                     Strings.StringToInt(kernelAddressString, kernelAdr, i);
                  ELSE
                     kernelAdr := context.(*Ebx*)Edi;
                  END;
                  Log.Int(kernelAdr); Log.Ln; (* DIA *)
               END;
            END
User avatar
Ivan Denisov
 
Posts: 265
Joined: Tue Sep 17, 2013 12:21 am
Location: Krasnoyarsk, Russia

PreviousNext

Return to Common questions

Who is online

Users browsing this forum: No registered users and 0 guests

cron