Re: Remote query for structure layout

David Blaikie via Gdb
2021-03-30T21:41:37Z

On Tue, Mar 30, 2021 at 2:33 PM Simon Marchi via Gdb <gdb@sourceware.org>
wrote:

> On 2021-03-30 4:35 p.m., Tim Newsome wrote:
> > On Sun, Mar 28, 2021 at 5:00 AM <gdb-request@sourceware.org> wrote:
> >
> >> I would like to propose a new command for the remote protocol that can
> be
> >> used to
> >> query structure layouts.
> >> Essentially a `qSymbol` equivalent for the output of `ptype`.
> >>
> >
> > I'm really interested in this. I've been working on OpenOCD FreeRTOS
> > support and as Thomas points out, it's a fragile mess.
> >
> > There's another use case that this would be great for. FreeRTOS stores
> > registers on the stack when it switches to another thread. OpenOCD needs
> to
> > know what this register layout is, and it also depends on compile time
> > options. With this mechanism I think it would be possible for FreeRTOS to
> > define a struct that represents how the registers are laid out on the
> > stack. E.g.:
> > struct register_stacking_t {
> > uint32_t x1;
> > uint32_t x2;
> > uint32_t x3;
> > uint32_t x4;
> > ...
> > uint32_t pc;
> > };
> >
> > Am I right that this will end up in the dwarf info even if the struct
> > itself isn't used anywhere in the FreeRTOS code? This would simplify so
> > much.
>
> It doesn't seem like it:
>
> $ cat test.cpp
> struct foo
> {
> int a;
> };
>
> int main() {
>
> }
> $ g++ test.cpp -g3 -O0
> $ llvm-dwarfdump -F -color a.out
> a.out: file format elf64-x86-64
>
> .debug_info contents:
> 0x00000000: Compile Unit: length = 0x00000053, format = DWARF32,
> version = 0x0004, abbr_offset = 0x0000, addr_size = 0x08 (next unit at
> 0x00000057)
>
> 0x0000000b: DW_TAG_compile_unit
> DW_AT_producer [DW_FORM_strp] ("GNU C++14 10.2.0
> -mtune=generic -march=x86-64 -g3 -O0")
> DW_AT_language [DW_FORM_data1] (DW_LANG_C_plus_plus)
> DW_AT_name [DW_FORM_strp] ("test.cpp")
> DW_AT_comp_dir [DW_FORM_strp]
> ("/home/simark/build/lttng-ust/doc/examples/easy-ust")
> DW_AT_low_pc [DW_FORM_addr] (0x0000000000001119)
> DW_AT_high_pc [DW_FORM_data8] (0x000000000000000b)
> DW_AT_stmt_list [DW_FORM_sec_offset] (0x00000000)
> DW_AT_GNU_macros [DW_FORM_sec_offset] (0x00000000)
>
> 0x00000031: DW_TAG_base_type
> DW_AT_byte_size [DW_FORM_data1] (0x04)
> DW_AT_encoding [DW_FORM_data1] (DW_ATE_signed)
> DW_AT_name [DW_FORM_string] ("int")
>
> 0x00000038: DW_TAG_subprogram
> DW_AT_external [DW_FORM_flag_present] (true)
> DW_AT_name [DW_FORM_strp] ("main")
> DW_AT_decl_file [DW_FORM_data1]
> ("/home/simark/build/lttng-ust/doc/examples/easy-ust/test.cpp")
> DW_AT_decl_line [DW_FORM_data1] (6)
> DW_AT_decl_column [DW_FORM_data1] (0x05)
> DW_AT_type [DW_FORM_ref4] (0x00000031 "int")
> DW_AT_low_pc [DW_FORM_addr] (0x0000000000001119)
> DW_AT_high_pc [DW_FORM_data8] (0x000000000000000b)
> DW_AT_frame_base [DW_FORM_exprloc]
> (DW_OP_call_frame_cfa)
> DW_AT_GNU_all_call_sites [DW_FORM_flag_present] (true)
>
> 0x00000056: NULL
>
> There might be some clever trick to force the compiler in emitting it
> though, but I suppose it will always be a bit fragile, dependent on the
> particular compiler.
>

Is the register layout in this struct part of the ABI? If so the debugger
could assume it/hardcode the knowledge.

If not, then it seems to me the right thing might be for the compiler to
have builtin support for emitting this struct under a reserved name into
every CU, perhaps? Not relying on source quirks to encourage it (as you
say, would leave you at the whims of the compiler implementation), but
actually make it explicitly part of compiler support for this architecture.