Bookstore

Recent

Author Topic: FpDebug and pointer dereferencing of literal addresses  (Read 932 times)

ccrause

  • Full Member
  • ***
  • Posts: 241
FpDebug and pointer dereferencing of literal addresses
« on: March 24, 2020, 08:37:04 pm »
Consider the following example code for debugging (-O):
Code: Pascal  [Select]
  1. program project1;
  2.  
  3. var
  4.   b: byte;
  5.   pb: pbyte;
  6.  
  7. begin
  8.   b := $ba;
  9.   if b = 0 then halt(0);
  10. end.

With a break point on line 9, it is possible to evaluate the following expression to view the data stored at a specific memory address (assuming of course the address is valid in the context):
Code: Text  [Select]
  1. pbyte($800100)^

If the declaration of variable pb is removed, FpDebug reports <Error: Identifier not found: "pbyte">.  I assume this is due to the missing type information for pbyte in the binary.  Would it be possible to add recognition of build-in Pascal pointer types to the expression parser of FpDebug so that general type casting of pointer types can work even if the types are not defined in the debug information?

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 6075
    • wiki
Re: FpDebug and pointer dereferencing of literal addresses
« Reply #1 on: March 24, 2020, 09:45:23 pm »
Yes.... But...
They probably should be optional. (at least pbyte, is afaik in the rtl, not in the compiler)

A user could define them different. Maybe just local. In that case using PByte outside the users scope, might get unexpected results.

If "byte" is avail, fpdebug should recognize  ^byte(1234)^

The real build in types byte, word, smallint, longint .... should probably have build in definitions.

ccrause

  • Full Member
  • ***
  • Posts: 241
Re: FpDebug and pointer dereferencing of literal addresses
« Reply #2 on: March 25, 2020, 06:28:40 am »
If "byte" is avail, fpdebug should recognize  ^byte(1234)^

Testing this on the original example on Linux-64:
Code: [Select]
@b  $0000000000634050
^byte($634050)^  <Error: Internal eval error>

I now realized I tested this on your mfr-fpdebug-disassembler-refactor branch. Using Lazarus trunk (r62804) I see different behaviour, not sure why yet:
Code: [Select]
@b  00
pbyte($634050)^  <Error: History has not yet reached $634050.>

Anyway, another suggestion for an easy solution would be to interpret dereferencing of a literal number as if an implicit pointer cast has been made:
i.e.: 1234^ is interpreted as pointer(1234)^

Any thoughts on this option?

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 6075
    • wiki
Re: FpDebug and pointer dereferencing of literal addresses
« Reply #3 on: March 25, 2020, 12:51:42 pm »
1) there is an option for watches "memory dump". Not sure how well that works...  IIRC it also needs the deref.

2) I think the debugger frontend needs a dedicated mem viewer (with hex and ascii next to each other)



Not sure where the first error (internal) comes from. Need to do some testing.

"History has not yet reached" => odd, I do not recall adding such an error, nor can I find that text in the source.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 6075
    • wiki
Re: FpDebug and pointer dereferencing of literal addresses
« Reply #4 on: March 25, 2020, 01:08:26 pm »
Anyway, another suggestion for an easy solution would be to interpret dereferencing of a literal number as if an implicit pointer cast has been made:
i.e.: 1234^ is interpreted as pointer(1234)^

That would be ok (but...), but need really strict checking. It must only be allowed if the number is a literal.

That means (1234)^ would likely fail, as it is an expression, not a literal. Otherwise you end up allowing deref, of none pointers for variables, and that should report errors (at least by default).

---
But...

Maybe it be better, if the "memory dump" option recognizes 1234, and uses it as an address.

Or introduce an operator for the debugger.  1234:^

ccrause

  • Full Member
  • ***
  • Posts: 241
Re: FpDebug and pointer dereferencing of literal addresses
« Reply #5 on: March 25, 2020, 01:29:59 pm »
"History has not yet reached" => odd, I do not recall adding such an error, nor can I find that text in the source.

My apologies, this is a gdb error so it has nothing to do with FpDebug itself.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 6075
    • wiki
Re: FpDebug and pointer dereferencing of literal addresses
« Reply #6 on: March 25, 2020, 02:02:51 pm »
This is strange

^byte(0) works
^byte($0) fails

ccrause

  • Full Member
  • ***
  • Posts: 241
