[Dwarf-Discuss] Location list entries for caller-saved registers at time of call
Hi! When GDB and LLDB perform virtual unwinding, they subtract one byte from the return addresses of the outer frames. This is for example necessary when unwinding from a non-returning call that is placed last in the function, as the return address then can point to a different function. I assume that this is also necessary to get the variables that were in scope at the time of the call, and the right location expressions for the variables, etc. As far as I have understood it, GCC utilizes this fact for location list entries that are expressed in caller-saved registers, by subtracting one from the (exclusive) ending address of the entries. This means that variables in outer frames that are located in caller- saved registers will be printed out as by GDB. I have not been able to find anything in the DWARF standard that describes this. Is this something that is defined by standard, or is it established praxis between GCC and GDB? If the latter, do you know of other producers and consumers that behave like this? The reason why I ask this is because Clang/LLVM at the moment ends location list entries expressed in caller-saved registers at the first instruction after the call. This means that variables in outer frames using such location list entries will incorrectly be evaluated using the inner-most frame's register values when debugging in GDB. (As a side note, as far as I have understood it, LLDB has fallback knowledge of the ABI, so caller-saved registers will be considered unavailable in outer frames, meaning that such location list entries are not an issue when combining Clang/LLVM and LLDB.) Best regards, David ___ Dwarf-Discuss mailing list Dwarf-Discuss@lists.dwarfstd.org http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org
Re: [Dwarf-Discuss] Location list entries for caller-saved registers at time of call
On tor, 2018-12-06 at 16:32 +0100, Andreas Arnez via Dwarf-Discuss wrote: > If GDB uses caller-saved register values from the inner-most frame in > outer frames, then this is a bug. Note that this could also be > caused > by bad CFI. Hmm, right. I'm not very familiar with the design philosophy of GDB, but as far as I have understood it they prefer to rely on producer to emit such information. In the LLVM bug report [0] I wrote for this I mentioned using DW_CFA_undefined for caller-saved registers, or at least for those that it knows are clobbered. Neither GCC nor Clang emits CFI for caller-saved registers at the moment. I have not been successful in finding out why, but my (uneducated) guess is that, maybe at least one of the reasons, is debug info size concerns? [0] https://bugs.llvm.org/show_bug.cgi?id=39752 Best regards, David ___ Dwarf-Discuss mailing list Dwarf-Discuss@lists.dwarfstd.org http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org
Re: [Dwarf-Discuss] Location list entries for caller-saved registers at time of call
On tor, 2018-12-06 at 17:47 -0800, Cary Coutant via Dwarf-Discuss wrote: > But we're getting sidetracked from the OP's question: Does GCC in > fact > subtract one from the upper bound of a location list entry for a > variable contained in a caller-saved register? I can think of no > reason why it should do this. If the compiled code does something > like > this: > > A: promote variable X into caller-save register R > ... > call f > B: ... > spill register R back to X > C: ... > > The location list entry for x should show it live in register R in > the > range [A..C). The call should not interrupt the range. > > It sounds like David has an example where the range list entry shows > x > in register R in the range [A..B-1), then presumably again for > [B..C), > leaving [B-1..B) uncovered. That would be a bug, in my opinion. > > David, can you show us an example? In the following example I used GCC 7.3.0, and compiled the below listed C code using `-O1 -gstrict-dwarf -gdwarf-5'. extern int get(); extern void set(int); int main() { int local = get(); set(local); local = 123; return local; } This produces the following location list for `local': 000c 000e 0014 (DW_OP_reg0 (rax)) 0011 0015 001f (DW_OP_const1u: 123; DW_OP_stack_value) 9: e8 00 00 00 00 callq e e: 89 c7 mov%eax,%edi 10: e8 00 00 00 00 callq 15 15: b8 7b 00 00 00 mov$0x7b,%eax As seen, there is a one-byte gap at the end of the call instruction to set(). As far as I have understood it, GCC emits a location list like this because it knows that the producer will subtract one from the return address when doing virtual unwinding. In this way, GDB will print the variable as "" when unwinding from set() to main(), even though it does not have knowledge of whether or not RAX is caller- saved. If we instead use Clang, there is no gap in the location list for the same code: [0x0008, 0x000f): DW_OP_reg0 RAX [0x000f, 0x0016): DW_OP_consts +123, DW_OP_stack_value) 3: e8 00 00 00 00 callq 8 8: 89 c7 mov%eax,%edi a: e8 00 00 00 00 callq f f: b8 7b 00 00 00 mov$0x7b,%eax When debugging the Clang-built binary in GDB, when unwinding from set() to main(), `local' will be evaluated using the value RAX has in set(), rather then being printed as "". Best regards, David ___ Dwarf-Discuss mailing list Dwarf-Discuss@lists.dwarfstd.org http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org
[Dwarf-Discuss] Use of Location Description operations in DWARF Expressions?
Hi! This is something that has popped up in a number of LLVM patch reviews, and is something that we would like to get some help with clarifying. For DWARF[345], may a DWARF Expression (described in section 2.5) contain any of the operations listed under the Location Descriptions section (2.6)? For example, may a DW_AT_call_value in DWARF5, which "is a DWARF expression", contain any of those operations (e.g. a DW_OP_piece)? DWARF5 section 2.5 specifies the following for the operations under section 2.6: "In addition to the general operations that are defined here, operations that are specific to location descriptions are defined in Section 2.6 on page 38." Reading section 2.5 and 2.6, I have interpreted the standard as if DWARF Expressions and Location Descriptions are disparate things; Location Descriptions may describe locations _using_ DWARF Expressions, but in places where a DWARF Expression is expected, you may not have a Location Description in its place. Is that correct? Given the above quote, and if my interpretation of how DWARF Expressions and Location Descriptions correlate is correct, I would assume that the answer to this mail's initial question is no. Or am I overlooking somethere here? Best regards, David ___ Dwarf-Discuss mailing list Dwarf-Discuss@lists.dwarfstd.org http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org
[Dwarf-discuss] Multiple inlined subroutines for a VLIW instruction bundle?
Hi! Is it possible to encode different backtrace information, including inlining, for two different instructions in a VLIW bundle? I'll probably use inprecise and non-standard wording below. Sorry if that is the case. Assume that the following C program: foo.h: static inline void foo_inl_inner() { __builtin_insn1(); // line 2 } static inline void foo_inl_outer() { foo_inl_inner(); // line 6 } bar.h: static inline void bar_inl() { __builtin_insn2(); // line 10 } main.c: int main() { foo_inl_outer(); // line 2 bar_inl(); // line 3 } where __builtin_#X corresponds to a hardware instruction #X, is compiled for a VLIW architecture. We may then end up with an VLIW instruction bundle where insn1 and insn2 are bundled together: { insn1 # foo.h:2 insn2 # bar.h:10 } We are able to describe the locations for the two operations in the instruction bundle by using the op_index register in the line number program, for example something like this: AddressLine Column File ISA Discriminator OpIndex Flags -- -- -- -- --- - --- 0x 2 2 2 0 0 0 is_stmt 0x 10 2 3 0 0 1 is_stmt [...] For our proprietary VLIW architecture we have debugging and profiling tools that are able to indicate which operations in a VLIW bundle that are of interest, and we would like to query the line information about those specific operations. If we do not care about inline subroutines, the use of the op_index register in the line number program is sufficient for us to query line and file for the different operations, for example: $ debug-tool --no-inlines [PC=...] [op-index=0] foo.h:2 $ debug-tool --no-inlines [PC=...] [op-index=0] bar.h:10 However, we would also want to be able to query information about the two call chains, showing the inlined subroutines, making it easier for our users to understand from where the operations originate from. For example: $ debug-tool --inlines [PC=...] [op-index=0] foo_inl_inner[foo.h:2] inlined @ foo_inl_outer[foo.h:6] inlined @ main[main.c:2] $ debug-tool --inlines [PC=...] [op-index=1] bar_inl[bar.h:10] inlined @ main[main.c:3] If I understand correctly, we would somehow need to encode that information in the "Subroutine and Entry Point Entries" debug information. Would a DWARF producer be allowed to emit DW_TAG_subprogram and concrete DW_TAG_inlined_subroutines entries that describe those two different call chains for the addresses of that single instruction bundle? For example, something like this: DW_TAG_subprogram DW_AT_name "main" DW_AT_low_pc 0x0 DW_AT_high_pc 0x2 DW_TAG_inlined_subroutine DW_AT_abstract_origin "foo_inl_outer" DW_AT_low_pc 0x0 DW_AT_high_pc 0x2 DW_TAG_inlined_subroutine DW_AT_abstract_origin "foo_inl_inner" DW_AT_low_pc 0x0 DW_AT_high_pc 0x2 DW_TAG_inlined_subroutine DW_AT_abstract_origin "bar_inl" DW_AT_low_pc 0x0 DW_AT_high_pc 0x2 If that is the case, I do not find anything in the standard that would help us connect the op_index values to those inlined subroutines. Is that correct? Or are there any other way that we could or should model information about inline subroutines for such VLIW instruction bundles? The above questions concern how to handle VLIW debug information with DWARFv5, but I think they may be relevant for non-VLIW architectures with the Location View Numbering information suggested for DWARFv6 [1], as you may encounter similar situations when merging instructions coming from different inlined subroutines. Best regards, David [1] https://dwarfstd.org/issues/170427.1.html -- Dwarf-discuss mailing list Dwarf-discuss@lists.dwarfstd.org https://lists.dwarfstd.org/mailman/listinfo/dwarf-discuss
Re: [Dwarf-discuss] Multiple inlined subroutines for a VLIW instruction bundle?
On Thu, 2024-10-17 at 12:30 +, John DelSignore wrote: > > Hi, > > I think the best way to encode the information depends on details of > the processor architecture. Hi John, Thanks for the reply, and it's interesting to hear about that Itanium case! The scheme that you describe below seems well-suited for such architectures with fixed-sized, aligned bundles. Unfortunately, for this particular architecture the distance between consecutive bundles is not constant, so it is not possible to tell where bundles start or end just by looking at the address. > The IA-64 (Intel Itanium architecture) had a VLIW instruction > encoding with a 128-bit instruction bundle consisting of three 41-bit > instruction slots per bundle plus a 5-bit template indicating the > type of instruction in each slot. Memory was 8-bit byte addressable, > and an instruction address was encoded as a 128-bit (16-byte) aligned > bundle address plus a bundle index. So, if the bundle was at address > 0x56780, the second instruction in the bundle was encoded as 0x56781. > It's been a long time since I have worked on an IA-64 systems, but I > believe this convention was used by both the processor and in the > DWARF. Of course our debugger needed to be modified to handle these > conventions, but it didn't require anything special the DWARF because > the bundle address+index convention carried through to all DWARF > addresses. A benefit with use of op_index for this architecture is that consumers can easily retrieve all locations that belong to a bundle by traversing the line table rows until the address changes. To achieve the same for this architecture when using the bundle-start-address + offset scheme, it would then seem like we would need to either somehow encode where bundles start or end in the debug information (using some sort of extension?), or let the consumer (or its user) figure out where bundle boundaries are by looking at disassembled binary output or some side table containing that information. If we wish to keep modeling with op_index, and it is not possible to represent multiple call chains for the same address in the "Subroutine and Entry Point Entries" debug information, I guess we need to either find a common shared scope for all the instructions in a bundle, or use some heuristic that picks the "most relevant" call chain from the different instructions in the bundle. It would be interesting to understand how other producers using op_index for a VLIW architecture or producers emitting the Location View Numbering information for a non-VLIW architecture have handled that. > Cheers, John D. Best regards, David -- Dwarf-discuss mailing list Dwarf-discuss@lists.dwarfstd.org https://lists.dwarfstd.org/mailman/listinfo/dwarf-discuss