LLDB using Valgrind's embedded gdbserver

Hello,

I am working on enhancing Valgrind’s embedded gdbserver to allow LLDB to use it (https://bugs.kde.org/show_bug.cgi?id=356174 ). After adding support for ‘qC’ packets to the embedded gdbserver, LLDB is able to continue the halted program running under Valgrind; however, a short moment later LLDB crashes.

I am using OS X 10.11.1 (15B42) and lldb-340.4.110.1.

The location of the segmentation fault is ABISysV_x86_64::GetArgumentValues(lldb_private::Thread&, lldb_private::ValueList&) const + 147:

The issue is LLDB wants to know information in the registers in the register context regarding how they map to "generic" registers. For x86_64 this means:

LLDB_REGNUM_GENERIC_PC -> rip
LLDB_REGNUM_GENERIC_SP -> rsp
LLDB_REGNUM_GENERIC_FP -> rbp
LLDB_REGNUM_GENERIC_RA -> <none for x86>
LLDB_REGNUM_GENERIC_FLAGS -> rflags
LLDB_REGNUM_GENERIC_ARG1 -> rdi
LLDB_REGNUM_GENERIC_ARG2 -> rsi
LLDB_REGNUM_GENERIC_ARG3 -> rdx
LLDB_REGNUM_GENERIC_ARG4 -> rcx
LLDB_REGNUM_GENERIC_ARG5 -> r8
LLDB_REGNUM_GENERIC_ARG6 -> r9

We also want to know what DWARF register number each register has, what compiler register number (for EH frame) each register is, and more.

There are two ways to do this:

1 - if you want to change the LLDB code
2 - if you want to make this work by only modifying valgrind's GDB server

If you go with option 1, it looks like the bug here is in:

static void
AugmentRegisterInfoViaABI (RegisterInfo &reg_info, ConstString reg_name, ABISP abi_sp)

It grabs the register info from the ABI and fills it in, but it wasn't filling in the generic register number. I just fixed this with:

r254743 | gclayton | 2015-12-04 10:37:48 -0800 (Fri, 04 Dec 2015) | 1 line

Fill in the generic register kind if in AugmentRegisterInfoViaABI if it is available.

So if you update your sources, it might start working.

If you don't want the change LLDB, you can make the XML returned for the registers contain extra attributes to specify these things. If you check the code in ProcessGDBRemote.cpp around line 4327:

bool
ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemoteDynamicRegisterInfo &dyn_reg_info, ABISP abi_sp)

You can see the extra attributes a "reg" element node can contain.

We extended the XML to include keys that LLDB can use. The assert that is causing the crash is the fact that we are asking a register context for the "generic" register that is "arg1". If you can modify the XML that is returned to mark up the registers so the generic name is attached to each register, it will help out LLDB. "debugserver" actually used this modified XML, so to see what it would look like with all of the new things we added you can copy what you need from the XML below. But lets look at the definition for "rip" alone:

  <reg name="rip" regnum="16" offset="128" bitsize="64" group="general" altname="pc" group_id="1" gcc_regnum="16" dwarf_regnum="16" generic="pc"/>

Note we specify regnum (the lldb register number), offset (the byte offset for this register in the register context), altname, group_id (the register group this should appear in, see the "groups" at the end of the XML to see the register set names), gcc_regnum which is the compiler register number, dwarf_regnum, and the generic register name ("pc", "sp", "fp", "arg1", "arg2", etc).

So our full XML which specifies the compiler register numbers, DWARF register numbers and generic register names looks like:

l<?xml version="1.0"?>
<target version="1.0">
<feature name="com.apple.debugserver.x86_64">
  <reg name="rax" regnum="0" offset="0" bitsize="64" group="general" group_id="1" gcc_regnum="0" dwarf_regnum="0"/>
  <reg name="rbx" regnum="1" offset="8" bitsize="64" group="general" group_id="1" gcc_regnum="3" dwarf_regnum="3"/>
  <reg name="rcx" regnum="2" offset="16" bitsize="64" group="general" altname="arg4" group_id="1" gcc_regnum="2" dwarf_regnum="2" generic="arg4"/>
  <reg name="rdx" regnum="3" offset="24" bitsize="64" group="general" altname="arg3" group_id="1" gcc_regnum="1" dwarf_regnum="1" generic="arg3"/>
  <reg name="rdi" regnum="4" offset="32" bitsize="64" group="general" altname="arg1" group_id="1" gcc_regnum="5" dwarf_regnum="5" generic="arg1"/>
  <reg name="rsi" regnum="5" offset="40" bitsize="64" group="general" altname="arg2" group_id="1" gcc_regnum="4" dwarf_regnum="4" generic="arg2"/>
  <reg name="rbp" regnum="6" offset="48" bitsize="64" group="general" altname="fp" group_id="1" gcc_regnum="6" dwarf_regnum="6" generic="fp"/>
  <reg name="rsp" regnum="7" offset="56" bitsize="64" group="general" altname="sp" group_id="1" gcc_regnum="7" dwarf_regnum="7" generic="sp"/>
  <reg name="r8" regnum="8" offset="64" bitsize="64" group="general" altname="arg5" group_id="1" gcc_regnum="8" dwarf_regnum="8" generic="arg5"/>
  <reg name="r9" regnum="9" offset="72" bitsize="64" group="general" altname="arg6" group_id="1" gcc_regnum="9" dwarf_regnum="9" generic="arg6"/>
  <reg name="r10" regnum="10" offset="80" bitsize="64" group="general" group_id="1" gcc_regnum="10" dwarf_regnum="10"/>
  <reg name="r11" regnum="11" offset="88" bitsize="64" group="general" group_id="1" gcc_regnum="11" dwarf_regnum="11"/>
  <reg name="r12" regnum="12" offset="96" bitsize="64" group="general" group_id="1" gcc_regnum="12" dwarf_regnum="12"/>
  <reg name="r13" regnum="13" offset="104" bitsize="64" group="general" group_id="1" gcc_regnum="13" dwarf_regnum="13"/>
  <reg name="r14" regnum="14" offset="112" bitsize="64" group="general" group_id="1" gcc_regnum="14" dwarf_regnum="14"/>
  <reg name="r15" regnum="15" offset="120" bitsize="64" group="general" group_id="1" gcc_regnum="15" dwarf_regnum="15"/>
  <reg name="rip" regnum="16" offset="128" bitsize="64" group="general" altname="pc" group_id="1" gcc_regnum="16" dwarf_regnum="16" generic="pc"/>
  <reg name="rflags" regnum="17" offset="136" bitsize="64" group="general" altname="flags" group_id="1" generic="flags"/>
  <reg name="cs" regnum="18" offset="144" bitsize="64" group="general" group_id="1"/>
  <reg name="fs" regnum="19" offset="152" bitsize="64" group="general" group_id="1"/>
  <reg name="gs" regnum="20" offset="160" bitsize="64" group="general" group_id="1"/>
  <reg name="fctrl" regnum="73" offset="168" bitsize="16" group="general" group_id="2"/>
  <reg name="fstat" regnum="74" offset="170" bitsize="16" group="general" group_id="2"/>
  <reg name="ftag" regnum="75" offset="172" bitsize="8" group="general" group_id="2"/>
  <reg name="fop" regnum="76" offset="173" bitsize="16" group="general" group_id="2"/>
  <reg name="fioff" regnum="77" offset="175" bitsize="32" group="general" group_id="2"/>
  <reg name="fiseg" regnum="78" offset="179" bitsize="16" group="general" group_id="2"/>
  <reg name="fooff" regnum="79" offset="181" bitsize="32" group="general" group_id="2"/>
  <reg name="foseg" regnum="80" offset="185" bitsize="16" group="general" group_id="2"/>
  <reg name="mxcsr" regnum="81" offset="187" bitsize="32" group="general" group_id="2"/>
  <reg name="mxcsrmask" regnum="82" offset="191" bitsize="32" group="general" group_id="2"/>
  <reg name="stmm0" regnum="83" offset="195" bitsize="80" group="vector" type="float" encoding="vector" format="vector-uint8" group_id="2" gcc_regnum="33" dwarf_regnum="33"/>
  <reg name="stmm1" regnum="84" offset="205" bitsize="80" group="vector" type="float" encoding="vector" format="vector-uint8" group_id="2" gcc_regnum="34" dwarf_regnum="34"/>
  <reg name="stmm2" regnum="85" offset="215" bitsize="80" group="vector" type="float" encoding="vector" format="vector-uint8" group_id="2" gcc_regnum="35" dwarf_regnum="35"/>
  <reg name="stmm3" regnum="86" offset="225" bitsize="80" group="vector" type="float" encoding="vector" format="vector-uint8" group_id="2" gcc_regnum="36" dwarf_regnum="36"/>
  <reg name="stmm4" regnum="87" offset="235" bitsize="80" group="vector" type="float" encoding="vector" format="vector-uint8" group_id="2" gcc_regnum="37" dwarf_regnum="37"/>
  <reg name="stmm5" regnum="88" offset="245" bitsize="80" group="vector" type="float" encoding="vector" format="vector-uint8" group_id="2" gcc_regnum="38" dwarf_regnum="38"/>
  <reg name="stmm6" regnum="89" offset="255" bitsize="80" group="vector" type="float" encoding="vector" format="vector-uint8" group_id="2" gcc_regnum="39" dwarf_regnum="39"/>
  <reg name="stmm7" regnum="90" offset="265" bitsize="80" group="vector" type="float" encoding="vector" format="vector-uint8" group_id="2" gcc_regnum="40" dwarf_regnum="40"/>
  <reg name="ymm0" regnum="91" offset="275" bitsize="256" group="vector" type="float" encoding="vector" format="vector-uint8" group_id="2" gcc_regnum="17" dwarf_regnum="17"/>
  <reg name="ymm1" regnum="92" offset="307" bitsize="256" group="vector" type="float" encoding="vector" format="vector-uint8" group_id="2" gcc_regnum="18" dwarf_regnum="18"/>
  <reg name="ymm2" regnum="93" offset="339" bitsize="256" group="vector" type="float" encoding="vector" format="vector-uint8" group_id="2" gcc_regnum="19" dwarf_regnum="19"/>
  <reg name="ymm3" regnum="94" offset="371" bitsize="256" group="vector" type="float" encoding="vector" format="vector-uint8" group_id="2" gcc_regnum="20" dwarf_regnum="20"/>
  <reg name="ymm4" regnum="95" offset="403" bitsize="256" group="vector" type="float" encoding="vector" format="vector-uint8" group_id="2" gcc_regnum="21" dwarf_regnum="21"/>
  <reg name="ymm5" regnum="96" offset="435" bitsize="256" group="vector" type="float" encoding="vector" format="vector-uint8" group_id="2" gcc_regnum="22" dwarf_regnum="22"/>
  <reg name="ymm6" regnum="97" offset="467" bitsize="256" group="vector" type="float" encoding="vector" format="vector-uint8" group_id="2" gcc_regnum="23" dwarf_regnum="23"/>
  <reg name="ymm7" regnum="98" offset="499" bitsize="256" group="vector" type="float" encoding="vector" format="vector-uint8" group_id="2" gcc_regnum="24" dwarf_regnum="24"/>
  <reg name="ymm8" regnum="99" offset="531" bitsize="256" group="vector" type="float" encoding="vector" format="vector-uint8" group_id="2" gcc_regnum="25" dwarf_regnum="25"/>
  <reg name="ymm9" regnum="100" offset="563" bitsize="256" group="vector" type="float" encoding="vector" format="vector-uint8" group_id="2" gcc_regnum="26" dwarf_regnum="26"/>
  <reg name="ymm10" regnum="101" offset="595" bitsize="256" group="vector" type="float" encoding="vector" format="vector-uint8" group_id="2" gcc_regnum="27" dwarf_regnum="27"/>
  <reg name="ymm11" regnum="102" offset="627" bitsize="256" group="vector" type="float" encoding="vector" format="vector-uint8" group_id="2" gcc_regnum="28" dwarf_regnum="28"/>
  <reg name="ymm12" regnum="103" offset="659" bitsize="256" group="vector" type="float" encoding="vector" format="vector-uint8" group_id="2" gcc_regnum="29" dwarf_regnum="29"/>
  <reg name="ymm13" regnum="104" offset="691" bitsize="256" group="vector" type="float" encoding="vector" format="vector-uint8" group_id="2" gcc_regnum="30" dwarf_regnum="30"/>
  <reg name="ymm14" regnum="105" offset="723" bitsize="256" group="vector" type="float" encoding="vector" format="vector-uint8" group_id="2" gcc_regnum="31" dwarf_regnum="31"/>
  <reg name="ymm15" regnum="106" offset="755" bitsize="256" group="vector" type="float" encoding="vector" format="vector-uint8" group_id="2" gcc_regnum="32" dwarf_regnum="32"/>
  <reg name="trapno" regnum="123" offset="787" bitsize="32" group="general" group_id="3"/>
  <reg name="err" regnum="124" offset="791" bitsize="32" group="general" group_id="3"/>
  <reg name="faultvaddr" regnum="125" offset="795" bitsize="64" group="general" group_id="3"/>
</feature>
<groups>
  <group id="1" name="General Purpose Registers"/>
  <group id="2" name="Floating Point Registers"/>
  <group id="3" name="Exception State Registers"/>
</groups>
</target>

So if you get the generic register numbers fixed, you should probably not be crashing anymore.

Greg Clayton

Hello Greg,

Thank you very much for this explanation. It makes perfect sense to me now the reason for the crash at ABISysV_x86_64.cpp:485, and that supplying the generic register information will solve the problem.

Testing out the following, the crash no longer occurs:

Daniel Trebbien