Re: FpDebug and pointer dereferencing of literal addresses
« Reply #7 on: March 25, 2020, 02:43:20 pm »
This is strange

^byte(0) works
^byte($0) fails
This (counter intuitive) behaviour is defined in TFpPascalExpressionPartConstantNumber.DoGetResultValue, where decimal based numbers are assumed to be unsigned and hex, octal and binary based numbers are assumed to be signed.  In TFpPascalExpressionPartOperatorDeRef.DoGetResultValue a check is done for svfDataAddress which will only be valid if the value field type is svfCardinal.  I would suggest that the signed/unsigned decision should be the opposite of the current logic.

Thank you for suggesting this dereference technique, it is usable once one understands the quirks.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 6075
    • wiki
Re: FpDebug and pointer dereferencing of literal addresses
« Reply #8 on: March 25, 2020, 03:30:42 pm »
This is how the compiler does it too.

Code: Pascal  [Select]
  1. writeln($ffffffffffffffff);
  2. writeln(qword($ffffffffffffffff));
  3. writeln(18446744073709551615);
  4. writeln(int64(18446744073709551615));

-1
18446744073709551615
18446744073709551615
-1

The hex defaults to signed. The decimal too signed



Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 6075
    • wiki
Re: FpDebug and pointer dereferencing of literal addresses
« Reply #9 on: March 25, 2020, 04:53:35 pm »
Respect, you were really close with your findings.

I committed a fix.

ccrause

  • Full Member
  • ***
  • Posts: 241
Re: FpDebug and pointer dereferencing of literal addresses
« Reply #10 on: March 25, 2020, 09:33:48 pm »
I committed a fix.
Thank you Martin. Your fix now allow any numerical literals memory address in the expression
Code: [Select]
^type(addr)^ where type is any type declared in the debug info (except pointer itself) and addr is any literal number in decimal, hexadecimal, octal or binary.

ccrause

  • Full Member
  • ***
  • Posts: 241
Re: FpDebug and pointer dereferencing of literal addresses
« Reply #11 on: March 25, 2020, 09:38:53 pm »
1) there is an option for watches "memory dump". Not sure how well that works...  IIRC it also needs the deref.
Yes, that works. Seems that pointer types needs the dereference to work.

Quote
2) I think the debugger frontend needs a dedicated mem viewer (with hex and ascii next to each other)
That would be useful indeed.

ccrause

  • Full Member
  • ***
  • Posts: 241
Re: FpDebug and pointer dereferencing of literal addresses
« Reply #12 on: March 26, 2020, 08:35:45 pm »
I committed a fix.
Thank you Martin. Your fix now allow any numerical literals memory address in the expression
Code: [Select]
^type(addr)^ where type is any type declared in the debug info (except pointer itself) and addr is any literal number in decimal, hexadecimal, octal or binary.

Actually pointer does work if one selects Memory Dump in the watch properties. I guess the fact that a pointer is untyped is the reason the other display types don't work (display <invalid>).

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 6075
    • wiki
Re: FpDebug and pointer dereferencing of literal addresses
« Reply #13 on: March 26, 2020, 09:32:25 pm »
Have not tested, what does not work / Not sure what you mean.

The intend is that you get a dump of the variable.

Ie.
Code: Pascal  [Select]
  1. var a: integer; b: TPoint; pa: PInteger

A memory dump of "a" is 4 bytes.
A memory dump of "pa^" is 4 bytes.
A memory dump of "b" is 8 bytes. (2 ints: x,y)



ccrause

  • Full Member
  • ***
  • Posts: 241
Re: FpDebug and pointer dereferencing of literal addresses
« Reply #14 on: March 27, 2020, 04:01:16 pm »
Have not tested, what does not work / Not sure what you mean.

When I first tested accessing memory via a pointer cast (with a pointer declaration to put the definition in the debug info):
Code: [Select]
pointer($1234)^Lazarus returned <invalid>. This was with the default style selected in Watch Properties. When the Memory Dump option is selected, it does show a memory dump.

Improving the default behaviour in TFpPascalPrettyPrinter.InternalPrintValue for AValue.Kind = skAddress could be to either do a memory dump, or to call DoUnknown.  Defaulting to memory dump is what I would expect, but at least calling DoUnknown would return a valid error (Unknown type...) rather than the current cryptic <invalid>.