View Issue Details

IDProjectCategoryView StatusLast Update
0032240LazarusDebuggerpublic2021-02-12 13:49
ReporterChristo Crause Assigned ToMartin Friebe  
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
Platformx86_64OSLinux 
Product Version1.9 (SVN) 
Fixed in Version2.2 
Summary0032240: Continuous attempts to disassemble AVR target in Lazarus when stopped at break point
DescriptionWhen debugging AVR code via remote debugger (avr-gdb), recent gdb versions (7.1 - 8.0) cause an offset of 0x800000 to be added to the program memory location. This results in contents of the data memory to be disassembled. The debugger heuristics to disassemble the memory around the break point then fails because it doesn't get useful information back from gdb.
Steps To ReproduceRefer to Lazarus forum thread: http://forum.lazarus-ide.org/index.php/topic,37405.msg254652.html#msg254652
Additional InformationReport of gdb issue: https://sourceware.org/bugzilla/show_bug.cgi?id=13519

I suspect this will not be an issue for versions of gdb < 7.1

A patch has been submitted, but has been ignored for quite some time, so I suspect Lazarus users trying to debug remote AVR targets may encounter this issue if they have recent versions of gdb.
TagsAVR
Fixed in Revision 64545
LazTarget2.2
Widgetset
Attached Files

Relationships

related to 0034430 assignedMartin Friebe Assembler window is empty and "Cannot access memory at address <x>". 

Activities

Christo Crause

2017-08-04 22:15

reporter   ~0102064

A suggested work-around - perhaps the disassemble attempt should be aborted after a fixed number of tries. I cannot think of something that can be done from Lazarus's side to make the disassemble command work in avr-gd

Christo Crause

2021-01-10 11:31

reporter   ~0128238

I haven't encountered this particular bug for quite a while, I suggest this gets marked as "unable to reproduce" or "no change required" so that I can close this issue.

Martin Friebe

2021-01-10 12:10

manager   ~0128241

The related issue happens (afaik), if the IDE calculates an address in front of the exe memory.
Both issues therefore deal with invalid addresses.

The disassembling code needs a general overhaul. But this is currently lowest priority.
I want to keep both issues open, so that if/when I finally get to it, I know what to keep in mind.

Christo Crause

2021-02-05 21:48

reporter   ~0128789

So I stumbled back into this problem. There are a couple of places where addresses are calculated without range checking in the gdb disassembler code, resulting in negative addresses. The attached patch fixes this.
gdbdisassemble.patch (4,150 bytes)   
diff --git a/components/debuggerintf/dbgintfdebuggerbase.pp b/components/debuggerintf/dbgintfdebuggerbase.pp
index 97545fd170..ec3ab1d5da 100644
--- a/components/debuggerintf/dbgintfdebuggerbase.pp
+++ b/components/debuggerintf/dbgintfdebuggerbase.pp
@@ -2314,7 +2314,7 @@ function TDBGDisassemblerRangeExtender.DisassembleRange(ALinesBefore,
   ALinesAfter: integer; AStartAddr: TDBGPtr; AnEndAddr: TDBGPtr): boolean;
 var
   TryStartAt, TryEndAt: TDisassemblerAddress;
-  TmpAddr: TDBGPtr;
+  TmpAddr, TmpOffset: TDBGPtr;
   GotCnt, LastGotCnt: Integer;
   RngBefore, RngAfter: TDBGDisassemblerEntryRange;
 begin
@@ -2335,7 +2335,11 @@ begin
   and (TryStartAt.Value - RngBefore.EntriesPtr[RngBefore.Count - 1]^.Addr > ALinesBefore * DAssBytesPerCommandAvg)
   then RngBefore := nil;
   {$POP}
-  TmpAddr := AStartAddr - Min(ALinesBefore * DAssBytesPerCommandAvg, DAssMaxRangeSize);
+  TmpOffset := Min(ALinesBefore * DAssBytesPerCommandAvg, DAssMaxRangeSize);
+  if TmpOffset > AStartAddr then
+    TmpAddr := 0
+  else
+    TmpAddr := AStartAddr - TmpOffset;
   TryStartAt.GuessedValue := TmpAddr;
   AdjustToRangeOrKnowFunctionStart(TryStartAt, RngBefore);
   // check max size
@@ -2445,7 +2449,11 @@ begin
     end;
 
     TryEndAt := InitAddress(RngAfter.RangeStartAddr, avFoundRange);
-    TmpAddr := TryEndAt.Value - Min((ALinesBefore - GotCnt) * DAssBytesPerCommandAvg, DAssMaxRangeSize);
+    TmpOffset := Min((ALinesBefore - GotCnt) * DAssBytesPerCommandAvg, DAssMaxRangeSize);
+    if TryEndAt.Value > TmpOffset then
+      TmpAddr := TryEndAt.Value - TmpOffset
+    else
+      TmpAddr := 0;
     TryStartAt := InitAddress(TryEndAt.Value - 1, avGuessed);
     TryStartAt.GuessedValue := TmpAddr;
     // and adjust
