Skip to content

Commit fc735fc

Browse files
committed
Introduce "LogBeforeReturn" templated function to simplify code that
logs something and then returns.
1 parent efbcd37 commit fc735fc

File tree

1 file changed

+79
-95
lines changed

1 file changed

+79
-95
lines changed

lldb/source/Plugins/InstrumentationRuntime/BoundsSafety/InstrumentationRuntimeBoundsSafety.cpp

Lines changed: 79 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "clang/CodeGen/ModuleBuilder.h"
3030

3131
#include <memory>
32+
#include <type_traits>
3233

3334
using namespace lldb;
3435
using namespace lldb_private;
@@ -51,6 +52,9 @@ const std::vector<std::string> &getBoundsSafetySoftTrapRuntimeFuncs() {
5152
#define SOFT_TRAP_FALLBACK_CATEGORY \
5253
SOFT_TRAP_CATEGORY_PREFIX "Bounds check failed"
5354

55+
using ComputedStopInfo =
56+
std::pair<std::optional<std::string>, std::optional<uint32_t>>;
57+
5458
class InstrumentationBoundsSafetyStopInfo : public StopInfo {
5559
public:
5660
~InstrumentationBoundsSafetyStopInfo() override = default;
@@ -76,16 +80,14 @@ class InstrumentationBoundsSafetyStopInfo : public StopInfo {
7680
private:
7781
InstrumentationBoundsSafetyStopInfo(Thread &thread);
7882

79-
std::pair<std::optional<std::string>, std::optional<uint32_t>>
83+
ComputedStopInfo
8084
ComputeStopReasonAndSuggestedStackFrame(bool &warning_emitted_for_failure);
8185

82-
std::pair<std::string, std::optional<uint32_t>>
83-
ComputeStopReasonAndSuggestedStackFrameWithDebugInfo(
86+
ComputedStopInfo ComputeStopReasonAndSuggestedStackFrameWithDebugInfo(
8487
lldb::StackFrameSP parent_sf, lldb::user_id_t debugger_id,
8588
bool &warning_emitted_for_failure);
8689

87-
std::pair<std::optional<std::string>, std::optional<uint32_t>>
88-
ComputeStopReasonAndSuggestedStackFrameWithoutDebugInfo(
90+
ComputedStopInfo ComputeStopReasonAndSuggestedStackFrameWithoutDebugInfo(
8991
ThreadSP thread_sp, lldb::user_id_t debugger_id,
9092
bool &warning_emitted_for_failure);
9193
};
@@ -118,24 +120,33 @@ InstrumentationBoundsSafetyStopInfo::InstrumentationBoundsSafetyStopInfo(
118120
}
119121
}
120122

121-
std::pair<std::optional<std::string>, std::optional<uint32_t>>
123+
// Helper functions to make it convenient to log a failure and then return.
124+
template <typename T, typename... ArgTys>
125+
[[nodiscard]] T LogBeforeReturn(ArgTys &&...Args) {
126+
Log *log_category = GetLog(LLDBLog::InstrumentationRuntime);
127+
LLDB_LOG(log_category, Args...);
128+
return T();
129+
}
130+
131+
template <typename... ArgTys>
132+
[[nodiscard]] ComputedStopInfo LogBeforeReturnCSI(ArgTys &&...Args) {
133+
return LogBeforeReturn<ComputedStopInfo>(Args...);
134+
}
135+
136+
ComputedStopInfo
122137
InstrumentationBoundsSafetyStopInfo::ComputeStopReasonAndSuggestedStackFrame(
123138
bool &warning_emitted_for_failure) {
124-
Log *log_category = GetLog(LLDBLog::InstrumentationRuntime);
125139
ThreadSP thread_sp = GetThread();
126-
if (!thread_sp) {
127-
LLDB_LOG(log_category, "failed to get thread while stopped");
128-
return {};
129-
}
140+
if (!thread_sp)
141+
return LogBeforeReturnCSI("failed to get thread while stopped");
130142

131143
lldb::user_id_t debugger_id =
132144
thread_sp->GetProcess()->GetTarget().GetDebugger().GetID();
133145

134146
StackFrameSP parent_sf = thread_sp->GetStackFrameAtIndex(1);
135-
if (!parent_sf) {
136-
LLDB_LOG(log_category, "got nullptr when fetching stackframe at index 1");
137-
return {};
138-
}
147+
if (!parent_sf)
148+
return LogBeforeReturnCSI(
149+
"got nullptr when fetching stackframe at index 1");
139150

140151
if (parent_sf->HasDebugInformation())
141152
return ComputeStopReasonAndSuggestedStackFrameWithDebugInfo(
@@ -147,8 +158,7 @@ InstrumentationBoundsSafetyStopInfo::ComputeStopReasonAndSuggestedStackFrame(
147158
thread_sp, debugger_id, warning_emitted_for_failure);
148159
}
149160

150-
std::pair<std::string, std::optional<uint32_t>>
151-
InstrumentationBoundsSafetyStopInfo::
161+
ComputedStopInfo InstrumentationBoundsSafetyStopInfo::
152162
ComputeStopReasonAndSuggestedStackFrameWithDebugInfo(
153163
lldb::StackFrameSP parent_sf, lldb::user_id_t debugger_id,
154164
bool &warning_emitted_for_failure) {
@@ -165,13 +175,11 @@ InstrumentationBoundsSafetyStopInfo::
165175

166176
auto MaybeTrapReason =
167177
clang::CodeGen::DemangleTrapReasonInDebugInfo(TrapReasonFuncName);
168-
if (!MaybeTrapReason.has_value()) {
169-
LLDB_LOG(
170-
GetLog(LLDBLog::InstrumentationRuntime),
178+
if (!MaybeTrapReason.has_value())
179+
return LogBeforeReturnCSI(
171180
"clang::CodeGen::DemangleTrapReasonInDebugInfo(\"{0}\") call failed",
172181
TrapReasonFuncName);
173-
return {};
174-
}
182+
175183
llvm::StringRef category = MaybeTrapReason.value().first;
176184
llvm::StringRef message = MaybeTrapReason.value().second;
177185

@@ -198,18 +206,15 @@ InstrumentationBoundsSafetyStopInfo::
198206
return std::make_pair(stop_reason, parent_sf->GetFrameIndex() + 1);
199207
}
200208

201-
std::pair<std::optional<std::string>, std::optional<uint32_t>>
202-
InstrumentationBoundsSafetyStopInfo::
209+
ComputedStopInfo InstrumentationBoundsSafetyStopInfo::
203210
ComputeStopReasonAndSuggestedStackFrameWithoutDebugInfo(
204211
ThreadSP thread_sp, lldb::user_id_t debugger_id,
205212
bool &warning_emitted_for_failure) {
206213

207-
Log *log_category = GetLog(LLDBLog::InstrumentationRuntime);
208214
StackFrameSP softtrap_sf = thread_sp->GetStackFrameAtIndex(0);
209-
if (!softtrap_sf) {
210-
LLDB_LOG(log_category, "got nullptr when fetching stackframe at index 0");
211-
return {};
212-
}
215+
if (!softtrap_sf)
216+
return LogBeforeReturnCSI(
217+
"got nullptr when fetching stackframe at index 0");
213218
llvm::StringRef trap_reason_func_name = softtrap_sf->GetFunctionName();
214219

215220
if (trap_reason_func_name == BoundsSafetySoftTrapMinimal) {
@@ -242,29 +247,25 @@ InstrumentationBoundsSafetyStopInfo::
242247
// __bounds_safety_soft_trap_s has one argument which is a pointer to a string
243248
// describing the trap or a nullptr.
244249
if (trap_reason_func_name != BoundsSafetySoftTrapStr) {
245-
LLDB_LOG(log_category,
246-
"unexpected function name. Expected \"{0}\" but got \"{1}\"",
247-
BoundsSafetySoftTrapStr.data(), trap_reason_func_name.data());
248250
assert(0 && "hit breakpoint for unexpected function name");
249-
return {};
251+
return LogBeforeReturnCSI(
252+
"unexpected function name. Expected \"{0}\" but got \"{1}\"",
253+
BoundsSafetySoftTrapStr.data(), trap_reason_func_name.data());
250254
}
251255

252256
RegisterContextSP rc = thread_sp->GetRegisterContext();
253-
if (!rc) {
254-
LLDB_LOG(log_category, "failed to get register context");
255-
return {};
256-
}
257+
if (!rc)
258+
return LogBeforeReturnCSI("failed to get register context");
257259

258260
// FIXME: LLDB should have an API that tells us for the current target if
259261
// `LLDB_REGNUM_GENERIC_ARG1` can be used.
260262
// https://github.com/llvm/llvm-project/issues/168602
261263
// Don't try for architectures where examining the first register won't
262264
// work.
263265
ProcessSP process = thread_sp->GetProcess();
264-
if (!process) {
265-
LLDB_LOG(log_category, "failed to get process");
266-
return {};
267-
}
266+
if (!process)
267+
return LogBeforeReturnCSI("failed to get process");
268+
268269
switch (process->GetTarget().GetArchitecture().GetCore()) {
269270
case ArchSpec::eCore_x86_32_i386:
270271
case ArchSpec::eCore_x86_32_i486:
@@ -288,22 +289,16 @@ InstrumentationBoundsSafetyStopInfo::
288289
// Examine the register for the first argument.
289290
const RegisterInfo *arg0_info = rc->GetRegisterInfo(
290291
lldb::RegisterKind::eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
291-
if (!arg0_info) {
292-
LLDB_LOG(log_category,
293-
"failed to get register info for LLDB_REGNUM_GENERIC_ARG1");
294-
return {};
295-
}
292+
if (!arg0_info)
293+
return LogBeforeReturnCSI(
294+
"failed to get register info for LLDB_REGNUM_GENERIC_ARG1");
296295
RegisterValue reg_value;
297-
if (!rc->ReadRegister(arg0_info, reg_value)) {
298-
LLDB_LOG(log_category, "failed to read register {0}", arg0_info->name);
299-
return {};
300-
}
296+
if (!rc->ReadRegister(arg0_info, reg_value))
297+
return LogBeforeReturnCSI("failed to read register {0}", arg0_info->name);
301298
uint64_t reg_value_as_int = reg_value.GetAsUInt64(UINT64_MAX);
302-
if (reg_value_as_int == UINT64_MAX) {
303-
LLDB_LOG(log_category, "failed to read register {0} as a UInt64",
304-
arg0_info->name);
305-
return {};
306-
}
299+
if (reg_value_as_int == UINT64_MAX)
300+
return LogBeforeReturnCSI("failed to read register {0} as a UInt64",
301+
arg0_info->name);
307302

308303
if (reg_value_as_int == 0) {
309304
// nullptr arg. The compiler will pass that if no trap reason string was
@@ -322,12 +317,11 @@ InstrumentationBoundsSafetyStopInfo::
322317
Status error_status;
323318
thread_sp->GetProcess()->ReadCStringFromMemory(reg_value_as_int, out_string,
324319
error_status);
325-
if (error_status.Fail()) {
326-
LLDB_LOG(log_category, "failed to read C string from address {0}",
327-
(void *)reg_value_as_int);
328-
return {};
329-
}
330-
LLDB_LOG(log_category,
320+
if (error_status.Fail())
321+
return LogBeforeReturnCSI("failed to read C string from address {0}",
322+
(void *)reg_value_as_int);
323+
324+
LLDB_LOG(GetLog(LLDBLog::InstrumentationRuntime),
331325
"read C string from {0} found in register {1}: \"{2}\"",
332326
(void *)reg_value_as_int, arg0_info->name, out_string.c_str());
333327
std::string stop_reason;
@@ -402,31 +396,23 @@ bool InstrumentationRuntimeBoundsSafety::NotifyBreakpointHit(
402396
InstrumentationRuntimeBoundsSafety *const instance =
403397
static_cast<InstrumentationRuntimeBoundsSafety *>(baton);
404398

405-
Log *log_category = GetLog(LLDBLog::InstrumentationRuntime);
406399
ProcessSP process_sp = instance->GetProcessSP();
407-
if (!process_sp) {
408-
LLDB_LOG(log_category, "failed to get process from baton");
409-
return false;
410-
}
400+
if (!process_sp)
401+
return LogBeforeReturn<bool>("failed to get process from baton");
411402
ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP();
412-
if (!thread_sp) {
413-
LLDB_LOG(log_category,
414-
"failed to get thread from StoppointCallbackContext");
415-
return false;
416-
}
417-
if (process_sp != context->exe_ctx_ref.GetProcessSP()) {
418-
LLDB_LOG(log_category,
419-
"process from baton ({0}) and StoppointCallbackContext ({1}) do "
420-
"not match",
421-
(void *)process_sp.get(),
422-
(void *)context->exe_ctx_ref.GetProcessSP().get());
423-
return false;
424-
}
403+
if (!thread_sp)
404+
return LogBeforeReturn<bool>(
405+
"failed to get thread from StoppointCallbackContext");
425406

426-
if (process_sp->GetModIDRef().IsLastResumeForUserExpression()) {
427-
LLDB_LOG(log_category, "IsLastResumeForUserExpression is true");
428-
return false;
429-
}
407+
if (process_sp != context->exe_ctx_ref.GetProcessSP())
408+
return LogBeforeReturn<bool>(
409+
"process from baton ({0}) and StoppointCallbackContext ({1}) do "
410+
"not match",
411+
(void *)process_sp.get(),
412+
(void *)context->exe_ctx_ref.GetProcessSP().get());
413+
414+
if (process_sp->GetModIDRef().IsLastResumeForUserExpression())
415+
return LogBeforeReturn<bool>("IsLastResumeForUserExpression is true");
430416

431417
// Maybe the stop reason and stackframe selection should be done by
432418
// a stackframe recognizer instead?
@@ -440,12 +426,9 @@ void InstrumentationRuntimeBoundsSafety::Activate() {
440426
if (IsActive())
441427
return;
442428

443-
Log *log_category = GetLog(LLDBLog::InstrumentationRuntime);
444429
ProcessSP process_sp = GetProcessSP();
445-
if (!process_sp) {
446-
LLDB_LOG(log_category, "could not get process during Activate()");
447-
return;
448-
}
430+
if (!process_sp)
431+
return LogBeforeReturn<void>("could not get process during Activate()");
449432

450433
BreakpointSP breakpoint = process_sp->GetTarget().CreateBreakpoint(
451434
/*containingModules=*/nullptr,
@@ -457,15 +440,15 @@ void InstrumentationRuntimeBoundsSafety::Activate() {
457440
/*request_hardware*/ false);
458441

459442
if (!breakpoint)
460-
return;
443+
return LogBeforeReturn<void>("failed to create breakpoint");
444+
461445
if (!breakpoint->HasResolvedLocations()) {
462-
LLDB_LOG(log_category,
463-
"breakpoint {0} for BoundsSafety soft traps did not resolve to "
464-
"any locations",
465-
breakpoint->GetID());
466446
assert(0 && "breakpoint has no resolved locations");
467447
process_sp->GetTarget().RemoveBreakpointByID(breakpoint->GetID());
468-
return;
448+
return LogBeforeReturn<void>(
449+
"breakpoint {0} for BoundsSafety soft traps did not resolve to "
450+
"any locations",
451+
breakpoint->GetID());
469452
}
470453

471454
// Note: When `sync=true` the suggested stackframe is completely ignored. So
@@ -475,7 +458,8 @@ void InstrumentationRuntimeBoundsSafety::Activate() {
475458
/*sync=*/false);
476459
breakpoint->SetBreakpointKind("bounds-safety-soft-trap");
477460
SetBreakpointID(breakpoint->GetID());
478-
LLDB_LOG(log_category, "created breakpoint {0} for BoundsSafety soft traps",
461+
LLDB_LOG(GetLog(LLDBLog::InstrumentationRuntime),
462+
"created breakpoint {0} for BoundsSafety soft traps",
479463
breakpoint->GetID());
480464
SetActive(true);
481465
}

0 commit comments

Comments
 (0)