FpDebug and pointer dereferencing of literal addresses lazarus / 12-Debugger ---------------------------------------------------------------------- ccrause · 2020-03-24 19:37 Consider the following example code for debugging (-O): Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program project1; var  b: byte;  pb: pbyte; begin  b := $ba;  if b = 0 then halt(0);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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i pbyte($800100)^ If the declaration of variable pb is removed, FpDebug reports .  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 · 2020-03-24 20:45 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 · 2020-03-25 05:28 Quote from: Martin_fr on March 24, 2020, 09:45:23 pmIf "byte" is avail, fpdebug should recognize  ^byte(1234)^ Testing this on the original example on Linux-64: Code: [Select]@b  $0000000000634050 ^byte($634050)^  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)^  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 · 2020-03-25 11:51 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 · 2020-03-25 12:08 Quote from: ccrause on March 25, 2020, 06:28:40 amAnyway, 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 · 2020-03-25 12:29 Quote from: Martin_fr on March 25, 2020, 12:51:42 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 · 2020-03-25 13:02 This is strange ^byte(0) works ^byte($0) fails ---------------------------------------------------------------------- ccrause · 2020-03-25 13:43 Quote from: Martin_fr on March 25, 2020, 02:02:51 pmThis 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 · 2020-03-25 14:30 This is how the compiler does it too. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i writeln($ff ffffffffffffff);writeln(qword($ffffffffffffffff));writeln(184467440737 09551615);writeln(int64(18446744073709551615)); -1 18446744073709551615 18446744073709551615 -1 The hex defaults to signed. The decimal too signed ---------------------------------------------------------------------- Martin_fr · 2020-03-25 15:53 Respect, you were really close with your findings. I committed a fix. ---------------------------------------------------------------------- ccrause · 2020-03-25 20:33 Quote from: Martin_fr on March 25, 2020, 04:53:35 pmI 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 · 2020-03-25 20:38 Quote from: Martin_fr on March 25, 2020, 12:51:42 pm1) 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. Quote2) I think the debugger frontend needs a dedicated mem viewer (with hex and ascii next to each other) That would be useful indeed. ---------------------------------------------------------------------- ccrause · 2020-03-26 19:35 Quote from: ccrause on March 25, 2020, 09:33:48 pmQuote from: Martin_fr on March 25, 2020, 04:53:35 pmI 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 ). ---------------------------------------------------------------------- Martin_fr · 2020-03-26 20:32 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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 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 · 2020-03-27 15:01 Quote from: Martin_fr on March 26, 2020, 09:32:25 pmHave 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 . 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 . ---------------------------------------------------------------------- Martin_fr · 2020-03-27 15:30 Quote from: ccrause on March 27, 2020, 04:01:16 pmImproving 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 . Yes, that would be ok. Can you bug report those issues, so they want be forgotten? ---------------------------------------------------------------------- ccrause · 2020-03-27 17:36 Quote from: Martin_fr on March 27, 2020, 04:30:29 pmCan you bug report those issues, so they want be forgotten? Issue 0036836