Skip to content

Commit 94a2cae

Browse files
committed
[lldb][Commands][NFC] Extract memory find expression evaluation into helpers
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 and 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 ddef9ce commit 94a2cae

File tree

3 files changed

+108
-43
lines changed

3 files changed

+108
-43
lines changed

lldb/source/Commands/CommandObjectMemory.cpp

Lines changed: 61 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -885,6 +885,55 @@ 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+
case 3:
912+
case 5:
913+
case 6:
914+
case 7:
915+
return llvm::createStringError("unknown type. pass a string instead");
916+
default:
917+
return llvm::createStringError(
918+
"result size larger than 8 bytes. pass a string instead");
919+
}
920+
921+
return llvm::Error::success();
922+
}
923+
924+
static llvm::Expected<ValueObjectSP>
925+
EvaluateExpression(llvm::StringRef expression, StackFrame &frame,
926+
Process &process) {
927+
ValueObjectSP result_sp;
928+
auto status =
929+
process.GetTarget().EvaluateExpression(expression, &frame, result_sp);
930+
if (status != eExpressionCompleted || !result_sp)
931+
return llvm::createStringError(
932+
"expression evaluation failed. pass a string instead");
933+
934+
return result_sp;
935+
}
936+
888937
// Find the specified data in memory
889938
class CommandObjectMemoryFind : public CommandObjectParsed {
890939
public:
@@ -1026,49 +1075,18 @@ class CommandObjectMemoryFind : public CommandObjectParsed {
10261075
}
10271076
buffer.CopyData(str);
10281077
} 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");
1078+
auto result_or_err = EvaluateExpression(
1079+
m_memory_options.m_expr.GetValueAs<llvm::StringRef>().value_or(""),
1080+
m_exe_ctx.GetFrameRef(), *process);
1081+
if (!result_or_err) {
1082+
result.AppendError(llvm::toString(result_or_err.takeError()));
1083+
return;
1084+
}
1085+
1086+
ValueObjectSP result_sp = *result_or_err;
1087+
1088+
if (auto err = CopyExpressionResult(*result_sp, buffer)) {
1089+
result.AppendError(llvm::toString(std::move(err)));
10721090
return;
10731091
}
10741092
} else {

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,34 @@ 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=["unknown type."],
87+
error=True,
88+
)
89+
90+
self.expect(
91+
'memory find -e "FiveBytes{}" `&bytedata[0]` `&bytedata[2]`',
92+
substrs=["unknown type."],
93+
error=True,
94+
)
95+
96+
self.expect(
97+
'memory find -e "SixBytes{}" `&bytedata[0]` `&bytedata[2]`',
98+
substrs=["unknown type."],
99+
error=True,
100+
)
101+
102+
self.expect(
103+
'memory find -e "SevenBytes{}" `&bytedata[0]` `&bytedata[2]`',
104+
substrs=["unknown type."],
105+
error=True,
106+
)
107+
108+
self.expect(
109+
'memory find -e "NineBytes{}" `&bytedata[0]` `&bytedata[2]`',
110+
substrs=["result size larger than 8 bytes."],
111+
error=True,
112+
)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,25 @@
11
#include <stdio.h>
22
#include <stdint.h>
33

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

0 commit comments

Comments
 (0)