Re: [Lazarus] Making fpdebug more cross-platform friendly

2021-12-16 Thread Sven Barth via lazarus
Martin Frb via lazarus  schrieb am Do., 16.
Dez. 2021, 23:27:

> Only, question is, if we need the ABI?
> - Do win64 and linux64 share the same ABI? (or win32 <> linux32)?
>Afaik SEH is win specific (and probably would be best of in the ABI?).
>But there could still be a base class that is shared between Win/Linux.
>

Yes, SEH is Windows specific. The ABI is mostly CPU specific however. E.g.
all the i386 calling conventions can be used on all OSes. On the x86_64
systems one usually uses either the SysV or the Win64 ABI, but both FPC and
Clang allow the use of the other calling convention as well. On the other
hand the register usage on m68k for example differs between Amiga and
non-Amiga (the stack pointer is a different register and the stack
alignment is 2 instead of 4 Byte) and this can't be changed.
So in my opinion the design should allow for as much code sharing/reuse as
possible, e.g. with a general x86_64 ABI with OS specifics (e.g. SEH) on
top.

Regards,
Sven

>
-- 
___
lazarus mailing list
lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] Making fpdebug more cross-platform friendly

2021-12-16 Thread Martin Frb via lazarus
Ok, for now limiting this to a smaller audience, to get some 
brainstorming done.

=> Original mail at the bottom.

Some initial thoughts.

*** First, I would suggest, that all calls go to T[Foo]DbgProccess ***
T[Foo]DbgProccess can then forward them.
Outside classes should not have knowledge, nor access to the delegates.
(Better start restricted, so we have more flexibility for future changes)

--

I can currently see the following areas, that could be separated as needed.

API:  Calls to the OS => start/stop/mem-access/register/access
ABI:  Conventions about register usage, and stack layout
    (registers are known by either name or dwarf-index)
CPU: Identifying specific asm instructions  (Breakpoint / ret / call )

IHMO:
- API remains hardcoded in T[Foo]DbgProccess.
- The others are private delegate classes.


- Your idea about WOW64_CONTEXT / _ARM64_NT_CONTEXT is imho API.
   It can not be CPU or ABI. If it were, we would need to subclass them 
for each API.
- Identifying breakpoint is CPU (not necessarily the current asm class / 
could be a new class)
- unwinding stack => could be either. (there may be an API of the OS, 
otherwise ABI, maybe with help of CPU)


Only, question is, if we need the ABI?
- Do win64 and linux64 share the same ABI? (or win32 <> linux32)?
  Afaik SEH is win specific (and probably would be best of in the ABI?).
  But there could still be a base class that is shared between Win/Linux.

