Skip to content

Commit f04b363

Browse files
committedMay 30, 2019
[lldb-server] Support 'g' packets
Differential Revision: https://reviews.llvm.org/D62221 Patch by Guilherme Andrade <guiandrade@google.com>. llvm-svn: 362063
1 parent 851f57e commit f04b363

File tree

9 files changed

+279
-47
lines changed

9 files changed

+279
-47
lines changed
 

Diff for: ‎lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteGPacket.py

-41
This file was deleted.

Diff for: ‎lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestLldbGdbServer.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -558,9 +558,7 @@ def p_returns_correct_data_size_for_each_qRegisterInfo(self):
558558
self.assertIsNotNone(reg_infos)
559559
self.assertTrue(len(reg_infos) > 0)
560560

561-
inferior_exe_path = self.getBuildArtifact("a.out")
562-
Target = self.dbg.CreateTarget(inferior_exe_path)
563-
byte_order = Target.GetByteOrder()
561+
byte_order = self.get_target_byte_order()
564562

565563
# Read value for each register.
566564
reg_index = 0

Diff for: ‎lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py

+5
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,11 @@ def get_debug_monitor_command_line_args(self, attach_pid=None):
378378
commandline_args += ["--named-pipe", self.named_pipe_path]
379379
return commandline_args
380380

381+
def get_target_byte_order(self):
382+
inferior_exe_path = self.getBuildArtifact("a.out")
383+
target = self.dbg.CreateTarget(inferior_exe_path)
384+
return target.GetByteOrder()
385+
381386
def launch_debug_monitor(self, attach_pid=None, logfile=None):
382387
# Create the command line.
383388
commandline_args = self.get_debug_monitor_command_line_args(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
LEVEL = ../../../make
2+
3+
CXX_SOURCES := main.cpp
4+
5+
include $(LEVEL)/Makefile.rules
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
from __future__ import print_function
2+
3+
4+
import gdbremote_testcase
5+
import textwrap
6+
from lldbsuite.test.decorators import *
7+
from lldbsuite.test.lldbtest import *
8+
from lldbsuite.test import lldbutil
9+
10+
11+
def _extract_register_value(reg_info, reg_bank, byte_order, bytes_per_entry=8):
12+
reg_offset = int(reg_info["offset"])*2
13+
reg_byte_size = int(2 * int(reg_info["bitsize"]) / 8)
14+
# Create slice with the contents of the register.
15+
reg_slice = reg_bank[reg_offset:reg_offset+reg_byte_size]
16+
17+
reg_value = []
18+
# Wrap slice according to bytes_per_entry.
19+
for entry in textwrap.wrap(reg_slice, 2 * bytes_per_entry):
20+
# Invert the bytes order if target uses little-endian.
21+
if byte_order == lldb.eByteOrderLittle:
22+
entry = "".join(reversed([entry[i:i+2] for i in range(0,
23+
len(entry),2)]))
24+
reg_value.append("0x" + entry)
25+
26+
return reg_value
27+
28+
29+
class TestGdbRemoteGPacket(gdbremote_testcase.GdbRemoteTestCaseBase):
30+
31+
mydir = TestBase.compute_mydir(__file__)
32+
33+
def run_test_g_packet(self):
34+
self.build()
35+
self.prep_debug_monitor_and_inferior()
36+
self.test_sequence.add_log_lines(
37+
["read packet: $g#67",
38+
{"direction": "send", "regex": r"^\$(.+)#[0-9a-fA-F]{2}$",
39+
"capture": {1: "register_bank"}}],
40+
True)
41+
self.connect_to_debug_monitor()
42+
context = self.expect_gdbremote_sequence()
43+
register_bank = context.get("register_bank")
44+
self.assertTrue(register_bank[0] != 'E')
45+
46+
self.test_sequence.add_log_lines(
47+
["read packet: $G" + register_bank + "#00",
48+
{"direction": "send", "regex": r"^\$(.+)#[0-9a-fA-F]{2}$",
49+
"capture": {1: "G_reply"}}],
50+
True)
51+
context = self.expect_gdbremote_sequence()
52+
self.assertTrue(context.get("G_reply")[0] != 'E')
53+
54+
@skipIfOutOfTreeDebugserver
55+
@debugserver_test
56+
@skipIfDarwinEmbedded
57+
def test_g_packet_debugserver(self):
58+
self.init_debugserver_test()
59+
self.run_test_g_packet()
60+
61+
@skipIf(archs=no_match(["x86_64"]))
62+
def g_returns_correct_data(self, with_suffix):
63+
procs = self.prep_debug_monitor_and_inferior()
64+
65+
self.add_register_info_collection_packets()
66+
if with_suffix:
67+
self.add_thread_suffix_request_packets()
68+
self.add_threadinfo_collection_packets()
69+
context = self.expect_gdbremote_sequence()
70+
self.assertIsNotNone(context)
71+
72+
# Gather register info.
73+
reg_infos = self.parse_register_info_packets(context)
74+
self.assertIsNotNone(reg_infos)
75+
self.add_lldb_register_index(reg_infos)
76+
# Index register info entries by name.
77+
reg_infos = {info['name']: info for info in reg_infos}
78+
79+
# Gather thread info.
80+
if with_suffix:
81+
threads = self.parse_threadinfo_packets(context)
82+
self.assertIsNotNone(threads)
83+
thread_id = threads[0]
84+
self.assertIsNotNone(thread_id)
85+
else:
86+
thread_id = None
87+
88+
# Send vCont packet to resume the inferior.
89+
self.test_sequence.add_log_lines(["read packet: $vCont;c#a8",
90+
{"direction": "send",
91+
"regex": r"^\$T([0-9a-fA-F]{2}).*#[0-9a-fA-F]{2}$",
92+
"capture": {1: "hex_exit_code"}},
93+
],
94+
True)
95+
96+
# Send g packet to retrieve the register bank
97+
if thread_id:
98+
g_request = "read packet: $g;thread:{:x}#00".format(thread_id)
99+
else:
100+
g_request = "read packet: $g#00"
101+
self.test_sequence.add_log_lines(
102+
[g_request,
103+
{"direction": "send", "regex": r"^\$(.+)#[0-9a-fA-F]{2}$",
104+
"capture": {1: "register_bank"}}],
105+
True)
106+
context = self.expect_gdbremote_sequence()
107+
self.assertIsNotNone(context)
108+
reg_bank = context.get("register_bank")
109+
self.assertTrue(reg_bank[0] != 'E')
110+
111+
byte_order = self.get_target_byte_order()
112+
get_reg_value = lambda reg_name : _extract_register_value(
113+
reg_infos[reg_name], reg_bank, byte_order)
114+
115+
self.assertEqual(['0x0102030405060708'], get_reg_value('r8'))
116+
self.assertEqual(['0x1112131415161718'], get_reg_value('r9'))
117+
self.assertEqual(['0x2122232425262728'], get_reg_value('r10'))
118+
self.assertEqual(['0x3132333435363738'], get_reg_value('r11'))
119+
self.assertEqual(['0x4142434445464748'], get_reg_value('r12'))
120+
self.assertEqual(['0x5152535455565758'], get_reg_value('r13'))
121+
self.assertEqual(['0x6162636465666768'], get_reg_value('r14'))
122+
self.assertEqual(['0x7172737475767778'], get_reg_value('r15'))
123+
124+
self.assertEqual(
125+
['0x020406080a0c0e01', '0x030507090b0d0f00'], get_reg_value('xmm8'))
126+
self.assertEqual(
127+
['0x121416181a1c1e11', '0x131517191b1d1f10'], get_reg_value('xmm9'))
128+
self.assertEqual(
129+
['0x222426282a2c2e21', '0x232527292b2d2f20'], get_reg_value('xmm10'))
130+
self.assertEqual(
131+
['0x323436383a3c3e31', '0x333537393b3d3f30'], get_reg_value('xmm11'))
132+
self.assertEqual(
133+
['0x424446484a4c4e41', '0x434547494b4d4f40'], get_reg_value('xmm12'))
134+
self.assertEqual(
135+
['0x525456585a5c5e51', '0x535557595b5d5f50'], get_reg_value('xmm13'))
136+
self.assertEqual(
137+
['0x626466686a6c6e61', '0x636567696b6d6f60'], get_reg_value('xmm14'))
138+
self.assertEqual(
139+
['0x727476787a7c7e71', '0x737577797b7d7f70'], get_reg_value('xmm15'))
140+
141+
@llgs_test
142+
def test_g_returns_correct_data_with_suffix_llgs(self):
143+
self.init_llgs_test()
144+
self.build()
145+
self.set_inferior_startup_launch()
146+
self.g_returns_correct_data(True)
147+
148+
@llgs_test
149+
def test_g_returns_correct_data_no_suffix_llgs(self):
150+
self.init_llgs_test()
151+
self.build()
152+
self.set_inferior_startup_launch()
153+
self.g_returns_correct_data(False)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#include <cstdint>
2+
3+
struct alignas(16) xmm_t {
4+
uint64_t a, b;
5+
};
6+
7+
int main() {
8+
uint64_t r8 = 0x0102030405060708;
9+
uint64_t r9 = 0x1112131415161718;
10+
uint64_t r10 = 0x2122232425262728;
11+
uint64_t r11 = 0x3132333435363738;
12+
uint64_t r12 = 0x4142434445464748;
13+
uint64_t r13 = 0x5152535455565758;
14+
uint64_t r14 = 0x6162636465666768;
15+
uint64_t r15 = 0x7172737475767778;
16+
17+
xmm_t xmm8 = {0x020406080A0C0E01, 0x030507090B0D0F00};
18+
xmm_t xmm9 = {0x121416181A1C1E11, 0x131517191B1D1F10};
19+
xmm_t xmm10 = {0x222426282A2C2E21, 0x232527292B2D2F20};
20+
xmm_t xmm11 = {0x323436383A3C3E31, 0x333537393B3D3F30};
21+
xmm_t xmm12 = {0x424446484A4C4E41, 0x434547494B4D4F40};
22+
xmm_t xmm13 = {0x525456585A5C5E51, 0x535557595B5D5F50};
23+
xmm_t xmm14 = {0x626466686A6C6E61, 0x636567696B6D6F60};
24+
xmm_t xmm15 = {0x727476787A7C7E71, 0x737577797B7D7F70};
25+
26+
asm volatile("movq %0, %%r8\n\t"
27+
"movq %1, %%r9\n\t"
28+
"movq %2, %%r10\n\t"
29+
"movq %3, %%r11\n\t"
30+
"movq %4, %%r12\n\t"
31+
"movq %5, %%r13\n\t"
32+
"movq %6, %%r14\n\t"
33+
"movq %7, %%r15\n\t"
34+
"\n\t"
35+
"movaps %8, %%xmm8\n\t"
36+
"movaps %9, %%xmm9\n\t"
37+
"movaps %10, %%xmm10\n\t"
38+
"movaps %11, %%xmm11\n\t"
39+
"movaps %12, %%xmm12\n\t"
40+
"movaps %13, %%xmm13\n\t"
41+
"movaps %14, %%xmm14\n\t"
42+
"movaps %15, %%xmm15\n\t"
43+
"\n\t"
44+
"int3"
45+
:
46+
: "g"(r8), "g"(r9), "g"(r10), "g"(r11), "g"(r12), "g"(r13),
47+
"g"(r14), "g"(r15), "m"(xmm8), "m"(xmm9), "m"(xmm10),
48+
"m"(xmm11), "m"(xmm12), "m"(xmm13), "m"(xmm14), "m"(xmm15)
49+
: "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
50+
"%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13",
51+
"%xmm14", "%xmm15");
52+
53+
return 0;
54+
}

Diff for: ‎lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp

+58
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,9 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() {
187187
StringExtractorGDBRemote::eServerPacketType_jTraceConfigRead,
188188
&GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead);
189189

190+
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_g,
191+
&GDBRemoteCommunicationServerLLGS::Handle_g);
192+
190193
RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_k,
191194
[this](StringExtractorGDBRemote packet, Status &error,
192195
bool &interrupt, bool &quit) {
@@ -1891,6 +1894,61 @@ GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo(
18911894
return SendPacketNoLock("l");
18921895
}
18931896

1897+
GDBRemoteCommunication::PacketResult
1898+
GDBRemoteCommunicationServerLLGS::Handle_g(StringExtractorGDBRemote &packet) {
1899+
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
1900+
1901+
// Move past packet name.
1902+
packet.SetFilePos(strlen("g"));
1903+
1904+
// Get the thread to use.
1905+
NativeThreadProtocol *thread = GetThreadFromSuffix(packet);
1906+
if (!thread) {
1907+
LLDB_LOG(log, "failed, no thread available");
1908+
return SendErrorResponse(0x15);
1909+
}
1910+
1911+
// Get the thread's register context.
1912+
NativeRegisterContext &reg_ctx = thread->GetRegisterContext();
1913+
1914+
std::vector<uint8_t> regs_buffer;
1915+
for (uint32_t reg_num = 0; reg_num < reg_ctx.GetUserRegisterCount();
1916+
++reg_num) {
1917+
const RegisterInfo *reg_info = reg_ctx.GetRegisterInfoAtIndex(reg_num);
1918+
1919+
if (reg_info == nullptr) {
1920+
LLDB_LOG(log, "failed to get register info for register index {0}",
1921+
reg_num);
1922+
return SendErrorResponse(0x15);
1923+
}
1924+
1925+
if (reg_info->value_regs != nullptr)
1926+
continue; // skip registers that are contained in other registers
1927+
1928+
RegisterValue reg_value;
1929+
Status error = reg_ctx.ReadRegister(reg_info, reg_value);
1930+
if (error.Fail()) {
1931+
LLDB_LOG(log, "failed to read register at index {0}", reg_num);
1932+
return SendErrorResponse(0x15);
1933+
}
1934+
1935+
if (reg_info->byte_offset + reg_info->byte_size >= regs_buffer.size())
1936+
// Resize the buffer to guarantee it can store the register offsetted
1937+
// data.
1938+
regs_buffer.resize(reg_info->byte_offset + reg_info->byte_size);
1939+
1940+
// Copy the register offsetted data to the buffer.
1941+
memcpy(regs_buffer.data() + reg_info->byte_offset, reg_value.GetBytes(),
1942+
reg_info->byte_size);
1943+
}
1944+
1945+
// Write the response.
1946+
StreamGDBRemote response;
1947+
response.PutBytesAsRawHex8(regs_buffer.data(), regs_buffer.size());
1948+
1949+
return SendPacketNoLock(response.GetString());
1950+
}
1951+
18941952
GDBRemoteCommunication::PacketResult
18951953
GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) {
18961954
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));

Diff for: ‎lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h

+2
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ class GDBRemoteCommunicationServerLLGS
178178

179179
PacketResult Handle_QPassSignals(StringExtractorGDBRemote &packet);
180180

181+
PacketResult Handle_g(StringExtractorGDBRemote &packet);
182+
181183
void SetCurrentThreadID(lldb::tid_t tid);
182184

183185
lldb::tid_t GetCurrentThreadID() const;

Diff for: ‎lldb/source/Utility/StringExtractorGDBRemote.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -377,9 +377,7 @@ StringExtractorGDBRemote::GetServerPacketType() const {
377377
break;
378378

379379
case 'g':
380-
if (packet_size == 1)
381-
return eServerPacketType_g;
382-
break;
380+
return eServerPacketType_g;
383381

384382
case 'G':
385383
return eServerPacketType_G;

0 commit comments

Comments
 (0)
Please sign in to comment.