The new test fails on x86 and arm64 public macOS bots: ``` 09:27:59 ====================================================================== 09:27:59 FAIL: test_append_frames (TestScriptedFrameProvider.ScriptedFrameProviderTestCase) 09:27:59 Test that we can add frames after real stack. 09:27:59 ---------------------------------------------------------------------- 09:27:59 Traceback (most recent call last): 09:27:59 File "/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/llvm-project/lldb/test/API/functionalities/scripted_frame_provider/TestScriptedFrameProvider.py", line 122, in test_append_frames 09:27:59 self.assertEqual(new_frame_count, original_frame_count + 1) 09:27:59 AssertionError: 5 != 6 09:27:59 Config=arm64-/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/lldb-build/bin/clang 09:27:59 ====================================================================== 09:27:59 FAIL: test_applies_to_thread (TestScriptedFrameProvider.ScriptedFrameProviderTestCase) 09:27:59 Test that applies_to_thread filters which threads get the provider. 09:27:59 ---------------------------------------------------------------------- 09:27:59 Traceback (most recent call last): 09:27:59 File "/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/llvm-project/lldb/test/API/functionalities/scripted_frame_provider/TestScriptedFrameProvider.py", line 218, in test_applies_to_thread 09:27:59 self.assertEqual( 09:27:59 AssertionError: 5 != 1 : Thread with ID 1 should have 1 synthetic frame 09:27:59 Config=arm64-/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/lldb-build/bin/clang 09:27:59 ====================================================================== 09:27:59 FAIL: test_prepend_frames (TestScriptedFrameProvider.ScriptedFrameProviderTestCase) 09:27:59 Test that we can add frames before real stack. 09:27:59 ---------------------------------------------------------------------- 09:27:59 Traceback (most recent call last): 09:27:59 File "/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/llvm-project/lldb/test/API/functionalities/scripted_frame_provider/TestScriptedFrameProvider.py", line 84, in test_prepend_frames 09:27:59 self.assertEqual(new_frame_count, original_frame_count + 2) 09:27:59 AssertionError: 5 != 7 09:27:59 Config=arm64-/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/lldb-build/bin/clang 09:27:59 ====================================================================== 09:27:59 FAIL: test_remove_frame_provider_by_id (TestScriptedFrameProvider.ScriptedFrameProviderTestCase) 09:27:59 Test that RemoveScriptedFrameProvider removes a specific provider by ID. 09:27:59 ---------------------------------------------------------------------- 09:27:59 Traceback (most recent call last): 09:27:59 File "/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/llvm-project/lldb/test/API/functionalities/scripted_frame_provider/TestScriptedFrameProvider.py", line 272, in test_remove_frame_provider_by_id 09:27:59 self.assertEqual(thread.GetNumFrames(), 3, "Should have 3 synthetic frames") 09:27:59 AssertionError: 5 != 3 : Should have 3 synthetic frames 09:27:59 Config=arm64-/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/lldb-build/bin/clang 09:27:59 ====================================================================== 09:27:59 FAIL: test_replace_all_frames (TestScriptedFrameProvider.ScriptedFrameProviderTestCase) 09:27:59 Test that we can replace the entire stack. 09:27:59 ---------------------------------------------------------------------- 09:27:59 Traceback (most recent call last): 09:27:59 File "/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/llvm-project/lldb/test/API/functionalities/scripted_frame_provider/TestScriptedFrameProvider.py", line 41, in test_replace_all_frames 09:27:59 self.assertEqual(thread.GetNumFrames(), 3, "Should have 3 synthetic frames") 09:27:59 AssertionError: 5 != 3 : Should have 3 synthetic frames 09:27:59 Config=arm64-/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/lldb-build/bin/clang 09:27:59 ====================================================================== 09:27:59 FAIL: test_scripted_frame_objects (TestScriptedFrameProvider.ScriptedFrameProviderTestCase) 09:27:59 Test that provider can return ScriptedFrame objects. 09:27:59 ---------------------------------------------------------------------- 09:27:59 Traceback (most recent call last): 09:27:59 File "/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/llvm-project/lldb/test/API/functionalities/scripted_frame_provider/TestScriptedFrameProvider.py", line 159, in test_scripted_frame_objects 09:27:59 self.assertEqual(frame0.GetFunctionName(), "custom_scripted_frame_0") 09:27:59 AssertionError: 'thread_func(int)' != 'custom_scripted_frame_0' 09:27:59 - thread_func(int) 09:27:59 + custom_scripted_frame_0 09:27:59 09:27:59 Config=arm64-/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/lldb-build/bin/clang 09:27:59 ---------------------------------------------------------------------- 09:27:59 Ran 6 tests in 14.242s 09:27:59 09:27:59 FAILED (failures=6) ``` Reverts llvm/llvm-project#161870
192 lines
6.8 KiB
C++
192 lines
6.8 KiB
C++
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "ScriptedFrame.h"
|
|
|
|
#include "lldb/Utility/DataBufferHeap.h"
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
|
|
void ScriptedFrame::CheckInterpreterAndScriptObject() const {
|
|
lldbassert(m_script_object_sp && "Invalid Script Object.");
|
|
lldbassert(GetInterface() && "Invalid Scripted Frame Interface.");
|
|
}
|
|
|
|
llvm::Expected<std::shared_ptr<ScriptedFrame>>
|
|
ScriptedFrame::Create(ScriptedThread &thread,
|
|
StructuredData::DictionarySP args_sp,
|
|
StructuredData::Generic *script_object) {
|
|
if (!thread.IsValid())
|
|
return llvm::createStringError("Invalid scripted thread.");
|
|
|
|
thread.CheckInterpreterAndScriptObject();
|
|
|
|
auto scripted_frame_interface =
|
|
thread.GetInterface()->CreateScriptedFrameInterface();
|
|
if (!scripted_frame_interface)
|
|
return llvm::createStringError("failed to create scripted frame interface");
|
|
|
|
llvm::StringRef frame_class_name;
|
|
if (!script_object) {
|
|
std::optional<std::string> class_name =
|
|
thread.GetInterface()->GetScriptedFramePluginName();
|
|
if (!class_name || class_name->empty())
|
|
return llvm::createStringError(
|
|
"failed to get scripted thread class name");
|
|
frame_class_name = *class_name;
|
|
}
|
|
|
|
ExecutionContext exe_ctx(thread);
|
|
auto obj_or_err = scripted_frame_interface->CreatePluginObject(
|
|
frame_class_name, exe_ctx, args_sp, script_object);
|
|
|
|
if (!obj_or_err)
|
|
return llvm::createStringError(
|
|
"failed to create script object: %s",
|
|
llvm::toString(obj_or_err.takeError()).c_str());
|
|
|
|
StructuredData::GenericSP owned_script_object_sp = *obj_or_err;
|
|
|
|
if (!owned_script_object_sp->IsValid())
|
|
return llvm::createStringError("created script object is invalid");
|
|
|
|
lldb::user_id_t frame_id = scripted_frame_interface->GetID();
|
|
|
|
lldb::addr_t pc = scripted_frame_interface->GetPC();
|
|
SymbolContext sc;
|
|
Address symbol_addr;
|
|
if (pc != LLDB_INVALID_ADDRESS) {
|
|
symbol_addr.SetLoadAddress(pc, &thread.GetProcess()->GetTarget());
|
|
symbol_addr.CalculateSymbolContext(&sc);
|
|
}
|
|
|
|
std::optional<SymbolContext> maybe_sym_ctx =
|
|
scripted_frame_interface->GetSymbolContext();
|
|
if (maybe_sym_ctx) {
|
|
sc = *maybe_sym_ctx;
|
|
}
|
|
|
|
StructuredData::DictionarySP reg_info =
|
|
scripted_frame_interface->GetRegisterInfo();
|
|
|
|
if (!reg_info)
|
|
return llvm::createStringError(
|
|
"failed to get scripted thread registers info");
|
|
|
|
std::shared_ptr<DynamicRegisterInfo> register_info_sp =
|
|
DynamicRegisterInfo::Create(
|
|
*reg_info, thread.GetProcess()->GetTarget().GetArchitecture());
|
|
|
|
lldb::RegisterContextSP reg_ctx_sp;
|
|
|
|
std::optional<std::string> reg_data =
|
|
scripted_frame_interface->GetRegisterContext();
|
|
if (reg_data) {
|
|
DataBufferSP data_sp(
|
|
std::make_shared<DataBufferHeap>(reg_data->c_str(), reg_data->size()));
|
|
|
|
if (!data_sp->GetByteSize())
|
|
return llvm::createStringError("failed to copy raw registers data");
|
|
|
|
std::shared_ptr<RegisterContextMemory> reg_ctx_memory =
|
|
std::make_shared<RegisterContextMemory>(
|
|
thread, frame_id, *register_info_sp, LLDB_INVALID_ADDRESS);
|
|
if (!reg_ctx_memory)
|
|
return llvm::createStringError("failed to create a register context.");
|
|
|
|
reg_ctx_memory->SetAllRegisterData(data_sp);
|
|
reg_ctx_sp = reg_ctx_memory;
|
|
}
|
|
|
|
return std::make_shared<ScriptedFrame>(
|
|
thread, scripted_frame_interface, frame_id, pc, sc, reg_ctx_sp,
|
|
register_info_sp, owned_script_object_sp);
|
|
}
|
|
|
|
ScriptedFrame::ScriptedFrame(ScriptedThread &thread,
|
|
ScriptedFrameInterfaceSP interface_sp,
|
|
lldb::user_id_t id, lldb::addr_t pc,
|
|
SymbolContext &sym_ctx,
|
|
lldb::RegisterContextSP reg_ctx_sp,
|
|
std::shared_ptr<DynamicRegisterInfo> reg_info_sp,
|
|
StructuredData::GenericSP script_object_sp)
|
|
: StackFrame(thread.shared_from_this(), /*frame_idx=*/id,
|
|
/*concrete_frame_idx=*/id, /*reg_context_sp=*/reg_ctx_sp,
|
|
/*cfa=*/0, /*pc=*/pc,
|
|
/*behaves_like_zeroth_frame=*/!id, /*symbol_ctx=*/&sym_ctx),
|
|
m_scripted_frame_interface_sp(interface_sp),
|
|
m_script_object_sp(script_object_sp), m_register_info_sp(reg_info_sp) {}
|
|
|
|
ScriptedFrame::~ScriptedFrame() {}
|
|
|
|
const char *ScriptedFrame::GetFunctionName() {
|
|
CheckInterpreterAndScriptObject();
|
|
std::optional<std::string> function_name = GetInterface()->GetFunctionName();
|
|
if (!function_name)
|
|
return nullptr;
|
|
return ConstString(function_name->c_str()).AsCString();
|
|
}
|
|
|
|
const char *ScriptedFrame::GetDisplayFunctionName() {
|
|
CheckInterpreterAndScriptObject();
|
|
std::optional<std::string> function_name =
|
|
GetInterface()->GetDisplayFunctionName();
|
|
if (!function_name)
|
|
return nullptr;
|
|
return ConstString(function_name->c_str()).AsCString();
|
|
}
|
|
|
|
bool ScriptedFrame::IsInlined() { return GetInterface()->IsInlined(); }
|
|
|
|
bool ScriptedFrame::IsArtificial() const {
|
|
return GetInterface()->IsArtificial();
|
|
}
|
|
|
|
bool ScriptedFrame::IsHidden() { return GetInterface()->IsHidden(); }
|
|
|
|
lldb::ScriptedFrameInterfaceSP ScriptedFrame::GetInterface() const {
|
|
return m_scripted_frame_interface_sp;
|
|
}
|
|
|
|
std::shared_ptr<DynamicRegisterInfo> ScriptedFrame::GetDynamicRegisterInfo() {
|
|
CheckInterpreterAndScriptObject();
|
|
|
|
if (!m_register_info_sp) {
|
|
StructuredData::DictionarySP reg_info = GetInterface()->GetRegisterInfo();
|
|
|
|
Status error;
|
|
if (!reg_info)
|
|
return ScriptedInterface::ErrorWithMessage<
|
|
std::shared_ptr<DynamicRegisterInfo>>(
|
|
LLVM_PRETTY_FUNCTION, "Failed to get scripted frame registers info.",
|
|
error, LLDBLog::Thread);
|
|
|
|
ThreadSP thread_sp = m_thread_wp.lock();
|
|
if (!thread_sp || !thread_sp->IsValid())
|
|
return ScriptedInterface::ErrorWithMessage<
|
|
std::shared_ptr<DynamicRegisterInfo>>(
|
|
LLVM_PRETTY_FUNCTION,
|
|
"Failed to get scripted frame registers info: invalid thread.", error,
|
|
LLDBLog::Thread);
|
|
|
|
ProcessSP process_sp = thread_sp->GetProcess();
|
|
if (!process_sp || !process_sp->IsValid())
|
|
return ScriptedInterface::ErrorWithMessage<
|
|
std::shared_ptr<DynamicRegisterInfo>>(
|
|
LLVM_PRETTY_FUNCTION,
|
|
"Failed to get scripted frame registers info: invalid process.",
|
|
error, LLDBLog::Thread);
|
|
|
|
m_register_info_sp = DynamicRegisterInfo::Create(
|
|
*reg_info, process_sp->GetTarget().GetArchitecture());
|
|
}
|
|
|
|
return m_register_info_sp;
|
|
}
|