Similar about ABI vs CPU.
Only here we definitely have a shared base class for inter 32/64bit 
(currently it's only one class / no subclasses for the bitness).

So IMHO there is a point in splitting them.

---
Mind that, FPC specific units could provide specialized sub-classes of 
any of the delegate classes.

E.g. dealing with $fin$MyProcedure subroutines. (Win-SEH)
For some purposes, finally blocks need to look like they are part of the 
main-procedure, not sub-routines of their own.


---

With the above some of the issues can be solved by combining different 
subclasses of each.


And then we would end up with combinations like this:
(I am not sure, if the ABI for Win and Linux are actually different..., 
but there would be win-seh)


TDbgWinProcess with:    x64-win ABI /  x64 CPU
TDbgWinProcess with:    i386-win-ABI    /  x32 CPU
TDbgWinProcess with:    arm-ABI    /  arm CPU
TDbgLinuxProcess with:    x64-linux-ABI    /  x64 CPU
TDbgLinuxProcess with:    i386-linux-ABI    /  x32 CPU
...

There is potential for some re-usable code there.

Since all access would be through T[Foo]DbgProccess code can be moved 
gradually.


---

However, setting Breakpoints for example may be a bit more complex.
For example:
- if there is a limit to the amount, or only certain locations can be set.
- If breakpoints are not set to memory, but like watchpoints on intel.

In those cases, it needs to be decided how much power to give to the CPU 
class.


Should the CPU class be able to make calls to read/write mem and/or 
change registers?
(That is the point, where it would be a separate class from the asm 
class, which at most reads mem)


Even, if the CPU class can handle it all by itself, it may still end up 
needing support in the main class (T[Foo]DbgProccess).
- There can be errors due to restrictions (user watch points have been 
set to the register needed for the breakpoint).
- There may be different requirement on the relative timing of those 
actions and other actions outside the CPU class.
  Those timings are not known by the CPU class. So we end up with a 
tighter coupling than desired.


--

Comments?
Ideas?





On 16/12/2021 12:10, Christo Crause via lazarus wrote:
Currently there are a few instances where x86 specific 
assumptions/code are used [1] in what I consider as the target 
agnostic level of fpdebug.  My proposal is to move these instances to 
a hardware target specific unit so that these target specific handling 
is clearly separated.  One location for the target specific code is 
perhaps the fpdbgdisas* units, since it already provides a number of 
hardware specific concepts such as identifying call & return 
instructions and some stack frame analysis.  Adding for example 
IsSoftwareBreakInstruction seems like a logical addition.


These changes are hindering some functionality on AVR and Xtensa 
targets, e.g. some instructions are incorrectly disassembled because 
they start with $CC, which is incorrectly  interpreted as a software 
break.  Also the StepOut functionality currently assumes the x86 ABI 
to locate the return address, which obviously fails for other targets. 
While these methods could in principle be hidden by new target 
specific overrides, it is not aligned with proper OOP principles.  I 
will start with some concepts to address these soon.


Similarly, but possibly a bit more tricky, is to separate the OS code 
from the OS view of the hardware.  This would imply for example that 
the register handling in fpdbglinuxclasses needs to be 

Re: [Lazarus] Making fpdebug more cross-platform friendly

2021-12-16 Thread Martin Frb via lazarus

On 16/12/2021 12:10, Christo Crause via lazarus wrote:
  One location for the target specific code is perhaps the fpdbgdisas* 
units, since it already provides a number of hardware specific 
concepts such as identifying call & return instructions and some stack 
frame analysis.  Adding for example IsSoftwareBreakInstruction seems 
like a logical addition.

The current Frame-analysis is not really in good shape.

It is more likely that the central entry point for hardware and/or OS 
specifics will be the subclassed TDbgProcess (or potentially in some 
cases the subclassed Thread, but I can't think of a case for that).
The process class can then decide to use the asm class, or have other 
means...


Dividing this between hardware and OS will be a story of its own.



These changes are hindering some functionality on AVR and Xtensa 
targets, e.g. some instructions are incorrectly disassembled because 
they start with $CC, which is incorrectly  interpreted as a software 
break.

So that needs to be controlled by the process class then.


Also the StepOut functionality currently assumes the x86 ABI to locate 
the return address, which obviously fails for other targets.  While 
these methods could in principle be hidden by new target specific 
overrides, it is not aligned with proper OOP principles.  I will start 
with some concepts to address these soon.


Probably there will be some need for delegate classes

Btw, this is a big one, and I have some todo on this too.
Currently the entire handling of win SEH is in LazDebuggerFp => that 
should move. But it needs exactly the above ability of having target 
specific functions.
Even one step further: => those are not even default for win, because 
they assume fpc generated code [1]. So they need to be added, similar 
like the fpc additions for dwarf (separate unit, with detection of 
compiler)


So it's likely they will undergo a big rework.

[1] They should be fixed to be generic.



Similarly, but possibly a bit more tricky, is to separate the OS code 
from the OS view of the hardware.  This would imply for example that 
the register handling in fpdbglinuxclasses needs to be separated from 
the rest of the code so that one could re-use the Linux layer, but 
swap out the hardware specific layer x86_Linux.  Similarly for 
Windows, the WOW64_CONTEXT could be part of an x86_Windows unit, so 
that it is possible to also define and use _ARM64_NT_CONTEXT for 
Windows on ARM64.




[1] Examples of x86 specific code not in a x86 specific unit
fpdbgclasses.pas: checking for int3 and its x86 encoding in 
TDbgProcess, TDbgThread and TBreakLocationMap


The above will probably best go into a delegation class. But the extend 
needs to be evaluated.
The first 2 actually should allow to override (so that is not the 
desired solution)...


fpdbgcontroller.pas: TDbgControllerCallRoutineCmd uses x86 call 
specific encoding in InsertCallInstructionCode and 
RestoreInstructionPointer, StoreRoutineResult using x86 register 
specific assumptions,
TDbgControllerStepOutCmd.SetReturnAdressBreakpoint assumes return 
address is stored according to x86 stack frame layout.

As I said, there will have to be a big rework.
Until then, quickfix it by overriding it in the backend (like 
LazDebuggerFp does).



More later

--
___
lazarus mailing list
lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


[Lazarus] Making fpdebug more cross-platform friendly

2021-12-16 Thread Christo Crause via lazarus
Currently there are a few instances where x86 specific assumptions/code are
used [1] in what I consider as the target agnostic level of fpdebug.  My
proposal is to move these instances to a hardware target specific unit so
that these target specific handling is clearly separated.  One location for
the target specific code is perhaps the fpdbgdisas* units, since it already
provides a number of hardware specific concepts such as identifying call &
return instructions and some stack frame analysis.  Adding for example
IsSoftwareBreakInstruction seems like a logical addition.

These changes are hindering some functionality on AVR and Xtensa targets,
e.g. some instructions are incorrectly disassembled because they start with
$CC, which is incorrectly  interpreted as a software break.  Also the
StepOut functionality currently assumes the x86 ABI to locate the return
address, which obviously fails for other targets.  While these methods
could in principle be hidden by new target specific overrides, it is not
aligned with proper OOP principles.  I will start with some concepts to
address these soon.

Similarly, but possibly a bit more tricky, is to separate the OS code from
the OS view of the hardware.  This would imply for example that the
register handling in fpdbglinuxclasses needs to be separated from the rest
of the code so that one could re-use the Linux layer, but swap out the
hardware specific layer x86_Linux.  Similarly for Windows, the
WOW64_CONTEXT could be part of an x86_Windows unit, so that it is possible
to also define and use _ARM64_NT_CONTEXT for Windows on ARM64.

Any thoughts, critique or suggestions are welcome.

Best wishes,
Christo

[1] Examples of x86 specific code not in a x86 specific unit
fpdbgclasses.pas: checking for int3 and its x86 encoding in TDbgProcess,
TDbgThread and TBreakLocationMap
fpdbgcontroller.pas: TDbgControllerCallRoutineCmd uses x86 call specific
encoding in InsertCallInstructionCode and RestoreInstructionPointer,
StoreRoutineResult using x86 register specific assumptions,
TDbgControllerStepOutCmd.SetReturnAdressBreakpoint assumes return address
is stored according to x86 stack frame layout.
-- 
___
lazarus mailing list
lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus