Skip to content

Commit ad5cac3

Browse files
authored
[lldb][debugserver] remove g/G packet handling from debugserver (#132127)
In 2013 we added the QSaveRegisterState and QRestoreRegisterState packets to checkpoint a thread's register state while executing an inferior function call, instead of using the g packet to read all registers into lldb, then the G packet to set them again after the func call. Since then, lldb has not sent g/G (except as a bug) - it either asks for registers individually (p/P) or or asks debugserver to save and restore the entire register set with these lldb extensions. Felipe recently had a codepath that fell back to using g/G and found that it does not work with the modern signed fp/sp/pc/lr registers that we can get -- it sidesteps around the clearing of the non-addressable bits that we do when reading/writing them, and results in a crash. ( #132079 ) Instead of fixing that issue, I am removing g/G from debugserver because it's not needed by lldb, and it will would be easy for future bugs to creep in to this packet that lldb should not use, but it can accidentally fall back to and result in subtle bugs. This does mean that a debugger using debugserver on darwin which doesn't use QSaveRegisterState/QRestoreRegisterState will need to fall back to reading & writing each register individually. I'm open to re-evaluating this decision if this proves to be needed, and supporting these lldb extensions is onerous.
1 parent e60e064 commit ad5cac3

File tree

3 files changed

+0
-132
lines changed

3 files changed

+0
-132
lines changed

lldb/test/API/tools/lldb-server/register-reading/TestGdbRemoteGPacket.py

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -25,39 +25,6 @@ def _extract_register_value(reg_info, reg_bank, byte_order, bytes_per_entry=8):
2525

2626

2727
class TestGdbRemoteGPacket(gdbremote_testcase.GdbRemoteTestCaseBase):
28-
@skipUnlessDarwin # G packet not supported
29-
def test_g_packet(self):
30-
self.build()
31-
self.prep_debug_monitor_and_inferior()
32-
self.test_sequence.add_log_lines(
33-
[
34-
"read packet: $g#67",
35-
{
36-
"direction": "send",
37-
"regex": r"^\$(.+)#[0-9a-fA-F]{2}$",
38-
"capture": {1: "register_bank"},
39-
},
40-
],
41-
True,
42-
)
43-
context = self.expect_gdbremote_sequence()
44-
register_bank = context.get("register_bank")
45-
self.assertNotEqual(register_bank[0], "E")
46-
47-
self.test_sequence.add_log_lines(
48-
[
49-
"read packet: $G" + register_bank + "#00",
50-
{
51-
"direction": "send",
52-
"regex": r"^\$(.+)#[0-9a-fA-F]{2}$",
53-
"capture": {1: "G_reply"},
54-
},
55-
],
56-
True,
57-
)
58-
context = self.expect_gdbremote_sequence()
59-
self.assertNotEqual(context.get("G_reply")[0], "E")
60-
6128
@skipIf(archs=no_match(["x86_64"]))
6229
def g_returns_correct_data(self, with_suffix):
6330
procs = self.prep_debug_monitor_and_inferior()

lldb/tools/debugserver/source/RNBRemote.cpp

Lines changed: 0 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -243,14 +243,10 @@ void RNBRemote::CreatePacketTable() {
243243
"Read memory"));
244244
t.push_back(Packet(read_register, &RNBRemote::HandlePacket_p, NULL, "p",
245245
"Read one register"));
246-
t.push_back(Packet(read_general_regs, &RNBRemote::HandlePacket_g, NULL, "g",
247-
"Read registers"));
248246
t.push_back(Packet(write_memory, &RNBRemote::HandlePacket_M, NULL, "M",
249247
"Write memory"));
250248
t.push_back(Packet(write_register, &RNBRemote::HandlePacket_P, NULL, "P",
251249
"Write one register"));
252-
t.push_back(Packet(write_general_regs, &RNBRemote::HandlePacket_G, NULL, "G",
253-
"Write registers"));
254250
t.push_back(Packet(insert_mem_bp, &RNBRemote::HandlePacket_z, NULL, "Z0",
255251
"Insert memory breakpoint"));
256252
t.push_back(Packet(remove_mem_bp, &RNBRemote::HandlePacket_z, NULL, "z0",
@@ -3288,97 +3284,6 @@ rnb_err_t RNBRemote::HandlePacket_X(const char *p) {
32883284
return SendPacket("OK");
32893285
}
32903286

3291-
/* 'g' -- read registers
3292-
Get the contents of the registers for the current thread,
3293-
send them to gdb.
3294-
Should the setting of the Hg packet determine which thread's registers
3295-
are returned? */
3296-
3297-
rnb_err_t RNBRemote::HandlePacket_g(const char *p) {
3298-
std::ostringstream ostrm;
3299-
if (!m_ctx.HasValidProcessID()) {
3300-
return SendErrorPacket("E11");
3301-
}
3302-
3303-
if (g_num_reg_entries == 0)
3304-
InitializeRegisters();
3305-
3306-
nub_process_t pid = m_ctx.ProcessID();
3307-
nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p + 1);
3308-
if (tid == INVALID_NUB_THREAD)
3309-
return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3310-
"No thread specified in p packet");
3311-
3312-
// Get the register context size first by calling with NULL buffer
3313-
nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0);
3314-
if (reg_ctx_size) {
3315-
// Now allocate enough space for the entire register context
3316-
std::vector<uint8_t> reg_ctx;
3317-
reg_ctx.resize(reg_ctx_size);
3318-
// Now read the register context
3319-
reg_ctx_size =
3320-
DNBThreadGetRegisterContext(pid, tid, &reg_ctx[0], reg_ctx.size());
3321-
if (reg_ctx_size) {
3322-
append_hex_value(ostrm, reg_ctx.data(), reg_ctx.size(), false);
3323-
return SendPacket(ostrm.str());
3324-
}
3325-
}
3326-
return SendErrorPacket("E74");
3327-
}
3328-
3329-
/* 'G XXX...' -- write registers
3330-
How is the thread for these specified, beyond "the current thread"?
3331-
Does gdb actually use the Hg packet to set this? */
3332-
3333-
rnb_err_t RNBRemote::HandlePacket_G(const char *p) {
3334-
if (!m_ctx.HasValidProcessID()) {
3335-
return SendErrorPacket("E11");
3336-
}
3337-
3338-
if (g_num_reg_entries == 0)
3339-
InitializeRegisters();
3340-
3341-
p += 1; // Skip the 'G'
3342-
3343-
nub_process_t pid = m_ctx.ProcessID();
3344-
nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p);
3345-
if (tid == INVALID_NUB_THREAD)
3346-
return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3347-
"No thread specified in p packet");
3348-
// Skip the thread specification in `G;thread:3488ea;[..data...]`
3349-
const char *last_semi = strrchr(p, ';');
3350-
if (last_semi)
3351-
p = last_semi + 1;
3352-
3353-
StdStringExtractor packet(p);
3354-
3355-
// Get the register context size first by calling with NULL buffer
3356-
nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0);
3357-
if (reg_ctx_size) {
3358-
// Now allocate enough space for the entire register context
3359-
std::vector<uint8_t> reg_ctx;
3360-
reg_ctx.resize(reg_ctx_size);
3361-
3362-
const nub_size_t bytes_extracted =
3363-
packet.GetHexBytes(&reg_ctx[0], reg_ctx.size(), 0xcc);
3364-
if (bytes_extracted == reg_ctx.size()) {
3365-
// Now write the register context
3366-
reg_ctx_size =
3367-
DNBThreadSetRegisterContext(pid, tid, reg_ctx.data(), reg_ctx.size());
3368-
if (reg_ctx_size == reg_ctx.size())
3369-
return SendPacket("OK");
3370-
else
3371-
return SendErrorPacket("E55");
3372-
} else {
3373-
DNBLogError("RNBRemote::HandlePacket_G(%s): extracted %llu of %llu "
3374-
"bytes, size mismatch\n",
3375-
p, (uint64_t)bytes_extracted, (uint64_t)reg_ctx_size);
3376-
return SendErrorPacket("E64");
3377-
}
3378-
}
3379-
return SendErrorPacket("E65");
3380-
}
3381-
33823287
static bool RNBRemoteShouldCancelCallback(void *not_used) {
33833288
RNBRemoteSP remoteSP(g_remoteSP);
33843289
if (remoteSP.get() != NULL) {

lldb/tools/debugserver/source/RNBRemote.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ class RNBRemote {
4646
cont, // 'c'
4747
continue_with_sig, // 'C'
4848
detach, // 'D'
49-
read_general_regs, // 'g'
50-
write_general_regs, // 'G'
5149
set_thread, // 'H'
5250
step_inferior_one_cycle, // 'i'
5351
signal_and_step_inf_one_cycle, // 'I'
@@ -221,8 +219,6 @@ class RNBRemote {
221219
rnb_err_t HandlePacket_M(const char *p);
222220
rnb_err_t HandlePacket_x(const char *p);
223221
rnb_err_t HandlePacket_X(const char *p);
224-
rnb_err_t HandlePacket_g(const char *p);
225-
rnb_err_t HandlePacket_G(const char *p);
226222
rnb_err_t HandlePacket_z(const char *p);
227223
rnb_err_t HandlePacket_T(const char *p);
228224
rnb_err_t HandlePacket_p(const char *p);

0 commit comments

Comments
 (0)