Skip to content

Commit dee9744

Browse files
fixup! Address review comments
1 parent 86c55d2 commit dee9744

File tree

3 files changed

+94
-83
lines changed

3 files changed

+94
-83
lines changed
Lines changed: 50 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
Tests the exit code/description coming from the debugserver.
2+
Tests debugserver support for MultiMemRead.
33
"""
44

55
import lldb
@@ -17,12 +17,16 @@ def send_process_packet(self, packet_str):
1717
# packet: <packet_str>
1818
# response: <response>
1919
reply = self.res.GetOutput().split("\n")
20-
reply[0] = reply[0].strip()
21-
reply[1] = reply[1].strip()
20+
packet = reply[0].strip()
21+
response = reply[1].strip()
2222

23-
self.assertTrue(reply[0].startswith("packet: "), reply[0])
24-
self.assertTrue(reply[1].startswith("response: "))
25-
return reply[1][len("response: ") :]
23+
self.assertTrue(packet.startswith("packet: "))
24+
self.assertTrue(response.startswith("response: "))
25+
return response[len("response: ") :]
26+
27+
def check_invalid_packet(self, packet_str):
28+
reply = self.send_process_packet("packet_str")
29+
self.assertEqual(reply, "E03")
2630

2731
def test_packets(self):
2832
self.build()
@@ -36,30 +40,41 @@ def test_packets(self):
3640

3741
mem_address_var = thread.frames[0].FindVariable("memory")
3842
self.assertTrue(mem_address_var)
39-
mem_address = int(mem_address_var.GetValue(), 16)
43+
mem_address = mem_address_var.GetValueAsUnsigned() + 42
4044

41-
reply = self.send_process_packet("MultiMemRead:")
42-
self.assertEqual(reply, "E03")
43-
reply = self.send_process_packet("MultiMemRead:ranges:")
44-
self.assertEqual(reply, "E03")
45-
reply = self.send_process_packet("MultiMemRead:ranges:10")
46-
self.assertEqual(reply, "E03")
47-
reply = self.send_process_packet("MultiMemRead:ranges:10,")
48-
self.assertEqual(reply, "E03")
49-
reply = self.send_process_packet("MultiMemRead:ranges:10,2")
50-
self.assertEqual(reply, "E03")
51-
reply = self.send_process_packet("MultiMemRead:ranges:10,2,")
52-
self.assertEqual(reply, "E03")
45+
# no ":"
46+
self.check_invalid_packet("MultiMemRead")
47+
# missing ranges
48+
self.check_invalid_packet("MultiMemRead:")
49+
# needs at least one range
50+
self.check_invalid_packet("MultiMemRead:ranges:")
51+
# needs at least one range
52+
self.check_invalid_packet("MultiMemRead:ranges:,")
53+
# a range is a pair of numbers
54+
self.check_invalid_packet("MultiMemRead:ranges:10")
55+
# a range is a pair of numbers
56+
self.check_invalid_packet("MultiMemRead:ranges:10,")
57+
# range list must end with ;
58+
self.check_invalid_packet("MultiMemRead:ranges:10,2")
59+
self.check_invalid_packet("MultiMemRead:ranges:10,2,")
60+
self.check_invalid_packet("MultiMemRead:ranges:10,2,3")
61+
# ranges are pairs of numbers.
62+
self.check_invalid_packet("MultiMemRead:ranges:10,2,3;")
63+
# unrecognized field
64+
self.check_invalid_packet("MultiMemRead:ranges:10,2;blah:;")
65+
# unrecognized field
66+
self.check_invalid_packet("MultiMemRead:blah:;ranges:10,2;")
67+
68+
# This is a valid way of testing for MultiMemRead support
69+
reply = self.send_process_packet("MultiMemRead:ranges:0,0;")
70+
self.assertEqual(reply, "0;")
71+
# Debugserver is permissive with trailing commas.
5372
reply = self.send_process_packet("MultiMemRead:ranges:10,2,;")
54-
self.assertEqual(reply, "0;") # Debugserver is permissive with trailing commas.
73+
self.assertEqual(reply, "0;")
5574
reply = self.send_process_packet("MultiMemRead:ranges:10,2;")
5675
self.assertEqual(reply, "0;")
5776
reply = self.send_process_packet(f"MultiMemRead:ranges:{mem_address:x},0;")
5877
self.assertEqual(reply, "0;")
59-
reply = self.send_process_packet(
60-
f"MultiMemRead:ranges:{mem_address:x},0;options:;"
61-
)
62-
self.assertEqual(reply, "0;")
6378
reply = self.send_process_packet(f"MultiMemRead:ranges:{mem_address:x},2;")
6479
self.assertEqual(reply, "2;ab")
6580
reply = self.send_process_packet(
@@ -70,3 +85,14 @@ def test_packets(self):
7085
f"MultiMemRead:ranges:{mem_address:x},2,{mem_address+2:x},4,{mem_address+6:x},8;"
7186
)
7287
self.assertEqual(reply, "2,4,8;abcdefghijklmn")
88+
89+
# Test zero length in the middle.
90+
reply = self.send_process_packet(
91+
f"MultiMemRead:ranges:{mem_address:x},2,{mem_address+2:x},0,{mem_address+6:x},8;"
92+
)
93+
self.assertEqual(reply, "2,0,8;abghijklmn")
94+
# Test zero length in the end.
95+
reply = self.send_process_packet(
96+
f"MultiMemRead:ranges:{mem_address:x},2,{mem_address+2:x},4,{mem_address+6:x},0;"
97+
)
98+
self.assertEqual(reply, "2,4,0;abcdef")

lldb/test/API/macosx/debugserver-multimemread/main.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44
int main(int argc, char **argv) {
55
char *memory = malloc(1024);
66
memset(memory, '-', 1024);
7-
for (int i = 0; i < 50; i++)
8-
memory[i] = 'a' + i;
7+
// Write "interesting" characters at an offset from the memory filled with
8+
// `-`. This way, if we read outside the range in either direction, we should
9+
// find `-`s`.
10+
int offset = 42;
11+
for (int i = offset; i < offset + 14; i++)
12+
memory[i] = 'a' + (i - offset);
913
return 0; // break here
1014
}

lldb/tools/debugserver/source/RNBRemote.cpp

Lines changed: 38 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,20 @@ uint64_t decode_uint64(const char *p, int base, char **end = nullptr,
147147
return addr;
148148
}
149149

150+
/// Attempts to parse a prefix of `number_str` as a uint64_t. If
151+
/// successful, the number is returned and the prefix is dropped from
152+
/// `number_str`.
153+
static std::optional<uint64_t> extract_u64(std::string_view &number_str) {
154+
char *str_end = nullptr;
155+
errno = 0;
156+
uint64_t number = strtoull(number_str.data(), &str_end, 16);
157+
if (errno != 0)
158+
return std::nullopt;
159+
assert(str_end);
160+
number_str.remove_prefix(str_end - number_str.data());
161+
return number;
162+
}
163+
150164
void append_hex_value(std::ostream &ostrm, const void *buf, size_t buf_size,
151165
bool swap) {
152166
int i;
@@ -180,6 +194,25 @@ void append_hexified_string(std::ostream &ostrm, const std::string &string) {
180194
}
181195
}
182196

197+
/// Returns true if `str` starts with `prefix`.
198+
static bool starts_with(std::string_view str, std::string_view prefix) {
199+
return str.substr(0, prefix.size()) == prefix;
200+
}
201+
202+
/// Splits `list_str` into multiple string_views separated by `,`.
203+
static std::vector<std::string_view>
204+
parse_comma_separated_list(std::string_view list_str) {
205+
std::vector<std::string_view> list;
206+
while (!list_str.empty()) {
207+
auto pos = list_str.find(',');
208+
list.push_back(list_str.substr(0, pos));
209+
if (pos == list_str.npos)
210+
break;
211+
list_str.remove_prefix(pos + 1);
212+
}
213+
return list;
214+
}
215+
183216
// from System.framework/Versions/B/PrivateHeaders/sys/codesign.h
184217
extern "C" {
185218
#define CS_OPS_STATUS 0 /* return status */
@@ -3165,42 +3198,6 @@ rnb_err_t RNBRemote::HandlePacket_m(const char *p) {
31653198
return SendPacket(ostrm.str());
31663199
}
31673200

3168-
/// Returns true if `str` starts with `prefix`.
3169-
static bool starts_with(std::string_view str, std::string_view prefix) {
3170-
return str.size() >= prefix.size() &&
3171-
str.compare(0, prefix.size(), prefix) == 0;
3172-
}
3173-
3174-
/// Attempts to parse a prefix of `number_str` as a number of type `T`. If
3175-
/// successful, the number is returned and the prefix is dropped from
3176-
/// `number_str`.
3177-
template <typename T>
3178-
static std::optional<T> extract_number(std::string_view &number_str) {
3179-
static_assert(std::is_integral<T>());
3180-
char *str_end = nullptr;
3181-
errno = 0;
3182-
nub_addr_t number = strtoull(number_str.data(), &str_end, 16);
3183-
if (errno != 0)
3184-
return std::nullopt;
3185-
assert(str_end);
3186-
number_str.remove_prefix(str_end - number_str.data());
3187-
return number;
3188-
}
3189-
3190-
/// Splits `list_str` into multiple string_views separated by `,`.
3191-
static std::vector<std::string_view>
3192-
parse_comma_separated_list(std::string_view list_str) {
3193-
std::vector<std::string_view> list;
3194-
while (!list_str.empty()) {
3195-
auto pos = list_str.find(',');
3196-
list.push_back(list_str.substr(0, pos));
3197-
if (pos == list_str.npos)
3198-
break;
3199-
list_str.remove_prefix(pos + 1);
3200-
}
3201-
return list;
3202-
}
3203-
32043201
rnb_err_t RNBRemote::HandlePacket_MultiMemRead(const char *p) {
32053202
const std::string_view packet_name("MultiMemRead:");
32063203
std::string_view packet(p);
@@ -3237,10 +3234,8 @@ rnb_err_t RNBRemote::HandlePacket_MultiMemRead(const char *p) {
32373234
"MultiMemRead has an odd number of numbers for the ranges");
32383235

32393236
for (unsigned idx = 0; idx < numbers_list.size(); idx += 2) {
3240-
std::optional<nub_addr_t> maybe_addr =
3241-
extract_number<nub_addr_t>(numbers_list[idx]);
3242-
std::optional<size_t> maybe_length =
3243-
extract_number<size_t>(numbers_list[idx + 1]);
3237+
std::optional<uint64_t> maybe_addr = extract_u64(numbers_list[idx]);
3238+
std::optional<uint64_t> maybe_length = extract_u64(numbers_list[idx + 1]);
32443239
if (!maybe_addr || !maybe_length)
32453240
return HandlePacket_ILLFORMED(__FILE__, __LINE__, packet.data(),
32463241
"Invalid MultiMemRead range");
@@ -3258,28 +3253,14 @@ rnb_err_t RNBRemote::HandlePacket_MultiMemRead(const char *p) {
32583253
return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
32593254
"MultiMemRead has an empty range list");
32603255

3261-
// If 'options:' is present, ensure it's empty.
3262-
const std::string_view options_prefix("options:");
3263-
if (starts_with(packet, options_prefix)) {
3264-
packet.remove_prefix(options_prefix.size());
3265-
if (packet.empty())
3266-
return HandlePacket_ILLFORMED(
3267-
__FILE__, __LINE__, packet.data(),
3268-
"Too short 'options' in MultiMemRead packet");
3269-
if (packet[0] != ';')
3270-
return HandlePacket_ILLFORMED(__FILE__, __LINE__, packet.data(),
3271-
"Unimplemented 'options' in MultiMemRead");
3272-
packet.remove_prefix(1);
3273-
}
3274-
32753256
if (!packet.empty())
3276-
return HandlePacket_ILLFORMED(__FILE__, __LINE__, p,
3277-
"Invalid MultiMemRead address_range");
3257+
return HandlePacket_ILLFORMED(
3258+
__FILE__, __LINE__, p, "MultiMemRead packet has unrecognized fields");
32783259

32793260
std::vector<std::vector<uint8_t>> buffers;
32803261
buffers.reserve(ranges.size());
32813262
for (auto [base_addr, length] : ranges) {
3282-
buffers.emplace_back(length, '\0');
3263+
buffers.emplace_back(length, 0);
32833264
nub_size_t bytes_read = DNBProcessMemoryRead(m_ctx.ProcessID(), base_addr,
32843265
length, buffers.back().data());
32853266
buffers.back().resize(bytes_read);

0 commit comments

Comments
 (0)