Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2022-06

CFI

3 messages · 2 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Joost van der Sluis

Hi all,

I'm working on FpDebug to add support for the Call Frame Information (CFI) which is part of the Dwarf specification. (Version 2 onwards)

This is a snippet of the information that the compiler typically generates: (x86_64-linux)

fde:
< 0><0x00401090:0x004010c1><JoJo><cie offset 0x00000000::cie index 0><fde offset 0x00000014 length: 0x00000024><eh offset none> 0x00401090: <off cfa=08(r7) > <off r16=-8(cfa) >
0x00401091: <off cfa=16(r7) > <off r3=-16(cfa) > <off r16=-8(cfa) >
0x004010c0: <off cfa=08(r7) > <off r16=-8(cfa) >

This basically means that when the instruction-pointer is at 0x00401090, the CFA (frame) can be obtained by taking register 7 (rsp) and add 8 to it. The return address (called r16 here) if obtained by taking the CFA, substract 8 and then read the value at that memory location.

So far so good. But then I need the next frame. So use the return address, substract one (To obtain the call address). And start over... but, the value of r7 is not available anymore.

But it seems like it that GDB has no problem with it.

This is what the Dwarf-5 specs say: (We/FPC always create CFI version 1 information, which corresponds with Dwarf-2, but the description in Dwarf-5 is easier to understand.)

"The default rule for all columns before interpretation of the initial instructions is the undefined rule. However, an ABI authoring body or a compilation system authoring body may specify an alternate default value for any or all columns."

'Undefined' means that the register is not available. So in principle we can not unwind the stack more the one level using the CFI provided by FreePascal. Unless.... there is some ABI rule that overrules the value of the r7 register.

Does anyone know if this is the case. And what are those ABI rules precisely, or should we add a column to the CFI information to describe r7?

Regards,

Joost.

Reply by email

Jonas Maebe
to Joost van der Sluis
Joost van der Sluis wrote 20 lines
This is a snippet of the information that the compiler typically generates: (x86_64-linux) fde: < 0><0x00401090:0x004010c1><JoJo><cie offset 0x00000000::cie index 0><fde offset 0x00000014 length: 0x00000024><eh offset none> 0x00401090: <off cfa=08(r7) > <off r16=-8(cfa) > 0x00401091: <off cfa=16(r7) > <off r3=-16(cfa) > <off r16=-8(cfa) > 0x004010c0: <off cfa=08(r7) > <off r16=-8(cfa) > This basically means that when the instruction-pointer is at 0x00401090, the CFA (frame) can be obtained by taking register 7 (rsp) and add 8 to it. The return address (called r16 here) if obtained by taking the CFA, substract 8 and then read the value at that memory location. So far so good. But then I need the next frame. So use the return address, substract one (To obtain the call address). And start over... but, the value of r7 is not available anymore.

The CFA (call frame address) is defined as "the value of %rsp at the call site in the previous frame" (*). So the value you calculated above in the first rule is the value of r7 in the previous frame and the call site address.

Jonas

(*)
https://gitlab.com/x86-psABIs/x86-64-ABI/-/jobs/2486914365/artifacts/download, definition of _Unwind_GetCFA

Reply by email

Joost van der Sluis
to Jonas Maebe

Op 07-06-2022 om 14:07 schreef Jonas Maebe via fpc-devel:

Show quoted text 27 lines
On 2022-06-07 11:09, Joost van der Sluis via fpc-devel wrote: > This is a snippet of the information that the compiler typically > generates: (x86_64-linux) > > fde: > <    0><0x00401090:0x004010c1><JoJo><cie offset 0x00000000::cie index > 0><fde offset 0x00000014 length: 0x00000024><eh offset none> >         0x00401090: <off cfa=08(r7) > <off r16=-8(cfa) > >         0x00401091: <off cfa=16(r7) > <off r3=-16(cfa) > <off > r16=-8(cfa) > >         0x004010c0: <off cfa=08(r7) > <off r16=-8(cfa) > > > This basically means that when the instruction-pointer is at > 0x00401090, the CFA (frame) can be obtained by taking register 7 (rsp) > and add 8 to it. > The return address (called r16 here) if obtained by taking the CFA, > substract 8 and then read the value at that memory location. > > So far so good. But then I need the next frame. So use the return > address, substract one (To obtain the call address). And start over... > but, the value of r7 is not available anymore. The CFA (call frame address) is defined as "the value of %rsp at the call site in the previous frame" (*). So the value you calculated above in the first rule is the value of r7 in the previous frame and the call site address.

Thanks, also for the link. Good to know that it is defined officially that way.

Regards,

Joost

Reply by email