diff --git a/components/lazdebuggergdbmi/gdbmidebugger.pp b/components/lazdebuggergdbmi/gdbmidebugger.pp
index 86f355df82..0d6baef40c 100644
--- a/components/lazdebuggergdbmi/gdbmidebugger.pp
+++ b/components/lazdebuggergdbmi/gdbmidebugger.pp
@@ -4493,7 +4493,10 @@ function TGDBMIDebuggerCommandDisassemble.DoExecute: Boolean;
   begin
     Result := False;
     // TODO: maybe try "info symbol <addr>
-    s := (AStartAddr.GuessedValue -1) div 4 * 4;  // 4 byte boundary
+    if AStartAddr.GuessedValue = 0 then
+      s := 0
+    else
+      s := (AStartAddr.GuessedValue -1) div 4 * 4;  // 4 byte boundary
     DisAssList := ExecDisassmble(s, s+1, False);
     if DisAssList.Count > 0 then begin
       DisAssItm := DisAssList.Item[0];
@@ -4786,7 +4789,7 @@ function TGDBMIDebuggerCommandDisassemble.DoExecute: Boolean;
     i, Cnt, DisAssStartIdx: Integer;
     NewRange: TDBGDisassemblerEntryRange;
     OrigLastAddress, OrigFirstAddress: TDisassemblerAddress;
-    TmpAddr: TDBGPtr;
+    TmpAddr, TmpOffset: TDBGPtr;
     BlockOk, SkipDisAssInFirstLoop, ContinueAfterSource: Boolean;
     Itm: TDisassemblerEntry;
   begin
@@ -4807,8 +4810,8 @@ function TGDBMIDebuggerCommandDisassemble.DoExecute: Boolean;
 
     // No nice startingpoint found, just start to disassemble aprox 5 instructions before it
     // and hope that when we started in the middle of an instruction it get sorted out.
-    // If so, the 4st for lines from the result must be discarded
-    if not (AFirstAddr.Validity in TrustedValidity)
+    // If so, the 4st four lines from the result must be discarded
+    if not (AFirstAddr.Validity in TrustedValidity) and (AFirstAddr.Value > 5 * DAssBytesPerCommandMax)
     then PadAddress(AFirstAddr, - 5 * DAssBytesPerCommandMax);
 
     // Adjust ALastAddr
@@ -4831,7 +4834,11 @@ function TGDBMIDebuggerCommandDisassemble.DoExecute: Boolean;
     // TODO: limit offset ONLY, if previous range known (already have disass)
     if (AFirstAddr.Offset >= 0)
     then begin
-      TmpAddr := AFirstAddr.Value - Min(AFirstAddr.Offset, DAssRangeOverFuncTreshold * DAssBytesPerCommandAvg);
+      TmpOffset := Min(AFirstAddr.Offset, DAssRangeOverFuncTreshold * DAssBytesPerCommandAvg);
+      if AFirstAddr.Value > TmpOffset then
+        TmpAddr := AFirstAddr.Value - TmpOffset
+      else
+        TmpAddr := 0;
       DisAssListWithSrc := ExecDisassmble(TmpAddr, ALastAddr.Value, True);
     end;
 
gdbdisassemble.patch (4,150 bytes)   

Martin Friebe

2021-02-12 00:29

manager   ~0128904

Applied the patch from 0032240:0128789 in rev 64545.

Does that solve the bug, or should it be kept open?

Christo Crause

2021-02-12 06:37

reporter   ~0128907

Testing with trunk r64547 and avr-gdb 8.3 does not show the bug in the description. It can be marked as fixed.

Christo Crause

2021-02-12 13:49

reporter   ~0128908

Thanks!

Issue History

Date Modified Username Field Change
2017-08-04 22:08 Christo Crause New Issue
2017-08-04 22:08 Christo Crause Status new => assigned
2017-08-04 22:08 Christo Crause Assigned To => Martin Friebe
2017-08-04 22:09 Christo Crause Tag Attached: AVR
2017-08-04 22:15 Christo Crause Note Added: 0102064
2021-01-10 11:31 Christo Crause Note Added: 0128238
2021-01-10 12:07 Martin Friebe Relationship added related to 0034430
2021-01-10 12:10 Martin Friebe Note Added: 0128241
2021-02-05 21:48 Christo Crause Note Added: 0128789
2021-02-05 21:48 Christo Crause File Added: gdbdisassemble.patch
2021-02-12 00:29 Martin Friebe Status assigned => feedback
2021-02-12 00:29 Martin Friebe LazTarget => -
2021-02-12 00:29 Martin Friebe Note Added: 0128904
2021-02-12 06:37 Christo Crause Note Added: 0128907
2021-02-12 06:37 Christo Crause Status feedback => assigned
2021-02-12 13:41 Martin Friebe Status assigned => resolved
2021-02-12 13:41 Martin Friebe Resolution open => fixed
2021-02-12 13:41 Martin Friebe Fixed in Version => 2.2
2021-02-12 13:41 Martin Friebe Fixed in Revision => 64545
2021-02-12 13:41 Martin Friebe LazTarget - => 2.2
2021-02-12 13:49 Christo Crause Status resolved => closed
2021-02-12 13:49 Christo Crause Note Added: 0128908