[fpc-devel] Overlapping addresses between 2 procedures in dwarf info / 3.2.0
Martin Frb
lazarus at mfriebe.de
Sat Dec 25 14:44:48 CET 2021
I am looking at some oddity I found following up
https://forum.lazarus.freepascal.org/index.php/topic,57568.0.html
Unfortunately, I have no code yet to reproduce it.
I have looked at the generated debug info, as given by objdump.
file format pei-x86-64
Compilation Unit @ offset 0x0:
Length: 0xa1 (32-bit)
Version: 2
Abbrev Offset: 0x0
Pointer Size: 8
<0><b>: Abbrev Number: 1 (DW_TAG_compile_unit)
<18> DW_AT_producer : Free Pascal 3.2.0 2021/02/21
The following part of the info looks wrong to me (original names replaced):
<1><cef4f>: Abbrev Number: 8 (DW_TAG_subprogram)
<cef50> DW_AT_name : FOO
<cef60> DW_AT_prototyped : 1
<cef61> DW_AT_calling_convention: 65 (user defined)
<cef62> DW_AT_external : 1
<cef63> DW_AT_low_pc : 0x10004a990
<cef6b> DW_AT_high_pc : 0x10004adc4 <<<<<<<<<<<<< NOTE THE
END ADDR
<1><cefa8>: Abbrev Number: 9 (DW_TAG_subprogram)
<cefa9> DW_AT_name : fin$000000B0
<cefb6> DW_AT_prototyped : 1
<cefb7> DW_AT_calling_convention: 65 (user defined)
<cefb8> DW_AT_low_pc : 0x10004a950
<cefc0> DW_AT_high_pc : 0x10004a988
<1><cefda>: Abbrev Number: 8 (DW_TAG_subprogram)
<cefdb> DW_AT_name : XYZ
<cefee> DW_AT_low_pc : 0x0 <<<<<<<<<<<<< code not included,
not used/called
<ceff6> DW_AT_high_pc : 0x0
<1><cf040>: Abbrev Number: 6 (DW_TAG_subprogram)
... Several other DW_TAG_subprogram, with address BEFORE FOO, and (as
far as I checked also line-numbers before FOO.
... I guess those are included here, because they did not get called
before, and the compiler adds the debug info only now ???
... Or could there be other reasons for the out-of-order inclusion???
<1><cf812>: Abbrev Number: 8 (DW_TAG_subprogram)
<cf813> DW_AT_name : BAR
<cf822> DW_AT_prototyped : 1
<cf823> DW_AT_calling_convention: 65 (user defined)
<cf824> DW_AT_external : 1
<cf825> DW_AT_low_pc : 0x10004adb0 <<<<<<<<<<<<< NOTE THE
START ADDR
<cf82d> DW_AT_high_pc : 0x10004ae26
BAR starts within FOO. That seems wrong? (also see the line info below)
From the code samples I received from the author, this is NOT a nested
proc.
This (and the line-info) leads to a crash of the app, when run under
gdb, as gdb adjusts the position of breakpoints, and ends setting it
into the middle of an asm instruction.
According to the author, the crash only happens if there are no calls to
XYZ. Otherwise the crash does not happen. I do not have info (yet), if
the overlapping addresses are present or not, if XYZ is used.
The inclusion/exclusion of XYZ triggers
https://gitlab.com/freepascal.org/fpc/source/-/issues/38117 which can
be seen in the line-info of this app too (i.e. line info contains none
relocated entries that compute to invalid addresses for those lines).
** The line-info of "FOO"
[0x00011cee] Extended opcode 2: set Address to 0x10004a990
[0x00011cf9] Set column to 1
[0x00011cfb] Advance Line by 2452 to 2453
[0x00011cfe] Copy
[0x00011cff] Advance PC by 37 to 0x10004a9b5
[0x00011d01] Copy
....
[0x00011d5b] Advance Line by -2 to 2453
[0x00011d5d] Copy
[0x00011d5e] Advance PC by 9 to 0x10004ad95
[0x00011d60] Special opcode 22: advance Address by 0 to 0x10004ad95
and Line by 23 to 2476
[0x00011d61] Extended opcode 2: set Address to 0x10004adc4
[0x00011d6c] Extended opcode 1: End of Sequence
It advances all the way to line 2476 / 0x10004ad95
Then it goes to address 0x10004adc4 (before "End of Sequence")
This is inside of "BAR".
** The line info shows that the next line (2484) is within the "not
included / not called" proc XYZ
[0x00011d6f] Extended opcode 2: set Address to 0x0
[0x00011d7a] Set column to 1
[0x00011d7c] Advance Line by 2483 to 2484
[0x00011d7f] Copy
[0x00011d80] Advance PC by 13 to 0xd
** The line-info of "BAR"
This continues from the line-info of XYZ (as seen by the none
relocated entries)
[0x00011db8] Special opcode 9: advance Address by 0 to 0x12c and
Line by 10 to 2500
....
[0x00011dc2] Special opcode 0: advance Address by 0 to 0x17c and
Line by 1 to 2504
[0x00011dc3] Advance PC by 80 to 0x1cc
[0x00011dc5] Set column to 1
[0x00011dc7] Special opcode 12: advance Address by 0 to 0x1cc and
Line by 13 to 2517
[0x00011dc8] Extended opcode 2: set Address to 0x0
[0x00011dd3] Extended opcode 1: End of Sequence
** BAR
[0x00011dd6] Extended opcode 2: set Address to 0x10004adb0
[0x00011de1] Set column to 1
[0x00011de3] Advance Line by 2521 to 2522
[0x00011de6] Copy
[0x00011de7] Advance PC by 21 to 0x10004adc5
[0x00011de9] Set column to 3
[0x00011deb] Special opcode 0: advance Address by 0 to 0x10004adc5
and Line by 1 to 2523
BAR starts at line 2522 (confirmed by the author).
The address 0x10004adb0 could be correct, as procs should afaik start
at 16 byte boundaries?
Line 2522 at 0x10004adb0 is an entry in the line info table, made by the
"copy" statement.
-----------------
So in conclusion something is wrong there.
As for the GDB crash (2500 is in the dead code, and gdb searches the
next line with code, which we know to be 2522 in BAR):
<info line "code1.pas":2500>
~"Line 2500 of \"code1.pas\" is at address 0x10004adb0 <FOO> but
contains no code.\n"
GDB found the line, after that I don't know what GDB did exactly
- line 2500 is in XYZ and gdb must have seen the address is not correct,
and ignored it.
- then probably it went to the last good line, and that is the "End of
Sequence"
=> which would explain "no code"
=> and explain the address found when setting the break
Setting a breakpoint:
<-break-insert "code1.pas:2500">
^done,bkpt={number="37",type="breakpoint",disp="keep",enabled="y",addr="0x000000010004adc4",func="FOO",file="code1.pas",line="2500",times="0",original-location="code1.pas:2500"}
The address 0x000000010004adc4 is indeed from the "End of Sequence" for
"BAR"
However, if that address is not in BAR (and if BAR ends long before),
then this is
- the address 1 byte before line 2523
- or the address $14 bytes into line 2522 (the last byte of asm code of
that line).
In that case, it is possible that this is not the start of an
asm-instruction, but in the middle of one, and then the app would crash,
after running the modified code (by having $CC somewhere in the operand
part of an asm instruction).
---------------
---------------
In any case, if the initial part of my analysis is correct then fpc
wrote incorrect address to the dwarf info (both the high/low_pc, and the
"End of Sequence").
Ideally we need a reproducible example.
But in order to get this, any idea what we are looking at, and therefore
how to strip the original code, so we can get such an example would be
helpful.
Any comments / ideas?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-devel/attachments/20211225/dee0cf9c/attachment.htm>
More information about the fpc-devel
mailing list