From 8f9d2106dbc1671fcd0b7f935dcd38359d90eb8b Mon Sep 17 00:00:00 2001 From: joost Date: Sun, 5 Apr 2015 20:08:17 +0000 Subject: [PATCH] FpDebug: Re-structured the reading of debug-information from multiple files. git-svn-id: trunk@48638 - --- components/fpdebug/fpdbgclasses.pp | 23 +-- components/fpdebug/fpdbgdarwinclasses.pas | 64 +++---- components/fpdebug/fpdbgdwarfdataclasses.pas | 170 +++++++++--------- .../fpdebug/fpdbgdwarfverboseprinter.pas | 4 +- components/fpdebug/fpdbginfo.pas | 4 +- components/fpdebug/fpdbglinuxclasses.pas | 6 +- components/fpdebug/fpdbgloader.pp | 46 ++++- components/fpdebug/fpdbgsymtablecontext.pas | 13 +- components/fpdebug/fpdbgwinclasses.pas | 12 +- 9 files changed, 194 insertions(+), 148 deletions(-) diff --git a/components/fpdebug/fpdbgclasses.pp b/components/fpdebug/fpdbgclasses.pp index 412814f6b3..f8481f12f3 100644 --- a/components/fpdebug/fpdbgclasses.pp +++ b/components/fpdebug/fpdbgclasses.pp @@ -190,13 +190,13 @@ type FName: String; FProcess: TDbgProcess; FSymbolTableInfo: TFpSymbolInfo; - FLoader: TDbgImageLoader; + FLoaderList: TDbgImageLoaderList; protected FDbgInfo: TDbgInfo; - function InitializeLoader: TDbgImageLoader; virtual; + procedure InitializeLoaders; virtual; procedure SetName(const AValue: String); - property Loader: TDbgImageLoader read FLoader write FLoader; + property LoaderList: TDbgImageLoaderList read FLoaderList write FLoaderList; public constructor Create(const AProcess: TDbgProcess); virtual; destructor Destroy; override; @@ -577,12 +577,13 @@ end; function TDbgInstance.AddrOffset: Int64; begin - Result := FLoader.ImageBase; + Result := FLoaderList.ImageBase; end; constructor TDbgInstance.Create(const AProcess: TDbgProcess); begin FProcess := AProcess; + FLoaderList := TDbgImageLoaderList.Create(True); inherited Create; end; @@ -591,7 +592,7 @@ destructor TDbgInstance.Destroy; begin FreeAndNil(FDbgInfo); FreeAndNil(FSymbolTableInfo); - FreeAndNil(FLoader); + FreeAndNil(FLoaderList); inherited; end; @@ -604,14 +605,14 @@ end; procedure TDbgInstance.LoadInfo; begin - FLoader := InitializeLoader; - if FLoader.Image64Bit then + InitializeLoaders; + if FLoaderList.Image64Bit then FMode:=dm64 else FMode:=dm32; - FDbgInfo := TFpDwarfInfo.Create(FLoader); + FDbgInfo := TFpDwarfInfo.Create(FLoaderList); TFpDwarfInfo(FDbgInfo).LoadCompilationUnits; - FSymbolTableInfo := TFpSymbolInfo.Create(FLoader); + FSymbolTableInfo := TFpSymbolInfo.Create(FLoaderList); end; function TDbgInstance.RemoveBreak(const AFileName: String; ALine: Cardinal): Boolean; @@ -630,9 +631,9 @@ begin FName := AValue; end; -function TDbgInstance.InitializeLoader: TDbgImageLoader; +procedure TDbgInstance.InitializeLoaders; begin - result := nil; + // Do nothing; end; { TDbgLibrary } diff --git a/components/fpdebug/fpdbgdarwinclasses.pas b/components/fpdebug/fpdbgdarwinclasses.pas index 9c0494c08e..954a718d57 100644 --- a/components/fpdebug/fpdbgdarwinclasses.pas +++ b/components/fpdebug/fpdbgdarwinclasses.pas @@ -134,7 +134,7 @@ type procedure OnForkEvent(Sender : TObject); {$endif} protected - function InitializeLoader: TDbgImageLoader; override; + procedure InitializeLoaders; override; function CreateThread(AthreadIdentifier: THandle; out IsMainThread: boolean): TDbgThread; override; function AnalyseDebugEvent(AThread: TDbgThread): TFPDEvent; override; public @@ -637,9 +637,34 @@ begin result := true; end; -function TDbgDarwinProcess.InitializeLoader: TDbgImageLoader; +procedure TDbgDarwinProcess.InitializeLoaders; +var + dSYMFilename: string; + ALoader: TDbgImageLoader; begin - result := TDbgImageLoader.Create(FExecutableFilename); + LoaderList.Add(TDbgImageLoader.Create(FExecutableFilename)); + + // JvdS: Mach-O binaries do not contain DWARF-debug info. Instead this info + // is stored inside the .o files, and the executable contains a map (in stabs- + // format) of all these .o files. An alternative to parsing this map and reading + // those .o files a dSYM-bundle could be used, which could be generated + // with dsymutil. + dSYMFilename:=ChangeFileExt(FExecutableFilename, '.dSYM'); + dSYMFilename:=dSYMFilename+'/Contents/Resources/DWARF/'+ExtractFileName(Name); + + if ExtractFileExt(dSYMFilename)='.app' then + dSYMFilename := ChangeFileExt(dSYMFilename,''); + + if FileExists(dSYMFilename) then + begin + ALoader := TDbgImageLoader.Create(dSYMFilename); + if GUIDToString(ALoader.UUID)<>GUIDToString(LoaderList[0].UUID) then + log('The unique UUID''s of the executable and the dSYM bundle with debug-info ('+dSYMFilename+') do not match. This can lead to problems during debugging.', dllInfo); + + LoaderList.Add(ALoader); + end + else + log('No dSYM bundle ('+dSYMFilename+') found.', dllInfo); end; function TDbgDarwinProcess.CreateThread(AthreadIdentifier: THandle; out IsMainThread: boolean): TDbgThread; @@ -670,42 +695,9 @@ begin end; procedure TDbgDarwinProcess.LoadInfo; -var - dSYMFilename: string; - ALoader: TDbgImageLoader; begin inherited LoadInfo; - // JvdS: Mach-O binaries do not contain DWARF-debug info. Instead this info - // is stored inside the .o files, and the executable contains a map (in stabs- - // format) of all these .o files. An alternative to parsing this map and reading - // those .o files a dSYM-bundle could be used, which could be generated - // with dsymutil. - dSYMFilename:=ChangeFileExt(Name, '.dSYM'); - dSYMFilename:=dSYMFilename+'/Contents/Resources/DWARF/'+ExtractFileName(Name); - - if ExtractFileExt(dSYMFilename)='.app' then - dSYMFilename := ChangeFileExt(dSYMFilename,''); - - if FileExists(dSYMFilename) then - begin - ALoader := TDbgImageLoader.Create(dSYMFilename); - if GUIDToString(ALoader.UUID)<>GUIDToString(Loader.UUID) then - log('The unique UUID''s of the executable and the dSYM bundle with debug-info ('+dSYMFilename+') do not match. This can lead to problems during debugging.', dllInfo); - FDbgInfo.Free; - Loader.Free; - Loader := ALoader; - FDbgInfo := TFpDwarfInfo.Create(Loader); - TFpDwarfInfo(FDbgInfo).LoadCompilationUnits; - - if FDbgInfo.HasInfo then - begin - if FSymInstances.IndexOf(Self)=-1 then - FSymInstances.Add(Self); - end; - end - else - log('No dSYM bundle ('+dSYMFilename+') found.', dllInfo); end; class function TDbgDarwinProcess.StartInstance(AFileName: string; AParams, AnEnvironment: TStrings; AWorkingDirectory, AConsoleTty: string; AOnLog: TOnLog; ReDirectOutput: boolean): TDbgProcess; diff --git a/components/fpdebug/fpdbgdwarfdataclasses.pas b/components/fpdebug/fpdbgdwarfdataclasses.pas index 36ed0df08e..5966f4be87 100644 --- a/components/fpdebug/fpdbgdwarfdataclasses.pas +++ b/components/fpdebug/fpdbgdwarfdataclasses.pas @@ -455,12 +455,26 @@ type end; {%endregion Base classes for handling Symbols in unit FPDbgDwarf} + TDwarfSectionInfo = record + Section: TDwarfSection; + VirtualAddress: QWord; + Size: QWord; // the virtual size + RawData: Pointer; + end; + PDwarfSectionInfo = ^TDwarfSectionInfo; + + TDwarfDebugFile = record + Sections: array[TDwarfSection] of TDwarfSectionInfo; + end; + PDwarfDebugFile = ^TDwarfDebugFile; + { TDwarfCompilationUnit } TDwarfCompilationUnitClass = class of TDwarfCompilationUnit; TDwarfCompilationUnit = class private FOwner: TFpDwarfInfo; + FDebugFile: PDwarfDebugFile; FDwarfSymbolClassMap: TFpDwarfSymbolClassMapClass; FValid: Boolean; // set if the compilationunit has compile unit tag. @@ -532,7 +546,7 @@ type function ReadValue(AAttribute: Pointer; AForm: Cardinal; out AValue: TByteDynArray): Boolean; public - constructor Create(AOwner: TFpDwarfInfo; ADataOffset: QWord; ALength: QWord; AVersion: Word; AAbbrevOffset: QWord; AAddressSize: Byte; AIsDwarf64: Boolean); virtual; + constructor Create(AOwner: TFpDwarfInfo; ADebugFile: PDwarfDebugFile; ADataOffset: QWord; ALength: QWord; AVersion: Word; AAbbrevOffset: QWord; AAddressSize: Byte; AIsDwarf64: Boolean); virtual; destructor Destroy; override; procedure ScanAllEntries; inline; function GetDefinition(AAbbrevPtr: Pointer; out ADefinition: TDwarfAbbrev): Boolean; inline; @@ -552,6 +566,7 @@ type property AddressSize: Byte read FAddressSize; // the address size of the target in bytes property IsDwarf64: Boolean read FIsDwarf64; // Set if the dwarf info in this unit is 64bit property Owner: TFpDwarfInfo read FOwner; + property DebugFile: PDwarfDebugFile read FDebugFile; property DwarfSymbolClassMap: TFpDwarfSymbolClassMapClass read FDwarfSymbolClassMap; property FirstScope: TDwarfScopeInfo read FScope; @@ -566,28 +581,19 @@ type { TFpDwarfInfo } - TDwarfSectionInfo = record - Section: TDwarfSection; - VirtualAddress: QWord; - Size: QWord; // the virtual size - RawData: Pointer; - end; - PDwarfSectionInfo = ^TDwarfSectionInfo; - TFpDwarfInfo = class(TDbgInfo) private FCompilationUnits: TList; FImageBase: QWord; FMemManager: TFpDbgMemManager; - FSections: array[TDwarfSection] of TDwarfSectionInfo; + FFiles: array of TDwarfDebugFile; function GetCompilationUnit(AIndex: Integer): TDwarfCompilationUnit; - function GetSections(AIndex: TDwarfSection): TDwarfSectionInfo; protected function GetCompilationUnitClass: TDwarfCompilationUnitClass; virtual; function FindCompilationUnitByOffs(AOffs: QWord): TDwarfCompilationUnit; function FindProcSymbol(AAddress: TDbgPtr): TDbgDwarfSymbolBase; public - constructor Create(ALoader: TDbgImageLoader); override; + constructor Create(ALoaderList: TDbgImageLoaderList); override; destructor Destroy; override; function FindContext(AThreadId, AStackFrame: Integer; AAddress: TDbgPtr = 0): TFpDbgInfoContext; override; function FindContext(AAddress: TDbgPtr): TFpDbgInfoContext; override; @@ -597,12 +603,10 @@ type function GetLineAddressMap(const AFileName: String): PDWarfLineMap; function LoadCompilationUnits: Integer; function PointerFromRVA(ARVA: QWord): Pointer; - function PointerFromVA(ASection: TDwarfSection; AVA: QWord): Pointer; function CompilationUnitsCount: Integer; property CompilationUnits[AIndex: Integer]: TDwarfCompilationUnit read GetCompilationUnit; property MemManager: TFpDbgMemManager read FMemManager write FMemManager; - property Sections [AIndex: TDwarfSection]: TDwarfSectionInfo read GetSections; property ImageBase: QWord read FImageBase; end; @@ -1406,7 +1410,6 @@ begin SetCapacity(AInfoLen div 16 + 1); {$Endif} SetLength(FDefinitions, 256); - //LoadAbbrevs(FOwner.PointerFromVA(dsAbbrev, FAbbrevOffset)); LoadAbbrevs(AnAbbrData + AnAbbrevOffset); {$IFnDEF USE_ABBREV_TMAP} Finish; @@ -2677,7 +2680,7 @@ begin Result := FCompUnit.ReadValue(InfoData, Form, Offs); if not Result then exit; - AValue := FCompUnit.FOwner.FSections[dsInfo].RawData + Offs; + AValue := FCompUnit.DebugFile^.Sections[dsInfo].RawData + Offs; if (AValue >= FCompUnit.FInfoData) and (AValue < FCompUnit.FInfoData + FCompUnit.FLength) then ACompUnit := FCompUnit else @@ -2803,22 +2806,28 @@ end; { TFpDwarfInfo } -constructor TFpDwarfInfo.Create(ALoader: TDbgImageLoader); +constructor TFpDwarfInfo.Create(ALoaderList: TDbgImageLoaderList); var Section: TDwarfSection; p: PDbgImageSection; + i: Integer; begin - inherited Create(ALoader); + inherited Create(ALoaderList); FCompilationUnits := TList.Create; - FImageBase := ALoader.ImageBase; - for Section := Low(Section) to High(Section) do + FImageBase := ALoaderList.ImageBase; + + SetLength(FFiles, ALoaderList.Count); + for i := 0 to ALoaderList.Count-1 do begin - p := ALoader.Section[DWARF_SECTION_NAME[Section]]; - if p = nil then Continue; - FSections[Section].Section := Section; - FSections[Section].RawData := p^.RawData; - FSections[Section].Size := p^.Size; - FSections[Section].VirtualAddress := p^.VirtualAddress; + for Section := Low(Section) to High(Section) do + begin + p := ALoaderList[i].Section[DWARF_SECTION_NAME[Section]]; + if p = nil then Continue; + FFiles[i].Sections[Section].Section := Section; + FFiles[i].Sections[Section].RawData := p^.RawData; + FFiles[i].Sections[Section].Size := p^.Size; + FFiles[i].Sections[Section].VirtualAddress := p^.VirtualAddress; + end; end; end; @@ -2862,11 +2871,6 @@ begin Result := TDwarfCompilationUnit(FCompilationUnits[Aindex]); end; -function TFpDwarfInfo.GetSections(AIndex: TDwarfSection): TDwarfSectionInfo; -begin - Result := FSections[AIndex]; -end; - function TFpDwarfInfo.GetCompilationUnitClass: TDwarfCompilationUnitClass; begin Result := TDwarfCompilationUnit; @@ -2878,10 +2882,10 @@ var p: Pointer; begin Result := nil; - p := FSections[dsInfo].RawData + AOffs; l := 0; h := FCompilationUnits.Count - 1; while h > l do begin + p := TDwarfCompilationUnit(FCompilationUnits[m]).DebugFile^.Sections[dsInfo].RawData + AOffs; m := (h + l + 1) div 2; if TDwarfCompilationUnit(FCompilationUnits[m]).FInfoData <= p then l := m @@ -2988,41 +2992,47 @@ var CU: TDwarfCompilationUnit; CUClass: TDwarfCompilationUnitClass; inf: TDwarfSectionInfo; + i: integer; begin CUClass := GetCompilationUnitClass; - inf := FSections[dsInfo]; - p := FSections[dsInfo].RawData; - pe := inf.RawData + inf.Size; - while (p <> nil) and (p < pe) do + for i := 0 to high(FFiles) do begin - if CU64^.Signature = DWARF_HEADER64_SIGNATURE - then begin - if CU64^.Version < 3 then - DebugLn(FPDBG_DWARF_WARNINGS, ['Unexpected 64 bit signature found for DWARF version 2']); // or version 1... - CU := CUClass.Create( - Self, - PtrUInt(CU64 + 1) - PtrUInt(FSections[dsInfo].RawData), - CU64^.Length - SizeOf(CU64^) + SizeOf(CU64^.Signature) + SizeOf(CU64^.Length), - CU64^.Version, - CU64^.AbbrevOffset, - CU64^.AddressSize, - True); - p := Pointer(@CU64^.Version) + CU64^.Length; - end - else begin - if CU32^.Length = 0 then Break; - CU := CUClass.Create( - Self, - PtrUInt(CU32 + 1) - PtrUInt(FSections[dsInfo].RawData), - CU32^.Length - SizeOf(CU32^) + SizeOf(CU32^.Length), - CU32^.Version, - CU32^.AbbrevOffset, - CU32^.AddressSize, - False); - p := Pointer(@CU32^.Version) + CU32^.Length; + inf := FFiles[i].Sections[dsInfo]; + p := inf.RawData; + pe := inf.RawData + inf.Size; + while (p <> nil) and (p < pe) do + begin + if CU64^.Signature = DWARF_HEADER64_SIGNATURE + then begin + if CU64^.Version < 3 then + DebugLn(FPDBG_DWARF_WARNINGS, ['Unexpected 64 bit signature found for DWARF version 2']); // or version 1... + CU := CUClass.Create( + Self, + @FFiles[i], + PtrUInt(CU64 + 1) - PtrUInt(inf.RawData), + CU64^.Length - SizeOf(CU64^) + SizeOf(CU64^.Signature) + SizeOf(CU64^.Length), + CU64^.Version, + CU64^.AbbrevOffset, + CU64^.AddressSize, + True); + p := Pointer(@CU64^.Version) + CU64^.Length; + end + else begin + if CU32^.Length = 0 then Break; + CU := CUClass.Create( + Self, + @FFiles[i], + PtrUInt(CU32 + 1) - PtrUInt(inf.RawData), + CU32^.Length - SizeOf(CU32^) + SizeOf(CU32^.Length), + CU32^.Version, + CU32^.AbbrevOffset, + CU32^.AddressSize, + False); + p := Pointer(@CU32^.Version) + CU32^.Length; + end; + FCompilationUnits.Add(CU); + if CU.Valid then SetHasInfo; end; - FCompilationUnits.Add(CU); - if CU.Valid then SetHasInfo; end; Result := FCompilationUnits.Count; end; @@ -3032,11 +3042,6 @@ begin Result := Pointer(PtrUInt(FImageBase + ARVA)); end; -function TFpDwarfInfo.PointerFromVA(ASection: TDwarfSection; AVA: QWord): Pointer; -begin - Result := FSections[ASection].RawData + AVA - FImageBase - FSections[ASection].VirtualAddress; -end; - function TFpDwarfInfo.CompilationUnitsCount: Integer; begin Result := FCompilationUnits.Count; @@ -3462,7 +3467,7 @@ begin FAddressMapBuild := True; end; -constructor TDwarfCompilationUnit.Create(AOwner: TFpDwarfInfo; ADataOffset: QWord; ALength: QWord; AVersion: Word; AAbbrevOffset: QWord; AAddressSize: Byte; AIsDwarf64: Boolean); +constructor TDwarfCompilationUnit.Create(AOwner: TFpDwarfInfo; ADebugFile: PDwarfDebugFile; ADataOffset: QWord; ALength: QWord; AVersion: Word; AAbbrevOffset: QWord; AAddressSize: Byte; AIsDwarf64: Boolean); procedure FillLineInfo(AData: Pointer); var LNP32: PDwarfLNPHeader32 absolute AData; @@ -3567,15 +3572,16 @@ begin //DebugLn(FPDBG_DWARF_VERBOSE, ['----------------------']); inherited Create; FOwner := AOwner; - FInfoData := FOwner.FSections[dsInfo].RawData + ADataOffset; + FDebugFile := ADebugFile; + FInfoData := ADebugFile^.Sections[dsInfo].RawData + ADataOffset; FLength := ALength; FVersion := AVersion; FAbbrevOffset := AAbbrevOffset; // check for address as offset - if FAbbrevOffset > FOwner.FSections[dsAbbrev].Size + if FAbbrevOffset > ADebugFile^.Sections[dsAbbrev].Size then begin - Offs := FAbbrevOffset - FOwner.FImageBase - FOwner.FSections[dsAbbrev].VirtualAddress; - if (Offs >= 0) and (Offs < FOwner.FSections[dsAbbrev].Size) + Offs := FAbbrevOffset - FOwner.FImageBase - ADebugFile^.Sections[dsAbbrev].VirtualAddress; + if (Offs >= 0) and (Offs < ADebugFile^.Sections[dsAbbrev].Size) then begin DebugLn(FPDBG_DWARF_WARNINGS, ['WARNING: Got Abbrev offset as address, adjusting..']); FAbbrevOffset := Offs; @@ -3585,8 +3591,8 @@ begin FAddressSize := AAddressSize; FIsDwarf64 := AIsDwarf64; - FAbbrevList := TDwarfAbbrevList.Create(FOwner.FSections[dsAbbrev].RawData, - FOwner.FSections[dsAbbrev].RawData + FOwner.FSections[dsAbbrev].Size, + FAbbrevList := TDwarfAbbrevList.Create(ADebugFile^.Sections[dsAbbrev].RawData, + ADebugFile^.Sections[dsAbbrev].RawData + ADebugFile^.Sections[dsAbbrev].Size, FAbbrevOffset, FLength); // use internally 64 bit target pointer @@ -3631,16 +3637,16 @@ begin and ReadValue(Attrib, Form, StatementListOffs) then begin // check for address as offset - if StatementListOffs < FOwner.FSections[dsLine].Size + if StatementListOffs < ADebugFile^.Sections[dsLine].Size then begin - FillLineInfo(FOwner.FSections[dsLine].RawData + StatementListOffs); + FillLineInfo(ADebugFile^.Sections[dsLine].RawData + StatementListOffs); end else begin - Offs := StatementListOffs - FOwner.FImageBase - FOwner.FSections[dsLine].VirtualAddress; - if (Offs >= 0) and (Offs < FOwner.FSections[dsLine].Size) + Offs := StatementListOffs - FOwner.FImageBase - ADebugFile^.Sections[dsLine].VirtualAddress; + if (Offs >= 0) and (Offs < ADebugFile^.Sections[dsLine].Size) then begin DebugLn(FPDBG_DWARF_WARNINGS, ['WARNING: Got Lineinfo offset as address, adjusting..']); - FillLineInfo(FOwner.FSections[dsLine].RawData + Offs); + FillLineInfo(ADebugFile^.Sections[dsLine].RawData + Offs); end; end; end; @@ -4097,7 +4103,7 @@ begin AValue := PChar(AAttribute); end; DW_FORM_strp: begin - AValue := pchar(PtrUInt(FOwner.Sections[dsStr].RawData)+PDWord(AAttribute)^); + AValue := pchar(PtrUInt(FDebugFile^.Sections[dsStr].RawData)+PDWord(AAttribute)^); end; else Result := False; @@ -4149,7 +4155,7 @@ begin AValue := PChar(AAttribute); end; DW_FORM_strp: begin - AValue := PChar(PtrUInt(FOwner.Sections[dsStr].RawData)+PDWord(AAttribute)^); + AValue := PChar(PtrUInt(FDebugFile^.Sections[dsStr].RawData)+PDWord(AAttribute)^); end; else Result := False; diff --git a/components/fpdebug/fpdbgdwarfverboseprinter.pas b/components/fpdebug/fpdbgdwarfverboseprinter.pas index 3d88b58a99..d4f40f7051 100644 --- a/components/fpdebug/fpdbgdwarfverboseprinter.pas +++ b/components/fpdebug/fpdbgdwarfverboseprinter.pas @@ -600,7 +600,7 @@ p := AData; DW_AT_type: begin DebugLn(FPDBG_DWARF_VERBOSE, ['-->']); try - p := FCU.Owner.Sections[dsInfo].RawData + Value - FCU.Owner.ImageBase - FCU.Owner.Sections[dsInfo].VirtualAddress; + p := FCU.DebugFile^.Sections[dsInfo].RawData + Value - FCU.Owner.ImageBase - FCU.DebugFile^.Sections[dsInfo].VirtualAddress; InternalDecode(p, p, Indent + ' '); except on E: Exception do DebugLn(FPDBG_DWARF_WARNINGS, [AIndent, ' ', E.Message]); @@ -642,7 +642,7 @@ begin DebugLn(FPDBG_DWARF_WARNINGS, ['No lineinfo']); Exit; end; - InternalDecode(AData, FCU.Owner.Sections[dsInfo].RawData + FCU.Owner.Sections[dsInfo].Size); + InternalDecode(AData, FCU.DebugFile^.Sections[dsInfo].RawData + FCU.DebugFile^.Sections[dsInfo].Size); end; procedure TDwarfStatementDecoder.InternalDecode(AData: Pointer; AMaxData: Pointer; const AIndent: String); diff --git a/components/fpdebug/fpdbginfo.pas b/components/fpdebug/fpdbginfo.pas index 76f8d0dcca..27c328deb4 100644 --- a/components/fpdebug/fpdbginfo.pas +++ b/components/fpdebug/fpdbginfo.pas @@ -474,7 +474,7 @@ type protected procedure SetHasInfo; public - constructor Create({%H-}ALoader: TDbgImageLoader); virtual; + constructor Create({%H-}ALoaderList: TDbgImageLoaderList); virtual; (* Context should be searched by Thread, and StackFrame. The Address can be derived from this. However a different Address may be froced. @@ -1352,7 +1352,7 @@ end; { TDbgInfo } -constructor TDbgInfo.Create(ALoader: TDbgImageLoader); +constructor TDbgInfo.Create(ALoaderList: TDbgImageLoaderList); begin inherited Create; end; diff --git a/components/fpdebug/fpdbglinuxclasses.pas b/components/fpdebug/fpdbglinuxclasses.pas index 2fe0a932de..eb5055b8dc 100644 --- a/components/fpdebug/fpdbglinuxclasses.pas +++ b/components/fpdebug/fpdbglinuxclasses.pas @@ -253,7 +253,7 @@ type procedure OnForkEvent(Sender : TObject); {$endif} protected - function InitializeLoader: TDbgImageLoader; override; + procedure InitializeLoaders; override; function CreateThread(AthreadIdentifier: THandle; out IsMainThread: boolean): TDbgThread; override; function AnalyseDebugEvent(AThread: TDbgThread): TFPDEvent; override; public @@ -555,9 +555,9 @@ end; { TDbgLinuxProcess } -function TDbgLinuxProcess.InitializeLoader: TDbgImageLoader; +procedure TDbgLinuxProcess.InitializeLoaders; begin - result := TDbgImageLoader.Create(Name); + LoaderList.Add(TDbgImageLoader.Create(Name)); end; function TDbgLinuxProcess.CreateThread(AthreadIdentifier: THandle; out IsMainThread: boolean): TDbgThread; diff --git a/components/fpdebug/fpdbgloader.pp b/components/fpdebug/fpdbgloader.pp index 750db7938a..0920f672f5 100644 --- a/components/fpdebug/fpdbgloader.pp +++ b/components/fpdebug/fpdbgloader.pp @@ -43,7 +43,7 @@ uses LCLType, FpImgReaderBase, FpImgReaderWinPE, FpImgReaderElf, FpImgReaderMacho, fpDbgSymTable, - Classes, SysUtils; + Classes, SysUtils, contnrs; type @@ -78,10 +78,54 @@ type property Section[const AName: String]: PDbgImageSection read GetSection; end; + { TDbgImageLoaderList } + TDbgImageLoaderList = class(TFPObjectList) + private + function GetImage64Bit: Boolean; + function GetImageBase: QWord; + function GetItem(Index: Integer): TDbgImageLoader; + procedure SetItem(Index: Integer; AValue: TDbgImageLoader); + public + property Items[Index: Integer]: TDbgImageLoader read GetItem write SetItem; default; + property ImageBase: QWord read GetImageBase; + Property Image64Bit: Boolean read GetImage64Bit; + end; implementation +{ TDbgImageLoaderList } + +function TDbgImageLoaderList.GetImage64Bit: Boolean; +begin + if Count<0 then + result := Items[0].Image64Bit + else + {$ifdef CPU64} + result := true + {$else} + result := false; + {$endif} +end; + +function TDbgImageLoaderList.GetImageBase: QWord; +begin + if Count<0 then + result := Items[0].ImageBase + else + result := 0; +end; + +function TDbgImageLoaderList.GetItem(Index: Integer): TDbgImageLoader; +begin + result := TDbgImageLoader(inherited GetItem(Index)); +end; + +procedure TDbgImageLoaderList.SetItem(Index: Integer; AValue: TDbgImageLoader); +begin + inherited SetItem(Index, AValue); +end; + { TDbgImageLoader } function TDbgImageLoader.GetImage64Bit: Boolean; diff --git a/components/fpdebug/fpdbgsymtablecontext.pas b/components/fpdebug/fpdbgsymtablecontext.pas index d63e7496a5..640392233d 100644 --- a/components/fpdebug/fpdbgsymtablecontext.pas +++ b/components/fpdebug/fpdbgsymtablecontext.pas @@ -42,7 +42,7 @@ type FContext: TFpSymbolContext; FImage64Bit: boolean; public - constructor Create(ALoader: TDbgImageLoader); override; + constructor Create(ALoaderList: TDbgImageLoaderList); override; destructor Destroy; override; function FindContext(AThreadId, AStackFrame: Integer; AAddress: TDbgPtr = 0): TFpDbgInfoContext; override; function FindContext(AAddress: TDbgPtr): TFpDbgInfoContext; override; @@ -104,15 +104,18 @@ end; { TFpSymbolInfo } -constructor TFpSymbolInfo.Create(ALoader: TDbgImageLoader); +constructor TFpSymbolInfo.Create(ALoaderList: TDbgImageLoaderList); +var + i: Integer; begin - inherited Create(ALoader); + inherited Create(ALoaderList); FContext := TFpSymbolContext.Create(self); FSymbolList := TfpSymbolList.Create; - ALoader.ParseSymbolTable(FSymbolList); - FImage64Bit := ALoader.Image64Bit; + for i := 0 to ALoaderList.Count-1 do + ALoaderList[i].ParseSymbolTable(FSymbolList); + FImage64Bit := ALoaderList.Image64Bit; end; destructor TFpSymbolInfo.Destroy; diff --git a/components/fpdebug/fpdbgwinclasses.pas b/components/fpdebug/fpdbgwinclasses.pas index bca3157d94..613d2265d5 100644 --- a/components/fpdebug/fpdbgwinclasses.pas +++ b/components/fpdebug/fpdbgwinclasses.pas @@ -93,7 +93,7 @@ type protected function GetHandle: THandle; override; function GetLastEventProcessIdentifier: THandle; override; - function InitializeLoader: TDbgImageLoader; override; + procedure InitializeLoaders; override; public destructor Destroy; override; @@ -131,7 +131,7 @@ type private FInfo: TLoadDLLDebugInfo; protected - function InitializeLoader: TDbgImageLoader; override; + procedure InitializeLoaders; override; public constructor Create(const AProcess: TDbgProcess; const ADefaultName: String; const AModuleHandle: THandle; const ABaseAddr: TDbgPtr; AInfo: TLoadDLLDebugInfo); @@ -245,9 +245,9 @@ end; { tDbgWinLibrary } -function tDbgWinLibrary.InitializeLoader: TDbgImageLoader; +procedure tDbgWinLibrary.InitializeLoaders; begin - result := TDbgImageLoader.Create(FInfo.hFile); + LoaderList.Add(TDbgImageLoader.Create(FInfo.hFile)); end; constructor tDbgWinLibrary.Create(const AProcess: TDbgProcess; @@ -278,9 +278,9 @@ begin Result:= MDebugEvent.LoadDll.hFile; end; -function TDbgWinProcess.InitializeLoader: TDbgImageLoader; +procedure TDbgWinProcess.InitializeLoaders; begin - result := TDbgImageLoader.Create(FInfo.hFile); + LoaderList.Add(TDbgImageLoader.Create(FInfo.hFile)); end; destructor TDbgWinProcess.Destroy;