diff --git a/components/fpdebug/fpdbgdwarfdataclasses.pas b/components/fpdebug/fpdbgdwarfdataclasses.pas index 0937b78ac3..5b4be5e8c4 100644 --- a/components/fpdebug/fpdbgdwarfdataclasses.pas +++ b/components/fpdebug/fpdbgdwarfdataclasses.pas @@ -3551,7 +3551,8 @@ function TDWarfLineMap.GetAddressesForLine(ALine: Cardinal; var AResultList: TDB NoData: Boolean; AFindSibling: TGetLineAddrFindSibling; AFoundLine: PInteger; AMaxSiblingDistance: integer; ACU: TDwarfCompilationUnit): Boolean; var - idx, offset, Addr1, Addr2: TDBGPtr; + idx: integer; + offset, Addr1, Addr2: TDBGPtr; LineOffsets: Array of Byte; Addresses: Array of TDBGPtr; o: Byte; @@ -3563,7 +3564,7 @@ begin offset := ALine mod 256; if idx >= Length(FLineIndexList) then begin if AFindSibling = fsBefore then begin - idx := Length(FLineIndexList); + idx := Length(FLineIndexList)-1; offset := 255; end else @@ -3606,7 +3607,15 @@ begin fsBefore: begin if i > 0 then begin dec(i); + CurOffs := CurOffs - o; offset := 0; // found line before + end + else begin + // i=0 => will trigger continue for outer loop + dec(idx); + if idx < 0 then + exit; + offset := 255; // Must be last entry from block before (if there is a block before) end; end; fsNext, fsNextFunc, fsNextFuncLazy: begin @@ -3625,7 +3634,19 @@ begin break; case AFindSibling of fsNone: exit; - else continue; + fsBefore: begin + if i = 0 then + continue; + assert(i=l, 'TDWarfLineMap.GetAddressesForLine: i=l'); + dec(i); + break; + end; + else begin + inc(idx); + if idx >= Length(FLineIndexList) then + exit; + continue; + end; end; until False; diff --git a/components/fpdebug/test/FpTest.lpi b/components/fpdebug/test/FpTest.lpi index b68b98ec19..9a452274f2 100644 --- a/components/fpdebug/test/FpTest.lpi +++ b/components/fpdebug/test/FpTest.lpi @@ -63,7 +63,7 @@ - + @@ -113,6 +113,11 @@ + + + + + diff --git a/components/fpdebug/test/FpTest.lpr b/components/fpdebug/test/FpTest.lpr index eba7c734e7..084e7d5439 100644 --- a/components/fpdebug/test/FpTest.lpr +++ b/components/fpdebug/test/FpTest.lpr @@ -5,7 +5,7 @@ program FpTest; uses Interfaces, Forms, GuiTestRunner, TestTypeInfo, TestHelperClasses, TestDwarfSetup1, TestDwarfSetupBasic, TestDwarfVarious, testdwarfsetupArray, TestMemManager, TestPascalParser, - TestErrorHandler; + TestErrorHandler, TestLineMap; {$R *.res} diff --git a/components/fpdebug/test/testlinemap.pas b/components/fpdebug/test/testlinemap.pas new file mode 100644 index 0000000000..e076b1f71a --- /dev/null +++ b/components/fpdebug/test/testlinemap.pas @@ -0,0 +1,181 @@ +unit TestLineMap; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, Math, FpDbgDwarfDataClasses, FpDbgInfo, DbgIntfBaseTypes, fpcunit, testutils, + testregistry; + +type + + { TTestLineMap } + + TTestLineMap = class(TTestCase) + private + LMap: TDWarfLineMap; + + procedure InitMap(l: array of integer); + procedure CheckNotFound(ASearch: Integer; AFindSibling: TGetLineAddrFindSibling; AMaxSiblingDistance: integer = 0); + procedure CheckFound(ASearch, AExp: Integer; AFindSibling: TGetLineAddrFindSibling; AMaxSiblingDistance: integer = 0); + published + procedure TestLineMapFsNone; + procedure TestLineMapFsBefore; + procedure TestLineMapFsNext; + end; + +implementation + +procedure TTestLineMap.InitMap(l: array of integer); +var + i: Integer; +begin + LMap := Default(TDWarfLineMap); + LMap.Init; + for i := 0 to Length(l) - 1 do + LMap.SetAddressForLine(l[i], l[i]); + LMap.Compress; +end; + +procedure TTestLineMap.CheckNotFound(ASearch: Integer; AFindSibling: TGetLineAddrFindSibling; + AMaxSiblingDistance: integer); +var + a: TDBGPtrArray; + r: Boolean; + fl: Integer; +begin + fl := -1; + r := LMap.GetAddressesForLine(ASearch, a, False, AFindSibling, @fl, AMaxSiblingDistance); + AssertFalse('not found '+IntToStr(ASearch), r); +end; + +procedure TTestLineMap.CheckFound(ASearch, AExp: Integer; AFindSibling: TGetLineAddrFindSibling; + AMaxSiblingDistance: integer); +var + a: TDBGPtrArray; + r: Boolean; + fl: Integer; +begin + fl := -1; + r := LMap.GetAddressesForLine(ASearch, a, False, AFindSibling, @fl, AMaxSiblingDistance); + AssertTrue('found '+IntToStr(ASearch), r); + AssertTrue('found (data) for '+IntToStr(ASearch), Length(a) = 1); + AssertEquals('found '+IntToStr(ASearch), AExp, fl); + AssertEquals('found (addr) '+IntToStr(ASearch), AExp, a[0]); +end; + +procedure TTestLineMap.TestLineMapFsNone; +begin + InitMap([10]); + + CheckFound(10, 10, fsNone); + CheckNotFound( 9, fsNone); + CheckNotFound(11, fsNone); + + InitMap([1000]); + CheckNotFound(1, fsNone); + CheckNotFound(99999, fsNone); + + + InitMap([10, 20]); + + CheckFound(10, 10, fsNone); + CheckFound(20, 20, fsNone); + CheckNotFound( 9, fsNone); + CheckNotFound(19, fsNone); + CheckNotFound(21, fsNone); + + InitMap([10, 2000]); + + CheckFound(10, 10, fsNone); + CheckFound(2000, 2000, fsNone); + CheckNotFound( 9, fsNone); + CheckNotFound(1999, fsNone); + CheckNotFound(2001, fsNone); +end; + +procedure TTestLineMap.TestLineMapFsBefore; +begin + InitMap([10]); + + CheckFound(10, 10, fsBefore); + CheckFound(11, 10, fsBefore); + CheckFound(19, 10, fsBefore); + CheckFound(19, 10, fsBefore, 9); + CheckNotFound(19, fsBefore, 8); + CheckNotFound( 9, fsBefore); + + InitMap([910, 920]); + + CheckFound(910, 910, fsBefore); + CheckFound(911, 910, fsBefore); + CheckFound(919, 910, fsBefore); + CheckFound(919, 910, fsBefore, 9); + CheckNotFound(919, fsBefore, 8); + + CheckFound(920, 920, fsBefore); + CheckFound(921, 920, fsBefore); + CheckFound(929, 920, fsBefore); + CheckFound(929, 920, fsBefore, 9); + CheckNotFound(929, fsBefore, 8); + + CheckFound(2920, 920, fsBefore); + CheckNotFound(909, fsBefore); + CheckNotFound(9, fsBefore); + + InitMap([511]); + CheckFound(2920, 511, fsBefore); + InitMap([512]); + CheckFound(2920, 512, fsBefore); + +end; + +procedure TTestLineMap.TestLineMapFsNext; +begin + InitMap([10]); + + CheckFound(10, 10, fsNext); + CheckFound( 9, 10, fsNext); + CheckFound( 1, 10, fsNext); + CheckFound( 1, 10, fsNext, 9); + CheckNotFound(11, fsNext, 8); + CheckNotFound(11, fsNext); + + InitMap([910, 920]); + + CheckFound(910, 910, fsNext); + CheckFound(909, 910, fsNext); + CheckFound(901, 910, fsNext); + CheckFound(901, 910, fsNext, 9); + CheckNotFound(901, fsNext, 8); + + CheckFound(920, 920, fsNext); + CheckFound(919, 920, fsNext); + CheckFound(911, 920, fsNext); + CheckFound(911, 920, fsNext, 9); + CheckNotFound(918, fsNext, 1); + CheckNotFound(911, fsNext, 8); + + CheckFound(1, 910, fsNext); + + CheckNotFound(921, fsNext); + CheckNotFound(1921, fsNext); + + InitMap([10, 2000]); + CheckFound(11, 2000, fsNext); + CheckFound(311, 2000, fsNext); + CheckNotFound(11, fsNext, 500); + + InitMap([255]); + CheckFound(11, 255, fsNext); + InitMap([256]); + CheckFound(11, 256, fsNext); +end; + + +initialization + + RegisterTest(TTestLineMap); +end. +