Sign in Join
Wiki copytemporary

FpDebug: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11# About
22
33FpDebug is a [[Debugger|debugger]] written in [[Pascal]] for Pascal.
44
55In detail:
66
77- FpDebug is written in Pascal
88- FpDebug uses the [[DWARF]] debug info format
99 - The current implementation is a subset of DWARF with support for DWARF version 2 and 3. However the "subset" is merely the state of implementation. The aim is to extend this to implement as much of the standard as possible.
1010 - The current implementation covers the subset that is used by FPC
1111 - FpDebug has special implementations to deal with FPC specific DWARF usage (bugs, missing info, implementation details)
1212- FpDebug "is for" (i.e. has a prioritized focus for) debugging Pascal
1313 - It accepts expressions (Watches) in Pascal (e.g. using @foo and foo^.x instead of *foo and foo-\>x)
1414 - Yet, it is open for having other interpreters added.
1515
1616## Different meanings of "FpDebug"
1717
1818FpDebug can refer to
1919
2020### The package "FpDebug"
2121
2222This is the engine of the debugger. It is not [[IDE]] specific. The package is used by several IDE backends:
2323
2424- LLDB Debugger (with fpdebug): This debugger uses LLDB as a backend. In order to display Pascal-style results, it uses the "fpdebug" engine to show locals/watches.
2525- [[GDB|GNU Debugger]] (with fpdebug): Using GDB for stepping/breakpoints/... and FpDebug for watches.
2626- FpDebug internal Dwarf debugger: Pure FpDebug. Stepping, Running, Breakpoint,Watches, Locals, Stack...
2727
2828### FpDebug as reference to the IDE backend [[LazDebuggerFp]]
2929
3030The actual name of the IDE backend is [[LazDebuggerFp]]. This is the name of the Package that needs to be installed to use the debugger. However as seen above, in none technical context (such as captions in the IDE) this is referred to as "FpDebug ..."
3131
3232### Other FpDebug projects
3333
3434The name is used for another project with the same goal.
3535
3636- <https://github.com/graemeg/fpdebug>
3737- <http://sourceforge.net/projects/duby/>
3838
3939## Installation in the IDE
4040
4141The FpDebug debugger is pre-installed. If your IDE is still configured to use another debugger backend, then go to:\
4242\- MainMenu -\> Tools -\> Options -\> Debugger -\> Debugger backend\
4343\- Select the debugger "FPDebug internal Dwarf-debugger"
4444
4545# Related topics
4646
4747- [[FpDebug-Watches-FunctionEval|Function evaluation in watches (Calling functions in the debugged app)]] (This is a feature of [[LazDebuggerFp]])
4848- [[FpDebug-Watches-Intrinsic-Functions|Intrinsic (build in) helper functions]]
4949
5050# General Debugging Issues
5151
5252These issues can not be fixed by the debugger alone. They need changes in FPC too. Some may also be affected by lack of support in DWARF.
5353
5454These issues apply to all debugger backends.
5555
5656## Properties
5757
5858Properties are one of the most wanted features for (any of) the debugger(s). Here is why they can not yet be inspected, and why it will still be a good while before this happens.
5959
60-Before going into details: For "<u>Properties without getter function</u>" (i.e., "<u>with direct field access</u>") FPC (as means to a workaround of the issue) currently adds an entry for a variable with the property name. This means such properties can be displayed. They can also be written by the debugger (if the debugger supports changing data), and if they are written this is done bypassing any Setter procedure, since the debugger has no clue there even is a setter.
60+Before going into details: For "Properties without getter function" (i.e., "with direct field access") FPC (as means to a workaround of the issue) currently adds an entry for a variable with the property name. This means such properties can be displayed. They can also be written by the debugger (if the debugger supports changing data), and if they are written this is done bypassing any Setter procedure, since the debugger has no clue there even is a setter.
6161
6262There are several missing pieces for allowing the debugger to show (and maybe modify) properties.
6363
6464- The debugger needs support to call functions (as of end 2021: partly supported)
6565- FPC needs a way to actually add info about the "properties" to the debug info. (as of end 2021: work has begun...)
6666
6767As for calling function. This may just be missing implementation in the debugger. This has not yet been investigated in any more depth. It may or may not require additional info in the DWARF generated by FPC
6868
6969As for adding "properties" to the debug info: DWARF (at least version 2 and 3 / not checked 4 or 5) does not actually have any way to encode this info. Consequently FPC currently does not add it either.
7070
7171In case that DWARF does not add this in time, DWARF allows for vendor specific data (afaik). Up until now, no debugger would have known about any "private fpc data", so there was no point. In future such data could be agreed between FPC and FpDebug. But that is still a good way off. FpDebug does not even do function calling yet.
7272
7373## Strings (vs PChar and Array of Char)
7474
7575Originally DWARF had no concept to encode strings. This has been added in DWARF 4 (need verification), but not yet been investigated for usability with FPC. Also FPC currently only implements DWARF 2 and 3 (with first steps towards version 4).
7676
7777This leaves only 2 ways to encode a string in DWARF.
7878
7979- As pointer to char
8080- As array of char
8181
8282Which one is used depends on the version of FPC, and if DWARF 2 or 3 is used.
8383
8484If it is "pointer to char", then this makes in indistinguishable from actual PChar. This is the reason all debuggers in Lazarus sometimes for a watch like "SomeString\[4\]" show the result "PChar: 'a'; String: 'b'". Because PChar is zero-based and string one-based, the index "4" can mean the 4th or the 5th char.
8585
8686Recent FPC use the "array of char" when they generate DWARF 3. In that they have (currently) implementation detail differences between how they encode strings and real array of char. (Such as the omission of an optional/redundant bit of information. In this case: DW_AT_byte_stride). Those details are meaningless from the point of any other debugger, but FpDebug can detect them as it knows about those implementation details. Of course this is extremely fragile, the next version of FPC can always change this.
8787
8888In a similar way FPC handles ShortStrings internally as record, and encodes them as this. Again distinguishing this is down to implementation details.
8989
9090## Modifying managed types
9191
9292This applies to any debugger that can set new values to a watch (modify variable in the debugged exe).
9393
9494Managed types can not be correctly modified.
9595
9696To modify managed types the debugger would need to know about:
9797
9898- the ref count
9999- copy on write behaviour
100100- how to allocate/free memory / or better how to call the inc/dec_ref methods for each types, so they will do the work correctly
101101
102102None of that info is available.
103103
104104If you assign a new value to a string or dynamic array, then the ref count of the old and new value must be adjusted. If needed memory must be allocated or freed. If that is not done correctly it will at least cause a memory leak. But it can also cause crashes or random other buggy behaviour when the debugged exe continues.
105105
106106In an array it is possible to change a single element. "SomeArray\[5\] := 7;". If the array is referenced from several variables, this will affect all of them. The same happens if you execute this statement in your app.
107107
108108String (AnsiString) have copy-on-write. If you do "SomeString\[4\] := 'a'" then the variable from which you accessed the string gets a new copy, and other variables (that share the memory) should not be affected. The debugger does not have that info. Nor does it have access to the refcount and memory alloc/de-alloc (or internal string procs).
109109
110110## Scope / Variable search order
111111
112112There are various issues where FPC does not put enough information into the DWARF info so that a debugger could compute the correct scope for all variables. In same cases this may be due to DWARF not offering this, or not offering it at the time where it was implemented or last updated in FPC. Some of it may be fixable, if FPC would change the way it encodes the info.
113113
114114### Nested Procedures
115115
116116``` pascal
117117var SomeVar: Integer; // global var
118118
119119procedure Outer(NumText: string);
120120var
121121 SomeVar: Integer; // local var, declared above "Nested"
122122
123123 procedure Nested;
124124 var
125125 I: Integer;
126126 begin
127127 WriteLn(OuterVarInScope);
128128 end;
129129
130130//var
131131// SomeVar: Integer; // local var, declared below "Nested"
132132begin
133133 Nested;
134134end;
135135```
136136
137137The local var "SomeVar" hides the global var of the same name, if you are in the procedure "Outer". The local var is also visible (and hides the global) if you are in "Nested".
138138
139139But if you comment the local var "declared above Nested" and uncomment the local var "declared below Nested", then the local var is no longer in the scope of "Nested". "Nested" would now see the global var. ("Outer" still sees the local).
140140
141141The DWARF info currently only tells the debugger that "SomeVar" is declared as local var in "Outer". And that "Nested" is inside "Outer". But the DWARF info does not include if "SomeVar" is declared above or below "Nested". So the debugger can not tell the difference. The debugger will in both cases show the local "SomeVar" when paused in "Nested"
142142
143143### Global vars from other units
144144
145145The DWARF info contains a section for each unit. All Symbols of a unit are listed in the correct section. However there is no info, which unit is in the "uses" clause of which other unit. And evidently even less, in which order they are used.
146146
147147If there are several global variables of the same name, one in each of several units, then FPC uses the order of the uses clause (right to left) to find the variable that will be seen from code in the current unit.
148148
149149If there is code in a unit FooBar that access a variable named NotInFooBar (that is not declared in unit FooBar), then this variable must be from one of the other units. If there are several variables named NotInFooBar in different units, then the debugger has no information which one FPC did use. The debugger is currently showing the first it finds. (Which is kind of random)
150150
151151# FPC Issues
152152
153153This affects all debuggers
154154
155155- resourcestring
156156
157157Currently not implemented <https://bugs.freepascal.org/view.php?id=35571>
158158
159159- const Foo = unicodestring('abc')
160160
161161No debug info implemented <https://bugs.freepascal.org/view.php?id=35569>
162162
163163- type Foo = object (Dwarf 3) - Fixed in 3.3.3
164164
165165Incorrectly encoded as class-instance <https://bugs.freepascal.org/view.php?id=36017>\
166166The debugger can not display the data.
167167
168168- Dynamic array when cross compiling
169169
170170<https://bugs.freepascal.org/view.php?id=35567>\
171171The debugger may calculate the length wrong.
172172
173173- Wrong stride for bitpacked array - Fixed in 3.3.3
174174
175175<https://bugs.freepascal.org/view.php?id=36144>\
176176FpDebug currently has a workaround
177177
178178# Status
179179
180180FpDebug supports Linux, Windows and MacOs.\
181181(LazDebuggerFp supports Linux and Windows only. Limited support for MacOS is available via LazDebuggerFpLldb)
182182
183183Any functionality regarding execution control (stepping/pausing...) is only tested for Linux and Windows. Support for this on Mac is incomplete/fragile.
184184
185185> **Note:** For Windows/Linux please see **[[Debugger Status]]**
186186
187187For Mac support is currently considered "Alpha" Data evaluation can be used on Mac via the "LLDB+FpDebug" backend
188188
189189The information is indicative and subject to updates / subject to further testing
190190
191191## Notes
192192
193193### Stepping out
194194
195195"Stepping out" relies on finding the caller address. The location of which depends on whether a function has a "stackframe" (use the BasePointer register) and has the frame already/still set-up. Detection of this is limited to a few standard situations. (Especially in none FPC code, or optimized code this will not be detectable).
196196
197197Within un-optimized FPC code this feature works.
198198
199199### Hardware Watchpoints (aka Data Breakpoints)
200200
201201Partly implemented for most data types (subset of the types supported by the hardware), including Conditions and other properties.
202202
203203All watchpoints will have global scope. Watching a local var will alert you the next time the variable's memory is overwritten (e.g. if another variable takes the memory).
204204
205205"Write only" watchpoints act as "read/write"
206206
207207Watchpoints also trigger if they are overwritten with the value they already have.
208208
209209Watchpoints do not show the before/after dialog.
210210
211211Watchpoints that are not aligned to an address that is a multiply of their size, may be triggered by neighbouring values. E.g., a Word starting at an odd address, can be triggered by the byte before or after it. A 64 bit pointer must be aligned to an 8 byte boundary, or can be triggered by neighbours.
212212
213213### Thread and Stack
214214
215215See "Stepping out". Relies on the same frame detection.
216216
217217### Watches / Locals / Inspect
218218
219219Implemented
220220
221221- Any missing types need to be discovered (i.e. not aware of any type that does not display, if not listed under "fpc issues"
222222- currency types may not display the decimal dot (they will show value * 1000)
223223- Expressions: The debugger accepts expressions that it will calculate. It expects Pascal syntax.
224224 - Expressions are calculated without range checks
225225- [[FpDebug-Watches-FunctionEval|function evaluation]]
226226- But not yet: Properties
227227
228228### Modify variables (not implemented)
229229
230230Done for simple types
231231
232232### Console Output
233233
234234On Windows console is opened by OS. On Linux the output goes to the debugger window "Console output"
235235
236236### Cross bit-ness Debugging (32/64 bit)
237237
238238FpDebug has no cross debugging between different platforms.
239239
240240However, if your IDE has a different bitness that your project FpDebug may be able to debug it.
241241
242242#### Windows
243243
244244A 64 bit IDE
245245can debug both 64bit and 32bit applications
246246
247247A 32 bit IDE
248248can only debug 32bit applications
249249
250250#### Linux
251251
252252Cross debugging has not yet been tested, but may be possible.
253253
254254# Not implemented yet
255255
256256- Changing Location of execution (while paused) / Resume execution from different line
257257- Properties
258258- ...
259259
260260---
261261*From the Free Pascal wiki, page "FpDebug", as it stood on 2023-03-11 after a change by Martin, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history