Skip to content

Commit e28bd1c

Browse files
Michael137tomtor
authored andcommitted
[lldb][Commands][NFC] Extract memory find expression evaluation into helpers (llvm#143686)
This patch factors out the `-e` option logic into two helper functions. The `EvaluateExpression` helper might seem redundant but I'll be adding to it in a follow-up patch to fix an issue when running `memory find -e` for Swift targets. Also adds test coverage for the error cases that were previously untested. rdar://152113525
1 parent 4ad2fc7 commit e28bd1c

File tree

3 files changed

+114
-43
lines changed

3 files changed

+114
-43
lines changed

lldb/source/Commands/CommandObjectMemory.cpp

Lines changed: 58 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -885,6 +885,52 @@ class CommandObjectMemoryRead : public CommandObjectParsed {
885885
#define LLDB_OPTIONS_memory_find
886886
#include "CommandOptions.inc"
887887

888+
static llvm::Error CopyExpressionResult(ValueObject &result,
889+
DataBufferHeap &buffer) {
890+
uint64_t value = result.GetValueAsUnsigned(0);
891+
auto size_or_err = result.GetCompilerType().GetByteSize(nullptr);
892+
if (!size_or_err)
893+
return size_or_err.takeError();
894+
895+
switch (*size_or_err) {
896+
case 1: {
897+
uint8_t byte = (uint8_t)value;
898+
buffer.CopyData(&byte, 1);
899+
} break;
900+
case 2: {
901+
uint16_t word = (uint16_t)value;
902+
buffer.CopyData(&word, 2);
903+
} break;
904+
case 4: {
905+
uint32_t lword = (uint32_t)value;
906+
buffer.CopyData(&lword, 4);
907+
} break;
908+
case 8: {
909+
buffer.CopyData(&value, 8);
910+
} break;
911+
default:
912+
return llvm::createStringError(
913+
"Only expressions resulting in 1, 2, 4, or 8-byte-sized values are "
914+
"supported. For other pattern sizes the --string (-s) option may be "
915+
"used.");
916+
}
917+
918+
return llvm::Error::success();
919+
}
920+
921+
static llvm::Expected<ValueObjectSP>
922+
EvaluateExpression(llvm::StringRef expression, StackFrame &frame,
923+
Process &process) {
924+
ValueObjectSP result_sp;
925+
auto status =
926+
process.GetTarget().EvaluateExpression(expression, &frame, result_sp);
927+
if (status != eExpressionCompleted || !result_sp)
928+
return llvm::createStringError(
929+
"expression evaluation failed. pass a string instead");
930+
931+
return result_sp;
932+
}
933+
888934
// Find the specified data in memory
889935
class CommandObjectMemoryFind : public CommandObjectParsed {
890936
public:
@@ -1026,49 +1072,18 @@ class CommandObjectMemoryFind : public CommandObjectParsed {
10261072
}
10271073
buffer.CopyData(str);
10281074
} else if (m_memory_options.m_expr.OptionWasSet()) {
1029-
StackFrame *frame = m_exe_ctx.GetFramePtr();
1030-
ValueObjectSP result_sp;
1031-
if ((eExpressionCompleted ==
1032-
process->GetTarget().EvaluateExpression(
1033-
m_memory_options.m_expr.GetValueAs<llvm::StringRef>().value_or(
1034-
""),
1035-
frame, result_sp)) &&
1036-
result_sp) {
1037-
uint64_t value = result_sp->GetValueAsUnsigned(0);
1038-
std::optional<uint64_t> size = llvm::expectedToOptional(
1039-
result_sp->GetCompilerType().GetByteSize(nullptr));
1040-
if (!size)
1041-
return;
1042-
switch (*size) {
1043-
case 1: {
1044-
uint8_t byte = (uint8_t)value;
1045-
buffer.CopyData(&byte, 1);
1046-
} break;
1047-
case 2: {
1048-
uint16_t word = (uint16_t)value;
1049-
buffer.CopyData(&word, 2);
1050-
} break;
1051-
case 4: {
1052-
uint32_t lword = (uint32_t)value;
1053-
buffer.CopyData(&lword, 4);
1054-
} break;
1055-
case 8: {
1056-
buffer.CopyData(&value, 8);
1057-
} break;
1058-
case 3:
1059-
case 5:
1060-
case 6:
1061-
case 7:
1062-
result.AppendError("unknown type. pass a string instead");
1063-
return;
1064-
default:
1065-
result.AppendError(
1066-
"result size larger than 8 bytes. pass a string instead");
1067-
return;
1068-
}
1069-
} else {
1070-
result.AppendError(
1071-
"expression evaluation failed. pass a string instead");
1075+
auto result_or_err = EvaluateExpression(
1076+
m_memory_options.m_expr.GetValueAs<llvm::StringRef>().value_or(""),
1077+
m_exe_ctx.GetFrameRef(), *process);
1078+
if (!result_or_err) {
1079+
result.AppendError(llvm::toString(result_or_err.takeError()));
1080+
return;
1081+
}
1082+
1083+
ValueObjectSP result_sp = *result_or_err;
1084+
1085+
if (auto err = CopyExpressionResult(*result_sp, buffer)) {
1086+
result.AppendError(llvm::toString(std::move(err)));
10721087
return;
10731088
}
10741089
} else {

lldb/test/API/functionalities/memory/find/TestMemoryFind.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,44 @@ def test_memory_find(self):
7979
'memory find -s "nothere" `stringdata` `stringdata+10`',
8080
substrs=["data not found within the range."],
8181
)
82+
83+
# Expression results with unsupported result types.
84+
self.expect(
85+
'memory find -e "ThreeBytes{}" `&bytedata[0]` `&bytedata[2]`',
86+
substrs=[
87+
"Only expressions resulting in 1, 2, 4, or 8-byte-sized values are supported"
88+
],
89+
error=True,
90+
)
91+
92+
self.expect(
93+
'memory find -e "FiveBytes{}" `&bytedata[0]` `&bytedata[2]`',
94+
substrs=[
95+
"Only expressions resulting in 1, 2, 4, or 8-byte-sized values are supported"
96+
],
97+
error=True,
98+
)
99+
100+
self.expect(
101+
'memory find -e "SixBytes{}" `&bytedata[0]` `&bytedata[2]`',
102+
substrs=[
103+
"Only expressions resulting in 1, 2, 4, or 8-byte-sized values are supported"
104+
],
105+
error=True,
106+
)
107+
108+
self.expect(
109+
'memory find -e "SevenBytes{}" `&bytedata[0]` `&bytedata[2]`',
110+
substrs=[
111+
"Only expressions resulting in 1, 2, 4, or 8-byte-sized values are supported"
112+
],
113+
error=True,
114+
)
115+
116+
self.expect(
117+
'memory find -e "NineBytes{}" `&bytedata[0]` `&bytedata[2]`',
118+
substrs=[
119+
"Only expressions resulting in 1, 2, 4, or 8-byte-sized values are supported"
120+
],
121+
error=True,
122+
)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,24 @@
11
#include <stdio.h>
22
#include <stdint.h>
33

4+
template <size_t T> struct [[gnu::packed]] Payload {
5+
uint8_t data[T];
6+
};
7+
8+
using ThreeBytes = Payload<3>;
9+
using FiveBytes = Payload<5>;
10+
using SixBytes = Payload<5>;
11+
using SevenBytes = Payload<7>;
12+
using NineBytes = Payload<9>;
13+
414
int main (int argc, char const *argv[])
515
{
616
const char* stringdata = "hello world; I like to write text in const char pointers";
717
uint8_t bytedata[] = {0xAA,0xBB,0xCC,0xDD,0xEE,0xFF,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99};
18+
ThreeBytes b1;
19+
FiveBytes b2;
20+
SixBytes b3;
21+
SevenBytes b4;
22+
NineBytes b5;
823
return 0; // break here
924
}

0 commit comments

Comments
 (0)