1 unit FpDbgDwarfFreePascal;
2
3 {$mode objfpc}{$H+}
4 {$TYPEDADDRESS on}
5
6 interface
7
8 uses
9 Classes, SysUtils, Types, math,
10 FpDbgDwarfDataClasses, FpDbgDwarf, FpDbgInfo,
11 FpDbgUtil, FpDbgDwarfConst, FpErrorMessages, FpdMemoryTools,
12 DbgIntfBaseTypes,
13 {$ifdef FORCE_LAZLOGGER_DUMMY} LazLoggerDummy {$else} LazLoggerBase {$endif}, LazStringUtils;
14
15 type
16
17 {%Region * ***** SymbolClassMap ***** *}
18
19 { TFpDwarfFreePascalSymbolClassMap }
20
21 TFpDwarfFreePascalSymbolClassMap = class(TFpDwarfDefaultSymbolClassMap)
22 strict private
23 class var ExistingClassMap: TFpSymbolDwarfClassMap;
24 private
25 FCompilerVersion: Cardinal;
26 protected
CanHandleCompUnitnull27 function CanHandleCompUnit(ACU: TDwarfCompilationUnit; AHelperData: Pointer): Boolean; override;
GetExistingClassMapnull28 class function GetExistingClassMap: PFpDwarfSymbolClassMap; override;
29 public
GetInstanceForCompUnitnull30 class function GetInstanceForCompUnit(ACU: TDwarfCompilationUnit): TFpSymbolDwarfClassMap; override;
ClassCanHandleCompUnitnull31 class function ClassCanHandleCompUnit(ACU: TDwarfCompilationUnit): Boolean; override;
32
GetInstanceForDbgInfonull33 class function GetInstanceForDbgInfo(ADbgInfo: TDbgInfo):TFpDwarfFreePascalSymbolClassMap;
34 public
35 constructor Create(ACU: TDwarfCompilationUnit; AHelperData: Pointer); override;
GetDwarfSymbolClassnull36 function GetDwarfSymbolClass(ATag: Cardinal): TDbgDwarfSymbolBaseClass; override;
CreateScopeForSymbolnull37 function CreateScopeForSymbol(ALocationContext: TFpDbgLocationContext; ASymbol: TFpSymbol;
38 ADwarf: TFpDwarfInfo): TFpDbgSymbolScope; override;
CreateProcSymbolnull39 //class function CreateProcSymbol(ACompilationUnit: TDwarfCompilationUnit;
40 // AInfo: PDwarfAddressInfo; AAddress: TDbgPtr): TDbgDwarfSymbolBase; override;
41
42 function GetInstanceClassNameFromPVmt(APVmt: TDbgPtr;
43 AContext: TFpDbgLocationContext; ASizeOfAddr: Integer;
44 out AClassName: String; out AnError: TFpError): boolean;
45 end;
46
47 { TFpDwarfFreePascalSymbolClassMapDwarf2 }
48
49 TFpDwarfFreePascalSymbolClassMapDwarf2 = class(TFpDwarfFreePascalSymbolClassMap)
50 strict private
51 class var ExistingClassMap: TFpSymbolDwarfClassMap;
52 protected
GetExistingClassMapnull53 class function GetExistingClassMap: PFpDwarfSymbolClassMap; override;
54 public
ClassCanHandleCompUnitnull55 class function ClassCanHandleCompUnit(ACU: TDwarfCompilationUnit): Boolean; override;
56 public
GetDwarfSymbolClassnull57 function GetDwarfSymbolClass(ATag: Cardinal): TDbgDwarfSymbolBaseClass; override;
CreateSymbolScopenull58 //class function CreateSymbolScope(AThreadId, AStackFrame: Integer; AnAddress: TDBGPtr; ASymbol: TFpSymbol;
59 // ADwarf: TFpDwarfInfo): TFpDbgSymbolScope; override;
60 //class function CreateProcSymbol(ACompilationUnit: TDwarfCompilationUnit;
61 // AInfo: PDwarfAddressInfo; AAddress: TDbgPtr): TDbgDwarfSymbolBase; override;
62 end;
63
64 { TFpDwarfFreePascalSymbolClassMapDwarf3 }
65
66 TFpDwarfFreePascalSymbolClassMapDwarf3 = class(TFpDwarfFreePascalSymbolClassMap)
67 strict private
68 class var ExistingClassMap: TFpSymbolDwarfClassMap;
69 protected
GetExistingClassMapnull70 class function GetExistingClassMap: PFpDwarfSymbolClassMap; override;
71 public
ClassCanHandleCompUnitnull72 class function ClassCanHandleCompUnit(ACU: TDwarfCompilationUnit): Boolean; override;
73 public
GetDwarfSymbolClassnull74 function GetDwarfSymbolClass(ATag: Cardinal): TDbgDwarfSymbolBaseClass; override;
CreateSymbolScopenull75 //class function CreateSymbolScope(AThreadId, AStackFrame: Integer; AnAddress: TDBGPtr; ASymbol: TFpSymbol;
76 // ADwarf: TFpDwarfInfo): TFpDbgSymbolScope; override;
77 //class function CreateProcSymbol(ACompilationUnit: TDwarfCompilationUnit;
78 // AInfo: PDwarfAddressInfo; AAddress: TDbgPtr): TDbgDwarfSymbolBase; override;
79 end;
80
81 {%EndRegion }
82
83 {%Region * ***** Context ***** *}
84
85 { TFpDwarfFreePascalSymbolScope }
86
87 TFpDwarfFreePascalSymbolScope = class(TFpDwarfInfoSymbolScope)
88 private
89 FOuterNestContext: TFpDbgSymbolScope;
90 FOuterNotFound: Boolean;
91 protected
FindLocalSymbolnull92 function FindLocalSymbol(const AName: String; const ANameInfo: TNameSearchInfo;
93 InfoEntry: TDwarfInformationEntry; out ADbgValue: TFpValue): Boolean; override;
94 public
95 destructor Destroy; override;
96 end;
97
98 {%EndRegion }
99
100 {%Region * ***** Value & Types ***** *}
101
102 (* *** Class vs ^Record vs ^Object *** *)
103
104 { TFpSymbolDwarfFreePascalTypeDeclaration }
105
106 TFpSymbolDwarfFreePascalTypeDeclaration = class(TFpSymbolDwarfTypeDeclaration)
107 protected
108 // fpc encodes classes as pointer, not ref (so Obj1 = obj2 compares the pointers)
109 // typedef > pointer > srtuct
110 // while a pointer to class/object: pointer > typedef > ....
DoGetNestedTypeInfonull111 function DoGetNestedTypeInfo: TFpSymbolDwarfType; override;
112 end;
113
114 { TFpSymbolDwarfFreePascalTypePointer }
115
116 TFpSymbolDwarfFreePascalTypePointer = class(TFpSymbolDwarfTypePointer)
117 private
118 FIsInternalPointer: Boolean;
GetIsInternalPointernull119 function GetIsInternalPointer: Boolean; inline;
IsInternalDynArrayPointernull120 function IsInternalDynArrayPointer: Boolean; inline;
121 protected
122 procedure TypeInfoNeeded; override;
123 procedure KindNeeded; override;
DoReadStridenull124 function DoReadStride(AValueObj: TFpValueDwarf; out AStride: TFpDbgValueSize): Boolean; override;
125 procedure ForwardToSymbolNeeded; override;
GetNextTypeInfoForDataAddressnull126 function GetNextTypeInfoForDataAddress(ATargetType: TFpSymbolDwarfType): TFpSymbolDwarfType; override;
GetDataAddressNextnull127 function GetDataAddressNext(AValueObj: TFpValueDwarf; var AnAddress: TFpDbgMemLocation;
128 out ADoneWork: Boolean; ATargetType: TFpSymbolDwarfType): Boolean; override;
DoReadDataSizenull129 function DoReadDataSize(const AValueObj: TFpValue; out ADataSize: TFpDbgValueSize): Boolean; override;
130 public
GetTypedValueObjectnull131 function GetTypedValueObject(ATypeCast: Boolean; AnOuterType: TFpSymbolDwarfType = nil): TFpValueDwarf; override;
132 property IsInternalPointer: Boolean read GetIsInternalPointer write FIsInternalPointer; // Class (also DynArray, but DynArray is handled without this)
133 end;
134
135 { TFpSymbolDwarfFreePascalTypeStructure }
136
137 TFpSymbolDwarfFreePascalTypeStructure = class(TFpSymbolDwarfTypeStructure)
138 protected
139 procedure KindNeeded; override;
GetInstanceClassnull140 //function GetInstanceClass(AValueObj: TFpValueDwarf): TFpSymbolDwarf; override;
141 class function GetInstanceClassNameFromPVmt(APVmt: TDbgPtr;
142 AContext: TFpDbgLocationContext; ASizeOfAddr: Integer;
143 out AClassName: String; out AnError: TFpError): boolean;
144 public
GetInstanceClassNamenull145 function GetInstanceClassName(AValueObj: TFpValue; out
146 AClassName: String): boolean; override;
147 end;
148
149 (* *** Record vs ShortString *** *)
150
151 { TFpSymbolDwarfV2FreePascalTypeStructure }
152
153 TFpSymbolDwarfV2FreePascalTypeStructure = class(TFpSymbolDwarfFreePascalTypeStructure)
154 private
155 FIsShortString: (issUnknown, issShortString, issStructure);
IsShortStringnull156 function IsShortString: Boolean;
157 protected
158 procedure KindNeeded; override;
GetNestedSymbolCountnull159 function GetNestedSymbolCount: Integer; override;
GetNestedSymbolByNamenull160 //function GetNestedSymbolByName(AIndex: String): TFpSymbol; override;
161 public
162 function GetTypedValueObject(ATypeCast: Boolean; AnOuterType: TFpSymbolDwarfType = nil): TFpValueDwarf; override;
163 end;
164
165 { TFpValueDwarfV2FreePascalShortString }
166
167 TFpValueDwarfV2FreePascalShortString = class(TFpValueDwarf)
168 protected
IsValidTypeCastnull169 function IsValidTypeCast: Boolean; override;
GetInternMemberByNamenull170 function GetInternMemberByName(const AIndex: String): TFpValue;
171 procedure Reset; override;
172 private
173 FValue: String;
174 FValueDone: Boolean;
175 protected
GetFieldFlagsnull176 function GetFieldFlags: TFpValueFieldFlags; override;
GetAsStringnull177 function GetAsString: AnsiString; override;
GetAsWideStringnull178 function GetAsWideString: WideString; override;
179 end;
180
181 (* *** "Open Array" in params *** *)
182
183 { TFpSymbolDwarfFreePascalSymbolTypeArray }
184
185 TFpSymbolDwarfFreePascalSymbolTypeArray = class(TFpSymbolDwarfTypeArray)
186 public
GetTypedValueObjectnull187 function GetTypedValueObject(ATypeCast: Boolean; AnOuterType: TFpSymbolDwarfType = nil): TFpValueDwarf; override;
188 end;
189
190 { TFpValueDwarfFreePascalArray }
191
192 TFpValueDwarfFreePascalArray = class(TFpValueDwarfArray)
193 protected
GetKindnull194 function GetKind: TDbgSymbolKind; override;
GetMemberCountnull195 function GetMemberCount: Integer; override;
DoGetStridenull196 function DoGetStride(out AStride: TFpDbgValueSize): Boolean; override;
DoGetMainStridenull197 function DoGetMainStride(out AStride: TFpDbgValueSize): Boolean; override;
DoGetDimStridenull198 function DoGetDimStride(AnIndex: integer; out AStride: TFpDbgValueSize): Boolean; override;
199 end;
200
201 (* *** Array vs AnsiString *** *)
202
203 { TFpSymbolDwarfV3FreePascalSymbolTypeArray }
204
205 TFpSymbolDwarfV3FreePascalSymbolTypeArray = class(TFpSymbolDwarfFreePascalSymbolTypeArray)
206 private type
207 TArrayOrStringType = (iasUnknown, iasArray, iasShortString, iasAnsiString, iasUnicodeString);
208 private
209 FArrayOrStringType: TArrayOrStringType;
GetInternalStringTypenull210 function GetInternalStringType: TArrayOrStringType;
211 protected
212 procedure KindNeeded; override;
DoReadSizenull213 function DoReadSize(const AValueObj: TFpValue; out ASize: TFpDbgValueSize): Boolean; override;
214 public
GetTypedValueObjectnull215 function GetTypedValueObject(ATypeCast: Boolean; AnOuterType: TFpSymbolDwarfType = nil): TFpValueDwarf; override;
216 end;
217
218 { TFpValueDwarfV3FreePascalString }
219
220 TFpValueDwarfV3FreePascalString = class(TFpValueDwarf) // short & ansi...
221 private
222 FValue: String;
223 FValueDone: Boolean;
GetDynamicCodePagenull224 function GetDynamicCodePage(Addr: TFpDbgMemLocation; out Codepage: TSystemCodePage): Boolean;
225 protected
IsValidTypeCastnull226 function IsValidTypeCast: Boolean; override;
227 procedure Reset; override;
GetFieldFlagsnull228 function GetFieldFlags: TFpValueFieldFlags; override;
GetAsStringnull229 function GetAsString: AnsiString; override;
GetAsWideStringnull230 function GetAsWideString: WideString; override;
231 end;
232
233 {%EndRegion }
234
235 implementation
236
237 uses
238 FpDbgCommon;
239
240 var
241 FPDBG_DWARF_VERBOSE: PLazLoggerLogGroup;
242
243 { TFpDwarfFreePascalSymbolClassMap }
244
CanHandleCompUnitnull245 function TFpDwarfFreePascalSymbolClassMap.CanHandleCompUnit(
246 ACU: TDwarfCompilationUnit; AHelperData: Pointer): Boolean;
247 begin
248 Result := (FCompilerVersion = PtrUInt(AHelperData)) and
249 inherited CanHandleCompUnit(ACU, AHelperData);
250 end;
251
TFpDwarfFreePascalSymbolClassMap.GetExistingClassMapnull252 class function TFpDwarfFreePascalSymbolClassMap.GetExistingClassMap: PFpDwarfSymbolClassMap;
253 begin
254 Result := @ExistingClassMap;
255 end;
256
TFpDwarfFreePascalSymbolClassMap.GetInstanceForCompUnitnull257 class function TFpDwarfFreePascalSymbolClassMap.GetInstanceForCompUnit(
258 ACU: TDwarfCompilationUnit): TFpSymbolDwarfClassMap;
259 var
260 s: String;
261 i, j, AVersion: Integer;
262 begin
263 AVersion := 0;
264 s := ACU.Producer+' ';
265 i := PosI('free pascal', s) + 11;
266
267 if i > 11 then begin
268 while (i < Length(s)) and (s[i] in [' ', #9]) do
269 inc(i);
270 delete(s, 1, i - 1);
271 i := pos('.', s);
272 if (i > 1) then begin
273 j := StrToIntDef(copy(s, 1, i - 1), 0);
274 if (j >= 0) then
275 AVersion := j * $10000;
276 delete(s, 1, i);
277 end;
278 if (AVersion > 0) then begin
279 i := pos('.', s);
280 if (i > 1) then begin
281 j := StrToIntDef(copy(s, 1, i - 1), 0);
282 if (j >= 0) and (j < 99) then
283 AVersion := AVersion + j * $100
284 else
285 AVersion := 0;
286 delete(s, 1, i);
287 end;
288 end;
289 if (AVersion > 0) then begin
290 i := pos(' ', s);
291 if (i > 1) then begin
292 j := StrToIntDef(copy(s, 1, i - 1), 0);
293 if (j >= 0) and (j < 99) then
294 AVersion := AVersion + j
295 else
296 AVersion := 0;
297 end;
298 end;
299 end;
300
301 Result := DoGetInstanceForCompUnit(ACU, Pointer(PtrUInt(AVersion)));
302 end;
303
TFpDwarfFreePascalSymbolClassMap.ClassCanHandleCompUnitnull304 class function TFpDwarfFreePascalSymbolClassMap.ClassCanHandleCompUnit(ACU: TDwarfCompilationUnit): Boolean;
305 begin
306 Result := PosI('free pascal', ACU.Producer) > 0;
307 end;
308
309 var
310 LastInfo: TDbgInfo = nil;
311 FoundMap: TFpDwarfFreePascalSymbolClassMap = nil;
312
TFpDwarfFreePascalSymbolClassMap.GetInstanceForDbgInfonull313 class function TFpDwarfFreePascalSymbolClassMap.GetInstanceForDbgInfo(
314 ADbgInfo: TDbgInfo): TFpDwarfFreePascalSymbolClassMap;
315 var
316 i: Integer;
317 begin
318 if ADbgInfo <> LastInfo then begin
319 FoundMap := nil;
320 LastInfo := nil;
321 end;
322
323 Result := FoundMap;
324 if LastInfo <> nil then
325 exit;
326
327 if not (ADbgInfo is TFpDwarfInfo) then
328 exit;
329
330 for i := 0 to TFpDwarfInfo(ADbgInfo).CompilationUnitsCount - 1 do
331 if TFpDwarfInfo(ADbgInfo).CompilationUnits[i].DwarfSymbolClassMap is TFpDwarfFreePascalSymbolClassMap
332 then begin
333 FoundMap := TFpDwarfFreePascalSymbolClassMap(TFpDwarfInfo(ADbgInfo).CompilationUnits[i].DwarfSymbolClassMap);
334 end;
335
336 Result := FoundMap;
337 LastInfo := ADbgInfo;
338 end;
339
340 constructor TFpDwarfFreePascalSymbolClassMap.Create(ACU: TDwarfCompilationUnit;
341 AHelperData: Pointer);
342 begin
343 FCompilerVersion := PtrUInt(AHelperData);
344 inherited Create(ACU, AHelperData);
345 end;
346
GetDwarfSymbolClassnull347 function TFpDwarfFreePascalSymbolClassMap.GetDwarfSymbolClass(
348 ATag: Cardinal): TDbgDwarfSymbolBaseClass;
349 begin
350 case ATag of
351 DW_TAG_typedef: Result := TFpSymbolDwarfFreePascalTypeDeclaration;
352 DW_TAG_pointer_type: Result := TFpSymbolDwarfFreePascalTypePointer;
353 DW_TAG_structure_type,
354 DW_TAG_class_type: Result := TFpSymbolDwarfFreePascalTypeStructure;
355 DW_TAG_array_type: Result := TFpSymbolDwarfFreePascalSymbolTypeArray;
356 else Result := inherited GetDwarfSymbolClass(ATag);
357 end;
358 end;
359
TFpDwarfFreePascalSymbolClassMap.CreateScopeForSymbolnull360 function TFpDwarfFreePascalSymbolClassMap.CreateScopeForSymbol(
361 ALocationContext: TFpDbgLocationContext; ASymbol: TFpSymbol;
362 ADwarf: TFpDwarfInfo): TFpDbgSymbolScope;
363 begin
364 Result := TFpDwarfFreePascalSymbolScope.Create(ALocationContext, ASymbol, ADwarf);
365 end;
366
GetInstanceClassNameFromPVmtnull367 function TFpDwarfFreePascalSymbolClassMap.GetInstanceClassNameFromPVmt(
368 APVmt: TDbgPtr; AContext: TFpDbgLocationContext; ASizeOfAddr: Integer; out
369 AClassName: String; out AnError: TFpError): boolean;
370 begin
371 Result := TFpSymbolDwarfFreePascalTypeStructure.GetInstanceClassNameFromPVmt(APVmt,
372 AContext, ASizeOfAddr, AClassName, AnError);
373 end;
374
375 { TFpDwarfFreePascalSymbolClassMapDwarf2 }
376
TFpDwarfFreePascalSymbolClassMapDwarf2.GetExistingClassMapnull377 class function TFpDwarfFreePascalSymbolClassMapDwarf2.GetExistingClassMap: PFpDwarfSymbolClassMap;
378 begin
379 Result := @ExistingClassMap;
380 end;
381
TFpDwarfFreePascalSymbolClassMapDwarf2.ClassCanHandleCompUnitnull382 class function TFpDwarfFreePascalSymbolClassMapDwarf2.ClassCanHandleCompUnit(
383 ACU: TDwarfCompilationUnit): Boolean;
384 begin
385 Result := inherited ClassCanHandleCompUnit(ACU);
386 Result := Result and (ACU.Version < 3);
387 end;
388
GetDwarfSymbolClassnull389 function TFpDwarfFreePascalSymbolClassMapDwarf2.GetDwarfSymbolClass(
390 ATag: Cardinal): TDbgDwarfSymbolBaseClass;
391 begin
392 case ATag of
393 DW_TAG_structure_type:
394 Result := TFpSymbolDwarfV2FreePascalTypeStructure; // maybe record
395 // // TODO:
396 // //DW_TAG_reference_type: Result := TFpSymbolDwarfTypeRef;
397 // //DW_TAG_typedef: Result := TFpSymbolDwarfTypeDeclaration;
398 // //DW_TAG_pointer_type: Result := TFpSymbolDwarfTypePointer;
399 // //
400 // //DW_TAG_base_type: Result := TFpSymbolDwarfTypeBasic;
401 // //DW_TAG_subrange_type: Result := TFpSymbolDwarfTypeSubRange;
402 // //DW_TAG_enumeration_type: Result := TFpSymbolDwarfTypeEnum;
403 // //DW_TAG_enumerator: Result := TFpSymbolDwarfDataEnumMember;
404 // //DW_TAG_array_type: Result := TFpSymbolDwarfTypeArray;
405 // ////
406 // //DW_TAG_compile_unit: Result := TFpSymbolDwarfUnit;
407 //
408 else
409 Result := inherited GetDwarfSymbolClass(ATag);
410 end;
411 end;
412
413 { TFpDwarfFreePascalSymbolClassMapDwarf3 }
414
TFpDwarfFreePascalSymbolClassMapDwarf3.GetExistingClassMapnull415 class function TFpDwarfFreePascalSymbolClassMapDwarf3.GetExistingClassMap: PFpDwarfSymbolClassMap;
416 begin
417 Result := @ExistingClassMap;
418 end;
419
TFpDwarfFreePascalSymbolClassMapDwarf3.ClassCanHandleCompUnitnull420 class function TFpDwarfFreePascalSymbolClassMapDwarf3.ClassCanHandleCompUnit(
421 ACU: TDwarfCompilationUnit): Boolean;
422 begin
423 Result := inherited ClassCanHandleCompUnit(ACU);
424 Result := Result and (ACU.Version >= 3);
425 end;
426
GetDwarfSymbolClassnull427 function TFpDwarfFreePascalSymbolClassMapDwarf3.GetDwarfSymbolClass(
428 ATag: Cardinal): TDbgDwarfSymbolBaseClass;
429 begin
430 case ATag of
431 DW_TAG_array_type:
432 Result := TFpSymbolDwarfV3FreePascalSymbolTypeArray;
433 // DW_TAG_structure_type:
434 // Result := TFpSymbolDwarfV2FreePascalTypeStructure; // maybe record
435 // // TODO:
436 // //DW_TAG_reference_type: Result := TFpSymbolDwarfTypeRef;
437 // //DW_TAG_typedef: Result := TFpSymbolDwarfTypeDeclaration;
438 // //DW_TAG_pointer_type: Result := TFpSymbolDwarfTypePointer;
439 // //
440 // //DW_TAG_base_type: Result := TFpSymbolDwarfTypeBasic;
441 // //DW_TAG_subrange_type: Result := TFpSymbolDwarfTypeSubRange;
442 // //DW_TAG_enumeration_type: Result := TFpSymbolDwarfTypeEnum;
443 // //DW_TAG_enumerator: Result := TFpSymbolDwarfDataEnumMember;
444 // //DW_TAG_array_type: Result := TFpSymbolDwarfTypeArray;
445 // ////
446 // //DW_TAG_compile_unit: Result := TFpSymbolDwarfUnit;
447 //
448 else
449 Result := inherited GetDwarfSymbolClass(ATag);
450 end;
451 end;
452
453 type
454
455 { TFpDbgDwarfSimpleLocationContext }
456
457 TFpDbgDwarfSimpleLocationContext = class(TFpDbgSimpleLocationContext)
458 protected
459 FStackFrame: Integer;
GetStackFramenull460 function GetStackFrame: Integer; override;
461 public
462 constructor Create(AMemManager: TFpDbgMemManager; AnAddress: TDbgPtr;
463 AnSizeOfAddr, AThreadId: Integer; AStackFrame: Integer);
464 end;
465
466 { TFpDbgDwarfSimpleLocationContext }
467
468 constructor TFpDbgDwarfSimpleLocationContext.Create(
469 AMemManager: TFpDbgMemManager; AnAddress: TDbgPtr; AnSizeOfAddr,
470 AThreadId: Integer; AStackFrame: Integer);
471 begin
472 inherited Create(AMemManager, AnAddress, AnSizeOfAddr, AThreadId, AStackFrame);
473 FStackFrame := AStackFrame;
474 end;
475
GetStackFramenull476 function TFpDbgDwarfSimpleLocationContext.GetStackFrame: Integer;
477 begin
478 Result := FStackFrame;
479 end;
480
481 { TFpDwarfFreePascalSymbolScope }
482
483 var
484 ParentFpLowerNameInfo, ParentFp2LowerNameInfo: TNameSearchInfo; // case sensitive
FindLocalSymbolnull485 function TFpDwarfFreePascalSymbolScope.FindLocalSymbol(const AName: String;
486 const ANameInfo: TNameSearchInfo; InfoEntry: TDwarfInformationEntry; out
487 ADbgValue: TFpValue): Boolean;
488 const
489 selfname = 'self';
490 // TODO: get reg num via memreader name-to-num
491 RegFp64 = 6;
492 RegPc64 = 16;
493 RegFp32 = 5;
494 RegPc32 = 8;
495 var
496 StartScopeIdx, RegFp, RegPc: Integer;
497 ParentFpVal: TFpValue;
498 SearchCtx: TFpDbgDwarfSimpleLocationContext;
499 par_fp, cur_fp, prev_fp, pc: TDbgPtr;
500 d, i: Integer;
501 ParentFpSym: TFpSymbolDwarf;
502 Ctx: TFpDbgSimpleLocationContext;
503 begin
504 Result := False;
505 if not(Symbol is TFpSymbolDwarfDataProc) then
506 exit;
507
508 if Dwarf.TargetInfo.bitness = b64 then begin
509 RegFP := RegFp64;
510 RegPc := RegPc64;
511 end
512 else begin
513 RegFP := RegFp32;
514 RegPc := RegPc32;
515 end;
516 if (Length(AName) = length(selfname)) and (CompareUtf8BothCase(PChar(ANameInfo.NameUpper), PChar(ANameInfo.NameLower), @selfname[1])) then begin
517 ADbgValue := GetSelfParameter;
518 if ADbgValue <> nil then begin
519 ADbgValue.AddReference;
520 Result := True;
521 exit;
522 end;
523 end;
524
525 StartScopeIdx := InfoEntry.ScopeIndex;
526 Result := inherited FindLocalSymbol(AName, ANameInfo, InfoEntry, ADbgValue);
527 if Result then
528 exit;
529
530 if FOuterNotFound then
531 exit;
532
533 if FOuterNestContext <> nil then begin
534 ADbgValue := FOuterNestContext.FindSymbol(AName); // TODO: pass upper/lower
535 Result := True; // self, global was done by outer
536 exit;
537 end;
538
539
540 InfoEntry.ScopeIndex := StartScopeIdx;
541 if not InfoEntry.GoNamedChildEx(ParentFpLowerNameInfo) then begin
542 InfoEntry.ScopeIndex := StartScopeIdx;
543 if not InfoEntry.GoNamedChildEx(ParentFp2LowerNameInfo) then begin
544 FOuterNotFound := True;
545 exit;
546 end;
547 end;
548
549 ParentFpSym := TFpSymbolDwarf.CreateSubClass(AName, InfoEntry);
550 ParentFpVal := ParentFpSym.Value;
551 if ParentFpVal = nil then begin
552 Result := False;
553 exit;
554 end;
555 ApplyContext(ParentFpVal);
556 if not (svfOrdinal in ParentFpVal.FieldFlags) then begin
557 DebugLn(FPDBG_DWARF_VERBOSE, 'no ordinal for parentfp');
558 ParentFpSym.ReleaseReference;
559 ParentFpVal.ReleaseReference;
560 FOuterNotFound := True;
561 exit;
562 end;
563
564 par_fp := ParentFpVal.AsCardinal;
565 ParentFpVal.ReleaseReference;
566 ParentFpSym.ReleaseReference;
567 if par_fp = 0 then begin
568 DebugLn(FPDBG_DWARF_VERBOSE, 'no ordinal for parentfp');
569 FOuterNotFound := True;
570 exit;
571 end;
572
573 // TODO: FindCallStackEntryByBasePointer, once all evaluates run in thread.
574 i := LocationContext.StackFrame + 1;
575 SearchCtx := TFpDbgDwarfSimpleLocationContext.Create(MemManager, 0, SizeOfAddress, LocationContext.ThreadId, i);
576
577 cur_fp := 0;
578 if LocationContext.ReadRegister(RegFp, cur_fp) then begin
579 if cur_fp > par_fp then
580 d := -1 // cur_fp must go down
581 else
582 d := 1; // cur_fp must go up
583 while not (cur_fp = par_fp) do begin
584 SearchCtx.FStackFrame := i;
585 // TODO: get reg num via memreader name-to-num
586 prev_fp := cur_fp;
587 if not SearchCtx.ReadRegister(RegFp, cur_fp) then
588 break;
589 inc(i);
590 if (cur_fp = prev_fp) or ((cur_fp < prev_fp) xor (d = -1)) then
591 break; // wrong direction
592 if i > LocationContext.StackFrame + 200 then break; // something wrong? // TODO better check
593 end;
594 dec(i);
595 end;
596
597 if (par_fp <> cur_fp) or (cur_fp = 0) or
598 (i <= 0) or
599 not SearchCtx.ReadRegister(RegPc, pc)
600 then begin
601 FOuterNotFound := True;
602 SearchCtx.ReleaseReference;
603 exit;
604 end;
605
606 SearchCtx.ReleaseReference;
607
608 Ctx := TFpDbgSimpleLocationContext.Create(MemManager, pc, SizeOfAddress, LocationContext.ThreadId, i);
609 FOuterNestContext := Dwarf.FindSymbolScope(Ctx, pc);
610 Ctx.ReleaseReference;
611
612 ADbgValue := FOuterNestContext.FindSymbol(AName); // TODO: pass upper/lower
613 Result := True; // self, global was done by outer
614 end;
615
616 destructor TFpDwarfFreePascalSymbolScope.Destroy;
617 begin
618 FOuterNestContext.ReleaseReference;
619 inherited Destroy;
620 end;
621
622 { TFpSymbolDwarfV2FreePascalTypeStructure }
623
TFpSymbolDwarfV2FreePascalTypeStructure.IsShortStringnull624 function TFpSymbolDwarfV2FreePascalTypeStructure.IsShortString: Boolean;
625 var
626 LenSym, StSym, StSymType: TFpSymbol;
627 begin
628 if FIsShortString <> issUnknown then
629 exit(FIsShortString = issShortString);
630
631 Result := False;
632 FIsShortString := issStructure;
633 if (inherited NestedSymbolCount <> 2) then
634 exit;
635
636 if (Name <> 'ShortString') and (Name <> 'LongString') then // DWARF-2 => user types are all caps
637 exit;
638
639 LenSym := inherited NestedSymbolByName['length'];
640 if (LenSym = nil) or (LenSym.Kind <> skCardinal) // or (LenSym.Size <> 1) // not implemented yet
641 then
642 exit;
643
644 StSym := inherited NestedSymbolByName['st'];
645 if (StSym = nil) then
646 exit;
647 StSymType := StSym.TypeInfo;
648 if (StSymType = nil) or (StSymType.Kind <> skArray) or not (StSymType is TFpSymbolDwarfTypeArray) then
649 exit;
650
651 FIsShortString := issShortString;
652 Result := True;
653 end;
654
TFpSymbolDwarfV2FreePascalTypeStructure.GetTypedValueObjectnull655 function TFpSymbolDwarfV2FreePascalTypeStructure.GetTypedValueObject(
656 ATypeCast: Boolean; AnOuterType: TFpSymbolDwarfType): TFpValueDwarf;
657 begin
658 if AnOuterType = nil then
659 AnOuterType := Self;
660 if not IsShortString then
661 Result := inherited GetTypedValueObject(ATypeCast, AnOuterType)
662 else
663 Result := TFpValueDwarfV2FreePascalShortString.Create(AnOuterType);
664 end;
665
666 procedure TFpSymbolDwarfV2FreePascalTypeStructure.KindNeeded;
667 begin
668 if not IsShortString then
669 inherited KindNeeded
670 else
671 SetKind(skString);
672 end;
673
GetNestedSymbolCountnull674 function TFpSymbolDwarfV2FreePascalTypeStructure.GetNestedSymbolCount: Integer;
675 begin
676 if IsShortString then
677 Result := 0
678 else
679 Result := inherited GetNestedSymbolCount;
680 end;
681
682 { TFpSymbolDwarfFreePascalTypeDeclaration }
683
TFpSymbolDwarfFreePascalTypeDeclaration.DoGetNestedTypeInfonull684 function TFpSymbolDwarfFreePascalTypeDeclaration.DoGetNestedTypeInfo: TFpSymbolDwarfType;
685 var
686 ti: TFpSymbolDwarfType;
687 begin
688 Result := inherited DoGetNestedTypeInfo;
689
690 // Is internal class pointer?
691 // Do not trigged any cached property of the pointer
692 if (Result = nil) or
693 not (Result is TFpSymbolDwarfFreePascalTypePointer)
694 then
695 exit;
696
697 ti := TFpSymbolDwarfFreePascalTypePointer(Result).NestedTypeInfo;
698 // only if it is NOT a declaration
699 if ti is TFpSymbolDwarfTypeStructure then
700 TFpSymbolDwarfFreePascalTypePointer(Result).IsInternalPointer := True;
701 end;
702
703 { TFpSymbolDwarfFreePascalTypePointer }
704
TFpSymbolDwarfFreePascalTypePointer.GetIsInternalPointernull705 function TFpSymbolDwarfFreePascalTypePointer.GetIsInternalPointer: Boolean;
706 begin
707 Result := FIsInternalPointer or IsInternalDynArrayPointer;
708 end;
709
IsInternalDynArrayPointernull710 function TFpSymbolDwarfFreePascalTypePointer.IsInternalDynArrayPointer: Boolean;
711 var
712 ti: TFpSymbol;
713 begin
714 Result := False;
715 ti := NestedTypeInfo; // Same as TypeInfo, but does not try to be forwarded
716 Result := ti is TFpSymbolDwarfTypeArray;
717 if Result then
718 Result := (sfDynArray in ti.Flags);
719 end;
720
721 procedure TFpSymbolDwarfFreePascalTypePointer.TypeInfoNeeded;
722 var
723 p: TFpSymbol;
724 begin
725 p := NestedTypeInfo;
726 if IsInternalPointer and (p <> nil) then
727 p := p.TypeInfo;
728 SetTypeInfo(p);
729 end;
730
731 procedure TFpSymbolDwarfFreePascalTypePointer.KindNeeded;
732 var
733 k: TDbgSymbolKind;
734 begin
735 if IsInternalPointer then begin
736 k := NestedTypeInfo.Kind;
737 if k in [skObject, skRecord] then // TODO
738 SetKind(skInterface)
739 else
740 SetKind(k);
741 end
742 else
743 inherited;
744 end;
745
DoReadStridenull746 function TFpSymbolDwarfFreePascalTypePointer.DoReadStride(
747 AValueObj: TFpValueDwarf; out AStride: TFpDbgValueSize): Boolean;
748 begin
749 if IsInternalPointer then
750 Result := NestedTypeInfo.ReadStride(AValueObj, AStride)
751 else
752 Result := inherited DoReadStride(AValueObj, AStride);
753 end;
754
755 procedure TFpSymbolDwarfFreePascalTypePointer.ForwardToSymbolNeeded;
756 begin
757 if IsInternalPointer then
758 SetForwardToSymbol(NestedTypeInfo) // Same as TypeInfo, but does not try to be forwarded
759 else
760 SetForwardToSymbol(nil); // inherited ForwardToSymbolNeeded;
761 end;
762
TFpSymbolDwarfFreePascalTypePointer.GetNextTypeInfoForDataAddressnull763 function TFpSymbolDwarfFreePascalTypePointer.GetNextTypeInfoForDataAddress(
764 ATargetType: TFpSymbolDwarfType): TFpSymbolDwarfType;
765 begin
766 if IsInternalPointer then
767 Result := NestedTypeInfo
768 else
769 Result := inherited;
770 end;
771
GetDataAddressNextnull772 function TFpSymbolDwarfFreePascalTypePointer.GetDataAddressNext(
773 AValueObj: TFpValueDwarf; var AnAddress: TFpDbgMemLocation; out
774 ADoneWork: Boolean; ATargetType: TFpSymbolDwarfType): Boolean;
775 begin
776 if (not IsInternalPointer) and (ATargetType = nil) then exit(True);
777
778 Result := inherited GetDataAddressNext(AValueObj, AnAddress, ADoneWork, ATargetType);
779 if (not Result) or ADoneWork then
780 exit;
781
782 Result := AValueObj.MemManager <> nil;
783 if not Result then
784 exit;
785 AnAddress := AValueObj.Context.ReadAddress(AnAddress, SizeVal(CompilationUnit.AddressSize));
786 Result := IsValidLoc(AnAddress);
787
788 if (not Result) and
789 IsError(AValueObj.Context.LastMemError)
790 then
791 SetLastError(AValueObj, AValueObj.Context.LastMemError);
792 end;
793
TFpSymbolDwarfFreePascalTypePointer.GetTypedValueObjectnull794 function TFpSymbolDwarfFreePascalTypePointer.GetTypedValueObject(
795 ATypeCast: Boolean; AnOuterType: TFpSymbolDwarfType): TFpValueDwarf;
796 begin
797 if AnOuterType = nil then
798 AnOuterType := Self;
799 if IsInternalPointer then
800 Result := NestedTypeInfo.GetTypedValueObject(ATypeCast, AnOuterType)
801 else
802 Result := inherited GetTypedValueObject(ATypeCast, AnOuterType);
803 end;
804
DoReadDataSizenull805 function TFpSymbolDwarfFreePascalTypePointer.DoReadDataSize(
806 const AValueObj: TFpValue; out ADataSize: TFpDbgValueSize): Boolean;
807 begin
808 if Kind = skClass then begin
809 // TODO: get/adjust a value object to have the deref address // see ConstRefOrExprFromAttrData
810 Result := NestedTypeInfo.ReadSize(AValueObj, ADataSize);
811 if not Result then
812 ADataSize := ZeroSize;
813 end
814 else
815 Result := inherited DoReadDataSize(AValueObj, ADataSize);
816 end;
817
818 { TFpSymbolDwarfFreePascalTypeStructure }
819
820 procedure TFpSymbolDwarfFreePascalTypeStructure.KindNeeded;
821 var
822 t: TDbgSymbolKind;
823 begin
824 (* DW_TAG_structure_type
825 - Is either objec or record.
826 - Except: fpc < 3.0 => can be class or interface too
827 DW_TAG_class_type
828 - Is either class, interface, or object (object only with virtual methods)
829
830 tested up to fpc 3.2 beta
831 *)
832 if (InformationEntry.AbbrevTag = DW_TAG_interface_type) then begin
833 SetKind(skInterface);
834 end
835 else
836 if TypeInfo <> nil then begin // inheritance
837 t := TypeInfo.Kind;
838 if t = skRecord then
839 t := skObject; // could be skInterface
840 SetKind(t); // skClass, skInterface or skObject
841 end
842 else
843 begin
844 if NestedSymbolByName['_vptr$TOBJECT'] <> nil then
845 SetKind(skClass)
846 else
847 if NestedSymbolByName['_vptr$'+Name] <> nil then // vptr is only present for skObject with virtual methods/Constructor
848 SetKind(skObject)
849 else
850 if (InformationEntry.AbbrevTag = DW_TAG_class_type) then
851 SetKind(skObject) // could be skInterface // fix in TFpSymbolDwarfFreePascalTypePointer.KindNeeded
852 else
853 SetKind(skRecord); // could be skObject(?) or skInterface // fix in TFpSymbolDwarfFreePascalTypePointer.KindNeeded
854 end;
855 end;
856
GetInstanceClassNamenull857 function TFpSymbolDwarfFreePascalTypeStructure.GetInstanceClassName(
858 AValueObj: TFpValue; out AClassName: String): boolean;
859 var
860 AnErr: TFpError;
861 begin
862 Result := AValueObj is TFpValueDwarf;
863 if not Result then
864 exit;
865 Result := GetInstanceClassNameFromPVmt(LocToAddrOrNil(AValueObj.DataAddress),
866 TFpValueDwarf(AValueObj).Context, TFpValueDwarf(AValueObj).Context.SizeOfAddress, AClassName, AnErr);
867 if not Result then
868 SetLastError(AValueObj, AnErr);
869 end;
870
TFpSymbolDwarfFreePascalTypeStructure.GetInstanceClassNameFromPVmtnull871 class function TFpSymbolDwarfFreePascalTypeStructure.GetInstanceClassNameFromPVmt
872 (APVmt: TDbgPtr; AContext: TFpDbgLocationContext; ASizeOfAddr: Integer; out
873 AClassName: String; out AnError: TFpError): boolean;
874 var
875 VmtAddr, ClassNameAddr: TFpDbgMemLocation;
876 NameLen: QWord;
877 begin
878 Result := False;
879 AnError := NoError;
880 AClassName := '';
881 if not AContext.ReadAddress(TargetLoc(APVmt), SizeVal(ASizeOfAddr), VmtAddr) then begin
882 AnError := AContext.LastMemError;
883 exit;
884 end;
885 if not IsReadableMem(VmtAddr) then begin
886 AnError := CreateError(fpErrCanNotReadMemAtAddr, [VmtAddr.Address]);
887 exit;
888 end;
889 {$PUSH}{$Q-}
890 VmtAddr.Address := VmtAddr.Address + TDBGPtr(3 * ASizeOfAddr);
891 {$POP}
892
893 if not AContext.ReadAddress(VmtAddr, SizeVal(ASizeOfAddr), ClassNameAddr) then begin
894 AnError := AContext.LastMemError;
895 exit;
896 end;
897 if not IsReadableMem(ClassNameAddr) then begin
898 AnError := CreateError(fpErrCanNotReadMemAtAddr, [ClassNameAddr.Address]);
899 exit;
900 end;
901 if not AContext.ReadUnsignedInt(ClassNameAddr, SizeVal(1), NameLen) then begin
902 AnError := AContext.LastMemError;
903 exit;
904 end;
905 if NameLen = 0 then begin
906 AnError := CreateError(fpErrAnyError, ['No name found']);
907 exit;
908 end;
909 if not AContext.MemManager.SetLength(AClassName, NameLen) then begin
910 AnError := AContext.LastMemError;
911 exit;
912 end;
913
914 ClassNameAddr.Address := ClassNameAddr.Address + 1;
915 Result := AContext.ReadMemory(ClassNameAddr, SizeVal(NameLen), @AClassName[1]);
916 if not Result then
917 AnError := AContext.LastMemError;
918 end;
919
920 { TFpValueDwarfV2FreePascalShortString }
921
TFpValueDwarfV2FreePascalShortString.IsValidTypeCastnull922 function TFpValueDwarfV2FreePascalShortString.IsValidTypeCast: Boolean;
923 begin
924 // currently only allow this / used by array access
925 Result := TypeCastSourceValue is TFpValueConstAddress;
926 end;
927
GetInternMemberByNamenull928 function TFpValueDwarfV2FreePascalShortString.GetInternMemberByName(
929 const AIndex: String): TFpValue;
930 begin
931 if HasTypeCastInfo then begin
932 Result := TypeInfo.GetNestedValueByName(AIndex);
933 TFpValueDwarf(Result).StructureValue := Self;
934 if (TFpValueDwarf(Result).Context = nil) then
935 TFpValueDwarf(Result).Context := Context;
936 end
937 else
938 Result := MemberByName[AIndex];
939 end;
940
941 procedure TFpValueDwarfV2FreePascalShortString.Reset;
942 begin
943 inherited Reset;
944 FValueDone := False;
945 end;
946
TFpValueDwarfV2FreePascalShortString.GetFieldFlagsnull947 function TFpValueDwarfV2FreePascalShortString.GetFieldFlags: TFpValueFieldFlags;
948 begin
949 Result := inherited GetFieldFlags;
950 Result := Result + [svfString];
951 end;
952
TFpValueDwarfV2FreePascalShortString.GetAsStringnull953 function TFpValueDwarfV2FreePascalShortString.GetAsString: AnsiString;
954 var
955 len: QWord;
956 Size: TFpDbgValueSize;
957 LenSym, StSym: TFpValueDwarf;
958 begin
959 if FValueDone then
960 exit(FValue);
961
962 LenSym := TFpValueDwarf(GetInternMemberByName('length'));
963 assert(LenSym is TFpValueDwarf, 'LenSym is TFpValueDwarf');
964 len := LenSym.AsCardinal;
965 LenSym.ReleaseReference;
966
967 if not GetSize(Size) then begin;
968 SetLastError(CreateError(fpErrAnyError));
969 exit('');
970 end;
971 if (Size < len) then begin
972 SetLastError(CreateError(fpErrAnyError));
973 exit('');
974 end;
975
976 if not MemManager.SetLength(Result, len) then begin
977 SetLastError(MemManager.LastError);
978 exit;
979 end;
980
981 StSym := TFpValueDwarf(GetInternMemberByName('st'));
982 assert(StSym is TFpValueDwarf, 'StSym is TFpValueDwarf');
983
984 if len > 0 then
985 if not Context.ReadMemory(StSym.DataAddress, SizeVal(len), @Result[1]) then begin
986 Result := ''; // TODO: error
987 SetLastError(Context.LastMemError);
988 StSym.ReleaseReference;
989 exit;
990 end;
991 StSym.ReleaseReference;
992
993 FValue := Result;
994 FValueDone := True;
995 end;
996
GetAsWideStringnull997 function TFpValueDwarfV2FreePascalShortString.GetAsWideString: WideString;
998 begin
999 Result := GetAsString;
1000 end;
1001
1002 { TFpSymbolDwarfFreePascalSymbolTypeArray }
1003
TFpSymbolDwarfFreePascalSymbolTypeArray.GetTypedValueObjectnull1004 function TFpSymbolDwarfFreePascalSymbolTypeArray.GetTypedValueObject(
1005 ATypeCast: Boolean; AnOuterType: TFpSymbolDwarfType): TFpValueDwarf;
1006 begin
1007 if AnOuterType = nil then
1008 AnOuterType := Self;
1009 Result := TFpValueDwarfFreePascalArray.Create(AnOuterType, Self);
1010 end;
1011
1012 { TFpValueDwarfFreePascalArray }
1013
GetKindnull1014 function TFpValueDwarfFreePascalArray.GetKind: TDbgSymbolKind;
1015 begin
1016 if TypeInfo <> nil then
1017 Result := TypeInfo.Kind
1018 else
1019 Result := inherited GetKind;
1020 end;
1021
GetMemberCountnull1022 function TFpValueDwarfFreePascalArray.GetMemberCount: Integer;
1023 var
1024 t, t2: TFpSymbol;
1025 Info: TDwarfInformationEntry;
1026 n: AnsiString;
1027 UpperBoundSym: TFpSymbolDwarf;
1028 val: TFpValue;
1029 l, h: Int64;
1030 Addr: TFpDbgMemLocation;
1031 begin
1032 Result := 0;
1033 t := TypeInfo;
1034 if (t.Kind <> skArray) or (t.NestedSymbolCount < 1) then // IndexTypeCount;
1035 exit(inherited GetMemberCount);
1036
1037 t2 := t.NestedSymbol[0]; // IndexType[0];
1038 if not (t2 is TFpSymbolDwarfTypeSubRange) then
1039 exit(inherited GetMemberCount);
1040
1041
1042 TFpSymbolDwarfTypeSubRange(t2).GetValueBounds(Self, l, h);
1043 if (l <> 0) or
1044 (TFpSymbolDwarfTypeSubRange(t2).LowBoundState <> rfConst) or
1045 (TFpSymbolDwarfTypeSubRange(t2).HighBoundState <> rfNotFound) or
1046 (TFpSymbolDwarfTypeSubRange(t2).CountState <> rfNotFound)
1047 then
1048 exit(inherited GetMemberCount);
1049
1050 // Check for open array param
1051 if (t is TFpSymbolDwarfTypeArray) and
1052 (DbgSymbol is TFpSymbolDwarfDataParameter) // open array exists only as param
1053 then begin
1054 Info := TFpSymbolDwarfDataParameter(DbgSymbol).InformationEntry.Clone;
1055 Info.GoNext;
1056 if Info.HasValidScope and
1057 Info.HasAttrib(DW_AT_location) and // the high param must have a location / cannot be a constant
1058 Info.ReadName(n)
1059 then begin
1060 if (n <> '') and (n[1] = '$') then // dwarf3 // TODO: make required in dwarf3
1061 delete(n, 1, 1);
1062 if (copy(n,1,4) = 'high')
1063 and (CompareText(copy(n, 5, length(n)), DbgSymbol.Name) = 0) then begin
1064 UpperBoundSym := TFpSymbolDwarf.CreateSubClass('', Info);
1065 if UpperBoundSym <> nil then begin
1066 val := UpperBoundSym.Value;
1067 if val <> nil then begin
1068 TFpValueDwarf(val).Context := Context;
1069 h := Val.AsInteger;
1070 val.ReleaseReference;
1071 if (h >= 0) and (h < maxLongint) then begin
1072 Result := h + 1;
1073 end
1074 else
1075 Result := 0;
1076 // TODO h < -1 => Error
1077 Info.ReleaseReference;
1078 UpperBoundSym.ReleaseReference;
1079 exit;
1080 end;
1081 end;
1082 end;
1083 end;
1084 Info.ReleaseReference;
1085 end;
1086
1087 // dynamic array
1088 if (sfDynArray in t.Flags) and (AsCardinal <> 0) and GetDwarfDataAddress(Addr) then begin
1089 if not (IsReadableMem(Addr) and (LocToAddr(Addr) > AddressSize)) then
1090 exit(0); // dyn array, but bad data
1091 Addr.Address := Addr.Address - AddressSize;
1092 if Context.ReadSignedInt(Addr, SizeVal(AddressSize), h) then begin
1093 // TODO h < -1 => Error
1094 if (h >= 0) and (h < maxLongint) then
1095 Result := h+1;
1096 exit;
1097 end
1098 else
1099 SetLastError(Context.LastMemError);
1100 Result := 0;
1101 exit;
1102 end;
1103
1104 // Should not be here. There is no knowledeg how many members there are
1105 Result := inherited GetMemberCount;
1106 end;
1107
DoGetStridenull1108 function TFpValueDwarfFreePascalArray.DoGetStride(out AStride: TFpDbgValueSize
1109 ): Boolean;
1110 begin
1111 if (TFpDwarfFreePascalSymbolClassMap(TypeInfo.CompilationUnit.DwarfSymbolClassMap).FCompilerVersion >= $030300)
1112 then
1113 Result := inherited DoGetStride(AStride)
1114 else
1115 Result := TFpSymbolDwarfType(TypeInfo.NestedSymbol[0]).ReadStride(Self, AStride);
1116 end;
1117
TFpValueDwarfFreePascalArray.DoGetMainStridenull1118 function TFpValueDwarfFreePascalArray.DoGetMainStride(out
1119 AStride: TFpDbgValueSize): Boolean;
1120 begin
1121 if (TFpDwarfFreePascalSymbolClassMap(TypeInfo.CompilationUnit.DwarfSymbolClassMap).FCompilerVersion >= $030300)
1122 then
1123 Result := inherited DoGetMainStride(AStride)
1124 else
1125 Result := GetMemberSize(AStride);
1126 end;
1127
TFpValueDwarfFreePascalArray.DoGetDimStridenull1128 function TFpValueDwarfFreePascalArray.DoGetDimStride(AnIndex: integer; out
1129 AStride: TFpDbgValueSize): Boolean;
1130 begin
1131 if (TFpDwarfFreePascalSymbolClassMap(TypeInfo.CompilationUnit.DwarfSymbolClassMap).FCompilerVersion >= $030300)
1132 then
1133 Result := inherited DoGetDimStride(AnIndex, AStride)
1134 else
1135 begin
1136 Result := True;
1137 AStride := ZeroSize;
1138 end;
1139 end;
1140
1141 { TFpSymbolDwarfV3FreePascalSymbolTypeArray }
1142
TFpSymbolDwarfV3FreePascalSymbolTypeArray.GetInternalStringTypenull1143 function TFpSymbolDwarfV3FreePascalSymbolTypeArray.GetInternalStringType: TArrayOrStringType;
1144 var
1145 Info: TDwarfInformationEntry;
1146 t: Cardinal;
1147 t2: TFpSymbol;
1148 CharSize: TFpDbgValueSize;
1149 LocData: array of byte;
1150 begin
1151 Result := FArrayOrStringType;
1152 if Result <> iasUnknown then
1153 exit;
1154
1155 FArrayOrStringType := iasArray;
1156 Result := FArrayOrStringType;
1157
1158 t2 := TypeInfo;
1159 if (t2 = nil) or (t2.Kind <> skChar) then
1160 exit;
1161
1162 // TODO: check lowbound = 1 (const)
1163
1164 Info := InformationEntry.FirstChild;
1165 if Info = nil then
1166 exit;
1167
1168 while Info.HasValidScope do begin
1169 t := Info.AbbrevTag;
1170 if (t = DW_TAG_enumeration_type) then
1171 break;
1172 if (t = DW_TAG_subrange_type) then begin
1173 if Info.HasAttrib(DW_AT_byte_stride) or Info.HasAttrib(DW_AT_type) then
1174 break;
1175
1176 // TODO: check the location parser, if it is a reference
1177
1178 if InformationEntry.ReadValue(DW_AT_data_location, LocData) then begin
1179 if (Length(LocData) = 3) and
1180 (LocData[0] = $97) and
1181 (LocData[1] = $31) and
1182 (LocData[2] = $22)
1183 then begin
1184 FArrayOrStringType := iasShortString;
1185 break;
1186 end;
1187 end;
1188
1189 if not t2.ReadSize(nil, CharSize) then
1190 CharSize := ZeroSize; // TODO: error
1191 if (CharSize.Size = 2) then
1192 FArrayOrStringType := iasUnicodeString
1193 else
1194 FArrayOrStringType := iasAnsiString;
1195 break;
1196 end;
1197 Info.GoNext;
1198 end;
1199
1200 Info.ReleaseReference;
1201 Result := FArrayOrStringType;
1202 end;
1203
TFpSymbolDwarfV3FreePascalSymbolTypeArray.GetTypedValueObjectnull1204 function TFpSymbolDwarfV3FreePascalSymbolTypeArray.GetTypedValueObject(
1205 ATypeCast: Boolean; AnOuterType: TFpSymbolDwarfType): TFpValueDwarf;
1206 begin
1207 if AnOuterType = nil then
1208 AnOuterType := Self;
1209 if GetInternalStringType in [iasShortString, iasAnsiString, iasUnicodeString] then
1210 Result := TFpValueDwarfV3FreePascalString.Create(AnOuterType)
1211 else
1212 Result := inherited GetTypedValueObject(ATypeCast, AnOuterType);
1213 end;
1214
1215 procedure TFpSymbolDwarfV3FreePascalSymbolTypeArray.KindNeeded;
1216 begin
1217 case GetInternalStringType of
1218 iasShortString:
1219 SetKind(skString);
1220 iasAnsiString:
1221 SetKind(skString); // TODO skAnsiString
1222 iasUnicodeString:
1223 SetKind(skWideString);
1224 else
1225 inherited KindNeeded;
1226 end;
1227 end;
1228
DoReadSizenull1229 function TFpSymbolDwarfV3FreePascalSymbolTypeArray.DoReadSize(
1230 const AValueObj: TFpValue; out ASize: TFpDbgValueSize): Boolean;
1231 begin
1232 if GetInternalStringType in [iasAnsiString, iasUnicodeString] then begin
1233 ASize := ZeroSize;
1234 ASize.Size := CompilationUnit.AddressSize;
1235 Result := True;
1236 end
1237 else begin
1238 Result := inherited DoReadSize(AValueObj, ASize);
1239 if (not Result) and (GetInternalStringType = iasArray) then begin
1240 ASize := ZeroSize;
1241 ASize.Size := CompilationUnit.AddressSize;
1242 Result := True;
1243 end;
1244 end;
1245 end;
1246
1247 { TFpValueDwarfV3FreePascalString }
1248
IsValidTypeCastnull1249 function TFpValueDwarfV3FreePascalString.IsValidTypeCast: Boolean;
1250 var
1251 f: TFpValueFieldFlags;
1252 begin
1253 Result := HasTypeCastInfo;
1254 If not Result then
1255 exit;
1256
1257 assert(TypeInfo.Kind in [skString, skWideString], 'TFpValueDwarfArray.IsValidTypeCast: TypeInfo.Kind = skArray');
1258
1259 f := TypeCastSourceValue.FieldFlags;
1260 if (f * [svfAddress, svfSize, svfSizeOfPointer] = [svfAddress]) or
1261 (svfOrdinal in f)
1262 then
1263 exit;
1264
1265 //if sfDynArray in TypeInfo.Flags then begin
1266 // // dyn array
1267 // if (svfOrdinal in f)then
1268 // exit;
1269 // if (f * [svfAddress, svfSize] = [svfAddress, svfSize]) and
1270 // (TypeCastSourceValue.Size = TypeInfo.CompilationUnit.AddressSize)
1271 // then
1272 // exit;
1273 // if (f * [svfAddress, svfSizeOfPointer] = [svfAddress, svfSizeOfPointer]) then
1274 // exit;
1275 //end
1276 //else begin
1277 // // stat array
1278 // if (f * [svfAddress, svfSize] = [svfAddress, svfSize]) and
1279 // (TypeCastSourceValue.Size = TypeInfo.Size)
1280 // then
1281 // exit;
1282 //end;
1283 Result := False;
1284 end;
1285
1286 procedure TFpValueDwarfV3FreePascalString.Reset;
1287 begin
1288 inherited Reset;
1289 FValueDone := False;
1290 end;
1291
TFpValueDwarfV3FreePascalString.GetFieldFlagsnull1292 function TFpValueDwarfV3FreePascalString.GetFieldFlags: TFpValueFieldFlags;
1293 begin
1294 Result := inherited GetFieldFlags;
1295 case TypeInfo.Kind of
1296 skWideString: Result := Result + [svfWideString];
1297 else Result := Result + [svfString];
1298 end;
1299 end;
1300
GetAsStringnull1301 function TFpValueDwarfV3FreePascalString.GetAsString: AnsiString;
1302 var
1303 t, t2: TFpSymbol;
1304 LowBound, HighBound, i: Int64;
1305 Addr, Addr2: TFpDbgMemLocation;
1306 WResult: WideString;
1307 RResult: RawByteString;
1308 AttrData: TDwarfAttribData;
1309 Codepage: TSystemCodePage;
1310 begin
1311 if FValueDone then
1312 exit(FValue);
1313
1314 // TODO: error handling
1315 FValue := '';
1316 Result := '';
1317 FValueDone := True;
1318
1319 // get length
1320 t := TypeInfo;
1321 if t.NestedSymbolCount < 1 then // subrange type
1322 exit;
1323
1324 t2 := t.NestedSymbol[0]; // subrange type
1325 if not( (t2 is TFpSymbolDwarfType) and TFpSymbolDwarfType(t2).GetValueBounds(self, LowBound, HighBound) )
1326 then
1327 exit;
1328
1329 GetDwarfDataAddress(Addr);
1330 if (not IsValidLoc(Addr)) and (svfOrdinal in TypeCastSourceValue.FieldFlags) then
1331 Addr := TargetLoc(TypeCastSourceValue.AsCardinal);
1332 if not IsReadableLoc(Addr) then
1333 exit;
1334
1335 assert((TypeInfo <> nil) and (TypeInfo.CompilationUnit <> nil) and (TypeInfo.CompilationUnit.DwarfSymbolClassMap is TFpDwarfFreePascalSymbolClassMapDwarf3), 'TFpValueDwarfV3FreePascalString.GetAsString: (Owner <> nil) and (Owner.CompilationUnit <> nil) and (TypeInfo.CompilationUnit.DwarfSymbolClassMap is TFpDwarfFreePascalSymbolClassMapDwarf3)');
1336 if (TFpDwarfFreePascalSymbolClassMapDwarf3(TypeInfo.CompilationUnit.DwarfSymbolClassMap).FCompilerVersion > 0) and
1337 (TFpDwarfFreePascalSymbolClassMapDwarf3(TypeInfo.CompilationUnit.DwarfSymbolClassMap).FCompilerVersion < $030100)
1338 then begin
1339 if t.Kind = skWideString then begin
1340 if (t2 is TFpSymbolDwarfTypeSubRange) and (LowBound = 1) then begin
1341 if (TFpSymbolDwarfTypeSubRange(t2).InformationEntry.GetAttribData(DW_AT_upper_bound, AttrData)) and
1342 (TFpSymbolDwarfTypeSubRange(t2).InformationEntry.AttribForm[AttrData.Idx] = DW_FORM_block1) and
1343 (IsReadableMem(Addr) and (LocToAddr(Addr) > AddressSize))
1344 then begin
1345 // fpc issue 0035359
1346 // read data and check for DW_OP_shr ?
1347 Addr2 := Addr;
1348 Addr2.Address := Addr2.Address - AddressSize;
1349 if Context.ReadSignedInt(Addr2, SizeVal(AddressSize), i) then begin
1350 if (i shr 1) = HighBound then
1351 HighBound := i;
1352 end
1353 end;
1354 end;
1355 end;
1356 end;
1357
1358 if HighBound < LowBound then
1359 exit; // empty string
1360
1361 if MemManager.MemLimits.MaxStringLen > 0 then begin
1362 {$PUSH}{$Q-}
1363 if QWord(HighBound - LowBound) > MemManager.MemLimits.MaxStringLen then
1364 HighBound := LowBound + MemManager.MemLimits.MaxStringLen;
1365 {$POP}
1366 end;
1367
1368 if t.Kind = skWideString then begin
1369 if not MemManager.SetLength(WResult, HighBound-LowBound+1) then begin
1370 WResult := '';
1371 SetLastError(MemManager.LastError);
1372 end
1373 else
1374 if not Context.ReadMemory(Addr, SizeVal((HighBound-LowBound+1)*2), @WResult[1]) then begin
1375 WResult := '';
1376 SetLastError(Context.LastMemError);
1377 end;
1378
1379 Result := WResult;
1380 end else
1381 if Addr.Address = Address.Address + 1 then begin
1382 // shortstring
1383 if not MemManager.SetLength(Result, HighBound-LowBound+1) then begin
1384 Result := '';
1385 SetLastError(MemManager.LastError);
1386 end
1387 else
1388 if not Context.ReadMemory(Addr, SizeVal(HighBound-LowBound+1), @Result[1]) then begin
1389 Result := '';
1390 SetLastError(Context.LastMemError);
1391 end;
1392 end
1393 else begin
1394 if not MemManager.SetLength(RResult, HighBound-LowBound+1) then begin
1395 Result := '';
1396 SetLastError(MemManager.LastError);
1397 end
1398 else
1399 if not Context.ReadMemory(Addr, SizeVal(HighBound-LowBound+1), @RResult[1]) then begin
1400 Result := '';
1401 SetLastError(Context.LastMemError);
1402 end else begin
1403 if GetDynamicCodePage(Addr, Codepage) then
1404 SetCodePage(RResult, Codepage, False);
1405 Result := RResult;
1406 end;
1407 end;
1408
1409 FValue := Result;
1410 end;
1411
GetAsWideStringnull1412 function TFpValueDwarfV3FreePascalString.GetAsWideString: WideString;
1413 begin
1414 // todo: widestring, but currently that is encoded as PWideChar
1415 Result := GetAsString;
1416 end;
1417
GetDynamicCodePagenull1418 function TFpValueDwarfV3FreePascalString.GetDynamicCodePage(Addr: TFpDbgMemLocation; out
1419 Codepage: TSystemCodePage): Boolean;
1420 var
1421 CodepageOffset: SmallInt;
1422 begin
fornull1423 // Only call this function for non-empty strings!
1424 Result := False;
1425 if not IsTargetNotNil(Addr) then
1426 exit;
1427
1428 // Only AnsiStrings in fpc 3.0.0 and higher have a dynamic codepage.
1429 if (TypeInfo.Kind = skString) and (TFpDwarfFreePascalSymbolClassMapDwarf3(TypeInfo.CompilationUnit.DwarfSymbolClassMap).FCompilerVersion >= $030000) then begin
1430 // Too bad the debug-information does not deliver this information. So we
1431 // use these hardcoded information, and hope that FPC does not change and
1432 // we never reach this point for a compilationunit that is not compiled by
1433 // fpc.
1434 CodepageOffset := AddressSize * 3;
1435 Addr.Address := Addr.Address - CodepageOffset;
1436 if Context.ReadMemory(Addr, SizeVal(2), @Codepage) then
1437 Result := CodePageToCodePageName(Codepage) <> '';
1438 end;
1439 end;
1440
1441 initialization
1442 DwarfSymbolClassMapList.AddMap(TFpDwarfFreePascalSymbolClassMapDwarf2);
1443 DwarfSymbolClassMapList.AddMap(TFpDwarfFreePascalSymbolClassMapDwarf3);
1444
1445 FPDBG_DWARF_VERBOSE := DebugLogger.FindOrRegisterLogGroup('FPDBG_DWARF_VERBOSE' {$IFDEF FPDBG_DWARF_VERBOSE} , True {$ENDIF} );
1446
1447 ParentFpLowerNameInfo := NameInfoForSearch('parentfp');
1448 ParentFp2LowerNameInfo := NameInfoForSearch('$parentfp');
1449 end.
1450
1451