Skip to content

lldb does not support "<vector>" and "<union>" when describing registers #87471

@DavidSpickett

Description

@DavidSpickett

This was reported to me by someone trying to debug SVE and SME code that switched streaming modes, using qemu-user. When in streaming mode they could not read the Z registers but they could in non-streaming mode. Qemu was returning valid data each time but lldb refused to display it in streaming mode.

The cause is a difference in how lldb-server and qemu describe the type of these registers. lldb-server describes them as:

<reg name="z31" bitsize="256" regnum="193" encoding="vector" format="vector-uint8" group="Scalable Vector Extension Registers" ehframe_regnum="127" dwarf_regnum="127" />

And this gets converted to eEncodingVector. We can see that lldb-server sets that in the source:

// Defines a Z vector register with 16-byte default size
#define DEFINE_ZREG(reg)                                                       \
  {                                                                            \
    #reg, nullptr, 16, 0, lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,   \
        SVE_REG_KIND(reg), nullptr, nullptr, nullptr,                          \
  }

This format lets us handle any amount of elements in the vector. So if you increase the vector length, no problem.

qemu on the other hand uses <vector> and <union> (see https://sourceware.org/gdb/current/onlinedocs/gdb.html/Target-Description-Format.html):

<vector id="svevqu" type="uint128" count="16"/>
<...>
</union><union id="svev">
  <field name="q" type="svevnq"/>
  <field name="d" type="svevnd"/>
  <field name="s" type="svevns"/>
  <field name="h" type="svevnh"/>
  <field name="b" type="svevnb"/>
</union>
<reg name="z0" bitsize="2048" regnum="34" type="svev"/>

lldb doesn't recognise the type svev and so defaults to unsigned int. That goes through

which only supports up to 128 bit numbers. So you can read the Z registers if the vector length is less than 128 bits (vg = 2) but as soon as it goes beyond that, lldb rejects the data.

The example I was given used streaming mode and set qemu's SVE/SME default vector lengths like:

-cpu max,sve-default-vector-length=16,sme-default-vector-length=64

But you can also reproduce by writing vg from within lldb register write vg 4.

We could add some arbitrary sized integer support (Scalar already stores the value using APSInt and APFloat). This would be the quick fix.

Long term we should support <vector> and <union> as they do have some advantages. <union> causes the debugger to display the vector in multiple ways, which can be useful for SVE where you don't know what type is in the register at a given point.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions