"reg read -a" and x86 drN registers

Hi Ed/all,

I’m working on Linux remote debugging. I’m getting a failure in one of the TestRegisters.py tests.

It stems from the fact that the register context’s register list is longer than the number of registers covered by the union of all register sets (CPU/FPU/AVX). (lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64.h has the x86 debug registers listed)

For local debugging, registers are enumerated by set rather than index so we don’t see any of those registers.

For remote debugging, registers are enumerated by register index so those registers are sent over to the host. This behavior differs from debugserver.

I have a couple of options here

  1. I can remove the debug registers from RegisterInfos_x86_64.h. I’m inclined to do this but they seem be used by FreeBSD but I’m not sure why.

  2. I can add a check that the register index being queried is part of a valid register set. (See patch below)

  3. I might be able to make these registers readable/writeable on Linux but I think we’ll want to use them internally in LLDB (to implement watchpoints?) and not display them to users at all.

Thoughts?

Thanks,

Vince

GDBRemoteCommunicationServer::Handle_qRegisterInfo (StringExtractorGDBRemote &pa
// Ensure we have a thread.
NativeThreadProtocolSP thread_sp (m_debugged_process_sp->GetThreadAtIndex (0));
if (!thread_sp)
return SendErrorResponse (69);

// Get the register context for the first thread.
NativeRegisterContextSP reg_context_sp (thread_sp->GetRegisterContext ());
if (!reg_context_sp)
return SendErrorResponse (69);

// Parse out the register number from the request.
packet.SetFilePos (strlen(“qRegisterInfo”));
const uint32_t reg_index = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ());
if (reg_index == std::numeric_limits<uint32_t>::max ())
return SendErrorResponse (69);

// Return the end of registers response if we’ve iterated one past the end of the register set.
if (reg_index >= reg_context_sp->GetRegisterCount ())
return SendErrorResponse (69);

  • // Verify that the register index is part of a valid register set
  • const char* reg_set_name = reg_context_sp->GetRegisterSetNameForRegisterAtIndex(reg_index);
  • if (!reg_set_name)
  • {
  • return SendErrorResponse (69);
  • }

When running qRegisterInfo, there can be no gaps in the register numbering. There should be no need to do anything special in GDBRemoteCommunicationServer::Handle_qRegisterInfo(). The remote llgs should be correctly responding to the qRegisterInfo packet and if it is truthful then there should be no problem. It sounds like the bug is in llgs and it is sending back the wrong responses for qRegisterInfo. Can you elaborate on what is not correct in the qRegisterInfo packets? Maybe attach a log from "log enable -f /tmp/packets.txt gdb-remote packets" and I can tell you more.

Greg

Hi Greg,

It’s enumerating the debug registers, which is different than what debugserver does.

< 60> read packet: $name:dr0;bitsize:64;offset:848;encoding:uint;format:hex;#54 < 19> send packet: $qRegisterInfo87#b1 < 60> read packet: $name:dr1;bitsize:64;offset:856;encoding:uint;format:hex;#54 < 19> send packet: $qRegisterInfo88#b2 < 60> read packet: $name:dr2;bitsize:64;offset:864;encoding:uint;format:hex;#54 < 19> send packet: $qRegisterInfo89#b3 < 60> read packet: $name:dr3;bitsize:64;offset:872;encoding:uint;format:hex;#54 < 19> send packet: $qRegisterInfo8a#db < 60> read packet: $name:dr4;bitsize:64;offset:880;encoding:uint;format:hex;#54 < 19> send packet: $qRegisterInfo8b#dc < 60> read packet: $name:dr5;bitsize:64;offset:888;encoding:uint;format:hex;#5d < 19> send packet: $qRegisterInfo8c#dd < 60> read packet: $name:dr6;bitsize:64;offset:896;encoding:uint;format:hex;#5d < 19> send packet: $qRegisterInfo8d#de < 60> read packet: $name:dr7;bitsize:64;offset:904;encoding:uint;format:hex;#54 < 19> send packet: $qRegisterInfo8e#df < 7> read packet: $E45#ae

Later on, trying to read these registers returns an error

< 20> send packet: $p85;thread:71ec;#35

< 68> read packet: $0000000000000000000000000000000000000000000000000000000000000000#00

< 20> send packet: $p86;thread:71ec;#36

< 7> read packet: $E15#ab

< 20> send packet: $p87;thread:71ec;#37

< 7> read packet: $E15#ab

< 20> send packet: $p88;thread:71ec;#38

< 7> read packet: $E15#ab

< 20> send packet: $p89;thread:71ec;#39

< 7> read packet: $E15#ab

< 20> send packet: $p8a;thread:71ec;#61

< 7> read packet: $E15#ab

< 20> send packet: $p8b;thread:71ec;#62

< 7> read packet: $E15#ab

< 20> send packet: $p8c;thread:71ec;#63

< 7> read packet: $E15#ab

< 20> send packet: $p8d;thread:71ec;#64

< 7> read packet: $E15#ab

I can probably fix the register read (not sure) but should I? These will be used internally by LLDB for watchpoints, right?

There should be no need to do anything special in GDBRemoteCommunicationServer::Handle_qRegisterInfo()

Then the solution is to remove the debug registers from RegisterInfos_x86_64.h

If the debugserver doesn't want to vend the debug registers, then it shouldn't return them in response to the qRegisterInfo packet. If it does want to vend them, then the read/write of those registers must work so yes you should fix the read/write register packet in llgs.