Importing rustc-1.56.0
Change-Id: I98941481270706fa55f8fb2cb91686ae3bd30f38
diff --git a/src/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp b/src/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp
index 7cae4cc..42d73ce 100644
--- a/src/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp
@@ -11,6 +11,7 @@
#include "ABISysV_arm64.h"
#include "Utility/ARM64_DWARF_Registers.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Target/Process.h"
LLDB_PLUGIN_DEFINE(ABIAArch64)
@@ -24,6 +25,18 @@
ABIMacOSX_arm64::Terminate();
}
+lldb::addr_t ABIAArch64::FixCodeAddress(lldb::addr_t pc) {
+ if (lldb::ProcessSP process_sp = GetProcessSP())
+ return FixAddress(pc, process_sp->GetCodeAddressMask());
+ return pc;
+}
+
+lldb::addr_t ABIAArch64::FixDataAddress(lldb::addr_t pc) {
+ if (lldb::ProcessSP process_sp = GetProcessSP())
+ return FixAddress(pc, process_sp->GetDataAddressMask());
+ return pc;
+}
+
std::pair<uint32_t, uint32_t>
ABIAArch64::GetEHAndDWARFNums(llvm::StringRef name) {
if (name == "pc")
diff --git a/src/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIAArch64.h b/src/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIAArch64.h
index bdff648..41bbf5c 100644
--- a/src/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIAArch64.h
+++ b/src/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIAArch64.h
@@ -16,7 +16,14 @@
static void Initialize();
static void Terminate();
+ virtual lldb::addr_t FixCodeAddress(lldb::addr_t pc) override;
+ virtual lldb::addr_t FixDataAddress(lldb::addr_t pc) override;
+
protected:
+ virtual lldb::addr_t FixAddress(lldb::addr_t pc, lldb::addr_t mask) {
+ return pc;
+ }
+
std::pair<uint32_t, uint32_t>
GetEHAndDWARFNums(llvm::StringRef name) override;
diff --git a/src/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp b/src/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp
index 09b319a..348a081 100644
--- a/src/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp
@@ -66,7 +66,7 @@
if (log) {
StreamString s;
- s.Printf("ABISysV_x86_64::PrepareTrivialCall (tid = 0x%" PRIx64
+ s.Printf("ABIMacOSX_arm64::PrepareTrivialCall (tid = 0x%" PRIx64
", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64
", return_addr = 0x%" PRIx64,
thread.GetID(), (uint64_t)sp, (uint64_t)func_addr,
@@ -86,7 +86,7 @@
eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
// x0 - x7 contain first 8 simple args
- if (args.size() > 8) // TODO handle more than 6 arguments
+ if (args.size() > 8) // TODO handle more than 8 arguments
return false;
for (size_t i = 0; i < args.size(); ++i) {
@@ -384,6 +384,7 @@
row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
row->SetOffset(0);
+ row->SetUnspecifiedRegistersAreUndefined(true);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
@@ -654,7 +655,7 @@
const uint32_t type_flags = return_compiler_type.GetTypeInfo(nullptr);
if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) {
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
bool success = false;
if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) {
@@ -814,6 +815,11 @@
return return_valobj_sp;
}
+lldb::addr_t ABIMacOSX_arm64::FixAddress(addr_t pc, addr_t mask) {
+ lldb::addr_t pac_sign_extension = 0x0080000000000000ULL;
+ return (pc & pac_sign_extension) ? pc | mask : pc & (~mask);
+}
+
void ABIMacOSX_arm64::Initialize() {
PluginManager::RegisterPlugin(GetPluginNameStatic(), pluginDesc,
CreateInstance);
diff --git a/src/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h b/src/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h
index fc8ccee..dc3ab35 100644
--- a/src/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h
+++ b/src/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h
@@ -62,6 +62,8 @@
return true;
}
+ lldb::addr_t FixAddress(lldb::addr_t pc, lldb::addr_t mask) override;
+
// Static Functions
static void Initialize();
diff --git a/src/llvm-project/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp b/src/llvm-project/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp
index 1214195..16fb38e 100644
--- a/src/llvm-project/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp
@@ -356,6 +356,7 @@
row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
row->SetOffset(0);
+ row->SetUnspecifiedRegistersAreUndefined(true);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
@@ -622,7 +623,7 @@
const uint32_t type_flags = return_compiler_type.GetTypeInfo(nullptr);
if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) {
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
bool success = false;
if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) {
@@ -781,6 +782,61 @@
return return_valobj_sp;
}
+lldb::addr_t ABISysV_arm64::FixAddress(addr_t pc, addr_t mask) {
+ lldb::addr_t pac_sign_extension = 0x0080000000000000ULL;
+ return (pc & pac_sign_extension) ? pc | mask : pc & (~mask);
+}
+
+// Reads code or data address mask for the current Linux process.
+static lldb::addr_t ReadLinuxProcessAddressMask(lldb::ProcessSP process_sp,
+ llvm::StringRef reg_name) {
+ // Linux configures user-space virtual addresses with top byte ignored.
+ // We set default value of mask such that top byte is masked out.
+ uint64_t address_mask = ~((1ULL << 56) - 1);
+ // If Pointer Authentication feature is enabled then Linux exposes
+ // PAC data and code mask register. Try reading relevant register
+ // below and merge it with default address mask calculated above.
+ lldb::ThreadSP thread_sp = process_sp->GetThreadList().GetSelectedThread();
+ if (thread_sp) {
+ lldb::RegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext();
+ if (reg_ctx_sp) {
+ const RegisterInfo *reg_info =
+ reg_ctx_sp->GetRegisterInfoByName(reg_name, 0);
+ if (reg_info) {
+ lldb::addr_t mask_reg_val = reg_ctx_sp->ReadRegisterAsUnsigned(
+ reg_info->kinds[eRegisterKindLLDB], LLDB_INVALID_ADDRESS);
+ if (mask_reg_val != LLDB_INVALID_ADDRESS)
+ address_mask |= mask_reg_val;
+ }
+ }
+ }
+ return address_mask;
+}
+
+lldb::addr_t ABISysV_arm64::FixCodeAddress(lldb::addr_t pc) {
+ if (lldb::ProcessSP process_sp = GetProcessSP()) {
+ if (process_sp->GetTarget().GetArchitecture().GetTriple().isOSLinux() &&
+ !process_sp->GetCodeAddressMask())
+ process_sp->SetCodeAddressMask(
+ ReadLinuxProcessAddressMask(process_sp, "code_mask"));
+
+ return FixAddress(pc, process_sp->GetCodeAddressMask());
+ }
+ return pc;
+}
+
+lldb::addr_t ABISysV_arm64::FixDataAddress(lldb::addr_t pc) {
+ if (lldb::ProcessSP process_sp = GetProcessSP()) {
+ if (process_sp->GetTarget().GetArchitecture().GetTriple().isOSLinux() &&
+ !process_sp->GetDataAddressMask())
+ process_sp->SetDataAddressMask(
+ ReadLinuxProcessAddressMask(process_sp, "data_mask"));
+
+ return FixAddress(pc, process_sp->GetDataAddressMask());
+ }
+ return pc;
+}
+
void ABISysV_arm64::Initialize() {
PluginManager::RegisterPlugin(GetPluginNameStatic(),
"SysV ABI for AArch64 targets", CreateInstance);
diff --git a/src/llvm-project/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h b/src/llvm-project/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h
index aeb74ac..3428a7a 100644
--- a/src/llvm-project/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h
+++ b/src/llvm-project/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h
@@ -67,6 +67,8 @@
bool GetPointerReturnRegister(const char *&name) override;
+ lldb::addr_t FixAddress(lldb::addr_t pc, lldb::addr_t mask) override;
+
// Static Functions
static void Initialize();
@@ -83,6 +85,9 @@
uint32_t GetPluginVersion() override;
+ lldb::addr_t FixCodeAddress(lldb::addr_t pc) override;
+ lldb::addr_t FixDataAddress(lldb::addr_t pc) override;
+
protected:
lldb::ValueObjectSP
GetReturnValueObjectImpl(lldb_private::Thread &thread,
diff --git a/src/llvm-project/lldb/source/Plugins/ABI/ARC/ABISysV_arc.cpp b/src/llvm-project/lldb/source/Plugins/ABI/ARC/ABISysV_arc.cpp
index be85867..60cdbc5 100644
--- a/src/llvm-project/lldb/source/Plugins/ABI/ARC/ABISysV_arc.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ABI/ARC/ABISysV_arc.cpp
@@ -466,7 +466,7 @@
if (!SetSizedInteger(value.GetScalar(), raw_value, byte_size, is_signed))
return ValueObjectSP();
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
}
// Pointer return type.
else if (type_flags & eTypeIsPointer) {
@@ -474,7 +474,7 @@
LLDB_REGNUM_GENERIC_ARG1);
value.GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_r0, 0);
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
}
// Floating point return type.
else if (type_flags & eTypeIsFloat) {
@@ -537,7 +537,7 @@
auto reg_info_r0 = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,
LLDB_REGNUM_GENERIC_ARG1);
value.GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_r0, 0);
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
}
// Floating point return type.
else if (retType.isFloatingPointTy()) {
diff --git a/src/llvm-project/lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.cpp b/src/llvm-project/lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.cpp
index 06c4590..e429f3e 100644
--- a/src/llvm-project/lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.cpp
@@ -1824,6 +1824,7 @@
row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
row->SetOffset(0);
+ row->SetUnspecifiedRegistersAreUndefined(true);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
diff --git a/src/llvm-project/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp b/src/llvm-project/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp
index 26b3152..3e544e0 100644
--- a/src/llvm-project/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp
@@ -1617,7 +1617,7 @@
thread.GetRegisterContext()->ReadRegisterAsUnsigned(r0_reg_info, 0) &
UINT32_MAX;
value.GetScalar() = ptr;
- } else if (compiler_type.IsVectorType(nullptr, nullptr)) {
+ } else if (compiler_type.IsVectorType()) {
if (IsArmHardFloat(thread) && (*byte_size == 8 || *byte_size == 16)) {
is_vfp_candidate = true;
vfp_byte_size = 8;
@@ -1704,7 +1704,7 @@
if (homogeneous_count > 0 && homogeneous_count <= 4) {
llvm::Optional<uint64_t> base_byte_size =
base_type.GetByteSize(&thread);
- if (base_type.IsVectorType(nullptr, nullptr)) {
+ if (base_type.IsVectorType()) {
if (base_byte_size &&
(*base_byte_size == 8 || *base_byte_size == 16)) {
is_vfp_candidate = true;
@@ -1940,6 +1940,7 @@
row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
row->SetOffset(0);
+ row->SetUnspecifiedRegistersAreUndefined(true);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
diff --git a/src/llvm-project/lldb/source/Plugins/ABI/Hexagon/ABISysV_hexagon.cpp b/src/llvm-project/lldb/source/Plugins/ABI/Hexagon/ABISysV_hexagon.cpp
index 47aaefd..6794f7d 100644
--- a/src/llvm-project/lldb/source/Plugins/ABI/Hexagon/ABISysV_hexagon.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ABI/Hexagon/ABISysV_hexagon.cpp
@@ -1225,6 +1225,7 @@
UnwindPlan::RowSP row(new UnwindPlan::Row);
+ row->SetUnspecifiedRegistersAreUndefined(true);
row->GetCFAValue().SetIsRegisterPlusOffset(LLDB_REGNUM_GENERIC_FP, 8);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, -8, true);
diff --git a/src/llvm-project/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp b/src/llvm-project/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp
index d66e092..538ec06 100644
--- a/src/llvm-project/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp
@@ -985,6 +985,7 @@
UnwindPlan::RowSP row(new UnwindPlan::Row);
+ row->SetUnspecifiedRegistersAreUndefined(true);
row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
diff --git a/src/llvm-project/lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp b/src/llvm-project/lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp
index 7515557..7220508 100644
--- a/src/llvm-project/lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp
@@ -764,7 +764,7 @@
const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);
if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) {
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
bool success = false;
if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) {
@@ -1156,6 +1156,7 @@
UnwindPlan::RowSP row(new UnwindPlan::Row);
+ row->SetUnspecifiedRegistersAreUndefined(true);
row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
diff --git a/src/llvm-project/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp b/src/llvm-project/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp
index 91d2e59..98a14b5 100644
--- a/src/llvm-project/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp
@@ -520,7 +520,7 @@
const uint32_t type_flags = return_compiler_type.GetTypeInfo();
if (type_flags & eTypeIsScalar) {
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
bool success = false;
if (type_flags & eTypeIsInteger) {
@@ -603,7 +603,7 @@
reg_ctx->GetRegisterInfoByName("r3", 0)->kinds[eRegisterKindLLDB];
value.GetScalar() =
(uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r3_id, 0);
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
return_valobj_sp = ValueObjectConstResult::Create(
thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
} else if (type_flags & eTypeIsVector) {
@@ -683,8 +683,6 @@
r3_value.GetData(r3_data);
rdx_value.GetData(rdx_data);
- uint32_t fp_bytes =
- 0; // Tracks how much of the xmm registers we've consumed so far
uint32_t integer_bytes =
0; // Tracks how much of the r3/rds registers we've consumed so far
@@ -751,7 +749,6 @@
break;
} else if (*field_bit_width == 64) {
copy_from_offset = 0;
- fp_bytes += field_byte_width;
} else if (*field_bit_width == 32) {
// This one is kind of complicated. If we are in an "eightbyte"
// with another float, we'll be stuffed into an xmm register with
@@ -815,8 +812,6 @@
copy_from_offset = integer_bytes - 8;
integer_bytes += field_byte_width;
}
- } else {
- fp_bytes += field_byte_width;
}
}
}
@@ -900,6 +895,7 @@
UnwindPlan::RowSP row(new UnwindPlan::Row);
const int32_t ptr_size = 4;
+ row->SetUnspecifiedRegistersAreUndefined(true);
row->GetCFAValue().SetIsRegisterDereferenced(sp_reg_num);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 1, true);
diff --git a/src/llvm-project/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp b/src/llvm-project/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp
index c7cb773..7cc9482 100644
--- a/src/llvm-project/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp
@@ -577,7 +577,7 @@
ValueSP NewScalarValue(CompilerType &type) {
ValueSP value_sp(new Value);
value_sp->SetCompilerType(type);
- value_sp->SetValueType(Value::eValueTypeScalar);
+ value_sp->SetValueType(Value::ValueType::Scalar);
return value_sp;
}
@@ -1003,6 +1003,7 @@
UnwindPlan::RowSP row(new UnwindPlan::Row);
const int32_t ptr_size = 8;
+ row->SetUnspecifiedRegistersAreUndefined(true);
row->GetCFAValue().SetIsRegisterDereferenced(sp_reg_num);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 2, true);
diff --git a/src/llvm-project/lldb/source/Plugins/ABI/SystemZ/ABISysV_s390x.cpp b/src/llvm-project/lldb/source/Plugins/ABI/SystemZ/ABISysV_s390x.cpp
index 22a6417..88e8511 100644
--- a/src/llvm-project/lldb/source/Plugins/ABI/SystemZ/ABISysV_s390x.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ABI/SystemZ/ABISysV_s390x.cpp
@@ -487,7 +487,7 @@
const uint32_t type_flags = return_compiler_type.GetTypeInfo();
if (type_flags & eTypeIsScalar) {
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
bool success = false;
if (type_flags & eTypeIsInteger) {
@@ -571,7 +571,7 @@
reg_ctx->GetRegisterInfoByName("r2", 0)->kinds[eRegisterKindLLDB];
value.GetScalar() =
(uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_id, 0);
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
return_valobj_sp = ValueObjectConstResult::Create(
thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
}
diff --git a/src/llvm-project/lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.cpp b/src/llvm-project/lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.cpp
index 89112de..461e4af 100644
--- a/src/llvm-project/lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.cpp
@@ -389,6 +389,7 @@
row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
row->SetOffset(0);
+ row->SetUnspecifiedRegistersAreUndefined(true);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
diff --git a/src/llvm-project/lldb/source/Plugins/ABI/X86/ABISysV_i386.cpp b/src/llvm-project/lldb/source/Plugins/ABI/X86/ABISysV_i386.cpp
index 2f47d3f..7d2f0a6 100644
--- a/src/llvm-project/lldb/source/Plugins/ABI/X86/ABISysV_i386.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ABI/X86/ABISysV_i386.cpp
@@ -378,14 +378,14 @@
uint32_t ptr =
thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
0xffffffff;
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
value.GetScalar() = ptr;
return_valobj_sp = ValueObjectConstResult::Create(
thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
} else if ((type_flags & eTypeIsScalar) ||
(type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point'
{
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
llvm::Optional<uint64_t> byte_size =
return_compiler_type.GetByteSize(&thread);
if (!byte_size)
@@ -453,7 +453,7 @@
uint32_t enm =
thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
0xffffffff;
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
value.GetScalar() = enm;
return_valobj_sp = ValueObjectConstResult::Create(
thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
@@ -652,6 +652,7 @@
row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size);
row->SetOffset(0);
+ row->SetUnspecifiedRegistersAreUndefined(true);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
diff --git a/src/llvm-project/lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp b/src/llvm-project/lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp
index 2aa2c02..196b45b 100644
--- a/src/llvm-project/lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp
@@ -399,7 +399,7 @@
const uint32_t type_flags = return_compiler_type.GetTypeInfo();
if (type_flags & eTypeIsScalar) {
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
bool success = false;
if (type_flags & eTypeIsInteger) {
@@ -487,7 +487,7 @@
value.GetScalar() =
(uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id,
0);
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
return_valobj_sp = ValueObjectConstResult::Create(
thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
} else if (type_flags & eTypeIsVector) {
@@ -887,6 +887,7 @@
const int32_t ptr_size = 8;
row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_rbp, 2 * ptr_size);
row->SetOffset(0);
+ row->SetUnspecifiedRegistersAreUndefined(true);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
diff --git a/src/llvm-project/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp b/src/llvm-project/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp
index 06e0ce4..6c473c6 100644
--- a/src/llvm-project/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp
@@ -408,7 +408,7 @@
const uint32_t type_flags = return_compiler_type.GetTypeInfo();
if (type_flags & eTypeIsScalar) {
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
bool success = false;
if (type_flags & eTypeIsInteger) {
@@ -494,7 +494,7 @@
value.GetScalar() =
(uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id,
0);
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
return_valobj_sp = ValueObjectConstResult::Create(
thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
} else if (type_flags & eTypeIsVector) {
@@ -767,6 +767,7 @@
const int32_t ptr_size = 8;
row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_rbp, 2 * ptr_size);
row->SetOffset(0);
+ row->SetUnspecifiedRegistersAreUndefined(true);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
diff --git a/src/llvm-project/lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.cpp b/src/llvm-project/lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.cpp
new file mode 100644
index 0000000..9994cc2
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.cpp
@@ -0,0 +1,45 @@
+//===-- ArchitectureAArch64.cpp -------------------------------------------===//
+//
+// 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 "Plugins/Architecture/AArch64/ArchitectureAArch64.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Utility/ArchSpec.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+LLDB_PLUGIN_DEFINE(ArchitectureAArch64)
+
+ConstString ArchitectureAArch64::GetPluginNameStatic() {
+ return ConstString("aarch64");
+}
+
+void ArchitectureAArch64::Initialize() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ "AArch64-specific algorithms",
+ &ArchitectureAArch64::Create);
+}
+
+void ArchitectureAArch64::Terminate() {
+ PluginManager::UnregisterPlugin(&ArchitectureAArch64::Create);
+}
+
+std::unique_ptr<Architecture>
+ArchitectureAArch64::Create(const ArchSpec &arch) {
+ auto machine = arch.GetMachine();
+ if (machine != llvm::Triple::aarch64 && machine != llvm::Triple::aarch64_be &&
+ machine != llvm::Triple::aarch64_32) {
+ return nullptr;
+ }
+ return std::unique_ptr<Architecture>(new ArchitectureAArch64());
+}
+
+ConstString ArchitectureAArch64::GetPluginName() {
+ return GetPluginNameStatic();
+}
+uint32_t ArchitectureAArch64::GetPluginVersion() { return 1; }
diff --git a/src/llvm-project/lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.h b/src/llvm-project/lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.h
new file mode 100644
index 0000000..775478c
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.h
@@ -0,0 +1,40 @@
+//===-- ArchitectureAArch64.h -----------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_ARCHITECTURE_AARCH64_ARCHITECTUREAARCH64_H
+#define LLDB_SOURCE_PLUGINS_ARCHITECTURE_AARCH64_ARCHITECTUREAARCH64_H
+
+#include "Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h"
+#include "lldb/Core/Architecture.h"
+
+namespace lldb_private {
+
+class ArchitectureAArch64 : public Architecture {
+public:
+ static ConstString GetPluginNameStatic();
+ static void Initialize();
+ static void Terminate();
+
+ ConstString GetPluginName() override;
+ uint32_t GetPluginVersion() override;
+
+ void OverrideStopInfo(Thread &thread) const override{};
+
+ const MemoryTagManager *GetMemoryTagManager() const override {
+ return &m_memory_tag_manager;
+ }
+
+private:
+ static std::unique_ptr<Architecture> Create(const ArchSpec &arch);
+ ArchitectureAArch64() = default;
+ MemoryTagManagerAArch64MTE m_memory_tag_manager;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_ARCHITECTURE_AARCH64_ARCHITECTUREAARCH64_H
diff --git a/src/llvm-project/lldb/source/Plugins/Architecture/AArch64/CMakeLists.txt b/src/llvm-project/lldb/source/Plugins/Architecture/AArch64/CMakeLists.txt
new file mode 100644
index 0000000..9bcf993
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Architecture/AArch64/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_lldb_library(lldbPluginArchitectureAArch64 PLUGIN
+ ArchitectureAArch64.cpp
+
+ LINK_LIBS
+ lldbPluginProcessUtility
+ lldbCore
+ lldbTarget
+ lldbUtility
+ LINK_COMPONENTS
+ Support
+ )
diff --git a/src/llvm-project/lldb/source/Plugins/Architecture/CMakeLists.txt b/src/llvm-project/lldb/source/Plugins/Architecture/CMakeLists.txt
index 14ad916..9ed8edf 100644
--- a/src/llvm-project/lldb/source/Plugins/Architecture/CMakeLists.txt
+++ b/src/llvm-project/lldb/source/Plugins/Architecture/CMakeLists.txt
@@ -1,3 +1,4 @@
add_subdirectory(Arm)
add_subdirectory(Mips)
add_subdirectory(PPC64)
+add_subdirectory(AArch64)
diff --git a/src/llvm-project/lldb/source/Plugins/Architecture/Mips/ArchitectureMips.cpp b/src/llvm-project/lldb/source/Plugins/Architecture/Mips/ArchitectureMips.cpp
index 2250896..757c915 100644
--- a/src/llvm-project/lldb/source/Plugins/Architecture/Mips/ArchitectureMips.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Architecture/Mips/ArchitectureMips.cpp
@@ -160,7 +160,6 @@
InstructionList instruction_list;
InstructionSP prev_insn;
- bool prefer_file_cache = true; // Read from file
uint32_t inst_to_choose = 0;
Address addr = resolved_addr;
@@ -171,8 +170,7 @@
uint32_t insn_size = 0;
disasm_sp->ParseInstructions(target, addr,
- {Disassembler::Limit::Bytes, i * 2}, nullptr,
- prefer_file_cache);
+ {Disassembler::Limit::Bytes, i * 2}, nullptr);
uint32_t num_insns = disasm_sp->GetInstructionList().GetSize();
if (num_insns) {
diff --git a/src/llvm-project/lldb/source/Plugins/CMakeLists.txt b/src/llvm-project/lldb/source/Plugins/CMakeLists.txt
index 3da23ec..9181a4e 100644
--- a/src/llvm-project/lldb/source/Plugins/CMakeLists.txt
+++ b/src/llvm-project/lldb/source/Plugins/CMakeLists.txt
@@ -20,6 +20,7 @@
add_subdirectory(SystemRuntime)
add_subdirectory(SymbolVendor)
add_subdirectory(Trace)
+add_subdirectory(TraceExporter)
add_subdirectory(TypeSystem)
add_subdirectory(UnwindAssembly)
diff --git a/src/llvm-project/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp b/src/llvm-project/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp
index 8a2d323..7cd505d 100644
--- a/src/llvm-project/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp
@@ -905,7 +905,8 @@
return Instance();
std::unique_ptr<llvm::MCContext> context_up(
- new llvm::MCContext(asm_info_up.get(), reg_info_up.get(), nullptr));
+ new llvm::MCContext(llvm::Triple(triple), asm_info_up.get(),
+ reg_info_up.get(), subtarget_info_up.get()));
if (!context_up)
return Instance();
diff --git a/src/llvm-project/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp b/src/llvm-project/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
index fd1916d..07b3da0 100644
--- a/src/llvm-project/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
+++ b/src/llvm-project/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
@@ -35,7 +35,7 @@
//#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
#ifdef ENABLE_DEBUG_PRINTF
-#include <stdio.h>
+#include <cstdio>
#define DEBUG_PRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
#define DEBUG_PRINTF(fmt, ...)
@@ -107,7 +107,7 @@
m_collection_sp->Initialize(g_dynamicloaderdarwinkernel_properties);
}
- ~DynamicLoaderDarwinKernelProperties() override {}
+ ~DynamicLoaderDarwinKernelProperties() override = default;
bool GetLoadKexts() const {
const uint32_t idx = ePropertyLoadKexts;
@@ -1093,16 +1093,16 @@
uint8_t buf[24];
DataExtractor data(buf, sizeof(buf), byte_order, addr_size);
const size_t count = 4 * sizeof(uint32_t) + addr_size;
- const bool prefer_file_cache = false;
+ const bool force_live_memory = true;
if (m_process->GetTarget().ReadPointerFromMemory(
- m_kext_summary_header_ptr_addr, prefer_file_cache, error,
- m_kext_summary_header_addr)) {
+ m_kext_summary_header_ptr_addr, error,
+ m_kext_summary_header_addr, force_live_memory)) {
// We got a valid address for our kext summary header and make sure it
// isn't NULL
if (m_kext_summary_header_addr.IsValid() &&
m_kext_summary_header_addr.GetFileAddress() != 0) {
const size_t bytes_read = m_process->GetTarget().ReadMemory(
- m_kext_summary_header_addr, prefer_file_cache, buf, count, error);
+ m_kext_summary_header_addr, buf, count, error, force_live_memory);
if (bytes_read == count) {
lldb::offset_t offset = 0;
m_kext_summary_header.version = data.GetU32(&offset);
@@ -1373,10 +1373,9 @@
DataBufferHeap data(count, 0);
Status error;
- const bool prefer_file_cache = false;
+ const bool force_live_memory = true;
const size_t bytes_read = m_process->GetTarget().ReadMemory(
- kext_summary_addr, prefer_file_cache, data.GetBytes(), data.GetByteSize(),
- error);
+ kext_summary_addr, data.GetBytes(), data.GetByteSize(), error, force_live_memory);
if (bytes_read == count) {
DataExtractor extractor(data.GetBytes(), data.GetByteSize(), endian,
diff --git a/src/llvm-project/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h b/src/llvm-project/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h
index 8659cd5..225d069 100644
--- a/src/llvm-project/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h
+++ b/src/llvm-project/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h
@@ -125,11 +125,7 @@
class KextImageInfo {
public:
- KextImageInfo()
- : m_name(), m_module_sp(), m_memory_module_sp(),
- m_load_process_stop_id(UINT32_MAX), m_uuid(),
- m_load_address(LLDB_INVALID_ADDRESS), m_size(0),
- m_kernel_image(false) {}
+ KextImageInfo() : m_name(), m_module_sp(), m_memory_module_sp(), m_uuid() {}
void Clear() {
m_load_address = LLDB_INVALID_ADDRESS;
@@ -201,24 +197,24 @@
std::string m_name;
lldb::ModuleSP m_module_sp;
lldb::ModuleSP m_memory_module_sp;
- uint32_t m_load_process_stop_id; // the stop-id when this module was added
- // to the Target
+ uint32_t m_load_process_stop_id =
+ UINT32_MAX; // the stop-id when this module was added
+ // to the Target
lldb_private::UUID
m_uuid; // UUID for this dylib if it has one, else all zeros
- lldb::addr_t m_load_address;
- uint64_t m_size;
- bool m_kernel_image; // true if this is the kernel, false if this is a kext
+ lldb::addr_t m_load_address = LLDB_INVALID_ADDRESS;
+ uint64_t m_size = 0;
+ bool m_kernel_image =
+ false; // true if this is the kernel, false if this is a kext
};
struct OSKextLoadedKextSummaryHeader {
- uint32_t version;
- uint32_t entry_size;
- uint32_t entry_count;
- lldb::addr_t image_infos_addr;
+ uint32_t version = 0;
+ uint32_t entry_size = 0;
+ uint32_t entry_count = 0;
+ lldb::addr_t image_infos_addr = LLDB_INVALID_ADDRESS;
- OSKextLoadedKextSummaryHeader()
- : version(0), entry_size(0), entry_count(0),
- image_infos_addr(LLDB_INVALID_ADDRESS) {}
+ OSKextLoadedKextSummaryHeader() = default;
uint32_t GetSize() {
switch (version) {
diff --git a/src/llvm-project/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h b/src/llvm-project/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h
index 5707f88..c34e02e 100644
--- a/src/llvm-project/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h
+++ b/src/llvm-project/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h
@@ -35,15 +35,13 @@
// the layout of this struct is not binary compatible, it is simply large
// enough to hold the information on both 32 and 64 bit platforms.
struct Rendezvous {
- uint64_t version;
- lldb::addr_t map_addr;
- lldb::addr_t brk;
- uint64_t state;
- lldb::addr_t ldbase;
+ uint64_t version = 0;
+ lldb::addr_t map_addr = LLDB_INVALID_ADDRESS;
+ lldb::addr_t brk = LLDB_INVALID_ADDRESS;
+ uint64_t state = 0;
+ lldb::addr_t ldbase = 0;
- Rendezvous()
- : version(0), map_addr(LLDB_INVALID_ADDRESS), brk(LLDB_INVALID_ADDRESS),
- state(0), ldbase(0) {}
+ Rendezvous() = default;
};
public:
diff --git a/src/llvm-project/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp b/src/llvm-project/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
index ddf6f12..95bd398 100644
--- a/src/llvm-project/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
+++ b/src/llvm-project/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
@@ -36,7 +36,7 @@
//#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
#ifdef ENABLE_DEBUG_PRINTF
-#include <stdio.h>
+#include <cstdio>
#define DEBUG_PRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
#define DEBUG_PRINTF(fmt, ...)
@@ -60,7 +60,7 @@
m_dyld_image_infos_stop_id(UINT32_MAX), m_dyld(), m_mutex() {}
// Destructor
-DynamicLoaderDarwin::~DynamicLoaderDarwin() {}
+DynamicLoaderDarwin::~DynamicLoaderDarwin() = default;
/// Called after attaching a process.
///
@@ -1086,7 +1086,7 @@
Status error;
const size_t tsl_data_size = addr_size * 3;
Target &target = m_process->GetTarget();
- if (target.ReadMemory(tls_addr, false, buf, tsl_data_size, error) ==
+ if (target.ReadMemory(tls_addr, buf, tsl_data_size, error, true) ==
tsl_data_size) {
const ByteOrder byte_order = m_process->GetByteOrder();
DataExtractor data(buf, sizeof(buf), byte_order, addr_size);
diff --git a/src/llvm-project/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h b/src/llvm-project/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h
index 4c9a27f..1b705e9 100644
--- a/src/llvm-project/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h
+++ b/src/llvm-project/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h
@@ -73,19 +73,17 @@
class Segment {
public:
- Segment()
- : name(), vmaddr(LLDB_INVALID_ADDRESS), vmsize(0), fileoff(0),
- filesize(0), maxprot(0), initprot(0), nsects(0), flags(0) {}
+ Segment() : name() {}
lldb_private::ConstString name;
- lldb::addr_t vmaddr;
- lldb::addr_t vmsize;
- lldb::addr_t fileoff;
- lldb::addr_t filesize;
- uint32_t maxprot;
- uint32_t initprot;
- uint32_t nsects;
- uint32_t flags;
+ lldb::addr_t vmaddr = LLDB_INVALID_ADDRESS;
+ lldb::addr_t vmsize = 0;
+ lldb::addr_t fileoff = 0;
+ lldb::addr_t filesize = 0;
+ uint32_t maxprot = 0;
+ uint32_t initprot = 0;
+ uint32_t nsects = 0;
+ uint32_t flags = 0;
bool operator==(const Segment &rhs) const {
return name == rhs.name && vmaddr == rhs.vmaddr && vmsize == rhs.vmsize;
diff --git a/src/llvm-project/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp b/src/llvm-project/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp
index 656a5bf..cad8a43 100644
--- a/src/llvm-project/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp
+++ b/src/llvm-project/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp
@@ -244,18 +244,18 @@
clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(
lldb::eEncodingUint, 32);
- mode_value.SetValueType(Value::eValueTypeScalar);
+ mode_value.SetValueType(Value::ValueType::Scalar);
mode_value.SetCompilerType(clang_uint32_type);
if (process->GetTarget().GetArchitecture().GetAddressByteSize() == 4) {
- count_value.SetValueType(Value::eValueTypeScalar);
+ count_value.SetValueType(Value::ValueType::Scalar);
count_value.SetCompilerType(clang_uint32_type);
} else {
- count_value.SetValueType(Value::eValueTypeScalar);
+ count_value.SetValueType(Value::ValueType::Scalar);
count_value.SetCompilerType(clang_uint64_type);
}
- headers_value.SetValueType(Value::eValueTypeScalar);
+ headers_value.SetValueType(Value::ValueType::Scalar);
headers_value.SetCompilerType(clang_void_ptr_type);
argument_values.PushValue(mode_value);
@@ -343,29 +343,26 @@
bool DynamicLoaderMacOS::SetNotificationBreakpoint() {
if (m_break_id == LLDB_INVALID_BREAK_ID) {
- ConstString g_symbol_name("_dyld_debugger_notification");
- const Symbol *symbol = nullptr;
ModuleSP dyld_sp(GetDYLDModule());
if (dyld_sp) {
- symbol = dyld_sp->FindFirstSymbolWithNameAndType(g_symbol_name,
- eSymbolTypeCode);
- }
- if (symbol &&
- (symbol->ValueIsAddress() || symbol->GetAddressRef().IsValid())) {
- addr_t symbol_address =
- symbol->GetAddressRef().GetOpcodeLoadAddress(&m_process->GetTarget());
- if (symbol_address != LLDB_INVALID_ADDRESS) {
- bool internal = true;
- bool hardware = false;
- Breakpoint *breakpoint =
- m_process->GetTarget()
- .CreateBreakpoint(symbol_address, internal, hardware)
- .get();
- breakpoint->SetCallback(DynamicLoaderMacOS::NotifyBreakpointHit, this,
- true);
- breakpoint->SetBreakpointKind("shared-library-event");
- m_break_id = breakpoint->GetID();
- }
+ bool internal = true;
+ bool hardware = false;
+ LazyBool skip_prologue = eLazyBoolNo;
+ FileSpecList *source_files = nullptr;
+ FileSpecList dyld_filelist;
+ dyld_filelist.Append(dyld_sp->GetObjectFile()->GetFileSpec());
+
+ Breakpoint *breakpoint =
+ m_process->GetTarget()
+ .CreateBreakpoint(&dyld_filelist, source_files,
+ "_dyld_debugger_notification",
+ eFunctionNameTypeFull, eLanguageTypeC, 0,
+ skip_prologue, internal, hardware)
+ .get();
+ breakpoint->SetCallback(DynamicLoaderMacOS::NotifyBreakpointHit, this,
+ true);
+ breakpoint->SetBreakpointKind("shared-library-event");
+ m_break_id = breakpoint->GetID();
}
}
return m_break_id != LLDB_INVALID_BREAK_ID;
diff --git a/src/llvm-project/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp b/src/llvm-project/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
index 5d48273..91b1682 100644
--- a/src/llvm-project/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
+++ b/src/llvm-project/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
@@ -32,7 +32,7 @@
//#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
#ifdef ENABLE_DEBUG_PRINTF
-#include <stdio.h>
+#include <cstdio>
#define DEBUG_PRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
#define DEBUG_PRINTF(fmt, ...)
@@ -355,7 +355,7 @@
CompilerType clang_uint32_type =
clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(
lldb::eEncodingUint, 32);
- input_value.SetValueType(Value::eValueTypeScalar);
+ input_value.SetValueType(Value::ValueType::Scalar);
input_value.SetCompilerType(clang_uint32_type);
// input_value.SetContext (Value::eContextTypeClangType,
// clang_uint32_type);
@@ -1114,6 +1114,12 @@
return false;
}
+bool DynamicLoaderMacOSXDYLD::IsFullyInitialized() {
+ if (ReadAllImageInfosStructure())
+ return m_dyld_all_image_infos.libSystemInitialized;
+ return false;
+}
+
void DynamicLoaderMacOSXDYLD::Initialize() {
PluginManager::RegisterPlugin(GetPluginNameStatic(),
GetPluginDescriptionStatic(), CreateInstance);
diff --git a/src/llvm-project/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h b/src/llvm-project/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h
index 21bf587..4b337d1 100644
--- a/src/llvm-project/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h
+++ b/src/llvm-project/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h
@@ -68,6 +68,8 @@
uint32_t GetPluginVersion() override;
+ bool IsFullyInitialized() override;
+
protected:
void PutToLog(lldb_private::Log *log) const;
@@ -96,20 +98,15 @@
lldb_private::FileSpec *lc_id_dylinker);
struct DYLDAllImageInfos {
- uint32_t version;
- uint32_t dylib_info_count; // Version >= 1
- lldb::addr_t dylib_info_addr; // Version >= 1
- lldb::addr_t notification; // Version >= 1
- bool processDetachedFromSharedRegion; // Version >= 1
- bool libSystemInitialized; // Version >= 2
- lldb::addr_t dyldImageLoadAddress; // Version >= 2
+ uint32_t version = 0;
+ uint32_t dylib_info_count = 0; // Version >= 1
+ lldb::addr_t dylib_info_addr = LLDB_INVALID_ADDRESS; // Version >= 1
+ lldb::addr_t notification = LLDB_INVALID_ADDRESS; // Version >= 1
+ bool processDetachedFromSharedRegion = false; // Version >= 1
+ bool libSystemInitialized = false; // Version >= 2
+ lldb::addr_t dyldImageLoadAddress = LLDB_INVALID_ADDRESS; // Version >= 2
- DYLDAllImageInfos()
- : version(0), dylib_info_count(0),
- dylib_info_addr(LLDB_INVALID_ADDRESS),
- notification(LLDB_INVALID_ADDRESS),
- processDetachedFromSharedRegion(false), libSystemInitialized(false),
- dyldImageLoadAddress(LLDB_INVALID_ADDRESS) {}
+ DYLDAllImageInfos() = default;
void Clear() {
version = 0;
diff --git a/src/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h b/src/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
index 3e88d88..5775f5a 100644
--- a/src/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
+++ b/src/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
@@ -38,13 +38,13 @@
// the layout of this struct is not binary compatible, it is simply large
// enough to hold the information on both 32 and 64 bit platforms.
struct Rendezvous {
- uint64_t version;
- lldb::addr_t map_addr;
- lldb::addr_t brk;
- uint64_t state;
- lldb::addr_t ldbase;
+ uint64_t version = 0;
+ lldb::addr_t map_addr = 0;
+ lldb::addr_t brk = 0;
+ uint64_t state = 0;
+ lldb::addr_t ldbase = 0;
- Rendezvous() : version(0), map_addr(0), brk(0), state(0), ldbase(0) {}
+ Rendezvous() = default;
};
public:
diff --git a/src/llvm-project/lldb/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp b/src/llvm-project/lldb/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp
index c1fceeb..8a5528f 100644
--- a/src/llvm-project/lldb/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp
+++ b/src/llvm-project/lldb/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp
@@ -10,6 +10,7 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "DynamicLoaderStatic.h"
@@ -105,6 +106,15 @@
// the file...
SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
if (section_sp) {
+ // If this section already has a load address set in the target,
+ // don't re-set it to the file address. Something may have
+ // set it to a more correct value already.
+ if (m_process->GetTarget()
+ .GetSectionLoadList()
+ .GetSectionLoadAddress(section_sp) !=
+ LLDB_INVALID_ADDRESS) {
+ continue;
+ }
if (m_process->GetTarget().SetSectionLoadAddress(
section_sp, section_sp->GetFileAddress()))
changed = true;
diff --git a/src/llvm-project/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp b/src/llvm-project/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp
index 7f9504b..54dfa3e 100644
--- a/src/llvm-project/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp
+++ b/src/llvm-project/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp
@@ -28,7 +28,7 @@
DynamicLoaderWindowsDYLD::DynamicLoaderWindowsDYLD(Process *process)
: DynamicLoader(process) {}
-DynamicLoaderWindowsDYLD::~DynamicLoaderWindowsDYLD() {}
+DynamicLoaderWindowsDYLD::~DynamicLoaderWindowsDYLD() = default;
void DynamicLoaderWindowsDYLD::Initialize() {
PluginManager::RegisterPlugin(GetPluginNameStatic(),
@@ -193,7 +193,7 @@
AddressRange range(pc, 2 * 15);
DisassemblerSP disassembler_sp = Disassembler::DisassembleRange(
- arch, nullptr, nullptr, m_process->GetTarget(), range, true);
+ arch, nullptr, nullptr, m_process->GetTarget(), range);
if (!disassembler_sp) {
return ThreadPlanSP();
}
diff --git a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
index 3edbc4a..85e2fcf 100644
--- a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
@@ -15,7 +15,6 @@
#include "lldb/Target/Target.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
-#include "stdlib.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
@@ -27,6 +26,7 @@
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
+#include <cstdlib>
using namespace llvm;
using namespace clang;
@@ -43,7 +43,7 @@
m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough);
}
-ASTResultSynthesizer::~ASTResultSynthesizer() {}
+ASTResultSynthesizer::~ASTResultSynthesizer() = default;
void ASTResultSynthesizer::Initialize(ASTContext &Context) {
m_ast_context = &Context;
diff --git a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp
index 40f0de4..a2722db 100644
--- a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp
@@ -9,7 +9,6 @@
#include "ASTStructExtractor.h"
#include "lldb/Utility/Log.h"
-#include "stdlib.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
@@ -21,6 +20,7 @@
#include "clang/Sema/Sema.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
+#include <cstdlib>
using namespace llvm;
using namespace clang;
@@ -38,7 +38,7 @@
m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough);
}
-ASTStructExtractor::~ASTStructExtractor() {}
+ASTStructExtractor::~ASTStructExtractor() = default;
void ASTStructExtractor::Initialize(ASTContext &Context) {
m_ast_context = &Context;
diff --git a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.cpp b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.cpp
index 1e438ed..a95fce1 100644
--- a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.cpp
@@ -8,17 +8,17 @@
#include "ASTUtils.h"
-lldb_private::ExternalASTSourceWrapper::~ExternalASTSourceWrapper() {}
+lldb_private::ExternalASTSourceWrapper::~ExternalASTSourceWrapper() = default;
void lldb_private::ExternalASTSourceWrapper::PrintStats() {
m_Source->PrintStats();
}
-lldb_private::ASTConsumerForwarder::~ASTConsumerForwarder() {}
+lldb_private::ASTConsumerForwarder::~ASTConsumerForwarder() = default;
void lldb_private::ASTConsumerForwarder::PrintStats() { m_c->PrintStats(); }
-lldb_private::SemaSourceWithPriorities::~SemaSourceWithPriorities() {}
+lldb_private::SemaSourceWithPriorities::~SemaSourceWithPriorities() = default;
void lldb_private::SemaSourceWithPriorities::PrintStats() {
for (size_t i = 0; i < Sources.size(); ++i)
diff --git a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp
index e2601a0..94647b0 100644
--- a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp
@@ -184,7 +184,7 @@
}
public:
- DeclContextOverride() {}
+ DeclContextOverride() = default;
void OverrideAllDeclsFromContainingFunction(clang::Decl *decl) {
for (DeclContext *decl_context = decl->getLexicalDeclContext();
@@ -359,9 +359,6 @@
if (!ClangUtil::IsClangType(type))
return false;
- // TODO: remove external completion BOOL
- // CompleteAndFetchChildren should get the Decl out and check for the
-
clang::QualType qual_type(
ClangUtil::GetCanonicalQualType(ClangUtil::RemoveFastQualifiers(type)));
@@ -435,8 +432,6 @@
bool ClangASTImporter::Import(const CompilerType &type) {
if (!ClangUtil::IsClangType(type))
return false;
- // TODO: remove external completion BOOL
- // CompleteAndFetchChildren should get the Decl out and check for the
clang::QualType qual_type(
ClangUtil::GetCanonicalQualType(ClangUtil::RemoveFastQualifiers(type)));
@@ -830,6 +825,10 @@
// Check which ASTContext this declaration originally came from.
DeclOrigin origin = m_master.GetDeclOrigin(From);
+
+ // Prevent infinite recursion when the origin tracking contains a cycle.
+ assert(origin.decl != From && "Origin points to itself?");
+
// If it originally came from the target ASTContext then we can just
// pretend that the original is the one we imported. This can happen for
// example when inspecting a persistent declaration from the scratch
@@ -889,6 +888,37 @@
LLDB_LOG(log, "[ClangASTImporter] Complete definition not found");
}
+ // Disable the minimal import for fields that have record types. There is
+ // no point in minimally importing the record behind their type as Clang
+ // will anyway request their definition when the FieldDecl is added to the
+ // RecordDecl (as Clang will query the FieldDecl's type for things such
+ // as a deleted constexpr destructor).
+ // By importing the type ahead of time we avoid some corner cases where
+ // the FieldDecl's record is importing in the middle of Clang's
+ // `DeclContext::addDecl` logic.
+ if (clang::FieldDecl *fd = dyn_cast<FieldDecl>(From)) {
+ // This is only necessary because we do the 'minimal import'. Remove this
+ // once LLDB stopped using that mode.
+ assert(isMinimalImport() && "Only necessary for minimal import");
+ QualType field_type = fd->getType();
+ if (field_type->isRecordType()) {
+ // First get the underlying record and minimally import it.
+ clang::TagDecl *record_decl = field_type->getAsTagDecl();
+ llvm::Expected<Decl *> imported = Import(record_decl);
+ if (!imported)
+ return imported.takeError();
+ // Check how/if the import got redirected to a different AST. Now
+ // import the definition of what was actually imported. If there is no
+ // origin then that means the record was imported by just picking a
+ // compatible type in the target AST (in which case there is no more
+ // importing to do).
+ if (clang::Decl *origin = m_master.GetDeclOrigin(*imported).decl) {
+ if (llvm::Error def_err = ImportDefinition(record_decl))
+ return std::move(def_err);
+ }
+ }
+ }
+
return ASTImporter::ImportImpl(From);
}
@@ -904,16 +934,6 @@
MapImported(from, to);
ASTImporter::Imported(from, to);
- /*
- if (to_objc_interface)
- to_objc_interface->startDefinition();
-
- CXXRecordDecl *to_cxx_record = dyn_cast<CXXRecordDecl>(to);
-
- if (to_cxx_record)
- to_cxx_record->startDefinition();
- */
-
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
if (llvm::Error err = ImportDefinition(from)) {
@@ -1088,22 +1108,23 @@
DeclOrigin origin = from_context_md->getOrigin(from);
if (origin.Valid()) {
- if (!to_context_md->hasOrigin(to) || user_id != LLDB_INVALID_UID)
- if (origin.ctx != &to->getASTContext())
+ if (origin.ctx != &to->getASTContext()) {
+ if (!to_context_md->hasOrigin(to) || user_id != LLDB_INVALID_UID)
to_context_md->setOrigin(to, origin);
- ImporterDelegateSP direct_completer =
- m_master.GetDelegate(&to->getASTContext(), origin.ctx);
+ ImporterDelegateSP direct_completer =
+ m_master.GetDelegate(&to->getASTContext(), origin.ctx);
- if (direct_completer.get() != this)
- direct_completer->ASTImporter::Imported(origin.decl, to);
+ if (direct_completer.get() != this)
+ direct_completer->ASTImporter::Imported(origin.decl, to);
- LLDB_LOG(log,
- " [ClangASTImporter] Propagated origin "
- "(Decl*){0}/(ASTContext*){1} from (ASTContext*){2} to "
- "(ASTContext*){3}",
- origin.decl, origin.ctx, &from->getASTContext(),
- &to->getASTContext());
+ LLDB_LOG(log,
+ " [ClangASTImporter] Propagated origin "
+ "(Decl*){0}/(ASTContext*){1} from (ASTContext*){2} to "
+ "(ASTContext*){3}",
+ origin.decl, origin.ctx, &from->getASTContext(),
+ &to->getASTContext());
+ }
} else {
if (m_new_decl_listener)
m_new_decl_listener->NewDeclImported(from, to);
diff --git a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.h b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.h
index bf4ad17..4f589d3 100644
--- a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.h
+++ b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.h
@@ -23,6 +23,7 @@
#include "lldb/Host/FileSystem.h"
#include "lldb/Symbol/CompilerDeclContext.h"
+#include "lldb/Utility/LLDBAssert.h"
#include "lldb/lldb-types.h"
#include "Plugins/ExpressionParser/Clang/CxxModuleHandler.h"
@@ -34,6 +35,32 @@
class ClangASTMetadata;
class TypeSystemClang;
+/// Manages and observes all Clang AST node importing in LLDB.
+///
+/// The ClangASTImporter takes care of two things:
+///
+/// 1. Keeps track of all ASTImporter instances in LLDB.
+///
+/// Clang's ASTImporter takes care of importing types from one ASTContext to
+/// another. This class expands this concept by allowing copying from several
+/// ASTContext instances to several other ASTContext instances. Instead of
+/// constructing a new ASTImporter manually to copy over a type/decl, this class
+/// can be asked to do this. It will construct a ASTImporter for the caller (and
+/// will cache the ASTImporter instance for later use) and then perform the
+/// import.
+///
+/// This mainly prevents that a caller might construct several ASTImporter
+/// instances for the same source/target ASTContext combination. As the
+/// ASTImporter has an internal state that keeps track of already imported
+/// declarations and so on, using only one ASTImporter instance is more
+/// efficient and less error-prone than using multiple.
+///
+/// 2. Keeps track of from where declarations were imported (origin-tracking).
+/// The ASTImporter instances in this class usually only performa a minimal
+/// import, i.e., only a shallow copy is made that is filled out on demand
+/// when more information is requested later on. This requires record-keeping
+/// of where any shallow clone originally came from so that the right original
+/// declaration can be found and used as the source of any missing information.
class ClangASTImporter {
public:
struct LayoutInfo {
@@ -52,12 +79,34 @@
: m_file_manager(clang::FileSystemOptions(),
FileSystem::Instance().GetVirtualFileSystem()) {}
+ /// Copies the given type and the respective declarations to the destination
+ /// type system.
+ ///
+ /// This function does a shallow copy and requires that the target AST
+ /// has an ExternalASTSource which queries this ClangASTImporter instance
+ /// for any additional information that is maybe lacking in the shallow copy.
+ /// This also means that the type system of src_type can *not* be deleted
+ /// after this function has been called. If you need to delete the source
+ /// type system you either need to delete the destination type system first
+ /// or use \ref ClangASTImporter::DeportType.
+ ///
+ /// \see ClangASTImporter::DeportType
CompilerType CopyType(TypeSystemClang &dst, const CompilerType &src_type);
+ /// \see ClangASTImporter::CopyType
clang::Decl *CopyDecl(clang::ASTContext *dst_ctx, clang::Decl *decl);
+ /// Copies the given type and the respective declarations to the destination
+ /// type system.
+ ///
+ /// Unlike CopyType this function ensures that types/declarations which are
+ /// originally from the AST of src_type are fully copied over. The type
+ /// system of src_type can safely be deleted after calling this function.
+ /// \see ClangASTImporter::CopyType
CompilerType DeportType(TypeSystemClang &dst, const CompilerType &src_type);
+ /// Copies the given decl to the destination type system.
+ /// \see ClangASTImporter::DeportType
clang::Decl *DeportDecl(clang::ASTContext *dst_ctx, clang::Decl *decl);
/// Sets the layout for the given RecordDecl. The layout will later be
@@ -78,8 +127,22 @@
llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
&vbase_offsets);
+ /// Returns true iff the given type was copied from another TypeSystemClang
+ /// and the original type in this other TypeSystemClang might contain
+ /// additional information (e.g., the definition of a 'class' type) that could
+ /// be imported.
+ ///
+ /// \see ClangASTImporter::Import
bool CanImport(const CompilerType &type);
+ /// If the given type was copied from another TypeSystemClang then copy over
+ /// all missing information (e.g., the definition of a 'class' type).
+ ///
+ /// \return True iff an original type in another TypeSystemClang was found.
+ /// Note: Does *not* return false if an original type was found but
+ /// no information was imported over.
+ ///
+ /// \see ClangASTImporter::Import
bool Import(const CompilerType &type);
bool CompleteType(const CompilerType &compiler_type);
@@ -94,6 +157,14 @@
bool RequireCompleteType(clang::QualType type);
+ /// Updates the internal origin-tracking information so that the given
+ /// 'original' decl is from now on used to import additional information
+ /// into the given decl.
+ ///
+ /// Usually the origin-tracking in the ClangASTImporter is automatically
+ /// updated when a declaration is imported, so the only valid reason to ever
+ /// call this is if there is a 'better' original decl and the target decl
+ /// is only a shallow clone that lacks any contents.
void SetDeclOrigin(const clang::Decl *decl, clang::Decl *original_decl);
ClangASTMetadata *GetDeclMetadata(const clang::Decl *decl);
@@ -145,10 +216,13 @@
void ForgetSource(clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx);
struct DeclOrigin {
- DeclOrigin() : ctx(nullptr), decl(nullptr) {}
+ DeclOrigin() = default;
DeclOrigin(clang::ASTContext *_ctx, clang::Decl *_decl)
- : ctx(_ctx), decl(_decl) {}
+ : ctx(_ctx), decl(_decl) {
+ // The decl has to be in its associated ASTContext.
+ assert(_decl == nullptr || &_decl->getASTContext() == _ctx);
+ }
DeclOrigin(const DeclOrigin &rhs) {
ctx = rhs.ctx;
@@ -162,8 +236,8 @@
bool Valid() const { return (ctx != nullptr || decl != nullptr); }
- clang::ASTContext *ctx;
- clang::Decl *decl;
+ clang::ASTContext *ctx = nullptr;
+ clang::Decl *decl = nullptr;
};
/// Listener interface used by the ASTImporterDelegate to inform other code
@@ -190,6 +264,16 @@
: clang::ASTImporter(*target_ctx, master.m_file_manager, *source_ctx,
master.m_file_manager, true /*minimal*/),
m_master(master), m_source_ctx(source_ctx) {
+ // Target and source ASTContext shouldn't be identical. Importing AST
+ // nodes within the same AST doesn't make any sense as the whole idea
+ // is to import them to a different AST.
+ lldbassert(target_ctx != source_ctx && "Can't import into itself");
+ // This is always doing a minimal import of any declarations. This means
+ // that there has to be an ExternalASTSource in the target ASTContext
+ // (that should implement the callbacks that complete any declarations
+ // on demand). Without an ExternalASTSource, this ASTImporter will just
+ // do a minimal import and the imported declarations won't be completed.
+ assert(target_ctx->getExternalSource() && "Missing ExternalSource");
setODRHandling(clang::ASTImporter::ODRHandlingType::Liberal);
}
@@ -272,6 +356,13 @@
/// Sets the DeclOrigin for the given Decl and overwrites any existing
/// DeclOrigin.
void setOrigin(const clang::Decl *decl, DeclOrigin origin) {
+ // Setting the origin of any decl to itself (or to a different decl
+ // in the same ASTContext) doesn't make any sense. It will also cause
+ // ASTImporterDelegate::ImportImpl to infinite recurse when trying to find
+ // the 'original' Decl when importing code.
+ assert(&decl->getASTContext() != origin.ctx &&
+ "Trying to set decl origin to its own ASTContext?");
+ assert(decl != origin.decl && "Trying to set decl origin to itself?");
m_origins[decl] = origin;
}
diff --git a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
index 0f34c48c..b434237 100644
--- a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
@@ -479,10 +479,7 @@
decl->getDeclKindName(), ast_dump);
}
- Decl *copied_decl = CopyDecl(decl);
-
- if (!copied_decl)
- continue;
+ CopyDecl(decl);
// FIXME: We should add the copied decl to the 'decls' list. This would
// add the copied Decl into the DeclContext and make sure that we
@@ -492,12 +489,6 @@
// lookup issues later on.
// We can't just add them for now as the ASTImporter already added the
// decl into the DeclContext and this would add it twice.
-
- if (FieldDecl *copied_field = dyn_cast<FieldDecl>(copied_decl)) {
- QualType copied_field_type = copied_field->getType();
-
- m_ast_importer_sp->RequireCompleteType(copied_field_type);
- }
} else {
SkippedDecls = true;
}
@@ -850,8 +841,8 @@
ConstString name) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- ClangModulesDeclVendor *modules_decl_vendor =
- m_target->GetClangModulesDeclVendor();
+ std::shared_ptr<ClangModulesDeclVendor> modules_decl_vendor =
+ GetClangModulesDeclVendor();
if (!modules_decl_vendor)
return;
@@ -1143,8 +1134,8 @@
// Check the modules only if the debug information didn't have a complete
// interface.
- if (ClangModulesDeclVendor *modules_decl_vendor =
- m_target->GetClangModulesDeclVendor()) {
+ if (std::shared_ptr<ClangModulesDeclVendor> modules_decl_vendor =
+ GetClangModulesDeclVendor()) {
ConstString interface_name(interface_decl->getNameAsString().c_str());
bool append = false;
uint32_t max_matches = 1;
@@ -1313,8 +1304,8 @@
// Check the modules only if the debug information didn't have a complete
// interface.
- ClangModulesDeclVendor *modules_decl_vendor =
- m_target->GetClangModulesDeclVendor();
+ std::shared_ptr<ClangModulesDeclVendor> modules_decl_vendor =
+ GetClangModulesDeclVendor();
if (!modules_decl_vendor)
break;
@@ -1570,10 +1561,10 @@
if (log) {
LLDB_LOG(log, "LRT returned:");
- LLDB_LOG(log, "LRT Original = (RecordDecl*)%p",
+ LLDB_LOG(log, "LRT Original = (RecordDecl*){0}",
static_cast<const void *>(origin_record.decl));
- LLDB_LOG(log, "LRT Size = %" PRId64, size);
- LLDB_LOG(log, "LRT Alignment = %" PRId64, alignment);
+ LLDB_LOG(log, "LRT Size = {0}", size);
+ LLDB_LOG(log, "LRT Alignment = {0}", alignment);
LLDB_LOG(log, "LRT Fields:");
for (RecordDecl::field_iterator fi = record->field_begin(),
fe = record->field_end();
@@ -1750,3 +1741,10 @@
return m_clang_ast_context->GetType(copied_qual_type);
}
+
+std::shared_ptr<ClangModulesDeclVendor>
+ClangASTSource::GetClangModulesDeclVendor() {
+ auto persistent_vars = llvm::cast<ClangPersistentVariables>(
+ m_target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC));
+ return persistent_vars->GetClangModulesDeclVendor();
+}
diff --git a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
index 14761fb..3afd1fd 100644
--- a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
+++ b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
@@ -314,6 +314,8 @@
/// The imported type.
CompilerType GuardedCopyType(const CompilerType &src_type);
+ std::shared_ptr<ClangModulesDeclVendor> GetClangModulesDeclVendor();
+
public:
/// Returns true if a name should be ignored by name lookup.
///
diff --git a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h
index bf52bec..6313117 100644
--- a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h
+++ b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h
@@ -22,7 +22,7 @@
public:
ClangDeclVendor(DeclVendorKind kind) : DeclVendor(kind) {}
- virtual ~ClangDeclVendor() {}
+ virtual ~ClangDeclVendor() = default;
using DeclVendor::FindDecls;
diff --git a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
index 852ce3b..731b81c 100644
--- a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
@@ -350,7 +350,7 @@
if (!var)
return false;
- LLDB_LOG(log, "Adding value for (NamedDecl*)%p [%s - %s] to the structure",
+ LLDB_LOG(log, "Adding value for (NamedDecl*){0} [{1} - {2}] to the structure",
decl, name, var->GetName());
// We know entity->m_parser_vars is valid because we used a parser variable
@@ -752,7 +752,7 @@
MaybeRegisterFunctionBody(parser_function_decl);
}
- LLDB_LOG(log, " CEDM::FEVD Found persistent decl %s", name);
+ LLDB_LOG(log, " CEDM::FEVD Found persistent decl {0}", name);
context.AddNamedDecl(parser_named_decl);
}
@@ -1021,7 +1021,8 @@
if (!m_target)
return;
- auto *modules_decl_vendor = m_target->GetClangModulesDeclVendor();
+ std::shared_ptr<ClangModulesDeclVendor> modules_decl_vendor =
+ GetClangModulesDeclVendor();
if (!modules_decl_vendor)
return;
@@ -1213,8 +1214,8 @@
std::vector<clang::NamedDecl *> decls_from_modules;
if (target) {
- if (ClangModulesDeclVendor *decl_vendor =
- target->GetClangModulesDeclVendor()) {
+ if (std::shared_ptr<ClangModulesDeclVendor> decl_vendor =
+ GetClangModulesDeclVendor()) {
decl_vendor->FindDecls(name, false, UINT32_MAX, decls_from_modules);
}
}
@@ -1493,7 +1494,7 @@
if (var_location_expr.GetExpressionData(const_value_extractor)) {
var_location = Value(const_value_extractor.GetDataStart(),
const_value_extractor.GetByteSize());
- var_location.SetValueType(Value::eValueTypeHostAddress);
+ var_location.SetValueType(Value::ValueType::HostAddress);
} else {
LLDB_LOG(log, "Error evaluating constant variable: {0}", err.AsCString());
return false;
@@ -1512,10 +1513,10 @@
if (parser_type)
*parser_type = TypeFromParser(type_to_use);
- if (var_location.GetContextType() == Value::eContextTypeInvalid)
+ if (var_location.GetContextType() == Value::ContextType::Invalid)
var_location.SetCompilerType(type_to_use);
- if (var_location.GetValueType() == Value::eValueTypeFileAddress) {
+ if (var_location.GetValueType() == Value::ValueType::FileAddress) {
SymbolContext var_sc;
var->CalculateSymbolContext(&var_sc);
@@ -1529,7 +1530,7 @@
if (load_addr != LLDB_INVALID_ADDRESS) {
var_location.GetScalar() = load_addr;
- var_location.SetValueType(Value::eValueTypeLoadAddress);
+ var_location.SetValueType(Value::ValueType::LoadAddress);
}
}
@@ -1665,11 +1666,11 @@
const Address symbol_address = symbol.GetAddress();
lldb::addr_t symbol_load_addr = symbol_address.GetLoadAddress(target);
- // parser_vars->m_lldb_value.SetContext(Value::eContextTypeClangType,
+ // parser_vars->m_lldb_value.SetContext(Value::ContextType::ClangType,
// user_type.GetOpaqueQualType());
parser_vars->m_lldb_value.SetCompilerType(user_type);
parser_vars->m_lldb_value.GetScalar() = symbol_load_addr;
- parser_vars->m_lldb_value.SetValueType(Value::eValueTypeLoadAddress);
+ parser_vars->m_lldb_value.SetValueType(Value::ValueType::LoadAddress);
parser_vars->m_named_decl = var_decl;
parser_vars->m_llvm_value = nullptr;
@@ -1860,14 +1861,14 @@
entity->GetParserVars(GetParserID());
if (load_addr != LLDB_INVALID_ADDRESS) {
- parser_vars->m_lldb_value.SetValueType(Value::eValueTypeLoadAddress);
+ parser_vars->m_lldb_value.SetValueType(Value::ValueType::LoadAddress);
parser_vars->m_lldb_value.GetScalar() = load_addr;
} else {
// We have to try finding a file address.
lldb::addr_t file_addr = fun_address.GetFileAddress();
- parser_vars->m_lldb_value.SetValueType(Value::eValueTypeFileAddress);
+ parser_vars->m_lldb_value.SetValueType(Value::ValueType::FileAddress);
parser_vars->m_lldb_value.GetScalar() = file_addr;
}
diff --git a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
index a9cd5d1..e39dc58 100644
--- a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
+++ b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
@@ -9,8 +9,8 @@
#ifndef LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGEXPRESSIONDECLMAP_H
#define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGEXPRESSIONDECLMAP_H
-#include <signal.h>
-#include <stdint.h>
+#include <csignal>
+#include <cstdint>
#include <vector>
@@ -248,10 +248,10 @@
lldb::SymbolType symbol_type);
struct TargetInfo {
- lldb::ByteOrder byte_order;
- size_t address_byte_size;
+ lldb::ByteOrder byte_order = lldb::eByteOrderInvalid;
+ size_t address_byte_size = 0;
- TargetInfo() : byte_order(lldb::eByteOrderInvalid), address_byte_size(0) {}
+ TargetInfo() = default;
bool IsValid() {
return (byte_order != lldb::eByteOrderInvalid && address_byte_size != 0);
@@ -308,7 +308,7 @@
/// The following values should not live beyond parsing
class ParserVars {
public:
- ParserVars() {}
+ ParserVars() = default;
Target *GetTarget() {
if (m_exe_ctx.GetTargetPtr())
@@ -353,16 +353,15 @@
/// The following values contain layout information for the materialized
/// struct, but are not specific to a single materialization
struct StructVars {
- StructVars()
- : m_struct_alignment(0), m_struct_size(0), m_struct_laid_out(false),
- m_result_name(), m_object_pointer_type(nullptr, nullptr) {}
+ StructVars() : m_result_name(), m_object_pointer_type(nullptr, nullptr) {}
- lldb::offset_t
- m_struct_alignment; ///< The alignment of the struct in bytes.
- size_t m_struct_size; ///< The size of the struct in bytes.
- bool m_struct_laid_out; ///< True if the struct has been laid out and the
- ///layout is valid (that is, no new fields have been
- ///added since).
+ lldb::offset_t m_struct_alignment =
+ 0; ///< The alignment of the struct in bytes.
+ size_t m_struct_size = 0; ///< The size of the struct in bytes.
+ bool m_struct_laid_out =
+ false; ///< True if the struct has been laid out and the
+ /// layout is valid (that is, no new fields have been
+ /// added since).
ConstString
m_result_name; ///< The name of the result variable ($1, for example)
TypeFromUser m_object_pointer_type; ///< The type of the "this" variable, if
diff --git a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h
index e33e5df..37bcaf0 100644
--- a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h
+++ b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h
@@ -38,7 +38,7 @@
ExpressionTypeSystemHelper::LLVMCastKind::eKindClangHelper) {}
/// Destructor
- virtual ~ClangExpressionHelper() {}
+ virtual ~ClangExpressionHelper() = default;
/// Return the object that the parser should use when resolving external
/// values. May be NULL if everything should be self-contained.
diff --git a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
index 7644a5e..0b5e1ab 100644
--- a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
@@ -343,6 +343,7 @@
const std::vector<const char *> groupsToIgnore = {
"unused-value",
"odr",
+ "unused-getter-return-value",
};
for (const char *group : groupsToIgnore) {
compiler.getDiagnostics().setSeverityForGroup(
@@ -513,7 +514,7 @@
LLDB_LOGF(log, "Using SIMD alignment: %d",
target_info->getSimdDefaultAlign());
LLDB_LOGF(log, "Target datalayout string: '%s'",
- target_info->getDataLayout().getStringRepresentation().c_str());
+ target_info->getDataLayoutString());
LLDB_LOGF(log, "Target ABI: '%s'", target_info->getABI().str().c_str());
LLDB_LOGF(log, "Target vector alignment: %d",
target_info->getMaxVectorAlign());
@@ -657,7 +658,8 @@
//
// FIXME: We shouldn't need to do this, the target should be immutable once
// created. This complexity should be lifted elsewhere.
- m_compiler->getTarget().adjust(m_compiler->getLangOpts());
+ m_compiler->getTarget().adjust(m_compiler->getDiagnostics(),
+ m_compiler->getLangOpts());
// 6. Set up the diagnostic buffer for reporting errors
@@ -686,11 +688,11 @@
break;
}
- if (ClangModulesDeclVendor *decl_vendor =
- target_sp->GetClangModulesDeclVendor()) {
- if (auto *clang_persistent_vars = llvm::cast<ClangPersistentVariables>(
- target_sp->GetPersistentExpressionStateForLanguage(
- lldb::eLanguageTypeC))) {
+ if (auto *clang_persistent_vars = llvm::cast<ClangPersistentVariables>(
+ target_sp->GetPersistentExpressionStateForLanguage(
+ lldb::eLanguageTypeC))) {
+ if (std::shared_ptr<ClangModulesDeclVendor> decl_vendor =
+ clang_persistent_vars->GetClangModulesDeclVendor()) {
std::unique_ptr<PPCallbacks> pp_callbacks(
new LLDBPreprocessorCallbacks(*decl_vendor, *clang_persistent_vars,
m_compiler->getSourceManager()));
@@ -723,7 +725,7 @@
m_compiler->getCodeGenOpts(), *m_llvm_context));
}
-ClangExpressionParser::~ClangExpressionParser() {}
+ClangExpressionParser::~ClangExpressionParser() = default;
namespace {
diff --git a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
index 180e08b..31707f8 100644
--- a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
@@ -31,6 +31,7 @@
using namespace lldb_private;
#define PREFIX_NAME "<lldb wrapper prefix>"
+#define SUFFIX_NAME "<lldb wrapper suffix>"
const llvm::StringRef ClangExpressionSourceCode::g_prefix_file_name = PREFIX_NAME;
@@ -73,6 +74,9 @@
}
)";
+const char *ClangExpressionSourceCode::g_expression_suffix =
+ "\n;\n#line 1 \"" SUFFIX_NAME "\"\n";
+
namespace {
class AddMacroState {
@@ -180,7 +184,7 @@
// containing only the user expression. This will hide our wrapper code
// from the user when we render diagnostics with Clang.
m_start_marker = "#line 1 \"" + filename.str() + "\"\n";
- m_end_marker = "\n;\n#line 1 \"<lldb wrapper suffix>\"\n";
+ m_end_marker = g_expression_suffix;
}
namespace {
@@ -314,10 +318,11 @@
}
}
- ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor();
auto *persistent_vars = llvm::cast<ClangPersistentVariables>(
target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC));
- if (decl_vendor && persistent_vars) {
+ std::shared_ptr<ClangModulesDeclVendor> decl_vendor =
+ persistent_vars->GetClangModulesDeclVendor();
+ if (decl_vendor) {
const ClangModulesDeclVendor::ModuleVector &hand_imported_modules =
persistent_vars->GetHandLoadedClangModules();
ClangModulesDeclVendor::ModuleVector modules_for_macros;
diff --git a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h
index 9a54f0e..54ae837 100644
--- a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h
+++ b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h
@@ -27,6 +27,7 @@
/// the user expression.
static const llvm::StringRef g_prefix_file_name;
static const char *g_expression_prefix;
+ static const char *g_expression_suffix;
/// The possible ways an expression can be wrapped.
enum class WrapKind {
diff --git a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h
index 58d5899..7bb68e7 100644
--- a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h
+++ b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h
@@ -9,9 +9,9 @@
#ifndef LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGEXPRESSIONVARIABLE_H
#define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGEXPRESSIONVARIABLE_H
-#include <signal.h>
-#include <stdint.h>
-#include <string.h>
+#include <csignal>
+#include <cstdint>
+#include <cstring>
#include <map>
#include <string>
@@ -116,19 +116,19 @@
/// The following values should not live beyond parsing
class ParserVars {
public:
- ParserVars()
- : m_named_decl(nullptr), m_llvm_value(nullptr),
- m_lldb_value(), m_lldb_var(), m_lldb_sym(nullptr) {}
+ ParserVars() : m_lldb_value(), m_lldb_var() {}
- const clang::NamedDecl
- *m_named_decl; ///< The Decl corresponding to this variable
- llvm::Value *m_llvm_value; ///< The IR value corresponding to this variable;
- ///usually a GlobalValue
+ const clang::NamedDecl *m_named_decl =
+ nullptr; ///< The Decl corresponding to this variable
+ llvm::Value *m_llvm_value =
+ nullptr; ///< The IR value corresponding to this variable;
+ /// usually a GlobalValue
lldb_private::Value
m_lldb_value; ///< The value found in LLDB for this variable
lldb::VariableSP m_lldb_var; ///< The original variable for this variable
- const lldb_private::Symbol *m_lldb_sym; ///< The original symbol for this
- ///variable, if it was a symbol
+ const lldb_private::Symbol *m_lldb_sym =
+ nullptr; ///< The original symbol for this
+ /// variable, if it was a symbol
};
private:
@@ -157,13 +157,13 @@
/// The following values are valid if the variable is used by JIT code
struct JITVars {
- JITVars() : m_alignment(0), m_size(0), m_offset(0) {}
+ JITVars() = default;
- lldb::offset_t
- m_alignment; ///< The required alignment of the variable, in bytes
- size_t m_size; ///< The space required for the variable, in bytes
- lldb::offset_t
- m_offset; ///< The offset of the variable in the struct, in bytes
+ lldb::offset_t m_alignment =
+ 0; ///< The required alignment of the variable, in bytes
+ size_t m_size = 0; ///< The space required for the variable, in bytes
+ lldb::offset_t m_offset =
+ 0; ///< The offset of the variable in the struct, in bytes
};
private:
diff --git a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp
index 0c9ad20..2cfa9a4 100644
--- a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp
@@ -59,7 +59,7 @@
}
// Destructor
-ClangFunctionCaller::~ClangFunctionCaller() {}
+ClangFunctionCaller::~ClangFunctionCaller() = default;
unsigned
diff --git a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
index c014ad5..336058a 100644
--- a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
@@ -42,9 +42,9 @@
using namespace lldb_private;
namespace {
-// Any Clang compiler requires a consumer for diagnostics. This one stores
-// them as strings so we can provide them to the user in case a module failed
-// to load.
+/// Any Clang compiler requires a consumer for diagnostics. This one stores
+/// them as strings so we can provide them to the user in case a module failed
+/// to load.
class StoringDiagnosticConsumer : public clang::DiagnosticConsumer {
public:
StoringDiagnosticConsumer();
@@ -74,8 +74,8 @@
Log *m_log;
};
-// The private implementation of our ClangModulesDeclVendor. Contains all the
-// Clang state required to load modules.
+/// The private implementation of our ClangModulesDeclVendor. Contains all the
+/// Clang state required to load modules.
class ClangModulesDeclVendorImpl : public ClangModulesDeclVendor {
public:
ClangModulesDeclVendorImpl(
@@ -100,9 +100,9 @@
std::function<bool(llvm::StringRef, llvm::StringRef)> handler) override;
private:
- void
- ReportModuleExportsHelper(std::set<ClangModulesDeclVendor::ModuleID> &exports,
- clang::Module *module);
+ typedef llvm::DenseSet<ModuleID> ExportedModuleSet;
+ void ReportModuleExportsHelper(ExportedModuleSet &exports,
+ clang::Module *module);
void ReportModuleExports(ModuleVector &exports, clang::Module *module);
@@ -120,7 +120,7 @@
typedef std::vector<ConstString> ImportedModule;
typedef std::map<ImportedModule, clang::Module *> ImportedModuleMap;
- typedef std::set<ModuleID> ImportedModuleSet;
+ typedef llvm::DenseSet<ModuleID> ImportedModuleSet;
ImportedModuleMap m_imported_modules;
ImportedModuleSet m_user_imported_modules;
// We assume that every ASTContext has an TypeSystemClang, so we also store
@@ -176,7 +176,7 @@
ClangModulesDeclVendor::ClangModulesDeclVendor()
: ClangDeclVendor(eClangModuleDeclVendor) {}
-ClangModulesDeclVendor::~ClangModulesDeclVendor() {}
+ClangModulesDeclVendor::~ClangModulesDeclVendor() = default;
ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl(
llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine,
@@ -195,8 +195,7 @@
}
void ClangModulesDeclVendorImpl::ReportModuleExportsHelper(
- std::set<ClangModulesDeclVendor::ModuleID> &exports,
- clang::Module *module) {
+ ExportedModuleSet &exports, clang::Module *module) {
if (exports.count(reinterpret_cast<ClangModulesDeclVendor::ModuleID>(module)))
return;
@@ -206,20 +205,18 @@
module->getExportedModules(sub_exports);
- for (clang::Module *module : sub_exports) {
+ for (clang::Module *module : sub_exports)
ReportModuleExportsHelper(exports, module);
- }
}
void ClangModulesDeclVendorImpl::ReportModuleExports(
ClangModulesDeclVendor::ModuleVector &exports, clang::Module *module) {
- std::set<ClangModulesDeclVendor::ModuleID> exports_set;
+ ExportedModuleSet exports_set;
ReportModuleExportsHelper(exports_set, module);
- for (ModuleID module : exports_set) {
+ for (ModuleID module : exports_set)
exports.push_back(module);
- }
}
bool ClangModulesDeclVendorImpl::AddModule(const SourceModule &module,
@@ -237,17 +234,15 @@
std::vector<ConstString> imported_module;
- for (ConstString path_component : module.path) {
+ for (ConstString path_component : module.path)
imported_module.push_back(path_component);
- }
{
ImportedModuleMap::iterator mi = m_imported_modules.find(imported_module);
if (mi != m_imported_modules.end()) {
- if (exported_modules) {
+ if (exported_modules)
ReportModuleExports(*exported_modules, mi->second);
- }
return true;
}
}
@@ -338,9 +333,8 @@
clang::Module *requested_module = DoGetModule(clang_path, true);
if (requested_module != nullptr) {
- if (exported_modules) {
+ if (exported_modules)
ReportModuleExports(*exported_modules, requested_module);
- }
m_imported_modules[imported_module] = requested_module;
@@ -388,9 +382,8 @@
ClangModulesDeclVendorImpl::FindDecls(ConstString name, bool append,
uint32_t max_matches,
std::vector<CompilerDecl> &decls) {
- if (!m_enabled) {
+ if (!m_enabled)
return 0;
- }
if (!append)
decls.clear();
@@ -423,18 +416,16 @@
void ClangModulesDeclVendorImpl::ForEachMacro(
const ClangModulesDeclVendor::ModuleVector &modules,
std::function<bool(llvm::StringRef, llvm::StringRef)> handler) {
- if (!m_enabled) {
+ if (!m_enabled)
return;
- }
typedef std::map<ModuleID, ssize_t> ModulePriorityMap;
ModulePriorityMap module_priorities;
ssize_t priority = 0;
- for (ModuleID module : modules) {
+ for (ModuleID module : modules)
module_priorities[module] = priority++;
- }
if (m_compiler_instance->getPreprocessor().getExternalSource()) {
m_compiler_instance->getPreprocessor()
@@ -455,9 +446,8 @@
.getExternalIdentifierLookup()) {
lookup->get(mi->first->getName());
}
- if (!ii) {
+ if (!ii)
ii = mi->first;
- }
}
ssize_t found_priority = -1;
@@ -504,24 +494,21 @@
for (auto pi = macro_info->param_begin(),
pe = macro_info->param_end();
pi != pe; ++pi) {
- if (!first_arg) {
+ if (!first_arg)
macro_expansion.append(", ");
- } else {
+ else
first_arg = false;
- }
macro_expansion.append((*pi)->getName().str());
}
if (macro_info->isC99Varargs()) {
- if (first_arg) {
+ if (first_arg)
macro_expansion.append("...");
- } else {
+ else
macro_expansion.append(", ...");
- }
- } else if (macro_info->isGNUVarargs()) {
+ } else if (macro_info->isGNUVarargs())
macro_expansion.append("...");
- }
macro_expansion.append(")");
}
@@ -533,11 +520,10 @@
for (clang::MacroInfo::tokens_iterator ti = macro_info->tokens_begin(),
te = macro_info->tokens_end();
ti != te; ++ti) {
- if (!first_token) {
+ if (!first_token)
macro_expansion.append(" ");
- } else {
+ else
first_token = false;
- }
if (ti->isLiteral()) {
if (const char *literal_data = ti->getLiteralData()) {
@@ -718,7 +704,7 @@
if (!instance->hasTarget())
return nullptr;
- instance->getTarget().adjust(instance->getLangOpts());
+ instance->getTarget().adjust(*diagnostics_engine, instance->getLangOpts());
if (!action->BeginSourceFile(*instance,
instance->getFrontendOpts().Inputs[0]))
diff --git a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp
index 42afac9..13d6a37 100644
--- a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp
@@ -8,6 +8,7 @@
#include "ClangPersistentVariables.h"
#include "ClangASTImporter.h"
+#include "ClangModulesDeclVendor.h"
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
#include "lldb/Core/Value.h"
@@ -23,8 +24,10 @@
using namespace lldb;
using namespace lldb_private;
-ClangPersistentVariables::ClangPersistentVariables()
- : lldb_private::PersistentExpressionState(LLVMCastKind::eKindClang) {}
+ClangPersistentVariables::ClangPersistentVariables(
+ std::shared_ptr<Target> target_sp)
+ : lldb_private::PersistentExpressionState(LLVMCastKind::eKindClang),
+ m_target_sp(target_sp) {}
ExpressionVariableSP ClangPersistentVariables::CreatePersistentVariable(
const lldb::ValueObjectSP &valobj_sp) {
@@ -109,6 +112,15 @@
return m_ast_importer_sp;
}
+std::shared_ptr<ClangModulesDeclVendor>
+ClangPersistentVariables::GetClangModulesDeclVendor() {
+ if (!m_modules_decl_vendor_sp) {
+ m_modules_decl_vendor_sp.reset(
+ ClangModulesDeclVendor::Create(*m_target_sp.get()));
+ }
+ return m_modules_decl_vendor_sp;
+}
+
ConstString
ClangPersistentVariables::GetNextPersistentVariableName(bool is_error) {
llvm::SmallString<64> name;
diff --git a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h
index f888b2d..b8a359d 100644
--- a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h
+++ b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h
@@ -19,6 +19,8 @@
namespace lldb_private {
class ClangASTImporter;
+class ClangModulesDeclVendor;
+class Target;
class TypeSystemClang;
/// \class ClangPersistentVariables ClangPersistentVariables.h
@@ -30,7 +32,7 @@
/// 0-based counter for naming result variables.
class ClangPersistentVariables : public PersistentExpressionState {
public:
- ClangPersistentVariables();
+ ClangPersistentVariables(std::shared_ptr<Target> target_sp);
~ClangPersistentVariables() override = default;
@@ -40,6 +42,7 @@
}
std::shared_ptr<ClangASTImporter> GetClangASTImporter();
+ std::shared_ptr<ClangModulesDeclVendor> GetClangModulesDeclVendor();
lldb::ExpressionVariableSP
CreatePersistentVariable(const lldb::ValueObjectSP &valobj_sp) override;
@@ -106,6 +109,8 @@
///these are the highest-
///< priority source for macros.
std::shared_ptr<ClangASTImporter> m_ast_importer_sp;
+ std::shared_ptr<ClangModulesDeclVendor> m_modules_decl_vendor_sp;
+ std::shared_ptr<Target> m_target_sp;
};
} // namespace lldb_private
diff --git a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
index 9be2947..1b205b1 100644
--- a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
@@ -8,7 +8,7 @@
#include "lldb/Host/Config.h"
-#include <stdio.h>
+#include <cstdio>
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@@ -90,7 +90,7 @@
}
}
-ClangUserExpression::~ClangUserExpression() {}
+ClangUserExpression::~ClangUserExpression() = default;
void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
@@ -349,10 +349,6 @@
static void SetupDeclVendor(ExecutionContext &exe_ctx, Target *target,
DiagnosticManager &diagnostic_manager) {
- ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor();
- if (!decl_vendor)
- return;
-
if (!target->GetEnableAutoImportClangModules())
return;
@@ -361,6 +357,11 @@
if (!persistent_state)
return;
+ std::shared_ptr<ClangModulesDeclVendor> decl_vendor =
+ persistent_state->GetClangModulesDeclVendor();
+ if (!decl_vendor)
+ return;
+
StackFrame *frame = exe_ctx.GetFramePtr();
if (!frame)
return;
diff --git a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp
index 9788a4e..a781163 100644
--- a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp
@@ -14,7 +14,7 @@
#include "ClangExpressionSourceCode.h"
#include "ClangPersistentVariables.h"
-#include <stdio.h>
+#include <cstdio>
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@@ -34,21 +34,38 @@
char ClangUtilityFunction::ID;
-/// Constructor
-///
-/// \param[in] text
-/// The text of the function. Must be a full translation unit.
-///
-/// \param[in] name
-/// The name of the function, as used in the text.
ClangUtilityFunction::ClangUtilityFunction(ExecutionContextScope &exe_scope,
- std::string text, std::string name)
+ std::string text, std::string name,
+ bool enable_debugging)
: UtilityFunction(
exe_scope,
- std::string(ClangExpressionSourceCode::g_expression_prefix) + text,
- std::move(name)) {}
+ std::string(ClangExpressionSourceCode::g_expression_prefix) + text +
+ std::string(ClangExpressionSourceCode::g_expression_suffix),
+ std::move(name), enable_debugging) {
+ // Write the source code to a file so that LLDB's source manager can display
+ // it when debugging the code.
+ if (enable_debugging) {
+ int temp_fd = -1;
+ llvm::SmallString<128> result_path;
+ llvm::sys::fs::createTemporaryFile("lldb", "expr", temp_fd, result_path);
+ if (temp_fd != -1) {
+ lldb_private::NativeFile file(temp_fd, File::eOpenOptionWrite, true);
+ text = "#line 1 \"" + std::string(result_path) + "\"\n" + text;
+ size_t bytes_written = text.size();
+ file.Write(text.c_str(), bytes_written);
+ if (bytes_written == text.size()) {
+ // If we successfully wrote the source to a temporary file, replace the
+ // function text with the next text containing the line directive.
+ m_function_text =
+ std::string(ClangExpressionSourceCode::g_expression_prefix) + text +
+ std::string(ClangExpressionSourceCode::g_expression_suffix);
+ }
+ file.Close();
+ }
+ }
+}
-ClangUtilityFunction::~ClangUtilityFunction() {}
+ClangUtilityFunction::~ClangUtilityFunction() = default;
/// Install the utility function into a process
///
diff --git a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
index 7914e14..b8a154b 100644
--- a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
+++ b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
@@ -48,8 +48,11 @@
///
/// \param[in] name
/// The name of the function, as used in the text.
+ ///
+ /// \param[in] enable_debugging
+ /// Enable debugging of this function.
ClangUtilityFunction(ExecutionContextScope &exe_scope, std::string text,
- std::string name);
+ std::string name, bool enable_debugging);
~ClangUtilityFunction() override;
@@ -71,9 +74,9 @@
private:
class ClangUtilityFunctionHelper : public ClangExpressionHelper {
public:
- ClangUtilityFunctionHelper() {}
+ ClangUtilityFunctionHelper() = default;
- ~ClangUtilityFunctionHelper() override {}
+ ~ClangUtilityFunctionHelper() override = default;
/// Return the object that the parser should use when resolving external
/// values. May be NULL if everything should be self-contained.
diff --git a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h
index b984db4..425106b 100644
--- a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h
+++ b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h
@@ -59,7 +59,7 @@
/// Creates a configuration by analyzing the given list of used source files.
explicit CppModuleConfiguration(const FileSpecList &support_files);
/// Creates an empty and invalid configuration.
- CppModuleConfiguration() {}
+ CppModuleConfiguration() = default;
/// Returns true iff this is a valid configuration that can be used to
/// load and compile modules.
diff --git a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp
index f953e86..74dd046 100644
--- a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp
@@ -33,6 +33,9 @@
"shared_ptr",
"unique_ptr",
"weak_ptr",
+ // iterator
+ "move_iterator",
+ "__wrap_iter",
// utility
"allocator",
"pair",
diff --git a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
index b35bf07..5655d54 100644
--- a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
@@ -14,6 +14,7 @@
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Operator.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
@@ -41,14 +42,12 @@
using namespace llvm;
-static char ID;
-
typedef SmallVector<Instruction *, 2> InstrList;
IRForTarget::FunctionValueCache::FunctionValueCache(Maker const &maker)
: m_maker(maker), m_values() {}
-IRForTarget::FunctionValueCache::~FunctionValueCache() {}
+IRForTarget::FunctionValueCache::~FunctionValueCache() = default;
llvm::Value *
IRForTarget::FunctionValueCache::GetValue(llvm::Function *function) {
@@ -72,13 +71,9 @@
lldb_private::IRExecutionUnit &execution_unit,
lldb_private::Stream &error_stream,
const char *func_name)
- : ModulePass(ID), m_resolve_vars(resolve_vars), m_func_name(func_name),
- m_module(nullptr), m_decl_map(decl_map),
- m_CFStringCreateWithBytes(nullptr), m_sel_registerName(nullptr),
- m_objc_getClass(nullptr), m_intptr_ty(nullptr),
- m_error_stream(error_stream), m_execution_unit(execution_unit),
- m_result_store(nullptr), m_result_is_pointer(false),
- m_reloc_placeholder(nullptr),
+ : m_resolve_vars(resolve_vars), m_func_name(func_name),
+ m_decl_map(decl_map), m_error_stream(error_stream),
+ m_execution_unit(execution_unit),
m_entry_instruction_finder(FindEntryInstruction) {}
/* Handy utility functions used at several places in the code */
@@ -105,8 +100,6 @@
return s;
}
-IRForTarget::~IRForTarget() {}
-
bool IRForTarget::FixFunctionLinkage(llvm::Function &llvm_function) {
llvm_function.setLinkage(GlobalValue::ExternalLinkage);
@@ -1582,20 +1575,14 @@
FunctionValueCache get_element_pointer_maker(
[&value_maker, &entry_instruction_finder, old_constant,
constant_expr](llvm::Function *function) -> llvm::Value * {
- Value *ptr = constant_expr->getOperand(0);
+ auto *gep = cast<llvm::GEPOperator>(constant_expr);
+ Value *ptr = gep->getPointerOperand();
if (ptr == old_constant)
ptr = value_maker.GetValue(function);
std::vector<Value *> index_vector;
-
- unsigned operand_index;
- unsigned num_operands = constant_expr->getNumOperands();
-
- for (operand_index = 1; operand_index < num_operands;
- ++operand_index) {
- Value *operand = constant_expr->getOperand(operand_index);
-
+ for (Value *operand : gep->indices()) {
if (operand == old_constant)
operand = value_maker.GetValue(function);
@@ -1605,7 +1592,7 @@
ArrayRef<Value *> indices(index_vector);
return GetElementPtrInst::Create(
- nullptr, ptr, indices, "",
+ gep->getSourceElementType(), ptr, indices, "",
llvm::cast<Instruction>(
entry_instruction_finder.GetValue(function)));
});
@@ -1788,7 +1775,8 @@
ConstantInt *offset_int(
ConstantInt::get(offset_type, offset, true));
GetElementPtrInst *get_element_ptr = GetElementPtrInst::Create(
- nullptr, argument, offset_int, "", entry_instruction);
+ argument->getType()->getPointerElementType(), argument,
+ offset_int, "", entry_instruction);
if (name == m_result_name && !m_result_is_pointer) {
BitCastInst *bit_cast = new BitCastInst(
@@ -2022,10 +2010,3 @@
return true;
}
-
-void IRForTarget::assignPassManager(PMStack &pass_mgr_stack,
- PassManagerType pass_mgr_type) {}
-
-PassManagerType IRForTarget::getPotentialPassManagerType() const {
- return PMT_ModulePassManager;
-}
diff --git a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h
index ebfc0ca..5f212fa 100644
--- a/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h
+++ b/src/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h
@@ -58,7 +58,7 @@
/// transformations to the IR which make it relocatable. These
/// transformations are discussed in more detail next to their relevant
/// functions.
-class IRForTarget : public llvm::ModulePass {
+class IRForTarget {
public:
enum class LookupResult { Success, Fail, Ignore };
@@ -87,9 +87,6 @@
lldb_private::Stream &error_stream,
const char *func_name = "$__lldb_expr");
- /// Destructor
- ~IRForTarget() override;
-
/// Run this IR transformer on a single module
///
/// Implementation of the llvm::ModulePass::runOnModule() function.
@@ -101,20 +98,7 @@
///
/// \return
/// True on success; false otherwise
- bool runOnModule(llvm::Module &llvm_module) override;
-
- /// Interface stub
- ///
- /// Implementation of the llvm::ModulePass::assignPassManager() function.
- void assignPassManager(llvm::PMStack &pass_mgr_stack,
- llvm::PassManagerType pass_mgr_type =
- llvm::PMT_ModulePassManager) override;
-
- /// Returns PMT_ModulePassManager
- ///
- /// Implementation of the llvm::ModulePass::getPotentialPassManagerType()
- /// function.
- llvm::PassManagerType getPotentialPassManagerType() const override;
+ bool runOnModule(llvm::Module &llvm_module);
private:
/// Ensures that the current function's linkage is set to external.
@@ -419,51 +403,46 @@
/// True on success; false otherwise
bool ReplaceVariables(llvm::Function &llvm_function);
- /// Flags
- bool m_resolve_vars; ///< True if external variable references and persistent
- ///variable references should be resolved
- lldb_private::ConstString
- m_func_name; ///< The name of the function to translate
- lldb_private::ConstString
- m_result_name; ///< The name of the result variable ($0, $1, ...)
- lldb_private::TypeFromParser
- m_result_type; ///< The type of the result variable.
- llvm::Module *m_module; ///< The module being processed, or NULL if that has
- ///not been determined yet.
- std::unique_ptr<llvm::DataLayout> m_target_data; ///< The target data for the
- ///module being processed, or
- ///NULL if there is no
- ///module.
- lldb_private::ClangExpressionDeclMap
- *m_decl_map; ///< The DeclMap containing the Decls
- llvm::FunctionCallee
- m_CFStringCreateWithBytes; ///< The address of the function
- /// CFStringCreateWithBytes, cast to the
- /// appropriate function pointer type
- llvm::FunctionCallee m_sel_registerName; ///< The address of the function
- /// sel_registerName, cast to the
- /// appropriate function pointer type
- llvm::FunctionCallee m_objc_getClass; ///< The address of the function
- /// objc_getClass, cast to the
- /// appropriate function pointer type
- llvm::IntegerType
- *m_intptr_ty; ///< The type of an integer large enough to hold a pointer.
- lldb_private::Stream
- &m_error_stream; ///< The stream on which errors should be printed
- lldb_private::IRExecutionUnit &
- m_execution_unit; ///< The execution unit containing the IR being created.
-
- llvm::StoreInst *m_result_store; ///< If non-NULL, the store instruction that
- ///writes to the result variable. If
- /// m_has_side_effects is true, this is
- /// NULL.
- bool m_result_is_pointer; ///< True if the function's result in the AST is a
- ///pointer (see comments in
- /// ASTResultSynthesizer::SynthesizeBodyResult)
-
+ /// True if external variable references and persistent variable references
+ /// should be resolved
+ bool m_resolve_vars;
+ /// The name of the function to translate
+ lldb_private::ConstString m_func_name;
+ /// The name of the result variable ($0, $1, ...)
+ lldb_private::ConstString m_result_name;
+ /// The type of the result variable.
+ lldb_private::TypeFromParser m_result_type;
+ /// The module being processed, or NULL if that has not been determined yet.
+ llvm::Module *m_module = nullptr;
+ /// The target data for the module being processed, or NULL if there is no
+ /// module.
+ std::unique_ptr<llvm::DataLayout> m_target_data;
+ /// The DeclMap containing the Decls
+ lldb_private::ClangExpressionDeclMap *m_decl_map;
+ /// The address of the function CFStringCreateWithBytes, cast to the
+ /// appropriate function pointer type
+ llvm::FunctionCallee m_CFStringCreateWithBytes;
+ /// The address of the function sel_registerName, cast to the appropriate
+ /// function pointer type.
+ llvm::FunctionCallee m_sel_registerName;
+ /// The address of the function objc_getClass, cast to the appropriate
+ /// function pointer type.
+ llvm::FunctionCallee m_objc_getClass;
+ /// The type of an integer large enough to hold a pointer.
+ llvm::IntegerType *m_intptr_ty = nullptr;
+ /// The stream on which errors should be printed.
+ lldb_private::Stream &m_error_stream;
+ /// The execution unit containing the IR being created.
+ lldb_private::IRExecutionUnit &m_execution_unit;
+ /// If non-NULL, the store instruction that writes to the result variable. If
+ /// m_has_side_effects is true, this is NULL.
+ llvm::StoreInst *m_result_store = nullptr;
+ /// True if the function's result in the AST is a pointer (see comments in
+ /// ASTResultSynthesizer::SynthesizeBodyResult)
+ bool m_result_is_pointer = false;
/// A placeholder that will be replaced by a pointer to the final location of
/// the static allocation.
- llvm::GlobalVariable *m_reloc_placeholder;
+ llvm::GlobalVariable *m_reloc_placeholder = nullptr;
class FunctionValueCache {
public:
diff --git a/src/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/src/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
index 5559127..bf0bbda 100644
--- a/src/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include <stdlib.h>
+#include <cstdlib>
#include "EmulateInstructionARM.h"
#include "EmulationStateARM.h"
diff --git a/src/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h b/src/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
index d15d80c..dfd7c92 100644
--- a/src/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
+++ b/src/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
@@ -19,8 +19,8 @@
// ITSession - Keep track of the IT Block progression.
class ITSession {
public:
- ITSession() : ITCounter(0), ITState(0) {}
- ~ITSession() {}
+ ITSession() = default;
+ ~ITSession() = default;
// InitIT - Initializes ITCounter/ITState.
bool InitIT(uint32_t bits7_0);
@@ -39,8 +39,8 @@
uint32_t GetCond();
private:
- uint32_t ITCounter; // Possible values: 0, 1, 2, 3, 4.
- uint32_t ITState; // A2.5.2 Consists of IT[7:5] and IT[4:0] initially.
+ uint32_t ITCounter = 0; // Possible values: 0, 1, 2, 3, 4.
+ uint32_t ITState = 0; // A2.5.2 Consists of IT[7:5] and IT[4:0] initially.
};
class EmulateInstructionARM : public EmulateInstruction {
diff --git a/src/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp b/src/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp
index aef08ba..569482c 100644
--- a/src/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp
@@ -20,11 +20,11 @@
using namespace lldb;
using namespace lldb_private;
-EmulationStateARM::EmulationStateARM() : m_gpr(), m_vfp_regs(), m_memory() {
+EmulationStateARM::EmulationStateARM() : m_vfp_regs(), m_memory() {
ClearPseudoRegisters();
}
-EmulationStateARM::~EmulationStateARM() {}
+EmulationStateARM::~EmulationStateARM() = default;
bool EmulationStateARM::LoadPseudoRegistersFromFrame(StackFrame &frame) {
RegisterContext *reg_ctx = frame.GetRegisterContext().get();
diff --git a/src/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.h b/src/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.h
index 955c7c6..28bc5d9 100644
--- a/src/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.h
+++ b/src/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.h
@@ -61,7 +61,7 @@
const lldb_private::RegisterValue ®_value);
private:
- uint32_t m_gpr[17];
+ uint32_t m_gpr[17] = {0};
struct _sd_regs {
uint32_t s_regs[32]; // sregs 0 - 31 & dregs 0 - 15
diff --git a/src/llvm-project/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp b/src/llvm-project/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
index d4cb726..a1a93c0 100644
--- a/src/llvm-project/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
@@ -8,7 +8,7 @@
#include "EmulateInstructionMIPS.h"
-#include <stdlib.h>
+#include <cstdlib>
#include "lldb/Core/Address.h"
#include "lldb/Core/Opcode.h"
@@ -159,8 +159,8 @@
target->createMCSubtargetInfo(triple.getTriple(), cpu, features));
assert(m_asm_info.get() && m_subtype_info.get());
- m_context = std::make_unique<llvm::MCContext>(m_asm_info.get(),
- m_reg_info.get(), nullptr);
+ m_context = std::make_unique<llvm::MCContext>(
+ triple, m_asm_info.get(), m_reg_info.get(), m_subtype_info.get());
assert(m_context.get());
m_disasm.reset(target->createMCDisassembler(*m_subtype_info, *m_context));
@@ -1018,8 +1018,9 @@
const size_t bytes_read =
target->ReadMemory(next_addr, /* Address of next instruction */
- true, /* prefer_file_cache */
- buf, sizeof(uint32_t), error, &load_addr);
+ buf, sizeof(uint32_t), error,
+ false, /* force_live_memory */
+ &load_addr);
if (bytes_read == 0)
return true;
diff --git a/src/llvm-project/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp b/src/llvm-project/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
index 4ccaf0d..6044d00 100644
--- a/src/llvm-project/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
@@ -8,7 +8,7 @@
#include "EmulateInstructionMIPS64.h"
-#include <stdlib.h>
+#include <cstdlib>
#include "lldb/Core/Address.h"
#include "lldb/Core/Opcode.h"
@@ -163,8 +163,8 @@
target->createMCSubtargetInfo(triple.getTriple(), cpu, features));
assert(m_asm_info.get() && m_subtype_info.get());
- m_context = std::make_unique<llvm::MCContext>(m_asm_info.get(),
- m_reg_info.get(), nullptr);
+ m_context = std::make_unique<llvm::MCContext>(
+ triple, m_asm_info.get(), m_reg_info.get(), m_subtype_info.get());
assert(m_context.get());
m_disasm.reset(target->createMCDisassembler(*m_subtype_info, *m_context));
diff --git a/src/llvm-project/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp b/src/llvm-project/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp
index 5d97513..4e78c36 100644
--- a/src/llvm-project/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp
@@ -8,7 +8,7 @@
#include "EmulateInstructionPPC64.h"
-#include <stdlib.h>
+#include <cstdlib>
#include "lldb/Core/PluginManager.h"
#include "lldb/Symbol/UnwindPlan.h"
diff --git a/src/llvm-project/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp b/src/llvm-project/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp
index 99784bd..9a88b34 100644
--- a/src/llvm-project/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp
+++ b/src/llvm-project/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp
@@ -127,7 +127,7 @@
StackFrameSP responsible_frame;
for (unsigned I = 0; I < thread_sp->GetStackFrameCount(); ++I) {
StackFrameSP frame = thread_sp->GetStackFrameAtIndex(I);
- Address addr = frame->GetFrameCodeAddress();
+ Address addr = frame->GetFrameCodeAddressForSymbolication();
if (addr.GetModule() == runtime_module_sp) // Skip PCs from the runtime.
continue;
@@ -135,11 +135,6 @@
if (!responsible_frame)
responsible_frame = frame;
- // First frame in stacktrace should point to a real PC, not return address.
- if (I != 0 && trace->GetSize() == 0) {
- addr.Slide(-1);
- }
-
lldb::addr_t PC = addr.GetLoadAddress(&target);
trace->AddItem(StructuredData::ObjectSP(new StructuredData::Integer(PC)));
}
@@ -271,8 +266,11 @@
info->GetObjectForDotSeparatedPath("tid");
tid_t tid = thread_id_obj ? thread_id_obj->GetIntegerValue() : 0;
- HistoryThread *history_thread = new HistoryThread(*process_sp, tid, PCs);
- ThreadSP new_thread_sp(history_thread);
+ // We gather symbolication addresses above, so no need for HistoryThread to
+ // try to infer the call addresses.
+ bool pcs_are_call_addresses = true;
+ ThreadSP new_thread_sp = std::make_shared<HistoryThread>(
+ *process_sp, tid, PCs, pcs_are_call_addresses);
// Save this in the Process' ExtendedThreadList so a strong pointer retains
// the object
diff --git a/src/llvm-project/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp b/src/llvm-project/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp
index b60eb53..58bc38a 100644
--- a/src/llvm-project/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp
+++ b/src/llvm-project/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp
@@ -29,7 +29,7 @@
#include "lldb/Target/Thread.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/Stream.h"
-#include <ctype.h>
+#include <cctype>
#include <memory>
@@ -150,8 +150,8 @@
StructuredData::Array *trace = new StructuredData::Array();
auto trace_sp = StructuredData::ObjectSP(trace);
for (unsigned I = 0; I < thread_sp->GetStackFrameCount(); ++I) {
- const Address FCA =
- thread_sp->GetStackFrameAtIndex(I)->GetFrameCodeAddress();
+ const Address FCA = thread_sp->GetStackFrameAtIndex(I)
+ ->GetFrameCodeAddressForSymbolication();
if (FCA.GetModule() == runtime_module_sp) // Skip PCs from the runtime.
continue;
@@ -324,8 +324,11 @@
info->GetObjectForDotSeparatedPath("tid");
tid_t tid = thread_id_obj ? thread_id_obj->GetIntegerValue() : 0;
- HistoryThread *history_thread = new HistoryThread(*process_sp, tid, PCs);
- ThreadSP new_thread_sp(history_thread);
+ // We gather symbolication addresses above, so no need for HistoryThread to
+ // try to infer the call addresses.
+ bool pcs_are_call_addresses = true;
+ ThreadSP new_thread_sp = std::make_shared<HistoryThread>(
+ *process_sp, tid, PCs, pcs_are_call_addresses);
std::string stop_reason_description = GetStopReasonDescription(info);
new_thread_sp->SetName(stop_reason_description.c_str());
diff --git a/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp b/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp
index 35788a6..1c498a2 100644
--- a/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp
@@ -74,14 +74,12 @@
const CompilerType reserved_type =
clang_ast_context->GetBasicType(lldb::eBasicTypeInt);
const char *const FuncPtr_name("__FuncPtr");
- const CompilerType FuncPtr_type =
- clang_ast_importer->CopyType(*clang_ast_context, function_pointer_type);
m_block_struct_type = clang_ast_context->CreateStructForIdentifier(
ConstString(), {{isa_name, isa_type},
{flags_name, flags_type},
{reserved_name, reserved_type},
- {FuncPtr_name, FuncPtr_type}});
+ {FuncPtr_name, function_pointer_type}});
}
~BlockPointerSyntheticFrontEnd() override = default;
diff --git a/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index d844498..895fd55 100644
--- a/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -59,6 +59,11 @@
return g_name;
}
+bool CPlusPlusLanguage::SymbolNameFitsToLanguage(Mangled mangled) const {
+ const char *mangled_name = mangled.GetMangledName().GetCString();
+ return mangled_name && CPlusPlusLanguage::IsCPPMangledName(mangled_name);
+}
+
// PluginInterface protocol
lldb_private::ConstString CPlusPlusLanguage::GetPluginName() {
@@ -1054,7 +1059,7 @@
.SetSkipReferences(false),
lldb_private::formatters::VectorTypeSummaryProvider,
"vector_type pointer summary provider"));
- if (valobj.GetCompilerType().IsVectorType(nullptr, nullptr)) {
+ if (valobj.GetCompilerType().IsVectorType()) {
if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled())
return formatter_sp;
}
@@ -1074,7 +1079,7 @@
.SetSkipReferences(false),
lldb_private::formatters::BlockPointerSummaryProvider,
"block pointer summary provider"));
- if (valobj.GetCompilerType().IsBlockPointerType(nullptr)) {
+ if (valobj.GetCompilerType().IsBlockPointerType()) {
return formatter_sp;
}
return nullptr;
@@ -1104,7 +1109,7 @@
.SetNonCacheable(true),
"vector_type synthetic children",
lldb_private::formatters::VectorTypeSyntheticFrontEndCreator));
- if (valobj.GetCompilerType().IsVectorType(nullptr, nullptr)) {
+ if (valobj.GetCompilerType().IsVectorType()) {
if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled())
return formatter_sp;
}
@@ -1123,7 +1128,7 @@
.SetNonCacheable(true),
"block pointer synthetic children",
lldb_private::formatters::BlockPointerSyntheticFrontEndCreator));
- if (valobj.GetCompilerType().IsBlockPointerType(nullptr)) {
+ if (valobj.GetCompilerType().IsBlockPointerType()) {
return formatter_sp;
}
return nullptr;
@@ -1147,7 +1152,7 @@
const auto suffixes = {".cpp", ".cxx", ".c++", ".cc", ".c",
".h", ".hh", ".hpp", ".hxx", ".h++"};
for (auto suffix : suffixes) {
- if (file_path.endswith_lower(suffix))
+ if (file_path.endswith_insensitive(suffix))
return true;
}
diff --git a/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h b/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
index e2b5d29..9163be4 100644
--- a/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
+++ b/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
@@ -28,8 +28,7 @@
class MethodName {
public:
MethodName()
- : m_full(), m_basename(), m_context(), m_arguments(), m_qualifiers(),
- m_parsed(false), m_parse_error(false) {}
+ : m_full(), m_basename(), m_context(), m_arguments(), m_qualifiers() {}
MethodName(ConstString s)
: m_full(s), m_basename(), m_context(), m_arguments(), m_qualifiers(),
@@ -68,8 +67,8 @@
llvm::StringRef m_context; // Decl context: "lldb::SBTarget"
llvm::StringRef m_arguments; // Arguments: "(unsigned int)"
llvm::StringRef m_qualifiers; // Qualifiers: "const"
- bool m_parsed;
- bool m_parse_error;
+ bool m_parsed = false;
+ bool m_parse_error = false;
};
CPlusPlusLanguage() = default;
@@ -105,6 +104,8 @@
static lldb_private::ConstString GetPluginNameStatic();
+ bool SymbolNameFitsToLanguage(Mangled mangled) const override;
+
static bool IsCPPMangledName(llvm::StringRef name);
// Extract C++ context and identifier from a string using heuristic matching
diff --git a/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h b/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h
index 6fe6b12..426434c 100644
--- a/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h
+++ b/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h
@@ -69,7 +69,7 @@
size_t begin_index = 0;
size_t end_index = 0;
- Range() {}
+ Range() = default;
Range(size_t begin, size_t end) : begin_index(begin), end_index(end) {
assert(end >= begin);
}
diff --git a/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
index 2b16ebe..8eda422 100644
--- a/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
@@ -379,8 +379,7 @@
lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
LibcxxSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
- : SyntheticChildrenFrontEnd(*valobj_sp), m_cntrl(nullptr), m_count_sp(),
- m_weak_count_sp(), m_ptr_size(0), m_byte_order(lldb::eByteOrderInvalid) {
+ : SyntheticChildrenFrontEnd(*valobj_sp), m_cntrl(nullptr) {
if (valobj_sp)
Update();
}
@@ -403,42 +402,23 @@
if (idx == 0)
return valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true);
- if (idx > 2)
- return lldb::ValueObjectSP();
-
if (idx == 1) {
- if (!m_count_sp) {
- ValueObjectSP shared_owners_sp(m_cntrl->GetChildMemberWithName(
- ConstString("__shared_owners_"), true));
- if (!shared_owners_sp)
- return lldb::ValueObjectSP();
- uint64_t count = 1 + shared_owners_sp->GetValueAsUnsigned(0);
- DataExtractor data(&count, 8, m_byte_order, m_ptr_size);
- m_count_sp = CreateValueObjectFromData(
- "count", data, valobj_sp->GetExecutionContextRef(),
- shared_owners_sp->GetCompilerType());
+ if (auto ptr_sp =
+ valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true)) {
+ Status status;
+ auto value_sp = ptr_sp->Dereference(status);
+ if (status.Success()) {
+ auto value_type_sp =
+ valobj_sp->GetCompilerType().GetTypeTemplateArgument(0);
+ return value_sp->Cast(value_type_sp);
+ }
}
- return m_count_sp;
- } else /* if (idx == 2) */
- {
- if (!m_weak_count_sp) {
- ValueObjectSP shared_weak_owners_sp(m_cntrl->GetChildMemberWithName(
- ConstString("__shared_weak_owners_"), true));
- if (!shared_weak_owners_sp)
- return lldb::ValueObjectSP();
- uint64_t count = 1 + shared_weak_owners_sp->GetValueAsUnsigned(0);
- DataExtractor data(&count, 8, m_byte_order, m_ptr_size);
- m_weak_count_sp = CreateValueObjectFromData(
- "count", data, valobj_sp->GetExecutionContextRef(),
- shared_weak_owners_sp->GetCompilerType());
- }
- return m_weak_count_sp;
}
+
+ return lldb::ValueObjectSP();
}
bool lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() {
- m_count_sp.reset();
- m_weak_count_sp.reset();
m_cntrl = nullptr;
ValueObjectSP valobj_sp = m_backend.GetSP();
@@ -449,9 +429,6 @@
if (!target_sp)
return false;
- m_byte_order = target_sp->GetArchitecture().GetByteOrder();
- m_ptr_size = target_sp->GetArchitecture().GetAddressByteSize();
-
lldb::ValueObjectSP cntrl_sp(
valobj_sp->GetChildMemberWithName(ConstString("__cntrl_"), true));
@@ -469,10 +446,8 @@
GetIndexOfChildWithName(ConstString name) {
if (name == "__ptr_")
return 0;
- if (name == "count")
+ if (name == "$$dereference$$")
return 1;
- if (name == "weak_count")
- return 2;
return UINT32_MAX;
}
@@ -488,7 +463,7 @@
lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
LibcxxUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
- : SyntheticChildrenFrontEnd(*valobj_sp), m_compressed_pair_sp() {
+ : SyntheticChildrenFrontEnd(*valobj_sp) {
if (valobj_sp)
Update();
}
@@ -505,19 +480,27 @@
size_t lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::
CalculateNumChildren() {
- return (m_compressed_pair_sp ? 1 : 0);
+ return (m_value_ptr_sp ? 1 : 0);
}
lldb::ValueObjectSP
lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::GetChildAtIndex(
size_t idx) {
- if (!m_compressed_pair_sp)
+ if (!m_value_ptr_sp)
return lldb::ValueObjectSP();
- if (idx != 0)
- return lldb::ValueObjectSP();
+ if (idx == 0)
+ return m_value_ptr_sp;
- return m_compressed_pair_sp;
+ if (idx == 1) {
+ Status status;
+ auto value_sp = m_value_ptr_sp->Dereference(status);
+ if (status.Success()) {
+ return value_sp;
+ }
+ }
+
+ return lldb::ValueObjectSP();
}
bool lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::Update() {
@@ -530,7 +513,7 @@
if (!ptr_sp)
return false;
- m_compressed_pair_sp = GetValueOfLibCXXCompressedPair(*ptr_sp);
+ m_value_ptr_sp = GetValueOfLibCXXCompressedPair(*ptr_sp);
return false;
}
@@ -544,6 +527,8 @@
GetIndexOfChildWithName(ConstString name) {
if (name == "__value_")
return 0;
+ if (name == "$$dereference$$")
+ return 1;
return UINT32_MAX;
}
diff --git a/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h b/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
index ea5a7c1..99e2065 100644
--- a/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
+++ b/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h
@@ -105,10 +105,6 @@
private:
ValueObject *m_cntrl;
- lldb::ValueObjectSP m_count_sp;
- lldb::ValueObjectSP m_weak_count_sp;
- uint8_t m_ptr_size;
- lldb::ByteOrder m_byte_order;
};
class LibcxxUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
@@ -128,7 +124,7 @@
~LibcxxUniquePtrSyntheticFrontEnd() override;
private:
- lldb::ValueObjectSP m_compressed_pair_sp;
+ lldb::ValueObjectSP m_value_ptr_sp;
};
SyntheticChildrenFrontEnd *
diff --git a/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp b/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp
index 6de4637..e5b868f 100644
--- a/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp
@@ -85,7 +85,7 @@
CompilerType type;
ValueObjectSP chunk;
// For small bitsets __first_ is not an array, but a plain size_t.
- if (m_first->GetCompilerType().IsArrayType(&type, nullptr, nullptr)) {
+ if (m_first->GetCompilerType().IsArrayType(&type)) {
llvm::Optional<uint64_t> bit_size =
type.GetBitSize(ctx.GetBestExecutionContextScope());
if (!bit_size || *bit_size == 0)
diff --git a/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp b/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
index 0d5ae16..47c6634 100644
--- a/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
@@ -27,8 +27,7 @@
class ListEntry {
public:
ListEntry() = default;
- ListEntry(ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {}
- ListEntry(const ListEntry &rhs) = default;
+ ListEntry(ValueObjectSP entry_sp) : m_entry_sp(std::move(entry_sp)) {}
ListEntry(ValueObject *entry)
: m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {}
@@ -73,9 +72,8 @@
class ListIterator {
public:
ListIterator() = default;
- ListIterator(ListEntry entry) : m_entry(entry) {}
- ListIterator(ValueObjectSP entry) : m_entry(entry) {}
- ListIterator(const ListIterator &rhs) = default;
+ ListIterator(ListEntry entry) : m_entry(std::move(entry)) {}
+ ListIterator(ValueObjectSP entry) : m_entry(std::move(entry)) {}
ListIterator(ValueObject *entry) : m_entry(entry) {}
ValueObjectSP value() { return m_entry.GetEntry(); }
diff --git a/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp b/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
index 64a199e..25c2bfd 100644
--- a/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
@@ -26,7 +26,6 @@
public:
MapEntry() = default;
explicit MapEntry(ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {}
- MapEntry(const MapEntry &rhs) = default;
explicit MapEntry(ValueObject *entry)
: m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {}
@@ -86,9 +85,9 @@
public:
MapIterator() = default;
MapIterator(MapEntry entry, size_t depth = 0)
- : m_entry(entry), m_max_depth(depth), m_error(false) {}
+ : m_entry(std::move(entry)), m_max_depth(depth), m_error(false) {}
MapIterator(ValueObjectSP entry, size_t depth = 0)
- : m_entry(entry), m_max_depth(depth), m_error(false) {}
+ : m_entry(std::move(entry)), m_max_depth(depth), m_error(false) {}
MapIterator(const MapIterator &rhs)
: m_entry(rhs.m_entry), m_max_depth(rhs.m_max_depth), m_error(false) {}
MapIterator(ValueObject *entry, size_t depth = 0)
@@ -138,7 +137,7 @@
}
private:
- MapEntry tree_min(MapEntry &&x) {
+ MapEntry tree_min(MapEntry x) {
if (x.null())
return MapEntry();
MapEntry left(x.left());
diff --git a/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp b/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp
index 0b34b4e..79e864a 100644
--- a/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp
@@ -99,9 +99,17 @@
if (ptr_obj)
m_ptr_obj = ptr_obj->Clone(ConstString("pointer")).get();
- ValueObjectSP del_obj = tuple_frontend->GetChildAtIndex(1);
- if (del_obj)
- m_del_obj = del_obj->Clone(ConstString("deleter")).get();
+ // Add a 'deleter' child if there was a non-empty deleter type specified.
+ //
+ // The object might have size=1 in the TypeSystem but occupies no dedicated
+ // storage due to no_unique_address, so infer the actual size from the total
+ // size of the unique_ptr class. If sizeof(unique_ptr) == sizeof(void*) then
+ // the deleter is empty and should be hidden.
+ if (tuple_sp->GetByteSize() > ptr_obj->GetByteSize()) {
+ ValueObjectSP del_obj = tuple_frontend->GetChildAtIndex(1);
+ if (del_obj)
+ m_del_obj = del_obj->Clone(ConstString("deleter")).get();
+ }
if (m_ptr_obj) {
Status error;
diff --git a/src/llvm-project/lldb/source/Plugins/Language/ObjC/Cocoa.cpp b/src/llvm-project/lldb/source/Plugins/Language/ObjC/Cocoa.cpp
index d871d347..1479f4f 100644
--- a/src/llvm-project/lldb/source/Plugins/Language/ObjC/Cocoa.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Language/ObjC/Cocoa.cpp
@@ -351,7 +351,7 @@
}
static void NSNumber_FormatLong(ValueObject &valobj, Stream &stream,
- uint64_t value, lldb::LanguageType lang) {
+ int64_t value, lldb::LanguageType lang) {
static ConstString g_TypeHint("NSNumber:long");
std::string prefix, suffix;
@@ -367,10 +367,10 @@
}
static void NSNumber_FormatInt128(ValueObject &valobj, Stream &stream,
- const llvm::APInt &value,
- lldb::LanguageType lang) {
+ const llvm::APInt &value,
+ lldb::LanguageType lang) {
static ConstString g_TypeHint("NSNumber:int128_t");
-
+
std::string prefix, suffix;
if (Language *language = Language::FindPlugin(lang)) {
if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix,
@@ -379,11 +379,11 @@
suffix.clear();
}
}
-
+
stream.PutCString(prefix.c_str());
const int radix = 10;
const bool isSigned = true;
- std::string str = value.toString(radix, isSigned);
+ std::string str = llvm::toString(value, radix, isSigned);
stream.PutCString(str.c_str());
stream.PutCString(suffix.c_str());
}
@@ -426,6 +426,7 @@
if (!process_sp)
return false;
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS);
ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);
if (!runtime)
@@ -456,9 +457,18 @@
return NSDecimalNumberSummaryProvider(valobj, stream, options);
if (class_name == "NSNumber" || class_name == "__NSCFNumber") {
- uint64_t value = 0;
+ int64_t value = 0;
uint64_t i_bits = 0;
- if (descriptor->GetTaggedPointerInfo(&i_bits, &value)) {
+ if (descriptor->GetTaggedPointerInfoSigned(&i_bits, &value)) {
+ // Check for "preserved" numbers. We still don't support them yet.
+ if (i_bits & 0x8) {
+ if (log)
+ log->Printf(
+ "Unsupported (preserved) NSNumber tagged pointer 0x%" PRIu64,
+ valobj_addr);
+ return false;
+ }
+
switch (i_bits) {
case 0:
NSNumber_FormatChar(valobj, stream, (char)value, options.GetLanguage());
@@ -498,49 +508,66 @@
f64 = 0x5,
sint128 = 0x6
};
-
+
uint64_t data_location = valobj_addr + 2 * ptr_size;
TypeCodes type_code;
-
+
if (new_format) {
- uint64_t cfinfoa =
- process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
- ptr_size, 0, error);
-
+ uint64_t cfinfoa = process_sp->ReadUnsignedIntegerFromMemory(
+ valobj_addr + ptr_size, ptr_size, 0, error);
+
if (error.Fail())
return false;
bool is_preserved_number = cfinfoa & 0x8;
if (is_preserved_number) {
- lldbassert(!static_cast<bool>("We should handle preserved numbers!"));
+ if (log)
+ log->Printf(
+ "Unsupported preserved NSNumber tagged pointer 0x%" PRIu64,
+ valobj_addr);
return false;
}
type_code = static_cast<TypeCodes>(cfinfoa & 0x7);
} else {
- uint8_t data_type =
- process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 1,
- 0, error) & 0x1F;
-
+ uint8_t data_type = process_sp->ReadUnsignedIntegerFromMemory(
+ valobj_addr + ptr_size, 1, 0, error) &
+ 0x1F;
+
if (error.Fail())
return false;
-
+
switch (data_type) {
- case 1: type_code = TypeCodes::sint8; break;
- case 2: type_code = TypeCodes::sint16; break;
- case 3: type_code = TypeCodes::sint32; break;
- case 17: data_location += 8; LLVM_FALLTHROUGH;
- case 4: type_code = TypeCodes::sint64; break;
- case 5: type_code = TypeCodes::f32; break;
- case 6: type_code = TypeCodes::f64; break;
- default: return false;
+ case 1:
+ type_code = TypeCodes::sint8;
+ break;
+ case 2:
+ type_code = TypeCodes::sint16;
+ break;
+ case 3:
+ type_code = TypeCodes::sint32;
+ break;
+ case 17:
+ data_location += 8;
+ LLVM_FALLTHROUGH;
+ case 4:
+ type_code = TypeCodes::sint64;
+ break;
+ case 5:
+ type_code = TypeCodes::f32;
+ break;
+ case 6:
+ type_code = TypeCodes::f64;
+ break;
+ default:
+ return false;
}
}
-
+
uint64_t value = 0;
bool success = false;
switch (type_code) {
- case TypeCodes::sint8:
+ case TypeCodes::sint8:
value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 1, 0,
error);
if (error.Fail())
@@ -548,7 +575,7 @@
NSNumber_FormatChar(valobj, stream, (char)value, options.GetLanguage());
success = true;
break;
- case TypeCodes::sint16:
+ case TypeCodes::sint16:
value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 2, 0,
error);
if (error.Fail())
@@ -573,8 +600,7 @@
NSNumber_FormatLong(valobj, stream, value, options.GetLanguage());
success = true;
break;
- case TypeCodes::f32:
- {
+ case TypeCodes::f32: {
uint32_t flt_as_int = process_sp->ReadUnsignedIntegerFromMemory(
data_location, 4, 0, error);
if (error.Fail())
@@ -585,8 +611,7 @@
success = true;
break;
}
- case TypeCodes::f64:
- {
+ case TypeCodes::f64: {
uint64_t dbl_as_lng = process_sp->ReadUnsignedIntegerFromMemory(
data_location, 8, 0, error);
if (error.Fail())
@@ -600,16 +625,17 @@
case TypeCodes::sint128: // internally, this is the same
{
uint64_t words[2];
- words[1] = process_sp->ReadUnsignedIntegerFromMemory(
- data_location, 8, 0, error);
+ words[1] = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8,
+ 0, error);
if (error.Fail())
return false;
- words[0] = process_sp->ReadUnsignedIntegerFromMemory(
- data_location + 8, 8, 0, error);
+ words[0] = process_sp->ReadUnsignedIntegerFromMemory(data_location + 8,
+ 8, 0, error);
if (error.Fail())
return false;
llvm::APInt i128_value(128, words);
- NSNumber_FormatInt128(valobj, stream, i128_value, options.GetLanguage());
+ NSNumber_FormatInt128(valobj, stream, i128_value,
+ options.GetLanguage());
success = true;
break;
}
diff --git a/src/llvm-project/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp b/src/llvm-project/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp
index efc80cc..a862da5 100644
--- a/src/llvm-project/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp
@@ -13,7 +13,7 @@
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Target/Target.h"
-#include <inttypes.h>
+#include <cinttypes>
using namespace lldb;
using namespace lldb_private;
diff --git a/src/llvm-project/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp b/src/llvm-project/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
index afb9c69..326f47a 100644
--- a/src/llvm-project/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
@@ -410,6 +410,7 @@
static const ConstString g_DictionaryM("__NSDictionaryM");
static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy");
static const ConstString g_DictionaryMImmutable("__NSDictionaryM_Immutable");
+ static const ConstString g_DictionaryMFrozen("__NSFrozenDictionaryM");
static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI");
static const ConstString g_Dictionary0("__NSDictionary0");
static const ConstString g_DictionaryCF("__CFDictionary");
@@ -427,7 +428,8 @@
return false;
value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
- } else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy) {
+ } else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy
+ || class_name == g_DictionaryMFrozen) {
AppleObjCRuntime *apple_runtime =
llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime);
Status error;
@@ -509,6 +511,7 @@
static const ConstString g_DictionaryM("__NSDictionaryM");
static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI");
static const ConstString g_DictionaryImmutable("__NSDictionaryM_Immutable");
+ static const ConstString g_DictionaryMFrozen("__NSFrozenDictionaryM");
static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy");
static const ConstString g_Dictionary0("__NSDictionary0");
static const ConstString g_DictionaryCF("__CFDictionary");
@@ -520,7 +523,7 @@
if (class_name == g_DictionaryI) {
return (new NSDictionaryISyntheticFrontEnd(valobj_sp));
- } else if (class_name == g_DictionaryM) {
+ } else if (class_name == g_DictionaryM || class_name == g_DictionaryMFrozen) {
if (runtime->GetFoundationVersion() >= 1437) {
return (new Foundation1437::NSDictionaryMSyntheticFrontEnd(valobj_sp));
} else if (runtime->GetFoundationVersion() >= 1428) {
diff --git a/src/llvm-project/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp b/src/llvm-project/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp
index a15b0f6..068bca9 100644
--- a/src/llvm-project/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp
@@ -209,14 +209,13 @@
m_process = nullptr;
}
- InlinedIndexes()
- : m_indexes(0), m_count(0), m_ptr_size(0), m_process(nullptr) {}
+ InlinedIndexes() {}
private:
- uint64_t m_indexes;
- size_t m_count;
- uint32_t m_ptr_size;
- Process *m_process;
+ uint64_t m_indexes = 0;
+ size_t m_count = 0;
+ uint32_t m_ptr_size = 0;
+ Process *m_process = nullptr;
// cfr. Foundation for the details of this code
size_t _lengthForInlinePayload(uint32_t ptr_size) {
@@ -271,10 +270,10 @@
m_count = 0;
}
- OutsourcedIndexes() : m_indexes(nullptr), m_count(0) {}
+ OutsourcedIndexes() {}
- ValueObject *m_indexes;
- size_t m_count;
+ ValueObject *m_indexes = nullptr;
+ size_t m_count = 0;
};
union {
@@ -288,9 +287,9 @@
m_outsourced.Clear();
}
- Impl() : m_mode(Mode::Invalid) {}
+ Impl() {}
- Mode m_mode;
+ Mode m_mode = Mode::Invalid;
} m_impl;
uint32_t m_ptr_size;
diff --git a/src/llvm-project/lldb/source/Plugins/Language/ObjC/NSSet.cpp b/src/llvm-project/lldb/source/Plugins/Language/ObjC/NSSet.cpp
index 4dbbe6f..43ef7b6 100644
--- a/src/llvm-project/lldb/source/Plugins/Language/ObjC/NSSet.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Language/ObjC/NSSet.cpp
@@ -444,18 +444,12 @@
if (!valobj_sp)
return false;
m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
- Status error;
- if (valobj_sp->IsPointerType()) {
- valobj_sp = valobj_sp->Dereference(error);
- if (error.Fail() || !valobj_sp)
- return false;
- }
- error.Clear();
lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
if (!process_sp)
return false;
m_ptr_size = process_sp->GetAddressByteSize();
- uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
+ uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
+ Status error;
if (m_ptr_size == 4) {
m_data_32 = new DataDescriptor_32();
process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32),
@@ -728,18 +722,12 @@
if (!valobj_sp)
return false;
m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
- Status error;
- if (valobj_sp->IsPointerType()) {
- valobj_sp = valobj_sp->Dereference(error);
- if (error.Fail() || !valobj_sp)
- return false;
- }
- error.Clear();
lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
if (!process_sp)
return false;
m_ptr_size = process_sp->GetAddressByteSize();
- uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
+ uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
+ Status error;
if (m_ptr_size == 4) {
m_data_32 = new D32();
process_sp->ReadMemory(data_location, m_data_32, sizeof(D32),
diff --git a/src/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp b/src/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
index 29391da..379c534 100644
--- a/src/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
@@ -225,14 +225,17 @@
return ConstString();
}
-std::vector<ConstString>
+std::vector<Language::MethodNameVariant>
ObjCLanguage::GetMethodNameVariants(ConstString method_name) const {
- std::vector<ConstString> variant_names;
+ std::vector<Language::MethodNameVariant> variant_names;
ObjCLanguage::MethodName objc_method(method_name.GetCString(), false);
if (!objc_method.IsValid(false)) {
return variant_names;
}
+ variant_names.emplace_back(objc_method.GetSelector(),
+ lldb::eFunctionNameTypeSelector);
+
const bool is_class_method =
objc_method.GetType() == MethodName::eTypeClassMethod;
const bool is_instance_method =
@@ -242,31 +245,43 @@
if (is_class_method || is_instance_method) {
if (name_sans_category)
- variant_names.emplace_back(name_sans_category);
+ variant_names.emplace_back(name_sans_category,
+ lldb::eFunctionNameTypeFull);
} else {
StreamString strm;
strm.Printf("+%s", objc_method.GetFullName().GetCString());
- variant_names.emplace_back(strm.GetString());
+ variant_names.emplace_back(ConstString(strm.GetString()),
+ lldb::eFunctionNameTypeFull);
strm.Clear();
strm.Printf("-%s", objc_method.GetFullName().GetCString());
- variant_names.emplace_back(strm.GetString());
+ variant_names.emplace_back(ConstString(strm.GetString()),
+ lldb::eFunctionNameTypeFull);
strm.Clear();
if (name_sans_category) {
strm.Printf("+%s", name_sans_category.GetCString());
- variant_names.emplace_back(strm.GetString());
+ variant_names.emplace_back(ConstString(strm.GetString()),
+ lldb::eFunctionNameTypeFull);
strm.Clear();
strm.Printf("-%s", name_sans_category.GetCString());
- variant_names.emplace_back(strm.GetString());
+ variant_names.emplace_back(ConstString(strm.GetString()),
+ lldb::eFunctionNameTypeFull);
}
}
return variant_names;
}
+bool ObjCLanguage::SymbolNameFitsToLanguage(Mangled mangled) const {
+ ConstString demangled_name = mangled.GetDemangledName();
+ if (!demangled_name)
+ return false;
+ return ObjCLanguage::IsPossibleObjCMethodName(demangled_name.GetCString());
+}
+
static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) {
if (!objc_category_sp)
return;
@@ -990,8 +1005,11 @@
bool result = false;
if (auto *target = exe_scope->CalculateTarget().get()) {
- if (auto *clang_modules_decl_vendor =
- target->GetClangModulesDeclVendor()) {
+ auto *persistent_vars = llvm::cast<ClangPersistentVariables>(
+ target->GetPersistentExpressionStateForLanguage(
+ lldb::eLanguageTypeC));
+ if (std::shared_ptr<ClangModulesDeclVendor> clang_modules_decl_vendor =
+ persistent_vars->GetClangModulesDeclVendor()) {
ConstString key_cs(key);
auto types = clang_modules_decl_vendor->FindTypes(
key_cs, /*max_matches*/ UINT32_MAX);
@@ -1116,7 +1134,7 @@
bool ObjCLanguage::IsSourceFile(llvm::StringRef file_path) const {
const auto suffixes = {".h", ".m", ".M"};
for (auto suffix : suffixes) {
- if (file_path.endswith_lower(suffix))
+ if (file_path.endswith_insensitive(suffix))
return true;
}
return false;
diff --git a/src/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h b/src/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
index 02c15e8..691c518 100644
--- a/src/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
+++ b/src/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
@@ -27,9 +27,7 @@
public:
enum Type { eTypeUnspecified, eTypeClassMethod, eTypeInstanceMethod };
- MethodName()
- : m_full(), m_class(), m_category(), m_selector(),
- m_type(eTypeUnspecified), m_category_is_valid(false) {}
+ MethodName() : m_full(), m_class(), m_category(), m_selector() {}
MethodName(const char *name, bool strict)
: m_full(), m_class(), m_category(), m_selector(),
@@ -81,8 +79,8 @@
m_class_category; // Class with category: "NSString(my_additions)"
ConstString m_category; // Category: "my_additions"
ConstString m_selector; // Selector: "myStringWithCString:"
- Type m_type;
- bool m_category_is_valid;
+ Type m_type = eTypeUnspecified;
+ bool m_category_is_valid = false;
};
ObjCLanguage() = default;
@@ -102,9 +100,12 @@
// variant_names[1] => "-[NSString(my_additions) myStringWithCString:]"
// variant_names[2] => "+[NSString myStringWithCString:]"
// variant_names[3] => "-[NSString myStringWithCString:]"
- std::vector<ConstString>
+ // Also returns the FunctionNameType of each possible name.
+ std::vector<Language::MethodNameVariant>
GetMethodNameVariants(ConstString method_name) const override;
+ bool SymbolNameFitsToLanguage(Mangled mangled) const override;
+
lldb::TypeCategoryImplSP GetFormatters() override;
std::vector<ConstString>
diff --git a/src/llvm-project/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp b/src/llvm-project/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp
index 0a4017e..3599785 100644
--- a/src/llvm-project/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp
@@ -19,7 +19,7 @@
bool ObjCPlusPlusLanguage::IsSourceFile(llvm::StringRef file_path) const {
const auto suffixes = {".h", ".mm"};
for (auto suffix : suffixes) {
- if (file_path.endswith_lower(suffix))
+ if (file_path.endswith_insensitive(suffix))
return true;
}
return false;
diff --git a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
index 24ab9cc..bed2a98 100644
--- a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
+++ b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include <string.h>
+#include <cstring>
#include <memory>
@@ -322,6 +322,9 @@
}
}
+ if (symbol == nullptr)
+ return optional_info;
+
// Case 1 or 3
if (scl.GetSize() >= 1) {
optional_info = line_entry_helper(target, scl[0], symbol,
@@ -397,8 +400,8 @@
// We create a ThreadPlan to keep stepping through using the address range
// of the current function.
ret_plan_sp = std::make_shared<ThreadPlanStepInRange>(
- thread, range_of_curr_func, sc, eOnlyThisThread, eLazyBoolYes,
- eLazyBoolYes);
+ thread, range_of_curr_func, sc, nullptr, eOnlyThisThread,
+ eLazyBoolYes, eLazyBoolYes);
return ret_plan_sp;
}
}
diff --git a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
index 6ea9751..f5b587c 100644
--- a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
+++ b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
@@ -196,7 +196,7 @@
//
class_type_or_name.Clear();
- value_type = Value::ValueType::eValueTypeScalar;
+ value_type = Value::ValueType::Scalar;
// Only a pointer or reference type can have a different dynamic and static
// type:
diff --git a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
index bdd5c29..405b8a6 100644
--- a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
+++ b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
@@ -252,6 +252,7 @@
}
bool ClassDescriptorV2::method_t::Read(Process *process, lldb::addr_t addr,
+ lldb::addr_t relative_selector_base_addr,
bool is_small, bool has_direct_sel) {
size_t ptr_size = process->GetAddressByteSize();
size_t size = GetSize(process, is_small);
@@ -281,6 +282,8 @@
0, error);
if (!error.Success())
return false;
+ } else if (relative_selector_base_addr != LLDB_INVALID_ADDRESS) {
+ m_name_ptr = relative_selector_base_addr + nameref_offset;
}
m_types_ptr = addr + 4 + types_offset;
m_imp_ptr = addr + 8 + imp_offset;
@@ -389,14 +392,14 @@
if (base_method_list->m_entsize != method_t::GetSize(process, is_small))
return false;
- std::unique_ptr<method_t> method;
- method = std::make_unique<method_t>();
-
+ std::unique_ptr<method_t> method = std::make_unique<method_t>();
+ lldb::addr_t relative_selector_base_addr =
+ m_runtime.GetRelativeSelectorBaseAddr();
for (uint32_t i = 0, e = base_method_list->m_count; i < e; ++i) {
method->Read(process,
base_method_list->m_first_ptr +
(i * base_method_list->m_entsize),
- is_small, has_direct_selector);
+ relative_selector_base_addr, is_small, has_direct_selector);
if (instance_method_func(method->m_name.c_str(), method->m_types.c_str()))
break;
@@ -514,8 +517,7 @@
return 0;
}
-ClassDescriptorV2::iVarsStorage::iVarsStorage()
- : m_filled(false), m_ivars(), m_mutex() {}
+ClassDescriptorV2::iVarsStorage::iVarsStorage() : m_ivars(), m_mutex() {}
size_t ClassDescriptorV2::iVarsStorage::size() { return m_ivars.size(); }
diff --git a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h
index 9ef21c6..7ba9579 100644
--- a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h
+++ b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h
@@ -41,6 +41,12 @@
return false;
}
+ bool GetTaggedPointerInfoSigned(uint64_t *info_bits = nullptr,
+ int64_t *value_bits = nullptr,
+ uint64_t *payload = nullptr) override {
+ return false;
+ }
+
uint64_t GetInstanceSize() override;
ObjCLanguageRuntime::ObjCISA GetISA() override { return m_objc_class_ptr; }
@@ -71,16 +77,14 @@
static const uint32_t RW_REALIZED = (1 << 31);
struct objc_class_t {
- ObjCLanguageRuntime::ObjCISA m_isa; // The class's metaclass.
- ObjCLanguageRuntime::ObjCISA m_superclass;
- lldb::addr_t m_cache_ptr;
- lldb::addr_t m_vtable_ptr;
- lldb::addr_t m_data_ptr;
- uint8_t m_flags;
+ ObjCLanguageRuntime::ObjCISA m_isa = 0; // The class's metaclass.
+ ObjCLanguageRuntime::ObjCISA m_superclass = 0;
+ lldb::addr_t m_cache_ptr = 0;
+ lldb::addr_t m_vtable_ptr = 0;
+ lldb::addr_t m_data_ptr = 0;
+ uint8_t m_flags = 0;
- objc_class_t()
- : m_isa(0), m_superclass(0), m_cache_ptr(0), m_vtable_ptr(0),
- m_data_ptr(0), m_flags(0) {}
+ objc_class_t() = default;
void Clear() {
m_isa = 0;
@@ -162,7 +166,8 @@
+ field_size; // IMP imp;
}
- bool Read(Process *process, lldb::addr_t addr, bool, bool);
+ bool Read(Process *process, lldb::addr_t addr,
+ lldb::addr_t relative_method_lists_base_addr, bool, bool);
};
struct ivar_list_t {
@@ -207,7 +212,7 @@
void fill(AppleObjCRuntimeV2 &runtime, ClassDescriptorV2 &descriptor);
private:
- bool m_filled;
+ bool m_filled = false;
std::vector<iVarDescriptor> m_ivars;
std::recursive_mutex m_mutex;
};
@@ -253,7 +258,7 @@
ClassDescriptorV2Tagged(
ObjCLanguageRuntime::ClassDescriptorSP actual_class_sp,
- uint64_t payload) {
+ uint64_t u_payload, int64_t s_payload) {
if (!actual_class_sp) {
m_valid = false;
return;
@@ -264,9 +269,10 @@
return;
}
m_valid = true;
- m_payload = payload;
+ m_payload = u_payload;
m_info_bits = (m_payload & 0x0FULL);
m_value_bits = (m_payload & ~0x0FULL) >> 4;
+ m_value_bits_signed = (s_payload & ~0x0FLL) >> 4;
}
~ClassDescriptorV2Tagged() override = default;
@@ -308,6 +314,18 @@
return true;
}
+ bool GetTaggedPointerInfoSigned(uint64_t *info_bits = nullptr,
+ int64_t *value_bits = nullptr,
+ uint64_t *payload = nullptr) override {
+ if (info_bits)
+ *info_bits = GetInfoBits();
+ if (value_bits)
+ *value_bits = GetValueBitsSigned();
+ if (payload)
+ *payload = GetPayload();
+ return true;
+ }
+
uint64_t GetInstanceSize() override {
return (IsValid() ? m_pointer_size : 0);
}
@@ -319,6 +337,10 @@
// these calls are not part of any formal tagged pointers specification
virtual uint64_t GetValueBits() { return (IsValid() ? m_value_bits : 0); }
+ virtual int64_t GetValueBitsSigned() {
+ return (IsValid() ? m_value_bits_signed : 0);
+ }
+
virtual uint64_t GetInfoBits() { return (IsValid() ? m_info_bits : 0); }
virtual uint64_t GetPayload() { return (IsValid() ? m_payload : 0); }
@@ -329,6 +351,7 @@
bool m_valid;
uint64_t m_info_bits;
uint64_t m_value_bits;
+ int64_t m_value_bits_signed;
uint64_t m_payload;
};
diff --git a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp
index 7b33130..9bc40c1 100644
--- a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp
+++ b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp
@@ -59,7 +59,7 @@
clang::DeclContext::lookup_result result =
non_const_interface_decl->lookup(name);
- return (result.size() != 0);
+ return (!result.empty());
} while (false);
SetNoExternalVisibleDeclsForName(decl_ctx, name);
@@ -555,7 +555,7 @@
if (!lookup_result.empty()) {
if (clang::ObjCInterfaceDecl *result_iface_decl =
- llvm::dyn_cast<clang::ObjCInterfaceDecl>(lookup_result[0])) {
+ llvm::dyn_cast<clang::ObjCInterfaceDecl>(*lookup_result.begin())) {
if (log) {
clang::QualType result_iface_type =
ast_ctx.getObjCInterfaceType(result_iface_decl);
diff --git a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
index 973a557..88e86c5 100644
--- a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
+++ b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
@@ -48,7 +48,7 @@
char AppleObjCRuntime::ID = 0;
-AppleObjCRuntime::~AppleObjCRuntime() {}
+AppleObjCRuntime::~AppleObjCRuntime() = default;
AppleObjCRuntime::AppleObjCRuntime(Process *process)
: ObjCLanguageRuntime(process), m_read_objc_library(false),
diff --git a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
index b37e5a9..98d0e9c 100644
--- a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
+++ b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
@@ -49,7 +49,7 @@
TypeAndOrName &class_type_or_name, Address &address,
Value::ValueType &value_type) {
class_type_or_name.Clear();
- value_type = Value::ValueType::eValueTypeScalar;
+ value_type = Value::ValueType::Scalar;
if (CouldHaveDynamicValue(in_value)) {
auto class_descriptor(GetClassDescriptor(in_value));
if (class_descriptor && class_descriptor->IsValid() &&
@@ -339,8 +339,6 @@
if (!objc_module_sp)
return;
- uint32_t isa_count = 0;
-
lldb::addr_t hash_table_ptr = GetISAHashTablePointer();
if (hash_table_ptr != LLDB_INVALID_ADDRESS) {
// Read the NXHashTable struct:
@@ -383,8 +381,6 @@
if (bucket_isa_count == 0)
continue;
- isa_count += bucket_isa_count;
-
ObjCISA isa;
if (bucket_isa_count == 1) {
// When we only have one entry in the bucket, the bucket data
diff --git a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
index 4eb7d97..12ee2cc 100644
--- a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
+++ b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
@@ -64,6 +64,12 @@
return false;
}
+ bool GetTaggedPointerInfoSigned(uint64_t *info_bits = nullptr,
+ int64_t *value_bits = nullptr,
+ uint64_t *payload = nullptr) override {
+ return false;
+ }
+
uint64_t GetInstanceSize() override { return m_instance_size; }
ObjCISA GetISA() override { return m_isa; }
@@ -120,8 +126,7 @@
class HashTableSignature {
public:
- HashTableSignature()
- : m_count(0), m_num_buckets(0), m_buckets_ptr(LLDB_INVALID_ADDRESS) {}
+ HashTableSignature() = default;
bool NeedsUpdate(uint32_t count, uint32_t num_buckets,
lldb::addr_t buckets_ptr) {
@@ -137,9 +142,9 @@
}
protected:
- uint32_t m_count;
- uint32_t m_num_buckets;
- lldb::addr_t m_buckets_ptr;
+ uint32_t m_count = 0;
+ uint32_t m_num_buckets = 0;
+ lldb::addr_t m_buckets_ptr = LLDB_INVALID_ADDRESS;
};
lldb::addr_t GetISAHashTablePointer();
diff --git a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
index ee84ccd..10512a9 100644
--- a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
+++ b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include <stdint.h>
+#include <cstdint>
#include <memory>
#include <string>
@@ -39,6 +39,7 @@
#include "lldb/Symbol/TypeList.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ABI.h"
+#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
@@ -75,8 +76,7 @@
static const char *g_get_dynamic_class_info_name =
"__lldb_apple_objc_v2_get_dynamic_class_info";
-// Testing using the new C++11 raw string literals. If this breaks GCC then we
-// will need to revert to the code above...
+
static const char *g_get_dynamic_class_info_body = R"(
extern "C"
@@ -121,14 +121,20 @@
if (grc)
{
const unsigned num_classes = grc->num_classes;
+ DEBUG_PRINTF ("num_classes = %u\n", grc->num_classes);
if (class_infos_ptr)
{
+ const unsigned num_buckets_minus_one = grc->num_buckets_minus_one;
+ DEBUG_PRINTF ("num_buckets_minus_one = %u\n", num_buckets_minus_one);
+
const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
+ DEBUG_PRINTF ("max_class_infos = %u\n", max_class_infos);
+
ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
BucketInfo *buckets = (BucketInfo *)grc->buckets;
-
+
uint32_t idx = 0;
- for (unsigned i=0; i<=grc->num_buckets_minus_one; ++i)
+ for (unsigned i=0; i<=num_buckets_minus_one; ++i)
{
if (buckets[i].name_ptr != NX_MAPNOTAKEY)
{
@@ -140,6 +146,7 @@
h = ((h << 5) + h) + c;
class_infos[idx].hash = h;
class_infos[idx].isa = buckets[i].isa;
+ DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, buckets[i].name_ptr);
}
++idx;
}
@@ -157,6 +164,75 @@
)";
+static const char *g_get_dynamic_class_info2_name =
+ "__lldb_apple_objc_v2_get_dynamic_class_info2";
+
+static const char *g_get_dynamic_class_info2_body = R"(
+
+extern "C" {
+ int printf(const char * format, ...);
+ void free(void *ptr);
+ Class* objc_copyRealizedClassList_nolock(unsigned int *outCount);
+ const char* objc_debug_class_getNameRaw(Class cls);
+}
+
+#define DEBUG_PRINTF(fmt, ...) if (should_log) printf(fmt, ## __VA_ARGS__)
+
+struct ClassInfo
+{
+ Class isa;
+ uint32_t hash;
+} __attribute__((__packed__));
+
+uint32_t
+__lldb_apple_objc_v2_get_dynamic_class_info2(void *gdb_objc_realized_classes_ptr,
+ void *class_infos_ptr,
+ uint32_t class_infos_byte_size,
+ uint32_t should_log)
+{
+ DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr);
+ DEBUG_PRINTF ("class_infos_byte_size = %u\n", class_infos_byte_size);
+
+ const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
+ DEBUG_PRINTF ("max_class_infos = %u\n", max_class_infos);
+
+ ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
+
+ uint32_t count = 0;
+ Class* realized_class_list = objc_copyRealizedClassList_nolock(&count);
+ DEBUG_PRINTF ("count = %u\n", count);
+
+ uint32_t idx = 0;
+ for (uint32_t i=0; i<=count; ++i)
+ {
+ if (idx < max_class_infos)
+ {
+ Class isa = realized_class_list[i];
+ const char *name_ptr = objc_debug_class_getNameRaw(isa);
+ if (name_ptr == NULL)
+ continue;
+ const char *s = name_ptr;
+ uint32_t h = 5381;
+ for (unsigned char c = *s; c; c = *++s)
+ h = ((h << 5) + h) + c;
+ class_infos[idx].hash = h;
+ class_infos[idx].isa = isa;
+ DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name_ptr);
+ }
+ idx++;
+ }
+
+ if (idx < max_class_infos)
+ {
+ class_infos[idx].isa = NULL;
+ class_infos[idx].hash = 0;
+ }
+
+ free(realized_class_list);
+ return count;
+}
+)";
+
// We'll substitute in class_getName or class_getNameRaw depending
// on which is present.
static const char *g_shared_cache_class_name_funcptr = R"(
@@ -169,8 +245,7 @@
static const char *g_get_shared_cache_class_info_name =
"__lldb_apple_objc_v2_get_shared_cache_class_info";
-// Testing using the new C++11 raw string literals. If this breaks GCC then we
-// will need to revert to the code above...
+
static const char *g_get_shared_cache_class_info_body = R"(
extern "C"
@@ -188,6 +263,12 @@
int32_t hiOffset;
};
+struct objc_classheader_v16_t {
+ uint64_t isDuplicate : 1,
+ objectCacheOffset : 47, // Offset from the shared cache base
+ dylibObjCIndex : 16;
+};
+
struct objc_clsopt_t {
uint32_t capacity;
uint32_t occupied;
@@ -205,6 +286,22 @@
// objc_classheader_t duplicateOffsets[duplicateCount];
};
+struct objc_clsopt_v16_t {
+ uint32_t version;
+ uint32_t capacity;
+ uint32_t occupied;
+ uint32_t shift;
+ uint32_t mask;
+ uint64_t salt;
+ uint32_t scramble[256];
+ uint8_t tab[0]; // tab[mask+1]
+ // uint8_t checkbytes[capacity];
+ // int32_t offset[capacity];
+ // objc_classheader_t clsOffsets[capacity];
+ // uint32_t duplicateCount;
+ // objc_classheader_t duplicateOffsets[duplicateCount];
+};
+
struct objc_opt_t {
uint32_t version;
int32_t selopt_offset;
@@ -220,6 +317,20 @@
int32_t clsopt_offset;
};
+struct objc_opt_v16_t {
+ uint32_t version;
+ uint32_t flags;
+ int32_t selopt_offset;
+ int32_t headeropt_ro_offset;
+ int32_t unused_clsopt_offset;
+ int32_t unused_protocolopt_offset;
+ int32_t headeropt_rw_offset;
+ int32_t unused_protocolopt2_offset;
+ int32_t largeSharedCachesClassOffset;
+ int32_t largeSharedCachesProtocolOffset;
+ uint64_t relativeMethodSelectorBaseAddressCacheOffset;
+};
+
struct ClassInfo
{
Class isa;
@@ -228,20 +339,33 @@
uint32_t
__lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr,
+ void *shared_cache_base_ptr,
void *class_infos_ptr,
+ uint64_t *relative_selector_offset,
uint32_t class_infos_byte_size,
uint32_t should_log)
{
+ *relative_selector_offset = 0;
uint32_t idx = 0;
DEBUG_PRINTF ("objc_opt_ro_ptr = %p\n", objc_opt_ro_ptr);
+ DEBUG_PRINTF ("shared_cache_base_ptr = %p\n", shared_cache_base_ptr);
DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr);
DEBUG_PRINTF ("class_infos_byte_size = %u (%llu class infos)\n", class_infos_byte_size, (uint64_t)(class_infos_byte_size/sizeof(ClassInfo)));
if (objc_opt_ro_ptr)
{
const objc_opt_t *objc_opt = (objc_opt_t *)objc_opt_ro_ptr;
const objc_opt_v14_t* objc_opt_v14 = (objc_opt_v14_t*)objc_opt_ro_ptr;
- const bool is_v14_format = objc_opt->version >= 14;
- if (is_v14_format)
+ const objc_opt_v16_t* objc_opt_v16 = (objc_opt_v16_t*)objc_opt_ro_ptr;
+ if (objc_opt->version >= 16)
+ {
+ *relative_selector_offset = objc_opt_v16->relativeMethodSelectorBaseAddressCacheOffset;
+ DEBUG_PRINTF ("objc_opt->version = %u\n", objc_opt_v16->version);
+ DEBUG_PRINTF ("objc_opt->flags = %u\n", objc_opt_v16->flags);
+ DEBUG_PRINTF ("objc_opt->selopt_offset = %d\n", objc_opt_v16->selopt_offset);
+ DEBUG_PRINTF ("objc_opt->headeropt_ro_offset = %d\n", objc_opt_v16->headeropt_ro_offset);
+ DEBUG_PRINTF ("objc_opt->relativeMethodSelectorBaseAddressCacheOffset = %d\n", *relative_selector_offset);
+ }
+ else if (objc_opt->version >= 14)
{
DEBUG_PRINTF ("objc_opt->version = %u\n", objc_opt_v14->version);
DEBUG_PRINTF ("objc_opt->flags = %u\n", objc_opt_v14->flags);
@@ -256,10 +380,126 @@
DEBUG_PRINTF ("objc_opt->headeropt_offset = %d\n", objc_opt->headeropt_offset);
DEBUG_PRINTF ("objc_opt->clsopt_offset = %d\n", objc_opt->clsopt_offset);
}
- if (objc_opt->version == 12 || objc_opt->version == 13 || objc_opt->version == 14 || objc_opt->version == 15)
+
+ if (objc_opt->version == 16)
+ {
+ const objc_clsopt_v16_t* clsopt = (const objc_clsopt_v16_t*)((uint8_t *)objc_opt + objc_opt_v16->largeSharedCachesClassOffset);
+ const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
+
+ DEBUG_PRINTF("max_class_infos = %llu\n", (uint64_t)max_class_infos);
+
+ ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
+
+ const uint8_t *checkbytes = &clsopt->tab[clsopt->mask+1];
+ const int32_t *offsets = (const int32_t *)(checkbytes + clsopt->capacity);
+ const objc_classheader_v16_t *classOffsets = (const objc_classheader_v16_t *)(offsets + clsopt->capacity);
+
+ DEBUG_PRINTF ("clsopt->capacity = %u\n", clsopt->capacity);
+ DEBUG_PRINTF ("clsopt->mask = 0x%8.8x\n", clsopt->mask);
+ DEBUG_PRINTF ("classOffsets = %p\n", classOffsets);
+
+ for (uint32_t i=0; i<clsopt->capacity; ++i)
+ {
+ const uint64_t objectCacheOffset = classOffsets[i].objectCacheOffset;
+ DEBUG_PRINTF("objectCacheOffset[%u] = %u\n", i, objectCacheOffset);
+
+ if (classOffsets[i].isDuplicate) {
+ DEBUG_PRINTF("isDuplicate = true\n");
+ continue; // duplicate
+ }
+
+ if (objectCacheOffset == 0) {
+ DEBUG_PRINTF("objectCacheOffset == invalidEntryOffset\n");
+ continue; // invalid offset
+ }
+
+ if (class_infos && idx < max_class_infos)
+ {
+ class_infos[idx].isa = (Class)((uint8_t *)shared_cache_base_ptr + objectCacheOffset);
+
+ // Lookup the class name.
+ const char *name = class_name_lookup_func(class_infos[idx].isa);
+ DEBUG_PRINTF("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name);
+
+ // Hash the class name so we don't have to read it.
+ const char *s = name;
+ uint32_t h = 5381;
+ for (unsigned char c = *s; c; c = *++s)
+ {
+ // class_getName demangles swift names and the hash must
+ // be calculated on the mangled name. hash==0 means lldb
+ // will fetch the mangled name and compute the hash in
+ // ParseClassInfoArray.
+ if (c == '.')
+ {
+ h = 0;
+ break;
+ }
+ h = ((h << 5) + h) + c;
+ }
+ class_infos[idx].hash = h;
+ }
+ else
+ {
+ DEBUG_PRINTF("not(class_infos && idx < max_class_infos)\n");
+ }
+ ++idx;
+ }
+
+ const uint32_t *duplicate_count_ptr = (uint32_t *)&classOffsets[clsopt->capacity];
+ const uint32_t duplicate_count = *duplicate_count_ptr;
+ const objc_classheader_v16_t *duplicateClassOffsets = (const objc_classheader_v16_t *)(&duplicate_count_ptr[1]);
+
+ DEBUG_PRINTF ("duplicate_count = %u\n", duplicate_count);
+ DEBUG_PRINTF ("duplicateClassOffsets = %p\n", duplicateClassOffsets);
+
+ for (uint32_t i=0; i<duplicate_count; ++i)
+ {
+ const uint64_t objectCacheOffset = classOffsets[i].objectCacheOffset;
+ DEBUG_PRINTF("objectCacheOffset[%u] = %u\n", i, objectCacheOffset);
+
+ if (classOffsets[i].isDuplicate) {
+ DEBUG_PRINTF("isDuplicate = true\n");
+ continue; // duplicate
+ }
+
+ if (objectCacheOffset == 0) {
+ DEBUG_PRINTF("objectCacheOffset == invalidEntryOffset\n");
+ continue; // invalid offset
+ }
+
+ if (class_infos && idx < max_class_infos)
+ {
+ class_infos[idx].isa = (Class)((uint8_t *)shared_cache_base_ptr + objectCacheOffset);
+
+ // Lookup the class name.
+ const char *name = class_name_lookup_func(class_infos[idx].isa);
+ DEBUG_PRINTF("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name);
+
+ // Hash the class name so we don't have to read it.
+ const char *s = name;
+ uint32_t h = 5381;
+ for (unsigned char c = *s; c; c = *++s)
+ {
+ // class_getName demangles swift names and the hash must
+ // be calculated on the mangled name. hash==0 means lldb
+ // will fetch the mangled name and compute the hash in
+ // ParseClassInfoArray.
+ if (c == '.')
+ {
+ h = 0;
+ break;
+ }
+ h = ((h << 5) + h) + c;
+ }
+ class_infos[idx].hash = h;
+ }
+ }
+ }
+ else if (objc_opt->version >= 12 && objc_opt->version <= 15)
{
const objc_clsopt_t* clsopt = NULL;
- if (is_v14_format)
+ if (objc_opt->version >= 14)
clsopt = (const objc_clsopt_t*)((uint8_t *)objc_opt_v14 + objc_opt_v14->clsopt_offset);
else
clsopt = (const objc_clsopt_t*)((uint8_t *)objc_opt + objc_opt->clsopt_offset);
@@ -291,7 +531,7 @@
DEBUG_PRINTF("clsOffset == invalidEntryOffset\n");
continue; // invalid offset
}
-
+
if (class_infos && idx < max_class_infos)
{
class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset);
@@ -321,7 +561,7 @@
}
++idx;
}
-
+
const uint32_t *duplicate_count_ptr = (uint32_t *)&classOffsets[clsopt->capacity];
const uint32_t duplicate_count = *duplicate_count_ptr;
const objc_classheader_t *duplicateClassOffsets = (const objc_classheader_t *)(&duplicate_count_ptr[1]);
@@ -334,7 +574,7 @@
continue; // duplicate
else if (clsOffset == invalidEntryOffset)
continue; // invalid offset
-
+
if (class_infos && idx < max_class_infos)
{
class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset);
@@ -353,7 +593,7 @@
{
h = 0;
break;
- }
+ }
h = ((h << 5) + h) + c;
}
class_infos[idx].hash = h;
@@ -380,55 +620,57 @@
error.SetErrorString("no process");
return default_value;
}
+
if (!module_sp) {
error.SetErrorString("no module");
return default_value;
}
+
if (!byte_size)
byte_size = process->GetAddressByteSize();
const Symbol *symbol =
module_sp->FindFirstSymbolWithNameAndType(name, lldb::eSymbolTypeData);
- if (symbol && symbol->ValueIsAddress()) {
- lldb::addr_t symbol_load_addr =
- symbol->GetAddressRef().GetLoadAddress(&process->GetTarget());
- if (symbol_load_addr != LLDB_INVALID_ADDRESS) {
- if (read_value)
- return process->ReadUnsignedIntegerFromMemory(
- symbol_load_addr, byte_size, default_value, error);
- else
- return symbol_load_addr;
- } else {
- error.SetErrorString("symbol address invalid");
- return default_value;
- }
- } else {
+
+ if (!symbol || !symbol->ValueIsAddress()) {
error.SetErrorString("no symbol");
return default_value;
}
+
+ lldb::addr_t symbol_load_addr =
+ symbol->GetAddressRef().GetLoadAddress(&process->GetTarget());
+ if (symbol_load_addr == LLDB_INVALID_ADDRESS) {
+ error.SetErrorString("symbol address invalid");
+ return default_value;
+ }
+
+ if (read_value)
+ return process->ReadUnsignedIntegerFromMemory(symbol_load_addr, byte_size,
+ default_value, error);
+ return symbol_load_addr;
}
static void RegisterObjCExceptionRecognizer(Process *process);
AppleObjCRuntimeV2::AppleObjCRuntimeV2(Process *process,
const ModuleSP &objc_module_sp)
- : AppleObjCRuntime(process), m_get_class_info_code(),
- m_get_class_info_args(LLDB_INVALID_ADDRESS),
- m_get_class_info_args_mutex(), m_get_shared_cache_class_info_code(),
- m_get_shared_cache_class_info_args(LLDB_INVALID_ADDRESS),
- m_get_shared_cache_class_info_args_mutex(), m_decl_vendor_up(),
+ : AppleObjCRuntime(process), m_objc_module_sp(objc_module_sp),
+ m_dynamic_class_info_extractor(*this),
+ m_shared_cache_class_info_extractor(*this), m_decl_vendor_up(),
m_tagged_pointer_obfuscator(LLDB_INVALID_ADDRESS),
- m_isa_hash_table_ptr(LLDB_INVALID_ADDRESS), m_hash_signature(),
- m_has_object_getClass(false), m_loaded_objc_opt(false),
- m_non_pointer_isa_cache_up(
- NonPointerISACache::CreateInstance(*this, objc_module_sp)),
+ m_isa_hash_table_ptr(LLDB_INVALID_ADDRESS),
+ m_relative_selector_base(LLDB_INVALID_ADDRESS), m_hash_signature(),
+ m_has_object_getClass(false), m_has_objc_copyRealizedClassList(false),
+ m_loaded_objc_opt(false), m_non_pointer_isa_cache_up(),
m_tagged_pointer_vendor_up(
TaggedPointerVendorV2::CreateInstance(*this, objc_module_sp)),
m_encoding_to_type_sp(), m_noclasses_warning_emitted(false),
- m_CFBoolean_values() {
+ m_CFBoolean_values(), m_realized_class_generation_count(0) {
static const ConstString g_gdb_object_getClass("gdb_object_getClass");
- m_has_object_getClass =
- (objc_module_sp->FindFirstSymbolWithNameAndType(
- g_gdb_object_getClass, eSymbolTypeCode) != nullptr);
+ m_has_object_getClass = HasSymbol(g_gdb_object_getClass);
+ static const ConstString g_objc_copyRealizedClassList(
+ "_ZL33objc_copyRealizedClassList_nolockPj");
+ m_has_objc_copyRealizedClassList = HasSymbol(g_objc_copyRealizedClassList);
+
RegisterObjCExceptionRecognizer(process);
}
@@ -451,7 +693,7 @@
assert(in_value.GetTargetSP().get() == m_process->CalculateTarget().get());
class_type_or_name.Clear();
- value_type = Value::ValueType::eValueTypeScalar;
+ value_type = Value::ValueType::Scalar;
// Make sure we can have a dynamic value before starting...
if (CouldHaveDynamicValue(in_value)) {
@@ -498,15 +740,21 @@
if (AppleObjCRuntime::GetObjCVersion(process, objc_module_sp) ==
ObjCRuntimeVersions::eAppleObjC_V2)
return new AppleObjCRuntimeV2(process, objc_module_sp);
- else
- return nullptr;
- } else
return nullptr;
+ }
+ return nullptr;
}
static constexpr OptionDefinition g_objc_classtable_dump_options[] = {
- {LLDB_OPT_SET_ALL, false, "verbose", 'v', OptionParser::eNoArgument,
- nullptr, {}, 0, eArgTypeNone,
+ {LLDB_OPT_SET_ALL,
+ false,
+ "verbose",
+ 'v',
+ OptionParser::eNoArgument,
+ nullptr,
+ {},
+ 0,
+ eArgTypeNone,
"Print ivar and method information in detail"}};
class CommandObjectObjC_ClassTable_Dump : public CommandObjectParsed {
@@ -548,12 +796,13 @@
};
CommandObjectObjC_ClassTable_Dump(CommandInterpreter &interpreter)
- : CommandObjectParsed(
- interpreter, "dump", "Dump information on Objective-C classes "
- "known to the current process.",
- "language objc class-table dump",
- eCommandRequiresProcess | eCommandProcessMustBeLaunched |
- eCommandProcessMustBePaused),
+ : CommandObjectParsed(interpreter, "dump",
+ "Dump information on Objective-C classes "
+ "known to the current process.",
+ "language objc class-table dump",
+ eCommandRequiresProcess |
+ eCommandProcessMustBeLaunched |
+ eCommandProcessMustBePaused),
m_options() {
CommandArgumentEntry arg;
CommandArgumentData index_arg;
@@ -581,8 +830,8 @@
case 0:
break;
case 1: {
- regex_up = std::make_unique<RegularExpression>(
- llvm::StringRef::withNullAsEmpty(command.GetArgumentAtIndex(0)));
+ regex_up =
+ std::make_unique<RegularExpression>(command.GetArgumentAtIndex(0));
if (!regex_up->IsValid()) {
result.AppendError(
"invalid argument - please provide a valid regular expression");
@@ -632,6 +881,7 @@
ivar.m_type.GetDisplayTypeName().AsCString("<unknown>"),
ivar.m_size, ivar.m_offset);
}
+
iterator->second->Describe(
nullptr,
[&std_out](const char *name, const char *type) -> bool {
@@ -655,11 +905,10 @@
}
result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
return true;
- } else {
- result.AppendError("current process has no Objective-C runtime loaded");
- result.SetStatus(lldb::eReturnStatusFailed);
- return false;
}
+ result.AppendError("current process has no Objective-C runtime loaded");
+ result.SetStatus(lldb::eReturnStatusFailed);
+ return false;
}
CommandOptions m_options;
@@ -741,11 +990,10 @@
}
result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
return true;
- } else {
- result.AppendError("current process has no Objective-C runtime loaded");
- result.SetStatus(lldb::eReturnStatusFailed);
- return false;
}
+ result.AppendError("current process has no Objective-C runtime loaded");
+ result.SetStatus(lldb::eReturnStatusFailed);
+ return false;
}
};
@@ -951,11 +1199,7 @@
class RemoteNXMapTable {
public:
- RemoteNXMapTable()
- : m_count(0), m_num_buckets_minus_one(0),
- m_buckets_ptr(LLDB_INVALID_ADDRESS), m_process(nullptr),
- m_end_iterator(*this, -1), m_load_addr(LLDB_INVALID_ADDRESS),
- m_map_pair_size(0), m_invalid_key(0) {}
+ RemoteNXMapTable() : m_end_iterator(*this, -1) {}
void Dump() {
printf("RemoteNXMapTable.m_load_addr = 0x%" PRIx64 "\n", m_load_addr);
@@ -1129,18 +1373,17 @@
private:
// contents of _NXMapTable struct
- uint32_t m_count;
- uint32_t m_num_buckets_minus_one;
- lldb::addr_t m_buckets_ptr;
- lldb_private::Process *m_process;
+ uint32_t m_count = 0;
+ uint32_t m_num_buckets_minus_one = 0;
+ lldb::addr_t m_buckets_ptr = LLDB_INVALID_ADDRESS;
+ lldb_private::Process *m_process = nullptr;
const_iterator m_end_iterator;
- lldb::addr_t m_load_addr;
- size_t m_map_pair_size;
- lldb::addr_t m_invalid_key;
+ lldb::addr_t m_load_addr = LLDB_INVALID_ADDRESS;
+ size_t m_map_pair_size = 0;
+ lldb::addr_t m_invalid_key = 0;
};
-AppleObjCRuntimeV2::HashTableSignature::HashTableSignature()
- : m_count(0), m_num_buckets(0), m_buckets_ptr(0) {}
+AppleObjCRuntimeV2::HashTableSignature::HashTableSignature() = default;
void AppleObjCRuntimeV2::HashTableSignature::UpdateSignature(
const RemoteNXMapTable &hash_table) {
@@ -1171,8 +1414,8 @@
ObjCLanguageRuntime::ClassDescriptorSP
AppleObjCRuntimeV2::GetClassDescriptorFromISA(ObjCISA isa) {
ObjCLanguageRuntime::ClassDescriptorSP class_descriptor_sp;
- if (m_non_pointer_isa_cache_up)
- class_descriptor_sp = m_non_pointer_isa_cache_up->GetClassDescriptor(isa);
+ if (auto *non_pointer_isa_cache = GetNonPointerIsaCache())
+ class_descriptor_sp = non_pointer_isa_cache->GetClassDescriptor(isa);
if (!class_descriptor_sp)
class_descriptor_sp = ObjCLanguageRuntime::GetClassDescriptorFromISA(isa);
return class_descriptor_sp;
@@ -1214,11 +1457,9 @@
objc_class_sp = GetClassDescriptorFromISA(isa);
if (isa && !objc_class_sp) {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS |
- LIBLLDB_LOG_TYPES));
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));
LLDB_LOGF(log,
- "0x%" PRIx64
- ": AppleObjCRuntimeV2::GetClassDescriptor() ISA was "
+ "0x%" PRIx64 ": AppleObjCRuntimeV2::GetClassDescriptor() ISA was "
"not in class descriptor cache 0x%" PRIx64,
isa_pointer, isa);
}
@@ -1229,28 +1470,29 @@
if (m_tagged_pointer_obfuscator != LLDB_INVALID_ADDRESS)
return m_tagged_pointer_obfuscator;
-
Process *process = GetProcess();
ModuleSP objc_module_sp(GetObjCModule());
if (!objc_module_sp)
return LLDB_INVALID_ADDRESS;
- static ConstString g_gdb_objc_obfuscator("objc_debug_taggedpointer_obfuscator");
+ static ConstString g_gdb_objc_obfuscator(
+ "objc_debug_taggedpointer_obfuscator");
const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(
- g_gdb_objc_obfuscator, lldb::eSymbolTypeAny);
+ g_gdb_objc_obfuscator, lldb::eSymbolTypeAny);
if (symbol) {
lldb::addr_t g_gdb_obj_obfuscator_ptr =
- symbol->GetLoadAddress(&process->GetTarget());
+ symbol->GetLoadAddress(&process->GetTarget());
if (g_gdb_obj_obfuscator_ptr != LLDB_INVALID_ADDRESS) {
Status error;
- m_tagged_pointer_obfuscator = process->ReadPointerFromMemory(
- g_gdb_obj_obfuscator_ptr, error);
+ m_tagged_pointer_obfuscator =
+ process->ReadPointerFromMemory(g_gdb_obj_obfuscator_ptr, error);
}
}
- // If we don't have a correct value at this point, there must be no obfuscation.
+ // If we don't have a correct value at this point, there must be no
+ // obfuscation.
if (m_tagged_pointer_obfuscator == LLDB_INVALID_ADDRESS)
m_tagged_pointer_obfuscator = 0;
@@ -1284,11 +1526,212 @@
return m_isa_hash_table_ptr;
}
-AppleObjCRuntimeV2::DescriptorMapUpdateResult
-AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(
- RemoteNXMapTable &hash_table) {
- Process *process = GetProcess();
+std::unique_ptr<UtilityFunction>
+AppleObjCRuntimeV2::DynamicClassInfoExtractor::GetClassInfoUtilityFunctionImpl(
+ ExecutionContext &exe_ctx, std::string code, std::string name) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));
+ LLDB_LOG(log, "Creating utility function {0}", name);
+
+ TypeSystemClang *ast =
+ ScratchTypeSystemClang::GetForTarget(exe_ctx.GetTargetRef());
+ if (!ast)
+ return {};
+
+ auto utility_fn_or_error = exe_ctx.GetTargetRef().CreateUtilityFunction(
+ std::move(code), std::move(name), eLanguageTypeC, exe_ctx);
+ if (!utility_fn_or_error) {
+ LLDB_LOG_ERROR(
+ log, utility_fn_or_error.takeError(),
+ "Failed to get utility function for implementation lookup: {0}");
+ return {};
+ }
+
+ // Make some types for our arguments.
+ CompilerType clang_uint32_t_type =
+ ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
+ CompilerType clang_void_pointer_type =
+ ast->GetBasicType(eBasicTypeVoid).GetPointerType();
+
+ // Make the runner function for our implementation utility function.
+ ValueList arguments;
+ Value value;
+ value.SetValueType(Value::ValueType::Scalar);
+ value.SetCompilerType(clang_void_pointer_type);
+ arguments.PushValue(value);
+ arguments.PushValue(value);
+ value.SetValueType(Value::ValueType::Scalar);
+ value.SetCompilerType(clang_uint32_t_type);
+ arguments.PushValue(value);
+ arguments.PushValue(value);
+
+ std::unique_ptr<UtilityFunction> utility_fn = std::move(*utility_fn_or_error);
+
+ Status error;
+ utility_fn->MakeFunctionCaller(clang_uint32_t_type, arguments,
+ exe_ctx.GetThreadSP(), error);
+
+ if (error.Fail()) {
+ LLDB_LOG(log,
+ "Failed to make function caller for implementation lookup: {0}.",
+ error.AsCString());
+ return {};
+ }
+
+ return utility_fn;
+}
+
+UtilityFunction *
+AppleObjCRuntimeV2::DynamicClassInfoExtractor::GetClassInfoUtilityFunction(
+ ExecutionContext &exe_ctx, Helper helper) {
+ switch (helper) {
+ case gdb_objc_realized_classes: {
+ if (!m_gdb_objc_realized_classes_helper.utility_function)
+ m_gdb_objc_realized_classes_helper.utility_function =
+ GetClassInfoUtilityFunctionImpl(exe_ctx,
+ g_get_dynamic_class_info_body,
+ g_get_dynamic_class_info_name);
+ return m_gdb_objc_realized_classes_helper.utility_function.get();
+ }
+ case objc_copyRealizedClassList: {
+ if (!m_objc_copyRealizedClassList_helper.utility_function)
+ m_objc_copyRealizedClassList_helper.utility_function =
+ GetClassInfoUtilityFunctionImpl(exe_ctx,
+ g_get_dynamic_class_info2_body,
+ g_get_dynamic_class_info2_name);
+ return m_objc_copyRealizedClassList_helper.utility_function.get();
+ }
+ }
+ llvm_unreachable("Unexpected helper");
+}
+
+lldb::addr_t &
+AppleObjCRuntimeV2::DynamicClassInfoExtractor::GetClassInfoArgs(Helper helper) {
+ switch (helper) {
+ case gdb_objc_realized_classes:
+ return m_gdb_objc_realized_classes_helper.args;
+ case objc_copyRealizedClassList:
+ return m_objc_copyRealizedClassList_helper.args;
+ }
+ llvm_unreachable("Unexpected helper");
+}
+
+AppleObjCRuntimeV2::DynamicClassInfoExtractor::Helper
+AppleObjCRuntimeV2::DynamicClassInfoExtractor::ComputeHelper() const {
+ if (!m_runtime.m_has_objc_copyRealizedClassList)
+ return DynamicClassInfoExtractor::gdb_objc_realized_classes;
+
+ if (Process *process = m_runtime.GetProcess()) {
+ if (DynamicLoader *loader = process->GetDynamicLoader()) {
+ if (loader->IsFullyInitialized())
+ return DynamicClassInfoExtractor::objc_copyRealizedClassList;
+ }
+ }
+
+ return DynamicClassInfoExtractor::gdb_objc_realized_classes;
+}
+
+std::unique_ptr<UtilityFunction>
+AppleObjCRuntimeV2::SharedCacheClassInfoExtractor::
+ GetClassInfoUtilityFunctionImpl(ExecutionContext &exe_ctx) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));
+
+ LLDB_LOG(log, "Creating utility function {0}",
+ g_get_shared_cache_class_info_name);
+
+ TypeSystemClang *ast =
+ ScratchTypeSystemClang::GetForTarget(exe_ctx.GetTargetRef());
+ if (!ast)
+ return {};
+
+ // If the inferior objc.dylib has the class_getNameRaw function, use that in
+ // our jitted expression. Else fall back to the old class_getName.
+ static ConstString g_class_getName_symbol_name("class_getName");
+ static ConstString g_class_getNameRaw_symbol_name(
+ "objc_debug_class_getNameRaw");
+
+ ConstString class_name_getter_function_name =
+ m_runtime.HasSymbol(g_class_getNameRaw_symbol_name)
+ ? g_class_getNameRaw_symbol_name
+ : g_class_getName_symbol_name;
+
+ // Substitute in the correct class_getName / class_getNameRaw function name,
+ // concatenate the two parts of our expression text. The format string has
+ // two %s's, so provide the name twice.
+ std::string shared_class_expression;
+ llvm::raw_string_ostream(shared_class_expression)
+ << llvm::format(g_shared_cache_class_name_funcptr,
+ class_name_getter_function_name.AsCString(),
+ class_name_getter_function_name.AsCString());
+
+ shared_class_expression += g_get_shared_cache_class_info_body;
+
+ auto utility_fn_or_error = exe_ctx.GetTargetRef().CreateUtilityFunction(
+ std::move(shared_class_expression), g_get_shared_cache_class_info_name,
+ eLanguageTypeC, exe_ctx);
+
+ if (!utility_fn_or_error) {
+ LLDB_LOG_ERROR(
+ log, utility_fn_or_error.takeError(),
+ "Failed to get utility function for implementation lookup: {0}");
+ return nullptr;
+ }
+
+ // Make some types for our arguments.
+ CompilerType clang_uint32_t_type =
+ ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
+ CompilerType clang_void_pointer_type =
+ ast->GetBasicType(eBasicTypeVoid).GetPointerType();
+ CompilerType clang_uint64_t_pointer_type =
+ ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 64)
+ .GetPointerType();
+
+ // Next make the function caller for our implementation utility function.
+ ValueList arguments;
+ Value value;
+ value.SetValueType(Value::ValueType::Scalar);
+ value.SetCompilerType(clang_void_pointer_type);
+ arguments.PushValue(value);
+ arguments.PushValue(value);
+ arguments.PushValue(value);
+
+ value.SetValueType(Value::ValueType::Scalar);
+ value.SetCompilerType(clang_uint64_t_pointer_type);
+ arguments.PushValue(value);
+
+ value.SetValueType(Value::ValueType::Scalar);
+ value.SetCompilerType(clang_uint32_t_type);
+ arguments.PushValue(value);
+ arguments.PushValue(value);
+
+ std::unique_ptr<UtilityFunction> utility_fn = std::move(*utility_fn_or_error);
+
+ Status error;
+ utility_fn->MakeFunctionCaller(clang_uint32_t_type, arguments,
+ exe_ctx.GetThreadSP(), error);
+
+ if (error.Fail()) {
+ LLDB_LOG(log,
+ "Failed to make function caller for implementation lookup: {0}.",
+ error.AsCString());
+ return {};
+ }
+
+ return utility_fn;
+}
+
+UtilityFunction *
+AppleObjCRuntimeV2::SharedCacheClassInfoExtractor::GetClassInfoUtilityFunction(
+ ExecutionContext &exe_ctx) {
+ if (!m_utility_function)
+ m_utility_function = GetClassInfoUtilityFunctionImpl(exe_ctx);
+ return m_utility_function.get();
+}
+
+AppleObjCRuntimeV2::DescriptorMapUpdateResult
+AppleObjCRuntimeV2::DynamicClassInfoExtractor::UpdateISAToDescriptorMap(
+ RemoteNXMapTable &hash_table) {
+ Process *process = m_runtime.GetProcess();
if (process == nullptr)
return DescriptorMapUpdateResult::Fail();
@@ -1316,65 +1759,36 @@
Status err;
+ // Compute which helper we're going to use for this update.
+ const DynamicClassInfoExtractor::Helper helper = ComputeHelper();
+
// Read the total number of classes from the hash table
- const uint32_t num_classes = hash_table.GetCount();
+ const uint32_t num_classes =
+ helper == DynamicClassInfoExtractor::gdb_objc_realized_classes
+ ? hash_table.GetCount()
+ : m_runtime.m_realized_class_generation_count;
if (num_classes == 0) {
- LLDB_LOGF(log, "No dynamic classes found in gdb_objc_realized_classes.");
+ LLDB_LOGF(log, "No dynamic classes found.");
return DescriptorMapUpdateResult::Success(0);
}
- // Make some types for our arguments
- CompilerType clang_uint32_t_type =
- ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
- CompilerType clang_void_pointer_type =
- ast->GetBasicType(eBasicTypeVoid).GetPointerType();
-
- ValueList arguments;
- FunctionCaller *get_class_info_function = nullptr;
-
- if (!m_get_class_info_code) {
- auto utility_fn_or_error = GetTargetRef().CreateUtilityFunction(
- g_get_dynamic_class_info_body, g_get_dynamic_class_info_name,
- eLanguageTypeC, exe_ctx);
- if (!utility_fn_or_error) {
- LLDB_LOG_ERROR(
- log, utility_fn_or_error.takeError(),
- "Failed to get utility function for implementation lookup: {0}");
- return DescriptorMapUpdateResult::Fail();
- }
- m_get_class_info_code = std::move(*utility_fn_or_error);
-
- // Next make the runner function for our implementation utility function.
- Value value;
- value.SetValueType(Value::eValueTypeScalar);
- value.SetCompilerType(clang_void_pointer_type);
- arguments.PushValue(value);
- arguments.PushValue(value);
-
- value.SetValueType(Value::eValueTypeScalar);
- value.SetCompilerType(clang_uint32_t_type);
- arguments.PushValue(value);
- arguments.PushValue(value);
-
- Status error;
- get_class_info_function = m_get_class_info_code->MakeFunctionCaller(
- clang_uint32_t_type, arguments, thread_sp, error);
-
- if (error.Fail()) {
- LLDB_LOGF(log,
- "Failed to make function caller for implementation lookup: %s.",
- error.AsCString());
- return DescriptorMapUpdateResult::Fail();
- }
- } else {
- get_class_info_function = m_get_class_info_code->GetFunctionCaller();
- if (!get_class_info_function) {
- LLDB_LOGF(log, "Failed to get implementation lookup function caller.");
- return DescriptorMapUpdateResult::Fail();
- }
- arguments = get_class_info_function->GetArgumentValues();
+ UtilityFunction *get_class_info_code =
+ GetClassInfoUtilityFunction(exe_ctx, helper);
+ if (!get_class_info_code) {
+ // The callee will have already logged a useful error message.
+ return DescriptorMapUpdateResult::Fail();
}
+ FunctionCaller *get_class_info_function =
+ get_class_info_code->GetFunctionCaller();
+
+ if (!get_class_info_function) {
+ LLDB_LOGF(log, "Failed to get implementation lookup function caller.");
+ return DescriptorMapUpdateResult::Fail();
+ }
+
+ ValueList arguments = get_class_info_function->GetArgumentValues();
+
DiagnosticManager diagnostics;
const uint32_t class_info_byte_size = addr_size + 4;
@@ -1390,18 +1804,18 @@
return DescriptorMapUpdateResult::Fail();
}
- std::lock_guard<std::mutex> guard(m_get_class_info_args_mutex);
+ std::lock_guard<std::mutex> guard(m_mutex);
// Fill in our function argument values
arguments.GetValueAtIndex(0)->GetScalar() = hash_table.GetTableLoadAddress();
arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr;
arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size;
-
+
// Only dump the runtime classes from the expression evaluation if the log is
// verbose:
Log *type_log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES);
bool dump_log = type_log && type_log->GetVerbose();
-
+
arguments.GetValueAtIndex(3)->GetScalar() = dump_log ? 1 : 0;
bool success = false;
@@ -1410,7 +1824,7 @@
// Write our function arguments into the process so we can run our function
if (get_class_info_function->WriteFunctionArguments(
- exe_ctx, m_get_class_info_args, arguments, diagnostics)) {
+ exe_ctx, GetClassInfoArgs(helper), arguments, diagnostics)) {
EvaluateExpressionOptions options;
options.SetUnwindOnError(true);
options.SetTryAllThreads(false);
@@ -1419,8 +1833,11 @@
options.SetTimeout(process->GetUtilityExpressionTimeout());
options.SetIsForUtilityExpr(true);
+ CompilerType clang_uint32_t_type =
+ ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
+
Value return_value;
- return_value.SetValueType(Value::eValueTypeScalar);
+ return_value.SetValueType(Value::ValueType::Scalar);
return_value.SetCompilerType(clang_uint32_t_type);
return_value.GetScalar() = 0;
@@ -1428,12 +1845,12 @@
// Run the function
ExpressionResults results = get_class_info_function->ExecuteFunction(
- exe_ctx, &m_get_class_info_args, options, diagnostics, return_value);
+ exe_ctx, &GetClassInfoArgs(helper), options, diagnostics, return_value);
if (results == eExpressionCompleted) {
// The result is the number of ClassInfo structures that were filled in
num_class_infos = return_value.GetScalar().ULong();
- LLDB_LOGF(log, "Discovered %u ObjC classes\n", num_class_infos);
+ LLDB_LOG(log, "Discovered {0} Objective-C classes", num_class_infos);
if (num_class_infos > 0) {
// Read the ClassInfo structures
DataBufferHeap buffer(num_class_infos * class_info_byte_size, 0);
@@ -1443,7 +1860,7 @@
DataExtractor class_infos_data(buffer.GetBytes(),
buffer.GetByteSize(),
process->GetByteOrder(), addr_size);
- ParseClassInfoArray(class_infos_data, num_class_infos);
+ m_runtime.ParseClassInfoArray(class_infos_data, num_class_infos);
}
}
success = true;
@@ -1507,15 +1924,16 @@
ClassDescriptorSP descriptor_sp(
new ClassDescriptorV2(*this, isa, nullptr));
- // The code in g_get_shared_cache_class_info_body sets the value of the hash
- // to 0 to signal a demangled symbol. We use class_getName() in that code to
- // find the class name, but this returns a demangled name for Swift symbols.
- // For those symbols, recompute the hash here by reading their name from the
- // runtime.
+ // The code in g_get_shared_cache_class_info_body sets the value of the
+ // hash to 0 to signal a demangled symbol. We use class_getName() in that
+ // code to find the class name, but this returns a demangled name for
+ // Swift symbols. For those symbols, recompute the hash here by reading
+ // their name from the runtime.
if (name_hash)
AddClass(isa, descriptor_sp, name_hash);
else
- AddClass(isa, descriptor_sp, descriptor_sp->GetClassName().AsCString(nullptr));
+ AddClass(isa, descriptor_sp,
+ descriptor_sp->GetClassName().AsCString(nullptr));
num_parsed++;
if (should_log)
LLDB_LOGF(log,
@@ -1531,10 +1949,20 @@
return num_parsed;
}
-AppleObjCRuntimeV2::DescriptorMapUpdateResult
-AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() {
- Process *process = GetProcess();
+bool AppleObjCRuntimeV2::HasSymbol(ConstString Name) {
+ if (!m_objc_module_sp)
+ return false;
+ if (const Symbol *symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType(
+ Name, lldb::eSymbolTypeCode)) {
+ if (symbol->ValueIsAddress() || symbol->GetAddressRef().IsValid())
+ return true;
+ }
+ return false;
+}
+AppleObjCRuntimeV2::DescriptorMapUpdateResult
+AppleObjCRuntimeV2::SharedCacheClassInfoExtractor::UpdateISAToDescriptorMap() {
+ Process *process = m_runtime.GetProcess();
if (process == nullptr)
return DescriptorMapUpdateResult::Fail();
@@ -1562,103 +1990,38 @@
uint32_t num_class_infos = 0;
- const lldb::addr_t objc_opt_ptr = GetSharedCacheReadOnlyAddress();
+ const lldb::addr_t objc_opt_ptr = m_runtime.GetSharedCacheReadOnlyAddress();
+ const lldb::addr_t shared_cache_base_addr =
+ m_runtime.GetSharedCacheBaseAddress();
- if (objc_opt_ptr == LLDB_INVALID_ADDRESS)
+ if (objc_opt_ptr == LLDB_INVALID_ADDRESS ||
+ shared_cache_base_addr == LLDB_INVALID_ADDRESS)
return DescriptorMapUpdateResult::Fail();
const uint32_t num_classes = 128 * 1024;
- // Make some types for our arguments
- CompilerType clang_uint32_t_type =
- ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
- CompilerType clang_void_pointer_type =
- ast->GetBasicType(eBasicTypeVoid).GetPointerType();
+ UtilityFunction *get_class_info_code = GetClassInfoUtilityFunction(exe_ctx);
+ FunctionCaller *get_shared_cache_class_info_function =
+ get_class_info_code->GetFunctionCaller();
- ValueList arguments;
- FunctionCaller *get_shared_cache_class_info_function = nullptr;
-
- if (!m_get_shared_cache_class_info_code) {
- Status error;
-
- // If the inferior objc.dylib has the class_getNameRaw function,
- // use that in our jitted expression. Else fall back to the old
- // class_getName.
- static ConstString g_class_getName_symbol_name("class_getName");
- static ConstString g_class_getNameRaw_symbol_name("objc_debug_class_getNameRaw");
- ConstString class_name_getter_function_name = g_class_getName_symbol_name;
-
- ObjCLanguageRuntime *objc_runtime = ObjCLanguageRuntime::Get(*process);
- if (objc_runtime) {
- for (lldb::ModuleSP mod_sp : process->GetTarget().GetImages().Modules()) {
- if (objc_runtime->IsModuleObjCLibrary(mod_sp)) {
- const Symbol *symbol =
- mod_sp->FindFirstSymbolWithNameAndType(g_class_getNameRaw_symbol_name,
- lldb::eSymbolTypeCode);
- if (symbol &&
- (symbol->ValueIsAddress() || symbol->GetAddressRef().IsValid())) {
- class_name_getter_function_name = g_class_getNameRaw_symbol_name;
- }
- }
- }
- }
-
- // Substitute in the correct class_getName / class_getNameRaw function name,
- // concatenate the two parts of our expression text. The format string
- // has two %s's, so provide the name twice.
- std::string shared_class_expression;
- llvm::raw_string_ostream(shared_class_expression) << llvm::format(
- g_shared_cache_class_name_funcptr,
- class_name_getter_function_name.AsCString(),
- class_name_getter_function_name.AsCString());
-
- shared_class_expression += g_get_shared_cache_class_info_body;
-
- auto utility_fn_or_error = exe_ctx.GetTargetRef().CreateUtilityFunction(
- std::move(shared_class_expression), g_get_shared_cache_class_info_name,
- eLanguageTypeC, exe_ctx);
- if (!utility_fn_or_error) {
- LLDB_LOG_ERROR(
- log, utility_fn_or_error.takeError(),
- "Failed to get utility function for implementation lookup: {0}");
- return DescriptorMapUpdateResult::Fail();
- }
-
- m_get_shared_cache_class_info_code = std::move(*utility_fn_or_error);
-
- // Next make the function caller for our implementation utility function.
- Value value;
- value.SetValueType(Value::eValueTypeScalar);
- value.SetCompilerType(clang_void_pointer_type);
- arguments.PushValue(value);
- arguments.PushValue(value);
-
- value.SetValueType(Value::eValueTypeScalar);
- value.SetCompilerType(clang_uint32_t_type);
- arguments.PushValue(value);
- arguments.PushValue(value);
-
- get_shared_cache_class_info_function =
- m_get_shared_cache_class_info_code->MakeFunctionCaller(
- clang_uint32_t_type, arguments, thread_sp, error);
-
- if (get_shared_cache_class_info_function == nullptr)
- return DescriptorMapUpdateResult::Fail();
-
- } else {
- get_shared_cache_class_info_function =
- m_get_shared_cache_class_info_code->GetFunctionCaller();
- if (get_shared_cache_class_info_function == nullptr)
- return DescriptorMapUpdateResult::Fail();
- arguments = get_shared_cache_class_info_function->GetArgumentValues();
+ if (!get_shared_cache_class_info_function) {
+ LLDB_LOGF(log, "Failed to get implementation lookup function caller.");
+ return DescriptorMapUpdateResult::Fail();
}
+ ValueList arguments =
+ get_shared_cache_class_info_function->GetArgumentValues();
+
DiagnosticManager diagnostics;
const uint32_t class_info_byte_size = addr_size + 4;
const uint32_t class_infos_byte_size = num_classes * class_info_byte_size;
lldb::addr_t class_infos_addr = process->AllocateMemory(
class_infos_byte_size, ePermissionsReadable | ePermissionsWritable, err);
+ const uint32_t relative_selector_offset_addr_size = 64;
+ lldb::addr_t relative_selector_offset_addr =
+ process->AllocateMemory(relative_selector_offset_addr_size,
+ ePermissionsReadable | ePermissionsWritable, err);
if (class_infos_addr == LLDB_INVALID_ADDRESS) {
LLDB_LOGF(log,
@@ -1668,18 +2031,20 @@
return DescriptorMapUpdateResult::Fail();
}
- std::lock_guard<std::mutex> guard(m_get_shared_cache_class_info_args_mutex);
+ std::lock_guard<std::mutex> guard(m_mutex);
// Fill in our function argument values
arguments.GetValueAtIndex(0)->GetScalar() = objc_opt_ptr;
- arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr;
- arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size;
+ arguments.GetValueAtIndex(1)->GetScalar() = shared_cache_base_addr;
+ arguments.GetValueAtIndex(2)->GetScalar() = class_infos_addr;
+ arguments.GetValueAtIndex(3)->GetScalar() = relative_selector_offset_addr;
+ arguments.GetValueAtIndex(4)->GetScalar() = class_infos_byte_size;
// Only dump the runtime classes from the expression evaluation if the log is
// verbose:
Log *type_log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES);
bool dump_log = type_log && type_log->GetVerbose();
-
- arguments.GetValueAtIndex(3)->GetScalar() = dump_log ? 1 : 0;
+
+ arguments.GetValueAtIndex(5)->GetScalar() = dump_log ? 1 : 0;
bool success = false;
@@ -1687,8 +2052,7 @@
// Write our function arguments into the process so we can run our function
if (get_shared_cache_class_info_function->WriteFunctionArguments(
- exe_ctx, m_get_shared_cache_class_info_args, arguments,
- diagnostics)) {
+ exe_ctx, m_args, arguments, diagnostics)) {
EvaluateExpressionOptions options;
options.SetUnwindOnError(true);
options.SetTryAllThreads(false);
@@ -1697,8 +2061,11 @@
options.SetTimeout(process->GetUtilityExpressionTimeout());
options.SetIsForUtilityExpr(true);
+ CompilerType clang_uint32_t_type =
+ ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
+
Value return_value;
- return_value.SetValueType(Value::eValueTypeScalar);
+ return_value.SetValueType(Value::ValueType::Scalar);
return_value.SetCompilerType(clang_uint32_t_type);
return_value.GetScalar() = 0;
@@ -1707,14 +2074,13 @@
// Run the function
ExpressionResults results =
get_shared_cache_class_info_function->ExecuteFunction(
- exe_ctx, &m_get_shared_cache_class_info_args, options, diagnostics,
- return_value);
+ exe_ctx, &m_args, options, diagnostics, return_value);
if (results == eExpressionCompleted) {
// The result is the number of ClassInfo structures that were filled in
num_class_infos = return_value.GetScalar().ULong();
- LLDB_LOGF(log, "Discovered %u ObjC classes in shared cache\n",
- num_class_infos);
+ LLDB_LOG(log, "Discovered {0} Objective-C classes in the shared cache",
+ num_class_infos);
assert(num_class_infos <= num_classes);
if (num_class_infos > 0) {
if (num_class_infos > num_classes) {
@@ -1725,16 +2091,38 @@
success = true;
}
+ // Read the relative selector offset.
+ DataBufferHeap relative_selector_offset_buffer(64, 0);
+ if (process->ReadMemory(relative_selector_offset_addr,
+ relative_selector_offset_buffer.GetBytes(),
+ relative_selector_offset_buffer.GetByteSize(),
+ err) ==
+ relative_selector_offset_buffer.GetByteSize()) {
+ DataExtractor relative_selector_offset_data(
+ relative_selector_offset_buffer.GetBytes(),
+ relative_selector_offset_buffer.GetByteSize(),
+ process->GetByteOrder(), addr_size);
+ lldb::offset_t offset = 0;
+ uint64_t relative_selector_offset =
+ relative_selector_offset_data.GetU64(&offset);
+ if (relative_selector_offset > 0) {
+ // The offset is relative to the objc_opt struct.
+ m_runtime.SetRelativeSelectorBaseAddr(objc_opt_ptr +
+ relative_selector_offset);
+ }
+ }
+
// Read the ClassInfo structures
- DataBufferHeap buffer(num_class_infos * class_info_byte_size, 0);
- if (process->ReadMemory(class_infos_addr, buffer.GetBytes(),
- buffer.GetByteSize(),
- err) == buffer.GetByteSize()) {
- DataExtractor class_infos_data(buffer.GetBytes(),
- buffer.GetByteSize(),
+ DataBufferHeap class_infos_buffer(
+ num_class_infos * class_info_byte_size, 0);
+ if (process->ReadMemory(class_infos_addr, class_infos_buffer.GetBytes(),
+ class_infos_buffer.GetByteSize(),
+ err) == class_infos_buffer.GetByteSize()) {
+ DataExtractor class_infos_data(class_infos_buffer.GetBytes(),
+ class_infos_buffer.GetByteSize(),
process->GetByteOrder(), addr_size);
- ParseClassInfoArray(class_infos_data, num_class_infos);
+ m_runtime.ParseClassInfoArray(class_infos_data, num_class_infos);
}
} else {
success = true;
@@ -1758,42 +2146,6 @@
return DescriptorMapUpdateResult(success, num_class_infos);
}
-bool AppleObjCRuntimeV2::UpdateISAToDescriptorMapFromMemory(
- RemoteNXMapTable &hash_table) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));
-
- Process *process = GetProcess();
-
- if (process == nullptr)
- return false;
-
- uint32_t num_map_table_isas = 0;
-
- ModuleSP objc_module_sp(GetObjCModule());
-
- if (objc_module_sp) {
- for (RemoteNXMapTable::element elt : hash_table) {
- ++num_map_table_isas;
-
- if (ISAIsCached(elt.second))
- continue;
-
- ClassDescriptorSP descriptor_sp = ClassDescriptorSP(
- new ClassDescriptorV2(*this, elt.second, elt.first.AsCString()));
-
- if (log && log->GetVerbose())
- LLDB_LOGF(log,
- "AppleObjCRuntimeV2 added (ObjCISA)0x%" PRIx64
- " (%s) from dynamic table to isa->descriptor cache",
- elt.second, elt.first.AsCString());
-
- AddClass(elt.second, descriptor_sp, elt.first.AsCString());
- }
- }
-
- return num_map_table_isas > 0;
-}
-
lldb::addr_t AppleObjCRuntimeV2::GetSharedCacheReadOnlyAddress() {
Process *process = GetProcess();
@@ -1827,6 +2179,19 @@
return LLDB_INVALID_ADDRESS;
}
+lldb::addr_t AppleObjCRuntimeV2::GetSharedCacheBaseAddress() {
+ StructuredData::ObjectSP info = m_process->GetSharedCacheInfo();
+ if (!info)
+ return LLDB_INVALID_ADDRESS;
+
+ StructuredData::Dictionary *info_dict = info->GetAsDictionary();
+ if (!info_dict)
+ return LLDB_INVALID_ADDRESS;
+
+ return info_dict->GetValueForKey("shared_cache_base_address")
+ ->GetIntegerValue(LLDB_INVALID_ADDRESS);
+}
+
void AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded() {
LLDB_SCOPED_TIMER();
@@ -1842,14 +2207,19 @@
// map, whether it was successful or not.
m_isa_to_descriptor_stop_id = process->GetStopID();
- if (!m_hash_signature.NeedsUpdate(process, this, hash_table))
+ // Ask the runtime is the realized class generation count changed. Unlike
+ // the hash table, this accounts for lazily named classes.
+ const bool class_count_changed = RealizedClassGenerationCountChanged();
+
+ if (!m_hash_signature.NeedsUpdate(process, this, hash_table) &&
+ !class_count_changed)
return;
m_hash_signature.UpdateSignature(hash_table);
- // Grab the dynamically loaded objc classes from the hash table in memory
+ // Grab the dynamically loaded Objective-C classes from memory.
DescriptorMapUpdateResult dynamic_update_result =
- UpdateISAToDescriptorMapDynamic(hash_table);
+ m_dynamic_class_info_extractor.UpdateISAToDescriptorMap(hash_table);
// Now get the objc classes that are baked into the Objective-C runtime in
// the shared cache, but only once per process as this data never changes
@@ -1865,7 +2235,7 @@
const uint32_t num_classes_to_warn_at = 500;
DescriptorMapUpdateResult shared_cache_update_result =
- UpdateISAToDescriptorMapSharedCache();
+ m_shared_cache_class_info_extractor.UpdateISAToDescriptorMap();
LLDB_LOGF(log,
"attempted to read objc class data - results: "
@@ -1895,6 +2265,35 @@
}
}
+bool AppleObjCRuntimeV2::RealizedClassGenerationCountChanged() {
+ Process *process = GetProcess();
+ if (!process)
+ return false;
+
+ Status error;
+ uint64_t objc_debug_realized_class_generation_count =
+ ExtractRuntimeGlobalSymbol(
+ process, ConstString("objc_debug_realized_class_generation_count"),
+ GetObjCModule(), error);
+ if (error.Fail())
+ return false;
+
+ if (m_realized_class_generation_count ==
+ objc_debug_realized_class_generation_count)
+ return false;
+
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));
+ LLDB_LOG(log,
+ "objc_debug_realized_class_generation_count changed from {0} to {1}",
+ m_realized_class_generation_count,
+ objc_debug_realized_class_generation_count);
+
+ m_realized_class_generation_count =
+ objc_debug_realized_class_generation_count;
+
+ return true;
+}
+
static bool DoesProcessHaveSharedCache(Process &process) {
PlatformSP platform_sp = process.GetTarget().GetPlatform();
if (!platform_sp)
@@ -1975,9 +2374,10 @@
const ConstString ivar_name_cs(class_and_ivar.second);
const char *ivar_name_cstr = ivar_name_cs.AsCString();
- auto ivar_func = [&ret, ivar_name_cstr](
- const char *name, const char *type, lldb::addr_t offset_addr,
- uint64_t size) -> lldb::addr_t {
+ auto ivar_func = [&ret,
+ ivar_name_cstr](const char *name, const char *type,
+ lldb::addr_t offset_addr,
+ uint64_t size) -> lldb::addr_t {
if (!strcmp(name, ivar_name_cstr)) {
ret = offset_addr;
return true;
@@ -2279,7 +2679,6 @@
AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::GetClassDescriptor(
lldb::addr_t ptr) {
ClassDescriptorSP actual_class_descriptor_sp;
- uint64_t data_payload;
uint64_t unobfuscated = (ptr) ^ m_runtime.GetTaggedPointerObfuscator();
if (!IsPossibleTaggedPointer(unobfuscated))
@@ -2307,12 +2706,15 @@
m_cache[slot] = actual_class_descriptor_sp;
}
- data_payload =
+ uint64_t data_payload =
(((uint64_t)unobfuscated << m_objc_debug_taggedpointer_payload_lshift) >>
m_objc_debug_taggedpointer_payload_rshift);
-
- return ClassDescriptorSP(
- new ClassDescriptorV2Tagged(actual_class_descriptor_sp, data_payload));
+ int64_t data_payload_signed =
+ ((int64_t)((int64_t)unobfuscated
+ << m_objc_debug_taggedpointer_payload_lshift) >>
+ m_objc_debug_taggedpointer_payload_rshift);
+ return ClassDescriptorSP(new ClassDescriptorV2Tagged(
+ actual_class_descriptor_sp, data_payload, data_payload_signed));
}
AppleObjCRuntimeV2::TaggedPointerVendorExtended::TaggedPointerVendorExtended(
@@ -2364,7 +2766,6 @@
AppleObjCRuntimeV2::TaggedPointerVendorExtended::GetClassDescriptor(
lldb::addr_t ptr) {
ClassDescriptorSP actual_class_descriptor_sp;
- uint64_t data_payload;
uint64_t unobfuscated = (ptr) ^ m_runtime.GetTaggedPointerObfuscator();
if (!IsPossibleTaggedPointer(unobfuscated))
@@ -2395,12 +2796,16 @@
m_ext_cache[slot] = actual_class_descriptor_sp;
}
- data_payload =
- (((uint64_t)unobfuscated << m_objc_debug_taggedpointer_ext_payload_lshift) >>
+ uint64_t data_payload = (((uint64_t)unobfuscated
+ << m_objc_debug_taggedpointer_ext_payload_lshift) >>
+ m_objc_debug_taggedpointer_ext_payload_rshift);
+ int64_t data_payload_signed =
+ ((int64_t)((int64_t)unobfuscated
+ << m_objc_debug_taggedpointer_ext_payload_lshift) >>
m_objc_debug_taggedpointer_ext_payload_rshift);
- return ClassDescriptorSP(
- new ClassDescriptorV2Tagged(actual_class_descriptor_sp, data_payload));
+ return ClassDescriptorSP(new ClassDescriptorV2Tagged(
+ actual_class_descriptor_sp, data_payload, data_payload_signed));
}
AppleObjCRuntimeV2::NonPointerISACache::NonPointerISACache(
@@ -2552,8 +2957,8 @@
AppleObjCRuntimeV2::GetPointerISA(ObjCISA isa) {
ObjCISA ret = isa;
- if (m_non_pointer_isa_cache_up)
- m_non_pointer_isa_cache_up->EvaluateNonPointerISA(isa, ret);
+ if (auto *non_pointer_isa_cache = GetNonPointerIsaCache())
+ non_pointer_isa_cache->EvaluateNonPointerISA(isa, ret);
return ret;
}
@@ -2598,13 +3003,14 @@
#pragma mark Frame recognizers
class ObjCExceptionRecognizedStackFrame : public RecognizedStackFrame {
- public:
+public:
ObjCExceptionRecognizedStackFrame(StackFrameSP frame_sp) {
ThreadSP thread_sp = frame_sp->GetThread();
ProcessSP process_sp = thread_sp->GetProcess();
const lldb::ABISP &abi = process_sp->GetABI();
- if (!abi) return;
+ if (!abi)
+ return;
TypeSystemClang *clang_ast_context =
ScratchTypeSystemClang::GetForTarget(process_sp->GetTarget());
@@ -2618,7 +3024,8 @@
input_value.SetCompilerType(voidstar);
args.PushValue(input_value);
- if (!abi->GetArgumentValues(*thread_sp, args)) return;
+ if (!abi->GetArgumentValues(*thread_sp, args))
+ return;
addr_t exception_addr = args.GetValueAtIndex(0)->GetScalar().ULongLong();
diff --git a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
index c6fb6ea..d0caa29 100644
--- a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
+++ b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
@@ -26,7 +26,6 @@
public:
~AppleObjCRuntimeV2() override = default;
- // Static Functions
static void Initialize();
static void Terminate();
@@ -46,7 +45,6 @@
return runtime->isA(&ID);
}
- // These are generic runtime functions:
bool GetDynamicTypeAndAddress(ValueObject &in_value,
lldb::DynamicValueType use_dynamic,
TypeAndOrName &class_type_or_name,
@@ -56,7 +54,6 @@
llvm::Expected<std::unique_ptr<UtilityFunction>>
CreateObjectChecker(std::string name, ExecutionContext &exe_ctx) override;
- // PluginInterface protocol
ConstString GetPluginName() override;
uint32_t GetPluginVersion() override;
@@ -88,6 +85,15 @@
lldb::addr_t GetTaggedPointerObfuscator();
+ /// Returns the base address for relative method list selector strings.
+ lldb::addr_t GetRelativeSelectorBaseAddr() {
+ return m_relative_selector_base;
+ }
+
+ void SetRelativeSelectorBaseAddr(lldb::addr_t relative_selector_base) {
+ m_relative_selector_base = relative_selector_base;
+ }
+
void GetValuesForGlobalCFBooleans(lldb::addr_t &cf_true,
lldb::addr_t &cf_false) override;
@@ -105,8 +111,8 @@
protected:
lldb::BreakpointResolverSP
- CreateExceptionResolver(const lldb::BreakpointSP &bkpt,
- bool catch_bp, bool throw_bp) override;
+ CreateExceptionResolver(const lldb::BreakpointSP &bkpt, bool catch_bp,
+ bool throw_bp) override;
private:
class HashTableSignature {
@@ -119,9 +125,9 @@
void UpdateSignature(const RemoteNXMapTable &hash_table);
protected:
- uint32_t m_count;
- uint32_t m_num_buckets;
- lldb::addr_t m_buckets_ptr;
+ uint32_t m_count = 0;
+ uint32_t m_num_buckets = 0;
+ lldb::addr_t m_buckets_ptr = 0;
};
class NonPointerISACache {
@@ -296,22 +302,99 @@
}
};
+ /// Abstraction to read the Objective-C class info.
+ class ClassInfoExtractor {
+ public:
+ ClassInfoExtractor(AppleObjCRuntimeV2 &runtime) : m_runtime(runtime) {}
+ std::mutex &GetMutex() { return m_mutex; }
+
+ protected:
+ /// The lifetime of this object is tied to that of the runtime.
+ AppleObjCRuntimeV2 &m_runtime;
+ std::mutex m_mutex;
+ };
+
+ /// We can read the class info from the Objective-C runtime using
+ /// gdb_objc_realized_classes or objc_copyRealizedClassList. The latter is
+ /// preferred because it includes lazily named classes, but it's not always
+ /// available or safe to call.
+ ///
+ /// We potentially need both for the same process, because we may need to use
+ /// gdb_objc_realized_classes until dyld is initialized and then switch over
+ /// to objc_copyRealizedClassList for lazily named classes.
+ class DynamicClassInfoExtractor : public ClassInfoExtractor {
+ public:
+ DynamicClassInfoExtractor(AppleObjCRuntimeV2 &runtime)
+ : ClassInfoExtractor(runtime) {}
+
+ DescriptorMapUpdateResult
+ UpdateISAToDescriptorMap(RemoteNXMapTable &hash_table);
+
+ private:
+ enum Helper { gdb_objc_realized_classes, objc_copyRealizedClassList };
+
+ /// Compute which helper to use. Prefer objc_copyRealizedClassList if it's
+ /// available and it's safe to call (i.e. dyld is fully initialized). Use
+ /// gdb_objc_realized_classes otherwise.
+ Helper ComputeHelper() const;
+
+ UtilityFunction *GetClassInfoUtilityFunction(ExecutionContext &exe_ctx,
+ Helper helper);
+ lldb::addr_t &GetClassInfoArgs(Helper helper);
+
+ std::unique_ptr<UtilityFunction>
+ GetClassInfoUtilityFunctionImpl(ExecutionContext &exe_ctx, std::string code,
+ std::string name);
+
+ /// Helper to read class info using the gdb_objc_realized_classes.
+ struct gdb_objc_realized_classes_helper {
+ std::unique_ptr<UtilityFunction> utility_function;
+ lldb::addr_t args = LLDB_INVALID_ADDRESS;
+ };
+
+ /// Helper to read class info using objc_copyRealizedClassList.
+ struct objc_copyRealizedClassList_helper {
+ std::unique_ptr<UtilityFunction> utility_function;
+ lldb::addr_t args = LLDB_INVALID_ADDRESS;
+ };
+
+ gdb_objc_realized_classes_helper m_gdb_objc_realized_classes_helper;
+ objc_copyRealizedClassList_helper m_objc_copyRealizedClassList_helper;
+ };
+
+ /// Abstraction to read the Objective-C class info from the shared cache.
+ class SharedCacheClassInfoExtractor : public ClassInfoExtractor {
+ public:
+ SharedCacheClassInfoExtractor(AppleObjCRuntimeV2 &runtime)
+ : ClassInfoExtractor(runtime) {}
+
+ DescriptorMapUpdateResult UpdateISAToDescriptorMap();
+
+ private:
+ UtilityFunction *GetClassInfoUtilityFunction(ExecutionContext &exe_ctx);
+
+ std::unique_ptr<UtilityFunction>
+ GetClassInfoUtilityFunctionImpl(ExecutionContext &exe_ctx);
+
+ std::unique_ptr<UtilityFunction> m_utility_function;
+ lldb::addr_t m_args = LLDB_INVALID_ADDRESS;
+ };
+
AppleObjCRuntimeV2(Process *process, const lldb::ModuleSP &objc_module_sp);
ObjCISA GetPointerISA(ObjCISA isa);
lldb::addr_t GetISAHashTablePointer();
- bool UpdateISAToDescriptorMapFromMemory(RemoteNXMapTable &hash_table);
-
- DescriptorMapUpdateResult
- UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table);
+ /// Update the generation count of realized classes. This is not an exact
+ /// count but rather a value that is incremented when new classes are realized
+ /// or destroyed. Unlike the count in gdb_objc_realized_classes, it will
+ /// change when lazily named classes get realized.
+ bool RealizedClassGenerationCountChanged();
uint32_t ParseClassInfoArray(const lldb_private::DataExtractor &data,
uint32_t num_class_infos);
- DescriptorMapUpdateResult UpdateISAToDescriptorMapSharedCache();
-
enum class SharedCacheWarningReason {
eExpressionExecutionFailure,
eNotEnoughClassesRead
@@ -320,30 +403,40 @@
void WarnIfNoClassesCached(SharedCacheWarningReason reason);
lldb::addr_t GetSharedCacheReadOnlyAddress();
+ lldb::addr_t GetSharedCacheBaseAddress();
bool GetCFBooleanValuesIfNeeded();
+ bool HasSymbol(ConstString Name);
+
+ NonPointerISACache *GetNonPointerIsaCache() {
+ if (!m_non_pointer_isa_cache_up)
+ m_non_pointer_isa_cache_up.reset(
+ NonPointerISACache::CreateInstance(*this, m_objc_module_sp));
+ return m_non_pointer_isa_cache_up.get();
+ }
+
friend class ClassDescriptorV2;
- std::unique_ptr<UtilityFunction> m_get_class_info_code;
- lldb::addr_t m_get_class_info_args;
- std::mutex m_get_class_info_args_mutex;
+ lldb::ModuleSP m_objc_module_sp;
- std::unique_ptr<UtilityFunction> m_get_shared_cache_class_info_code;
- lldb::addr_t m_get_shared_cache_class_info_args;
- std::mutex m_get_shared_cache_class_info_args_mutex;
+ DynamicClassInfoExtractor m_dynamic_class_info_extractor;
+ SharedCacheClassInfoExtractor m_shared_cache_class_info_extractor;
std::unique_ptr<DeclVendor> m_decl_vendor_up;
lldb::addr_t m_tagged_pointer_obfuscator;
lldb::addr_t m_isa_hash_table_ptr;
+ lldb::addr_t m_relative_selector_base;
HashTableSignature m_hash_signature;
bool m_has_object_getClass;
+ bool m_has_objc_copyRealizedClassList;
bool m_loaded_objc_opt;
std::unique_ptr<NonPointerISACache> m_non_pointer_isa_cache_up;
std::unique_ptr<TaggedPointerVendor> m_tagged_pointer_vendor_up;
EncodingToTypeSP m_encoding_to_type_sp;
bool m_noclasses_warning_emitted;
llvm::Optional<std::pair<lldb::addr_t, lldb::addr_t>> m_CFBoolean_values;
+ uint64_t m_realized_class_generation_count;
};
} // namespace lldb_private
diff --git a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
index bcc1f6f..aa6306b 100644
--- a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
+++ b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
@@ -285,7 +285,7 @@
SetUpRegion();
}
-AppleObjCTrampolineHandler::~AppleObjCTrampolineHandler() {}
+AppleObjCTrampolineHandler::~AppleObjCTrampolineHandler() = default;
void AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::SetUpRegion() {
// The header looks like:
@@ -526,7 +526,7 @@
CompilerType clang_void_ptr_type =
clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
- input_value.SetValueType(Value::eValueTypeScalar);
+ input_value.SetValueType(Value::ValueType::Scalar);
// input_value.SetContext (Value::eContextTypeClangType,
// clang_void_ptr_type);
input_value.SetCompilerType(clang_void_ptr_type);
@@ -936,7 +936,7 @@
Value void_ptr_value;
CompilerType clang_void_ptr_type =
clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
- void_ptr_value.SetValueType(Value::eValueTypeScalar);
+ void_ptr_value.SetValueType(Value::ValueType::Scalar);
// void_ptr_value.SetContext (Value::eContextTypeClangType,
// clang_void_ptr_type);
void_ptr_value.SetCompilerType(clang_void_ptr_type);
@@ -1048,7 +1048,7 @@
Value isa_value(*(argument_values.GetValueAtIndex(obj_index)));
- isa_value.SetValueType(Value::eValueTypeLoadAddress);
+ isa_value.SetValueType(Value::ValueType::LoadAddress);
isa_value.ResolveValue(&exe_ctx);
if (isa_value.GetScalar().IsValid()) {
isa_addr = isa_value.GetScalar().ULongLong();
@@ -1110,7 +1110,7 @@
CompilerType clang_int_type =
clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(
lldb::eEncodingSint, 32);
- flag_value.SetValueType(Value::eValueTypeScalar);
+ flag_value.SetValueType(Value::ValueType::Scalar);
// flag_value.SetContext (Value::eContextTypeClangType, clang_int_type);
flag_value.SetCompilerType(clang_int_type);
@@ -1157,13 +1157,8 @@
flag_value.GetScalar() = 0; // FIXME - Set to 0 when debugging is done.
dispatch_values.PushValue(flag_value);
- // The step through code might have to fill in the cache, so it
- // is not safe to run only one thread. So we override the
- // stop_others value passed in to us here:
- const bool trampoline_stop_others = false;
ret_plan_sp = std::make_shared<AppleThreadPlanStepThroughObjCTrampoline>(
- thread, *this, dispatch_values, isa_addr, sel_addr,
- trampoline_stop_others);
+ thread, *this, dispatch_values, isa_addr, sel_addr);
if (log) {
StreamString s;
ret_plan_sp->GetDescription(&s, eDescriptionLevelFull);
@@ -1182,13 +1177,9 @@
MsgsendMap::iterator pos;
pos = m_opt_dispatch_map.find(curr_pc);
if (pos != m_opt_dispatch_map.end()) {
-
const char *opt_name = g_opt_dispatch_names[(*pos).second];
-
- bool trampoline_stop_others = false;
- LazyBool step_in_should_stop = eLazyBoolCalculate;
- ret_plan_sp = std::make_shared<AppleThreadPlanStepThroughDirectDispatch> (
- thread, *this, opt_name, trampoline_stop_others, step_in_should_stop);
+ ret_plan_sp = std::make_shared<AppleThreadPlanStepThroughDirectDispatch>(
+ thread, *this, opt_name);
}
}
diff --git a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h
index 27aebd8..546b500 100644
--- a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h
+++ b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h
@@ -76,10 +76,7 @@
class VTableRegion {
public:
- VTableRegion()
- : m_valid(false), m_owner(nullptr),
- m_header_addr(LLDB_INVALID_ADDRESS), m_code_start_addr(0),
- m_code_end_addr(0), m_next_region(0) {}
+ VTableRegion() = default;
VTableRegion(AppleObjCVTables *owner, lldb::addr_t header_addr);
@@ -99,13 +96,13 @@
void Dump(Stream &s);
- bool m_valid;
- AppleObjCVTables *m_owner;
- lldb::addr_t m_header_addr;
- lldb::addr_t m_code_start_addr;
- lldb::addr_t m_code_end_addr;
+ bool m_valid = false;
+ AppleObjCVTables *m_owner = nullptr;
+ lldb::addr_t m_header_addr = LLDB_INVALID_ADDRESS;
+ lldb::addr_t m_code_start_addr = 0;
+ lldb::addr_t m_code_end_addr = 0;
std::vector<VTableDescriptor> m_descriptors;
- lldb::addr_t m_next_region;
+ lldb::addr_t m_next_region = 0;
};
public:
diff --git a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp
index b19d3d9..7b01215 100644
--- a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp
+++ b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp
@@ -59,7 +59,7 @@
// "{CGRect=\"origin\"{CGPoint=\"x\"d\"y\"d}\"size\"{CGSize=\"width\"d\"height\"d}}"
AppleObjCTypeEncodingParser::StructElement::StructElement()
- : name(""), type(clang::QualType()), bitfield(0) {}
+ : name(""), type(clang::QualType()) {}
AppleObjCTypeEncodingParser::StructElement
AppleObjCTypeEncodingParser::ReadStructElement(TypeSystemClang &ast_ctx,
diff --git a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h
index 9a10896..6e533b5 100644
--- a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h
+++ b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h
@@ -29,7 +29,7 @@
struct StructElement {
std::string name;
clang::QualType type;
- uint32_t bitfield;
+ uint32_t bitfield = 0;
StructElement();
~StructElement() = default;
diff --git a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
index 653e007..1dc8034 100644
--- a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
+++ b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
@@ -30,19 +30,17 @@
AppleThreadPlanStepThroughObjCTrampoline::
AppleThreadPlanStepThroughObjCTrampoline(
Thread &thread, AppleObjCTrampolineHandler &trampoline_handler,
- ValueList &input_values, lldb::addr_t isa_addr, lldb::addr_t sel_addr,
- bool stop_others)
+ ValueList &input_values, lldb::addr_t isa_addr, lldb::addr_t sel_addr)
: ThreadPlan(ThreadPlan::eKindGeneric,
"MacOSX Step through ObjC Trampoline", thread, eVoteNoOpinion,
eVoteNoOpinion),
m_trampoline_handler(trampoline_handler),
m_args_addr(LLDB_INVALID_ADDRESS), m_input_values(input_values),
- m_isa_addr(isa_addr), m_sel_addr(sel_addr), m_impl_function(nullptr),
- m_stop_others(stop_others) {}
+ m_isa_addr(isa_addr), m_sel_addr(sel_addr), m_impl_function(nullptr) {}
// Destructor
AppleThreadPlanStepThroughObjCTrampoline::
- ~AppleThreadPlanStepThroughObjCTrampoline() {}
+ ~AppleThreadPlanStepThroughObjCTrampoline() = default;
void AppleThreadPlanStepThroughObjCTrampoline::DidPush() {
// Setting up the memory space for the called function text might require
@@ -66,7 +64,7 @@
EvaluateExpressionOptions options;
options.SetUnwindOnError(true);
options.SetIgnoreBreakpoints(true);
- options.SetStopOthers(m_stop_others);
+ options.SetStopOthers(false);
GetThread().CalculateExecutionContext(exc_ctx);
m_func_sp = m_impl_function->GetThreadPlanToCallFunction(
exc_ctx, m_args_addr, options, diagnostics);
@@ -157,7 +155,7 @@
const bool first_insn = true;
const uint32_t frame_idx = 0;
m_run_to_sp = GetThread().QueueThreadPlanForStepOutNoShouldStop(
- abort_other_plans, &sc, first_insn, m_stop_others, eVoteNoOpinion,
+ abort_other_plans, &sc, first_insn, false, eVoteNoOpinion,
eVoteNoOpinion, frame_idx, status);
if (m_run_to_sp && status.Success())
m_run_to_sp->SetPrivate(true);
@@ -179,7 +177,7 @@
// Extract the target address from the value:
m_run_to_sp = std::make_shared<ThreadPlanRunToAddress>(
- GetThread(), target_so_addr, m_stop_others);
+ GetThread(), target_so_addr, false);
PushPlan(m_run_to_sp);
return false;
} else if (GetThread().IsThreadPlanDone(m_run_to_sp.get())) {
@@ -222,10 +220,9 @@
AppleThreadPlanStepThroughDirectDispatch ::
AppleThreadPlanStepThroughDirectDispatch(
Thread &thread, AppleObjCTrampolineHandler &handler,
- llvm::StringRef dispatch_func_name, bool stop_others,
- LazyBool step_in_avoids_code_without_debug_info)
- : ThreadPlanStepOut(thread, nullptr, true /* first instruction */,
- stop_others, eVoteNoOpinion, eVoteNoOpinion,
+ llvm::StringRef dispatch_func_name)
+ : ThreadPlanStepOut(thread, nullptr, true /* first instruction */, false,
+ eVoteNoOpinion, eVoteNoOpinion,
0 /* Step out of zeroth frame */,
eLazyBoolNo /* Our parent plan will decide this
when we are done */
@@ -234,7 +231,7 @@
false /* Don't gather the return value */),
m_trampoline_handler(handler),
m_dispatch_func_name(std::string(dispatch_func_name)),
- m_at_msg_send(false), m_stop_others(stop_others) {
+ m_at_msg_send(false) {
// Set breakpoints on the dispatch functions:
auto bkpt_callback = [&] (lldb::addr_t addr,
const AppleObjCTrampolineHandler
@@ -249,20 +246,7 @@
// We'll set the step-out plan in the DidPush so it gets queued in the right
// order.
- bool avoid_nodebug = true;
-
- switch (step_in_avoids_code_without_debug_info) {
- case eLazyBoolYes:
- avoid_nodebug = true;
- break;
- case eLazyBoolNo:
- avoid_nodebug = false;
- break;
- case eLazyBoolCalculate:
- avoid_nodebug = GetThread().GetStepInAvoidsNoDebug();
- break;
- }
- if (avoid_nodebug)
+ if (GetThread().GetStepInAvoidsNoDebug())
GetFlags().Set(ThreadPlanShouldStopHere::eStepInAvoidNoDebug);
else
GetFlags().Clear(ThreadPlanShouldStopHere::eStepInAvoidNoDebug);
@@ -398,8 +382,8 @@
// There's no way we could have gotten here without an ObjC language
// runtime.
assert(objc_runtime);
- m_objc_step_through_sp
- = objc_runtime->GetStepThroughTrampolinePlan(GetThread(), m_stop_others);
+ m_objc_step_through_sp =
+ objc_runtime->GetStepThroughTrampolinePlan(GetThread(), false);
// If we failed to find the target for this dispatch, just keep going and
// let the step out complete.
if (!m_objc_step_through_sp) {
diff --git a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h
index 89aed89..b5b4507 100644
--- a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h
+++ b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h
@@ -24,8 +24,7 @@
public:
AppleThreadPlanStepThroughObjCTrampoline(
Thread &thread, AppleObjCTrampolineHandler &trampoline_handler,
- ValueList &values, lldb::addr_t isa_addr, lldb::addr_t sel_addr,
- bool stop_others);
+ ValueList &values, lldb::addr_t isa_addr, lldb::addr_t sel_addr);
~AppleThreadPlanStepThroughObjCTrampoline() override;
@@ -39,7 +38,9 @@
bool ShouldStop(Event *event_ptr) override;
- bool StopOthers() override { return m_stop_others; }
+ // The step through code might have to fill in the cache, so it is not safe
+ // to run only one thread.
+ bool StopOthers() override { return false; }
// The base class MischiefManaged does some cleanup - so you have to call it
// in your MischiefManaged derived class.
@@ -69,15 +70,13 @@
FunctionCaller *m_impl_function; /// This is a pointer to a impl function that
/// is owned by the client that pushes this
/// plan.
- bool m_stop_others; /// Whether we should stop other threads.
};
class AppleThreadPlanStepThroughDirectDispatch: public ThreadPlanStepOut {
public:
- AppleThreadPlanStepThroughDirectDispatch(
- Thread &thread, AppleObjCTrampolineHandler &handler,
- llvm::StringRef dispatch_func_name, bool stop_others,
- LazyBool step_in_avoids_code_without_debug_info);
+ AppleThreadPlanStepThroughDirectDispatch(Thread &thread,
+ AppleObjCTrampolineHandler &handler,
+ llvm::StringRef dispatch_func_name);
~AppleThreadPlanStepThroughDirectDispatch() override;
@@ -85,7 +84,7 @@
bool ShouldStop(Event *event_ptr) override;
- bool StopOthers() override { return m_stop_others; }
+ bool StopOthers() override { return false; }
bool MischiefManaged() override;
@@ -107,7 +106,6 @@
std::vector<lldb::BreakpointSP> m_msgSend_bkpts; /// Breakpoints on the objc
/// dispatch functions.
bool m_at_msg_send; /// Are we currently handling an msg_send
- bool m_stop_others; /// Whether we should stop other threads.
};
diff --git a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp
index 2ccf9b3..65bf3e6 100644
--- a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp
+++ b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp
@@ -32,7 +32,7 @@
char ObjCLanguageRuntime::ID = 0;
// Destructor
-ObjCLanguageRuntime::~ObjCLanguageRuntime() {}
+ObjCLanguageRuntime::~ObjCLanguageRuntime() = default;
ObjCLanguageRuntime::ObjCLanguageRuntime(Process *process)
: LanguageRuntime(process), m_impl_cache(),
@@ -305,7 +305,7 @@
return CompilerType();
}
-ObjCLanguageRuntime::EncodingToType::~EncodingToType() {}
+ObjCLanguageRuntime::EncodingToType::~EncodingToType() = default;
ObjCLanguageRuntime::EncodingToTypeSP ObjCLanguageRuntime::GetEncodingToType() {
return nullptr;
@@ -363,7 +363,8 @@
m_class_names.insert(class_name);
}
-ObjCLanguageRuntime::ObjCExceptionPrecondition::ObjCExceptionPrecondition() {}
+ObjCLanguageRuntime::ObjCExceptionPrecondition::ObjCExceptionPrecondition() =
+ default;
bool ObjCLanguageRuntime::ObjCExceptionPrecondition::EvaluatePrecondition(
StoppointCallbackContext &context) {
diff --git a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h
index 683eff7..15fce04 100644
--- a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h
+++ b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h
@@ -49,9 +49,7 @@
// implementations of the runtime, and more might come
class ClassDescriptor {
public:
- ClassDescriptor()
- : m_is_kvo(eLazyBoolCalculate), m_is_cf(eLazyBoolCalculate),
- m_type_wp() {}
+ ClassDescriptor() : m_type_wp() {}
virtual ~ClassDescriptor() = default;
@@ -87,10 +85,20 @@
virtual bool IsValid() = 0;
+ /// There are two routines in the ObjC runtime that tagged pointer clients
+ /// can call to get the value from their tagged pointer, one that retrieves
+ /// it as an unsigned value and one a signed value. These two
+ /// GetTaggedPointerInfo methods mirror those two ObjC runtime calls.
+ /// @{
virtual bool GetTaggedPointerInfo(uint64_t *info_bits = nullptr,
uint64_t *value_bits = nullptr,
uint64_t *payload = nullptr) = 0;
+ virtual bool GetTaggedPointerInfoSigned(uint64_t *info_bits = nullptr,
+ int64_t *value_bits = nullptr,
+ uint64_t *payload = nullptr) = 0;
+ /// @}
+
virtual uint64_t GetInstanceSize() = 0;
// use to implement version-specific additional constraints on pointers
@@ -135,8 +143,8 @@
bool check_version_specific = false) const;
private:
- LazyBool m_is_kvo;
- LazyBool m_is_cf;
+ LazyBool m_is_kvo = eLazyBoolCalculate;
+ LazyBool m_is_cf = eLazyBoolCalculate;
lldb::TypeWP m_type_wp;
};
diff --git a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp
index 6858c71..08a752e 100644
--- a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp
+++ b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp
@@ -185,7 +185,7 @@
EarlyPasses->add(new RenderScriptRuntimeModulePass(process));
}
-RSIRPasses::~RSIRPasses() {}
+RSIRPasses::~RSIRPasses() = default;
} // namespace lldb_renderscript
} // namespace lldb_private
diff --git a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
index dd93122..10ff5aa 100644
--- a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
+++ b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
@@ -61,7 +61,7 @@
template <typename type_t> class empirical_type {
public:
// Ctor. Contents is invalid when constructed.
- empirical_type() : valid(false) {}
+ empirical_type() = default;
// Return true and copy contents to out if valid, else return false.
bool get(type_t &out) const {
@@ -99,7 +99,7 @@
}
protected:
- bool valid;
+ bool valid = false;
type_t data;
};
@@ -2228,7 +2228,7 @@
return JITAllocationSize(alloc, frame_ptr);
}
-// Function attempts to set the type_name member of the paramaterised Element
+// Function attempts to set the type_name member of the parameterised Element
// object. This string should be the name of the struct type the Element
// represents. We need this string for pretty printing the Element to users.
void RenderScriptRuntime::FindStructTypeName(Element &elem,
@@ -4087,9 +4087,7 @@
class CommandOptions : public Options {
public:
- CommandOptions()
- : Options(),
- m_kernel_types(RSReduceBreakpointResolver::eKernelTypeAll) {}
+ CommandOptions() : Options() {}
~CommandOptions() override = default;
@@ -4175,7 +4173,7 @@
return true;
}
- int m_kernel_types;
+ int m_kernel_types = RSReduceBreakpointResolver::eKernelTypeAll;
llvm::StringRef m_reduce_name;
RSCoordinate m_coord;
bool m_have_coord;
@@ -4189,7 +4187,6 @@
result.AppendErrorWithFormat("'%s' takes 1 argument of reduction name, "
"and an optional kernel type list",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -4203,7 +4200,6 @@
auto coord = m_options.m_have_coord ? &m_options.m_coord : nullptr;
if (!runtime->PlaceBreakpointOnReduction(target, outstream, name, coord,
m_options.m_kernel_types)) {
- result.SetStatus(eReturnStatusFailed);
result.AppendError("Error: unable to place breakpoint on reduction");
return false;
}
@@ -4291,7 +4287,6 @@
result.AppendErrorWithFormat(
"'%s' takes 1 argument of kernel name, and an optional coordinate.",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -4304,7 +4299,6 @@
auto name = command.GetArgumentAtIndex(0);
auto coord = m_options.m_have_coord ? &m_options.m_coord : nullptr;
if (!runtime->PlaceBreakpointOnKernel(target, outstream, name, coord)) {
- result.SetStatus(eReturnStatusFailed);
result.AppendErrorWithFormat(
"Error: unable to set breakpoint on kernel '%s'", name);
return false;
@@ -4342,7 +4336,6 @@
if (argc != 1) {
result.AppendErrorWithFormat(
"'%s' takes 1 argument of 'enable' or 'disable'", m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -4361,7 +4354,6 @@
} else {
result.AppendErrorWithFormat(
"Argument must be either 'enable' or 'disable'");
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -4568,7 +4560,6 @@
result.AppendErrorWithFormat("'%s' takes 1 argument, an allocation ID. "
"As well as an optional -f argument",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -4583,7 +4574,6 @@
if (!success) {
result.AppendErrorWithFormat("invalid allocation id argument '%s'",
id_cstr);
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -4608,7 +4598,6 @@
std::string error = llvm::toString(file.takeError());
result.AppendErrorWithFormat("Couldn't open file '%s': %s",
path.c_str(), error.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
} else
@@ -4653,7 +4642,7 @@
class CommandOptions : public Options {
public:
- CommandOptions() : Options(), m_id(0) {}
+ CommandOptions() : Options() {}
~CommandOptions() override = default;
@@ -4681,7 +4670,7 @@
return llvm::makeArrayRef(g_renderscript_runtime_alloc_list_options);
}
- uint32_t m_id;
+ uint32_t m_id = 0;
};
bool DoExecute(Args &command, CommandReturnObject &result) override {
@@ -4717,7 +4706,6 @@
result.AppendErrorWithFormat(
"'%s' takes 2 arguments, an allocation ID and filename to read from.",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -4732,7 +4720,6 @@
if (!success) {
result.AppendErrorWithFormat("invalid allocation id argument '%s'",
id_cstr);
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -4768,7 +4755,6 @@
result.AppendErrorWithFormat(
"'%s' takes 2 arguments, an allocation ID and filename to read from.",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -4783,7 +4769,6 @@
if (!success) {
result.AppendErrorWithFormat("invalid allocation id argument '%s'",
id_cstr);
- result.SetStatus(eReturnStatusFailed);
return false;
}
diff --git a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h
index 5e37265..2785c3b 100644
--- a/src/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h
+++ b/src/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h
@@ -44,9 +44,9 @@
typedef std::shared_ptr<RSScriptGroupDescriptor> RSScriptGroupDescriptorSP;
struct RSCoordinate {
- uint32_t x, y, z;
+ uint32_t x = 0, y = 0, z = 0;
- RSCoordinate() : x(), y(), z(){};
+ RSCoordinate() = default;
bool operator==(const lldb_renderscript::RSCoordinate &rhs) {
return x == rhs.x && y == rhs.y && z == rhs.z;
diff --git a/src/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp b/src/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
index 211eb9c..7ff9175 100644
--- a/src/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
@@ -42,9 +42,7 @@
LLDB_PLUGIN_DEFINE(ObjectContainerBSDArchive)
-ObjectContainerBSDArchive::Object::Object()
- : ar_name(), modification_time(0), uid(0), gid(0), mode(0), size(0),
- file_offset(0), file_size(0) {}
+ObjectContainerBSDArchive::Object::Object() : ar_name() {}
void ObjectContainerBSDArchive::Object::Clear() {
ar_name.Clear();
@@ -142,7 +140,7 @@
: m_arch(arch), m_modification_time(time), m_file_offset(file_offset),
m_objects(), m_data(data) {}
-ObjectContainerBSDArchive::Archive::~Archive() {}
+ObjectContainerBSDArchive::Archive::~Archive() = default;
size_t ObjectContainerBSDArchive::Archive::ParseObjects() {
DataExtractor &data = m_data;
@@ -375,7 +373,7 @@
m_archive_sp = archive_sp;
}
-ObjectContainerBSDArchive::~ObjectContainerBSDArchive() {}
+ObjectContainerBSDArchive::~ObjectContainerBSDArchive() = default;
bool ObjectContainerBSDArchive::ParseHeader() {
if (m_archive_sp.get() == nullptr) {
diff --git a/src/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h b/src/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h
index f6862af..9830e9b 100644
--- a/src/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h
+++ b/src/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h
@@ -84,25 +84,25 @@
lldb_private::ConstString ar_name;
/// Object modification time in the archive.
- uint32_t modification_time;
+ uint32_t modification_time = 0;
/// Object user id in the archive.
- uint16_t uid;
+ uint16_t uid = 0;
/// Object group id in the archive.
- uint16_t gid;
+ uint16_t gid = 0;
/// Object octal file permissions in the archive.
- uint16_t mode;
+ uint16_t mode = 0;
/// Object size in bytes in the archive.
- uint32_t size;
+ uint32_t size = 0;
/// File offset in bytes from the beginning of the file of the object data.
- lldb::offset_t file_offset;
+ lldb::offset_t file_offset = 0;
/// Length of the object data.
- lldb::offset_t file_size;
+ lldb::offset_t file_size = 0;
};
class Archive {
diff --git a/src/llvm-project/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp b/src/llvm-project/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp
index bb56379..d0a493d 100644
--- a/src/llvm-project/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp
@@ -79,7 +79,7 @@
memset(&m_header, 0, sizeof(m_header));
}
-ObjectContainerUniversalMachO::~ObjectContainerUniversalMachO() {}
+ObjectContainerUniversalMachO::~ObjectContainerUniversalMachO() = default;
bool ObjectContainerUniversalMachO::ParseHeader() {
bool success = ParseHeader(m_data, m_header, m_fat_archs);
diff --git a/src/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/src/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index cad9ce2..a5e86f0 100644
--- a/src/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -16,6 +16,7 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Progress.h"
#include "lldb/Core/Section.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/LZMA.h"
@@ -37,6 +38,7 @@
#include "llvm/Object/Decompressor.h"
#include "llvm/Support/ARMBuildAttributes.h"
#include "llvm/Support/CRC.h"
+#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/MipsABIFlags.h"
@@ -857,8 +859,7 @@
if (symbol.d_tag == DT_MIPS_RLD_MAP) {
// DT_MIPS_RLD_MAP tag stores an absolute address of the debug pointer.
Address addr;
- if (target->ReadPointerFromMemory(dyn_base + offset, false, error,
- addr))
+ if (target->ReadPointerFromMemory(dyn_base + offset, error, addr, true))
return addr;
}
if (symbol.d_tag == DT_MIPS_RLD_MAP_REL) {
@@ -866,7 +867,7 @@
// relative to the address of the tag.
uint64_t rel_offset;
rel_offset = target->ReadUnsignedIntegerFromMemory(
- dyn_base + offset, false, GetAddressByteSize(), UINT64_MAX, error);
+ dyn_base + offset, GetAddressByteSize(), UINT64_MAX, error, true);
if (error.Success() && rel_offset != UINT64_MAX) {
Address addr;
addr_t debug_ptr_address =
@@ -1861,7 +1862,7 @@
// unified section list.
if (GetType() != eTypeDebugInfo)
unified_section_list = *m_sections_up;
-
+
// If there's a .gnu_debugdata section, we'll try to read the .symtab that's
// embedded in there and replace the one in the original object file (if any).
// If there's none in the orignal object file, we add it to it.
@@ -1879,7 +1880,7 @@
unified_section_list.AddSection(symtab_section_sp);
}
}
- }
+ }
}
std::shared_ptr<ObjectFileELF> ObjectFileELF::GetGnuDebugDataObjectFile() {
@@ -1923,7 +1924,7 @@
ArchSpec spec = m_gnu_debug_data_object_file->GetArchitecture();
if (spec && m_gnu_debug_data_object_file->SetModulesArchitecture(spec))
return m_gnu_debug_data_object_file;
-
+
return nullptr;
}
@@ -2707,6 +2708,9 @@
if (!module_sp)
return nullptr;
+ Progress progress(llvm::formatv("Parsing symbol table for {0}",
+ m_file.GetFilename().AsCString("<Unknown>")));
+
// We always want to use the main object file so we (hopefully) only have one
// cached copy of our symtab, dynamic sections, etc.
ObjectFile *module_obj_file = module_sp->GetObjectFile();
@@ -2770,14 +2774,14 @@
user_id_t reloc_id = reloc_section->GetID();
const ELFSectionHeaderInfo *reloc_header =
GetSectionHeaderByIndex(reloc_id);
- assert(reloc_header);
+ if (reloc_header) {
+ if (m_symtab_up == nullptr)
+ m_symtab_up =
+ std::make_unique<Symtab>(reloc_section->GetObjectFile());
- if (m_symtab_up == nullptr)
- m_symtab_up =
- std::make_unique<Symtab>(reloc_section->GetObjectFile());
-
- ParseTrampolineSymbols(m_symtab_up.get(), symbol_id, reloc_header,
- reloc_id);
+ ParseTrampolineSymbols(m_symtab_up.get(), symbol_id, reloc_header,
+ reloc_id);
+ }
}
}
@@ -2809,31 +2813,37 @@
if (is_valid_entry_point && !m_symtab_up->FindSymbolContainingFileAddress(
entry_point_file_addr)) {
uint64_t symbol_id = m_symtab_up->GetNumSymbols();
- Symbol symbol(symbol_id,
- GetNextSyntheticSymbolName().GetCString(), // Symbol name.
- eSymbolTypeCode, // Type of this symbol.
- true, // Is this globally visible?
- false, // Is this symbol debug info?
- false, // Is this symbol a trampoline?
- true, // Is this symbol artificial?
- entry_point_addr.GetSection(), // Section where this
- // symbol is defined.
- 0, // Offset in section or symbol value.
- 0, // Size.
- false, // Size is valid.
- false, // Contains linker annotations?
- 0); // Symbol flags.
- m_symtab_up->AddSymbol(symbol);
+ // Don't set the name for any synthetic symbols, the Symbol
+ // object will generate one if needed when the name is accessed
+ // via accessors.
+ SectionSP section_sp = entry_point_addr.GetSection();
+ Symbol symbol(
+ /*symID=*/symbol_id,
+ /*name=*/llvm::StringRef(), // Name will be auto generated.
+ /*type=*/eSymbolTypeCode,
+ /*external=*/true,
+ /*is_debug=*/false,
+ /*is_trampoline=*/false,
+ /*is_artificial=*/true,
+ /*section_sp=*/section_sp,
+ /*offset=*/0,
+ /*size=*/0, // FDE can span multiple symbols so don't use its size.
+ /*size_is_valid=*/false,
+ /*contains_linker_annotations=*/false,
+ /*flags=*/0);
// When the entry point is arm thumb we need to explicitly set its
// class address to reflect that. This is important because expression
// evaluation relies on correctly setting a breakpoint at this
// address.
if (arch.GetMachine() == llvm::Triple::arm &&
- (entry_point_file_addr & 1))
+ (entry_point_file_addr & 1)) {
+ symbol.GetAddressRef().SetOffset(entry_point_addr.GetOffset() ^ 1);
m_address_class_map[entry_point_file_addr ^ 1] =
AddressClass::eCodeAlternateISA;
- else
+ } else {
m_address_class_map[entry_point_file_addr] = AddressClass::eCode;
+ }
+ m_symtab_up->AddSymbol(symbol);
}
}
@@ -2897,8 +2907,11 @@
// recalculate the index first.
std::vector<Symbol> new_symbols;
- eh_frame->ForEachFDEEntries([this, symbol_table, section_list, &new_symbols](
- lldb::addr_t file_addr, uint32_t size, dw_offset_t) {
+ size_t num_symbols = symbol_table->GetNumSymbols();
+ uint64_t last_symbol_id =
+ num_symbols ? symbol_table->SymbolAtIndex(num_symbols - 1)->GetID() : 0;
+ eh_frame->ForEachFDEEntries([&](lldb::addr_t file_addr, uint32_t size,
+ dw_offset_t) {
Symbol *symbol = symbol_table->FindSymbolAtFileAddress(file_addr);
if (symbol) {
if (!symbol->GetByteSizeIsValid()) {
@@ -2910,22 +2923,24 @@
section_list->FindSectionContainingFileAddress(file_addr);
if (section_sp) {
addr_t offset = file_addr - section_sp->GetFileAddress();
- const char *symbol_name = GetNextSyntheticSymbolName().GetCString();
- uint64_t symbol_id = symbol_table->GetNumSymbols();
+ uint64_t symbol_id = ++last_symbol_id;
+ // Don't set the name for any synthetic symbols, the Symbol
+ // object will generate one if needed when the name is accessed
+ // via accessors.
Symbol eh_symbol(
- symbol_id, // Symbol table index.
- symbol_name, // Symbol name.
- eSymbolTypeCode, // Type of this symbol.
- true, // Is this globally visible?
- false, // Is this symbol debug info?
- false, // Is this symbol a trampoline?
- true, // Is this symbol artificial?
- section_sp, // Section in which this symbol is defined or null.
- offset, // Offset in section or symbol value.
- 0, // Size: Don't specify the size as an FDE can
- false, // Size is valid: cover multiple symbols.
- false, // Contains linker annotations?
- 0); // Symbol flags.
+ /*symID=*/symbol_id,
+ /*name=*/llvm::StringRef(), // Name will be auto generated.
+ /*type=*/eSymbolTypeCode,
+ /*external=*/true,
+ /*is_debug=*/false,
+ /*is_trampoline=*/false,
+ /*is_artificial=*/true,
+ /*section_sp=*/section_sp,
+ /*offset=*/offset,
+ /*size=*/0, // FDE can span multiple symbols so don't use its size.
+ /*size_is_valid=*/false,
+ /*contains_linker_annotations=*/false,
+ /*flags=*/0);
new_symbols.push_back(eh_symbol);
}
}
diff --git a/src/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/src/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
index 062271f..e678c2f 100644
--- a/src/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/src/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -9,7 +9,7 @@
#ifndef LLDB_SOURCE_PLUGINS_OBJECTFILE_ELF_OBJECTFILEELF_H
#define LLDB_SOURCE_PLUGINS_OBJECTFILE_ELF_OBJECTFILEELF_H
-#include <stdint.h>
+#include <cstdint>
#include <vector>
@@ -22,13 +22,13 @@
#include "ELFHeader.h"
struct ELFNote {
- elf::elf_word n_namesz;
- elf::elf_word n_descsz;
- elf::elf_word n_type;
+ elf::elf_word n_namesz = 0;
+ elf::elf_word n_descsz = 0;
+ elf::elf_word n_type = 0;
std::string n_name;
- ELFNote() : n_namesz(0), n_descsz(0), n_type(0) {}
+ ELFNote() = default;
/// Parse an ELFNote entry from the given DataExtractor starting at position
/// \p offset.
diff --git a/src/llvm-project/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp b/src/llvm-project/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
index 93c2c9f..f93ac92 100644
--- a/src/llvm-project/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
@@ -100,7 +100,7 @@
}
}
-ObjectFileJIT::~ObjectFileJIT() {}
+ObjectFileJIT::~ObjectFileJIT() = default;
bool ObjectFileJIT::ParseHeader() {
// JIT code is never in a file, nor is it required to have any header
diff --git a/src/llvm-project/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/src/llvm-project/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
index 463a2a5..fd1a23d 100644
--- a/src/llvm-project/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -17,10 +17,13 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Progress.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Host/Host.h"
+#include "lldb/Host/SafeMachO.h"
#include "lldb/Symbol/DWARFCallFrameInfo.h"
+#include "lldb/Symbol/LocateSymbolFile.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/MemoryRegionInfo.h"
@@ -41,8 +44,8 @@
#include "lldb/Utility/Timer.h"
#include "lldb/Utility/UUID.h"
-#include "lldb/Host/SafeMachO.h"
-
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "ObjectFileMachO.h"
@@ -59,8 +62,54 @@
#include <uuid/uuid.h>
#endif
+#include <bitset>
#include <memory>
+#if LLVM_SUPPORT_XCODE_SIGNPOSTS
+// Unfortunately the signpost header pulls in the system MachO header, too.
+#undef CPU_TYPE_ARM
+#undef CPU_TYPE_ARM64
+#undef CPU_TYPE_ARM64_32
+#undef CPU_TYPE_I386
+#undef CPU_TYPE_X86_64
+#undef MH_BINDATLOAD
+#undef MH_BUNDLE
+#undef MH_CIGAM
+#undef MH_CIGAM_64
+#undef MH_CORE
+#undef MH_DSYM
+#undef MH_DYLDLINK
+#undef MH_DYLIB
+#undef MH_DYLIB_STUB
+#undef MH_DYLINKER
+#undef MH_DYLINKER
+#undef MH_EXECUTE
+#undef MH_FVMLIB
+#undef MH_INCRLINK
+#undef MH_KEXT_BUNDLE
+#undef MH_MAGIC
+#undef MH_MAGIC_64
+#undef MH_NOUNDEFS
+#undef MH_OBJECT
+#undef MH_OBJECT
+#undef MH_PRELOAD
+
+#undef LC_BUILD_VERSION
+#undef LC_VERSION_MIN_MACOSX
+#undef LC_VERSION_MIN_IPHONEOS
+#undef LC_VERSION_MIN_TVOS
+#undef LC_VERSION_MIN_WATCHOS
+
+#undef PLATFORM_MACOS
+#undef PLATFORM_MACCATALYST
+#undef PLATFORM_IOS
+#undef PLATFORM_IOSSIMULATOR
+#undef PLATFORM_TVOS
+#undef PLATFORM_TVOSSIMULATOR
+#undef PLATFORM_WATCHOS
+#undef PLATFORM_WATCHOSSIMULATOR
+#endif
+
#define THUMB_ADDRESS_BIT_MASK 0xfffffffffffffffeull
using namespace lldb;
using namespace lldb_private;
@@ -738,11 +787,11 @@
switch (magic) {
case MH_MAGIC:
case MH_CIGAM:
- return sizeof(struct mach_header);
+ return sizeof(struct llvm::MachO::mach_header);
case MH_MAGIC_64:
case MH_CIGAM_64:
- return sizeof(struct mach_header_64);
+ return sizeof(struct llvm::MachO::mach_header_64);
break;
default:
@@ -1061,7 +1110,7 @@
// None found.
return false;
} else {
- memset(&m_header, 0, sizeof(struct mach_header));
+ memset(&m_header, 0, sizeof(struct llvm::MachO::mach_header));
}
return false;
}
@@ -1271,7 +1320,7 @@
for (uint32_t i = 0; i < m_header.ncmds; ++i) {
const lldb::offset_t load_cmd_offset = offset;
- load_command lc;
+ llvm::MachO::load_command lc;
if (m_data.GetU32(&offset, &lc.cmd, 2) == nullptr)
break;
if (lc.cmd == LC_DYSYMTAB) {
@@ -1298,7 +1347,7 @@
EncryptedFileRanges result;
lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
- encryption_info_command encryption_cmd;
+ llvm::MachO::encryption_info_command encryption_cmd;
for (uint32_t i = 0; i < m_header.ncmds; ++i) {
const lldb::offset_t load_cmd_offset = offset;
if (m_data.GetU32(&offset, &encryption_cmd, 2) == nullptr)
@@ -1323,14 +1372,14 @@
return result;
}
-void ObjectFileMachO::SanitizeSegmentCommand(segment_command_64 &seg_cmd,
- uint32_t cmd_idx) {
+void ObjectFileMachO::SanitizeSegmentCommand(
+ llvm::MachO::segment_command_64 &seg_cmd, uint32_t cmd_idx) {
if (m_length == 0 || seg_cmd.filesize == 0)
return;
if ((m_header.flags & MH_DYLIB_IN_CACHE) && !IsInMemory()) {
// In shared cache images, the load commands are relative to the
- // shared cache file, and not the the specific image we are
+ // shared cache file, and not the specific image we are
// examining. Let's fix this up so that it looks like a normal
// image.
if (strncmp(seg_cmd.segname, "__TEXT", sizeof(seg_cmd.segname)) == 0)
@@ -1380,7 +1429,8 @@
}
}
-static uint32_t GetSegmentPermissions(const segment_command_64 &seg_cmd) {
+static uint32_t
+GetSegmentPermissions(const llvm::MachO::segment_command_64 &seg_cmd) {
uint32_t result = 0;
if (seg_cmd.initprot & VM_PROT_READ)
result |= ePermissionsReadable;
@@ -1548,11 +1598,10 @@
: EncryptedRanges(std::move(EncryptedRanges)), UnifiedList(UnifiedList) {}
};
-void ObjectFileMachO::ProcessSegmentCommand(const load_command &load_cmd_,
- lldb::offset_t offset,
- uint32_t cmd_idx,
- SegmentParsingContext &context) {
- segment_command_64 load_cmd;
+void ObjectFileMachO::ProcessSegmentCommand(
+ const llvm::MachO::load_command &load_cmd_, lldb::offset_t offset,
+ uint32_t cmd_idx, SegmentParsingContext &context) {
+ llvm::MachO::segment_command_64 load_cmd;
memcpy(&load_cmd, &load_cmd_, sizeof(load_cmd_));
if (!m_data.GetU8(&offset, (uint8_t *)load_cmd.segname, 16))
@@ -1653,7 +1702,7 @@
m_sections_up->AddSection(unified_section_sp);
}
- struct section_64 sect64;
+ llvm::MachO::section_64 sect64;
::memset(§64, 0, sizeof(sect64));
// Push a section into our mach sections for the section at index zero
// (NO_SECT) if we don't have any mach sections yet...
@@ -1825,8 +1874,8 @@
}
}
-void ObjectFileMachO::ProcessDysymtabCommand(const load_command &load_cmd,
- lldb::offset_t offset) {
+void ObjectFileMachO::ProcessDysymtabCommand(
+ const llvm::MachO::load_command &load_cmd, lldb::offset_t offset) {
m_dysymtab.cmd = load_cmd.cmd;
m_dysymtab.cmdsize = load_cmd.cmdsize;
m_data.GetU32(&offset, &m_dysymtab.ilocalsym,
@@ -1846,7 +1895,7 @@
offset = MachHeaderSizeFromMagic(m_header.magic);
SegmentParsingContext context(GetEncryptedFileRanges(), unified_section_list);
- struct load_command load_cmd;
+ llvm::MachO::load_command load_cmd;
for (uint32_t i = 0; i < m_header.ncmds; ++i) {
const lldb::offset_t load_cmd_offset = offset;
if (m_data.GetU32(&offset, &load_cmd, 2) == nullptr)
@@ -1893,9 +1942,9 @@
filename = first_section_sp->GetObjectFile()->GetFileSpec().GetPath();
Host::SystemLog(Host::eSystemLogError,
- "error: unable to find section %d for a symbol in %s, corrupt file?\n",
- n_sect,
- filename.c_str());
+ "error: unable to find section %d for a symbol in "
+ "%s, corrupt file?\n",
+ n_sect, filename.c_str());
}
}
if (m_section_infos[n_sect].vm_range.Contains(file_addr)) {
@@ -2167,9 +2216,12 @@
if (!module_sp)
return 0;
- struct symtab_command symtab_load_command = {0, 0, 0, 0, 0, 0};
- struct linkedit_data_command function_starts_load_command = {0, 0, 0, 0};
- struct dyld_info_command dyld_info = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ Progress progress(llvm::formatv("Parsing symbol table for {0}",
+ m_file.GetFilename().AsCString("<Unknown>")));
+
+ llvm::MachO::symtab_command symtab_load_command = {0, 0, 0, 0, 0, 0};
+ llvm::MachO::linkedit_data_command function_starts_load_command = {0, 0, 0, 0};
+ llvm::MachO::dyld_info_command dyld_info = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
// The data element of type bool indicates that this entry is thumb
// code.
typedef AddressDataArray<lldb::addr_t, bool, 100> FunctionStarts;
@@ -2178,7 +2230,16 @@
// We add symbols to the table in the order of most information (nlist
// records) to least (function starts), and avoid duplicating symbols
// via this set.
- std::set<addr_t> symbols_added;
+ llvm::DenseSet<addr_t> symbols_added;
+
+ // We are using a llvm::DenseSet for "symbols_added" so we must be sure we
+ // do not add the tombstone or empty keys to the set.
+ auto add_symbol_addr = [&symbols_added](lldb::addr_t file_addr) {
+ // Don't add the tombstone or empty keys.
+ if (file_addr == UINT64_MAX || file_addr == UINT64_MAX - 1)
+ return;
+ symbols_added.insert(file_addr);
+ };
FunctionStarts function_starts;
lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
uint32_t i;
@@ -2191,7 +2252,7 @@
for (i = 0; i < m_header.ncmds; ++i) {
const lldb::offset_t cmd_offset = offset;
// Read in the load command and load command size
- struct load_command lc;
+ llvm::MachO::load_command lc;
if (m_data.GetU32(&offset, &lc, 2) == nullptr)
break;
// Watch for the symbol table load command
@@ -2578,7 +2639,7 @@
typedef std::set<ConstString> IndirectSymbols;
IndirectSymbols indirect_symbol_names;
-#if defined(__APPLE__) && TARGET_OS_EMBEDDED
+#if TARGET_OS_IPHONE
// Some recent builds of the dyld_shared_cache (hereafter: DSC) have been
// optimized by moving LOCAL symbols out of the memory mapped portion of
@@ -3635,9 +3696,9 @@
symbol_section);
sym[GSYM_sym_idx].GetAddressRef().SetOffset(
symbol_value);
- symbols_added.insert(sym[GSYM_sym_idx]
- .GetAddress()
- .GetFileAddress());
+ add_symbol_addr(sym[GSYM_sym_idx]
+ .GetAddress()
+ .GetFileAddress());
// We just need the flags from the linker
// symbol, so put these flags
// into the N_GSYM flags to avoid duplicate
@@ -3657,7 +3718,7 @@
if (set_value) {
sym[sym_idx].GetAddressRef().SetSection(symbol_section);
sym[sym_idx].GetAddressRef().SetOffset(symbol_value);
- symbols_added.insert(
+ add_symbol_addr(
sym[sym_idx].GetAddress().GetFileAddress());
}
sym[sym_idx].SetFlags(nlist.n_type << 16 | nlist.n_desc);
@@ -4470,7 +4531,7 @@
// invalid address of zero when the global is a common symbol.
sym[GSYM_sym_idx].GetAddressRef().SetSection(symbol_section);
sym[GSYM_sym_idx].GetAddressRef().SetOffset(symbol_value);
- symbols_added.insert(
+ add_symbol_addr(
sym[GSYM_sym_idx].GetAddress().GetFileAddress());
// We just need the flags from the linker symbol, so put these
// flags into the N_GSYM flags to avoid duplicate symbols in
@@ -4489,7 +4550,8 @@
if (set_value) {
sym[sym_idx].GetAddressRef().SetSection(symbol_section);
sym[sym_idx].GetAddressRef().SetOffset(symbol_value);
- symbols_added.insert(sym[sym_idx].GetAddress().GetFileAddress());
+ if (symbol_section)
+ add_symbol_addr(sym[sym_idx].GetAddress().GetFileAddress());
}
sym[sym_idx].SetFlags(nlist.n_type << 16 | nlist.n_desc);
if (nlist.n_desc & N_WEAK_REF)
@@ -4585,7 +4647,7 @@
sym[sym_idx].SetIsSynthetic(true);
sym[sym_idx].SetExternal(true);
sym[sym_idx].GetAddressRef() = symbol_addr;
- symbols_added.insert(symbol_addr.GetFileAddress());
+ add_symbol_addr(symbol_addr.GetFileAddress());
if (e.entry.flags & TRIE_SYMBOL_IS_THUMB)
sym[sym_idx].SetFlags(MACHO_NLIST_ARM_SYMBOL_IS_THUMB);
++sym_idx;
@@ -4635,12 +4697,14 @@
symbol_byte_size = section_end_file_addr - symbol_file_addr;
}
sym[sym_idx].SetID(synthetic_sym_id++);
- sym[sym_idx].GetMangled().SetDemangledName(
- GetNextSyntheticSymbolName());
+ // Don't set the name for any synthetic symbols, the Symbol
+ // object will generate one if needed when the name is accessed
+ // via accessors.
+ sym[sym_idx].GetMangled().SetDemangledName(ConstString());
sym[sym_idx].SetType(eSymbolTypeCode);
sym[sym_idx].SetIsSynthetic(true);
sym[sym_idx].GetAddressRef() = symbol_addr;
- symbols_added.insert(symbol_addr.GetFileAddress());
+ add_symbol_addr(symbol_addr.GetFileAddress());
if (symbol_flags)
sym[sym_idx].SetFlags(symbol_flags);
if (symbol_byte_size)
@@ -4741,7 +4805,7 @@
sym[sym_idx].SetType(eSymbolTypeResolver);
sym[sym_idx].SetIsSynthetic(true);
sym[sym_idx].GetAddressRef() = so_addr;
- symbols_added.insert(so_addr.GetFileAddress());
+ add_symbol_addr(so_addr.GetFileAddress());
sym[sym_idx].SetByteSize(symbol_stub_byte_size);
++sym_idx;
}
@@ -4838,7 +4902,7 @@
const lldb_private::DataExtractor &data,
lldb::offset_t lc_offset) {
uint32_t i;
- struct uuid_command load_cmd;
+ llvm::MachO::uuid_command load_cmd;
lldb::offset_t offset = lc_offset;
for (i = 0; i < header.ncmds; ++i) {
@@ -4986,7 +5050,7 @@
return add_triple(base_triple);
}
- struct load_command load_cmd;
+ llvm::MachO::load_command load_cmd;
// See if there is an LC_VERSION_MIN_* load command that can give
// us the OS type.
@@ -4996,7 +5060,7 @@
if (data.GetU32(&offset, &load_cmd, 2) == NULL)
break;
- struct version_min_command version_min;
+ llvm::MachO::version_min_command version_min;
switch (load_cmd.cmd) {
case llvm::MachO::LC_VERSION_MIN_MACOSX:
case llvm::MachO::LC_VERSION_MIN_IPHONEOS:
@@ -5048,7 +5112,7 @@
do {
if (load_cmd.cmd == llvm::MachO::LC_BUILD_VERSION) {
- struct build_version_command build_version;
+ llvm::MachO::build_version_command build_version;
if (load_cmd.cmdsize < sizeof(build_version)) {
// Malformed load command.
break;
@@ -5129,7 +5193,7 @@
ModuleSP module_sp(GetModule());
if (module_sp) {
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
- struct load_command load_cmd;
+ llvm::MachO::load_command load_cmd;
lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
std::vector<std::string> rpath_paths;
std::vector<std::string> rpath_relative_paths;
@@ -5265,7 +5329,7 @@
ModuleSP module_sp(GetModule());
if (module_sp) {
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
- struct load_command load_cmd;
+ llvm::MachO::load_command load_cmd;
lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
uint32_t i;
lldb::addr_t start_address = LLDB_INVALID_ADDRESS;
@@ -5422,7 +5486,7 @@
m_thread_context_offsets_valid = true;
lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
FileRangeArray::Entry file_range;
- thread_command thread_cmd;
+ llvm::MachO::thread_command thread_cmd;
for (uint32_t i = 0; i < m_header.ncmds; ++i) {
const uint32_t cmd_offset = offset;
if (m_data.GetU32(&offset, &thread_cmd, 2) == nullptr)
@@ -5451,7 +5515,7 @@
lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
for (uint32_t i = 0; i < m_header.ncmds; ++i) {
const uint32_t cmd_offset = offset;
- load_command lc;
+ llvm::MachO::load_command lc;
if (m_data.GetU32(&offset, &lc.cmd, 2) == nullptr)
break;
if (lc.cmd == LC_NOTE) {
@@ -5491,7 +5555,7 @@
offset = MachHeaderSizeFromMagic(m_header.magic);
for (uint32_t i = 0; i < m_header.ncmds; ++i) {
const uint32_t cmd_offset = offset;
- struct ident_command ident_command;
+ llvm::MachO::ident_command ident_command;
if (m_data.GetU32(&offset, &ident_command, 2) == nullptr)
break;
if (ident_command.cmd == LC_IDENT && ident_command.cmdsize != 0) {
@@ -5510,6 +5574,46 @@
return result;
}
+addr_t ObjectFileMachO::GetAddressMask() {
+ addr_t mask = 0;
+ ModuleSP module_sp(GetModule());
+ if (module_sp) {
+ std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
+ lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
+ for (uint32_t i = 0; i < m_header.ncmds; ++i) {
+ const uint32_t cmd_offset = offset;
+ llvm::MachO::load_command lc;
+ if (m_data.GetU32(&offset, &lc.cmd, 2) == nullptr)
+ break;
+ if (lc.cmd == LC_NOTE) {
+ char data_owner[17];
+ m_data.CopyData(offset, 16, data_owner);
+ data_owner[16] = '\0';
+ offset += 16;
+ uint64_t fileoff = m_data.GetU64_unchecked(&offset);
+
+ // "addrable bits" has a uint32_t version and a uint32_t
+ // number of bits used in addressing.
+ if (strcmp("addrable bits", data_owner) == 0) {
+ offset = fileoff;
+ uint32_t version;
+ if (m_data.GetU32(&offset, &version, 1) != nullptr) {
+ if (version == 3) {
+ uint32_t num_addr_bits = m_data.GetU32_unchecked(&offset);
+ if (num_addr_bits != 0) {
+ mask = ~((1ULL << num_addr_bits) - 1);
+ }
+ break;
+ }
+ }
+ }
+ }
+ offset = cmd_offset + lc.cmdsize;
+ }
+ }
+ return mask;
+}
+
bool ObjectFileMachO::GetCorefileMainBinaryInfo(addr_t &address, UUID &uuid,
ObjectFile::BinaryType &type) {
address = LLDB_INVALID_ADDRESS;
@@ -5520,7 +5624,7 @@
lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
for (uint32_t i = 0; i < m_header.ncmds; ++i) {
const uint32_t cmd_offset = offset;
- load_command lc;
+ llvm::MachO::load_command lc;
if (m_data.GetU32(&offset, &lc.cmd, 2) == nullptr)
break;
if (lc.cmd == LC_NOTE) {
@@ -5730,7 +5834,7 @@
ModuleSP module_sp(GetModule());
if (module_sp) {
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
- struct dylib_command load_cmd;
+ llvm::MachO::dylib_command load_cmd;
lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
uint32_t version_cmd = 0;
uint64_t version = 0;
@@ -5897,7 +6001,7 @@
for (uint32_t i = 0; i < m_header.ncmds; ++i) {
const lldb::offset_t load_cmd_offset = offset;
- version_min_command lc;
+ llvm::MachO::version_min_command lc;
if (m_data.GetU32(&offset, &lc.cmd, 2) == nullptr)
break;
if (lc.cmd == llvm::MachO::LC_VERSION_MIN_MACOSX ||
@@ -5958,7 +6062,7 @@
for (uint32_t i = 0; i < m_header.ncmds; ++i) {
const lldb::offset_t load_cmd_offset = offset;
- version_min_command lc;
+ llvm::MachO::version_min_command lc;
if (m_data.GetU32(&offset, &lc.cmd, 2) == nullptr)
break;
if (lc.cmd == llvm::MachO::LC_VERSION_MIN_MACOSX ||
@@ -5987,7 +6091,7 @@
for (uint32_t i = 0; i < m_header.ncmds; ++i) {
const lldb::offset_t load_cmd_offset = offset;
- version_min_command lc;
+ llvm::MachO::version_min_command lc;
if (m_data.GetU32(&offset, &lc.cmd, 2) == nullptr)
break;
if (lc.cmd == llvm::MachO::LC_BUILD_VERSION) {
@@ -6144,11 +6248,257 @@
return num_loaded_sections > 0;
}
+struct all_image_infos_header {
+ uint32_t version; // currently 1
+ uint32_t imgcount; // number of binary images
+ uint64_t entries_fileoff; // file offset in the corefile of where the array of
+ // struct entry's begin.
+ uint32_t entries_size; // size of 'struct entry'.
+ uint32_t unused;
+};
+
+struct image_entry {
+ uint64_t filepath_offset; // offset in corefile to c-string of the file path,
+ // UINT64_MAX if unavailable.
+ uuid_t uuid; // uint8_t[16]. should be set to all zeroes if
+ // uuid is unknown.
+ uint64_t load_address; // UINT64_MAX if unknown.
+ uint64_t seg_addrs_offset; // offset to the array of struct segment_vmaddr's.
+ uint32_t segment_count; // The number of segments for this binary.
+ uint32_t unused;
+
+ image_entry() {
+ filepath_offset = UINT64_MAX;
+ memset(&uuid, 0, sizeof(uuid_t));
+ segment_count = 0;
+ load_address = UINT64_MAX;
+ seg_addrs_offset = UINT64_MAX;
+ unused = 0;
+ }
+ image_entry(const image_entry &rhs) {
+ filepath_offset = rhs.filepath_offset;
+ memcpy(&uuid, &rhs.uuid, sizeof(uuid_t));
+ segment_count = rhs.segment_count;
+ seg_addrs_offset = rhs.seg_addrs_offset;
+ load_address = rhs.load_address;
+ unused = rhs.unused;
+ }
+};
+
+struct segment_vmaddr {
+ char segname[16];
+ uint64_t vmaddr;
+ uint64_t unused;
+
+ segment_vmaddr() {
+ memset(&segname, 0, 16);
+ vmaddr = UINT64_MAX;
+ unused = 0;
+ }
+ segment_vmaddr(const segment_vmaddr &rhs) {
+ memcpy(&segname, &rhs.segname, 16);
+ vmaddr = rhs.vmaddr;
+ unused = rhs.unused;
+ }
+};
+
+// Write the payload for the "all image infos" LC_NOTE into
+// the supplied all_image_infos_payload, assuming that this
+// will be written into the corefile starting at
+// initial_file_offset.
+//
+// The placement of this payload is a little tricky. We're
+// laying this out as
+//
+// 1. header (struct all_image_info_header)
+// 2. Array of fixed-size (struct image_entry)'s, one
+// per binary image present in the process.
+// 3. Arrays of (struct segment_vmaddr)'s, a varying number
+// for each binary image.
+// 4. Variable length c-strings of binary image filepaths,
+// one per binary.
+//
+// To compute where everything will be laid out in the
+// payload, we need to iterate over the images and calculate
+// how many segment_vmaddr structures each image will need,
+// and how long each image's filepath c-string is. There
+// are some multiple passes over the image list while calculating
+// everything.
+
+static offset_t
+CreateAllImageInfosPayload(const lldb::ProcessSP &process_sp,
+ offset_t initial_file_offset,
+ StreamString &all_image_infos_payload) {
+ Target &target = process_sp->GetTarget();
+ const ModuleList &modules = target.GetImages();
+ size_t modules_count = modules.GetSize();
+
+ std::set<std::string> executing_uuids;
+ ThreadList &thread_list(process_sp->GetThreadList());
+ for (uint32_t i = 0; i < thread_list.GetSize(); i++) {
+ ThreadSP thread_sp = thread_list.GetThreadAtIndex(i);
+ uint32_t stack_frame_count = thread_sp->GetStackFrameCount();
+ for (uint32_t j = 0; j < stack_frame_count; j++) {
+ StackFrameSP stack_frame_sp = thread_sp->GetStackFrameAtIndex(j);
+ Address pc = stack_frame_sp->GetFrameCodeAddress();
+ ModuleSP module_sp = pc.GetModule();
+ if (module_sp) {
+ UUID uuid = module_sp->GetUUID();
+ if (uuid.IsValid()) {
+ executing_uuids.insert(uuid.GetAsString());
+ }
+ }
+ }
+ }
+
+ struct all_image_infos_header infos;
+ infos.version = 1;
+ infos.imgcount = modules_count;
+ infos.entries_size = sizeof(image_entry);
+ infos.entries_fileoff = initial_file_offset + sizeof(all_image_infos_header);
+ infos.unused = 0;
+
+ all_image_infos_payload.PutHex32(infos.version);
+ all_image_infos_payload.PutHex32(infos.imgcount);
+ all_image_infos_payload.PutHex64(infos.entries_fileoff);
+ all_image_infos_payload.PutHex32(infos.entries_size);
+ all_image_infos_payload.PutHex32(infos.unused);
+
+ // First create the structures for all of the segment name+vmaddr vectors
+ // for each module, so we will know the size of them as we add the
+ // module entries.
+ std::vector<std::vector<segment_vmaddr>> modules_segment_vmaddrs;
+ for (size_t i = 0; i < modules_count; i++) {
+ ModuleSP module = modules.GetModuleAtIndex(i);
+
+ SectionList *sections = module->GetSectionList();
+ size_t sections_count = sections->GetSize();
+ std::vector<segment_vmaddr> segment_vmaddrs;
+ for (size_t j = 0; j < sections_count; j++) {
+ SectionSP section = sections->GetSectionAtIndex(j);
+ if (!section->GetParent().get()) {
+ addr_t vmaddr = section->GetLoadBaseAddress(&target);
+ if (vmaddr == LLDB_INVALID_ADDRESS)
+ continue;
+ ConstString name = section->GetName();
+ segment_vmaddr seg_vmaddr;
+ strncpy(seg_vmaddr.segname, name.AsCString(),
+ sizeof(seg_vmaddr.segname));
+ seg_vmaddr.vmaddr = vmaddr;
+ seg_vmaddr.unused = 0;
+ segment_vmaddrs.push_back(seg_vmaddr);
+ }
+ }
+ modules_segment_vmaddrs.push_back(segment_vmaddrs);
+ }
+
+ offset_t size_of_vmaddr_structs = 0;
+ for (size_t i = 0; i < modules_segment_vmaddrs.size(); i++) {
+ size_of_vmaddr_structs +=
+ modules_segment_vmaddrs[i].size() * sizeof(segment_vmaddr);
+ }
+
+ offset_t size_of_filepath_cstrings = 0;
+ for (size_t i = 0; i < modules_count; i++) {
+ ModuleSP module_sp = modules.GetModuleAtIndex(i);
+ size_of_filepath_cstrings += module_sp->GetFileSpec().GetPath().size() + 1;
+ }
+
+ // Calculate the file offsets of our "all image infos" payload in the
+ // corefile. initial_file_offset the original value passed in to this method.
+
+ offset_t start_of_entries =
+ initial_file_offset + sizeof(all_image_infos_header);
+ offset_t start_of_seg_vmaddrs =
+ start_of_entries + sizeof(image_entry) * modules_count;
+ offset_t start_of_filenames = start_of_seg_vmaddrs + size_of_vmaddr_structs;
+
+ offset_t final_file_offset = start_of_filenames + size_of_filepath_cstrings;
+
+ // Now write the one-per-module 'struct image_entry' into the
+ // StringStream; keep track of where the struct segment_vmaddr
+ // entries for each module will end up in the corefile.
+
+ offset_t current_string_offset = start_of_filenames;
+ offset_t current_segaddrs_offset = start_of_seg_vmaddrs;
+ std::vector<struct image_entry> image_entries;
+ for (size_t i = 0; i < modules_count; i++) {
+ ModuleSP module_sp = modules.GetModuleAtIndex(i);
+
+ struct image_entry ent;
+ memcpy(&ent.uuid, module_sp->GetUUID().GetBytes().data(), sizeof(ent.uuid));
+ if (modules_segment_vmaddrs[i].size() > 0) {
+ ent.segment_count = modules_segment_vmaddrs[i].size();
+ ent.seg_addrs_offset = current_segaddrs_offset;
+ }
+ ent.filepath_offset = current_string_offset;
+ ObjectFile *objfile = module_sp->GetObjectFile();
+ if (objfile) {
+ Address base_addr(objfile->GetBaseAddress());
+ if (base_addr.IsValid()) {
+ ent.load_address = base_addr.GetLoadAddress(&target);
+ }
+ }
+
+ all_image_infos_payload.PutHex64(ent.filepath_offset);
+ all_image_infos_payload.PutRawBytes(ent.uuid, sizeof(ent.uuid));
+ all_image_infos_payload.PutHex64(ent.load_address);
+ all_image_infos_payload.PutHex64(ent.seg_addrs_offset);
+ all_image_infos_payload.PutHex32(ent.segment_count);
+
+ if (executing_uuids.find(module_sp->GetUUID().GetAsString()) !=
+ executing_uuids.end())
+ all_image_infos_payload.PutHex32(1);
+ else
+ all_image_infos_payload.PutHex32(0);
+
+ current_segaddrs_offset += ent.segment_count * sizeof(segment_vmaddr);
+ current_string_offset += module_sp->GetFileSpec().GetPath().size() + 1;
+ }
+
+ // Now write the struct segment_vmaddr entries into the StringStream.
+
+ for (size_t i = 0; i < modules_segment_vmaddrs.size(); i++) {
+ if (modules_segment_vmaddrs[i].size() == 0)
+ continue;
+ for (struct segment_vmaddr segvm : modules_segment_vmaddrs[i]) {
+ all_image_infos_payload.PutRawBytes(segvm.segname, sizeof(segvm.segname));
+ all_image_infos_payload.PutHex64(segvm.vmaddr);
+ all_image_infos_payload.PutHex64(segvm.unused);
+ }
+ }
+
+ for (size_t i = 0; i < modules_count; i++) {
+ ModuleSP module_sp = modules.GetModuleAtIndex(i);
+ std::string filepath = module_sp->GetFileSpec().GetPath();
+ all_image_infos_payload.PutRawBytes(filepath.data(), filepath.size() + 1);
+ }
+
+ return final_file_offset;
+}
+
+// Temp struct used to combine contiguous memory regions with
+// identical permissions.
+struct page_object {
+ addr_t addr;
+ addr_t size;
+ uint32_t prot;
+};
+
bool ObjectFileMachO::SaveCore(const lldb::ProcessSP &process_sp,
- const FileSpec &outfile, Status &error) {
+ const FileSpec &outfile,
+ lldb::SaveCoreStyle &core_style, Status &error) {
if (!process_sp)
return false;
+ // For Mach-O, we can only create full corefiles or dirty-page-only
+ // corefiles. The default is dirty-page-only.
+ if (core_style != SaveCoreStyle::eSaveCoreFull) {
+ core_style = SaveCoreStyle::eSaveCoreDirtyOnly;
+ } else {
+ core_style = SaveCoreStyle::eSaveCoreFull;
+ }
+
Target &target = process_sp->GetTarget();
const ArchSpec target_arch = target.GetArchitecture();
const llvm::Triple &target_triple = target_arch.GetTriple();
@@ -6176,20 +6526,16 @@
}
if (make_core) {
- std::vector<segment_command_64> segment_load_commands;
+ std::vector<llvm::MachO::segment_command_64> segment_load_commands;
// uint32_t range_info_idx = 0;
MemoryRegionInfo range_info;
Status range_error = process_sp->GetMemoryRegionInfo(0, range_info);
const uint32_t addr_byte_size = target_arch.GetAddressByteSize();
const ByteOrder byte_order = target_arch.GetByteOrder();
+ std::vector<page_object> pages_to_copy;
+
if (range_error.Success()) {
while (range_info.GetRange().GetRangeBase() != LLDB_INVALID_ADDRESS) {
- const addr_t addr = range_info.GetRange().GetRangeBase();
- const addr_t size = range_info.GetRange().GetByteSize();
-
- if (size == 0)
- break;
-
// Calculate correct protections
uint32_t prot = 0;
if (range_info.GetReadable() == MemoryRegionInfo::eYes)
@@ -6199,32 +6545,33 @@
if (range_info.GetExecutable() == MemoryRegionInfo::eYes)
prot |= VM_PROT_EXECUTE;
+ const addr_t addr = range_info.GetRange().GetRangeBase();
+ const addr_t size = range_info.GetRange().GetByteSize();
+
+ if (size == 0)
+ break;
+
if (prot != 0) {
- uint32_t cmd_type = LC_SEGMENT_64;
- uint32_t segment_size = sizeof(segment_command_64);
- if (addr_byte_size == 4) {
- cmd_type = LC_SEGMENT;
- segment_size = sizeof(segment_command);
+ addr_t pagesize = range_info.GetPageSize();
+ const llvm::Optional<std::vector<addr_t>> &dirty_page_list =
+ range_info.GetDirtyPageList();
+ if (core_style == SaveCoreStyle::eSaveCoreDirtyOnly &&
+ dirty_page_list.hasValue()) {
+ core_style = SaveCoreStyle::eSaveCoreDirtyOnly;
+ for (addr_t dirtypage : dirty_page_list.getValue()) {
+ page_object obj;
+ obj.addr = dirtypage;
+ obj.size = pagesize;
+ obj.prot = prot;
+ pages_to_copy.push_back(obj);
+ }
+ } else {
+ page_object obj;
+ obj.addr = addr;
+ obj.size = size;
+ obj.prot = prot;
+ pages_to_copy.push_back(obj);
}
- segment_command_64 segment = {
- cmd_type, // uint32_t cmd;
- segment_size, // uint32_t cmdsize;
- {0}, // char segname[16];
- addr, // uint64_t vmaddr; // uint32_t for 32-bit Mach-O
- size, // uint64_t vmsize; // uint32_t for 32-bit Mach-O
- 0, // uint64_t fileoff; // uint32_t for 32-bit Mach-O
- size, // uint64_t filesize; // uint32_t for 32-bit Mach-O
- prot, // uint32_t maxprot;
- prot, // uint32_t initprot;
- 0, // uint32_t nsects;
- 0}; // uint32_t flags;
- segment_load_commands.push_back(segment);
- } else {
- // No protections and a size of 1 used to be returned from old
- // debugservers when we asked about a region that was past the
- // last memory region and it indicates the end...
- if (size == 1)
- break;
}
range_error = process_sp->GetMemoryRegionInfo(
@@ -6233,9 +6580,54 @@
break;
}
+ // Combine contiguous entries that have the same
+ // protections so we don't have an excess of
+ // load commands.
+ std::vector<page_object> combined_page_objects;
+ page_object last_obj;
+ last_obj.addr = LLDB_INVALID_ADDRESS;
+ for (page_object obj : pages_to_copy) {
+ if (last_obj.addr == LLDB_INVALID_ADDRESS) {
+ last_obj = obj;
+ continue;
+ }
+ if (last_obj.addr + last_obj.size == obj.addr &&
+ last_obj.prot == obj.prot) {
+ last_obj.size += obj.size;
+ continue;
+ }
+ combined_page_objects.push_back(last_obj);
+ last_obj = obj;
+ }
+
+ for (page_object obj : combined_page_objects) {
+ uint32_t cmd_type = LC_SEGMENT_64;
+ uint32_t segment_size = sizeof(llvm::MachO::segment_command_64);
+ if (addr_byte_size == 4) {
+ cmd_type = LC_SEGMENT;
+ segment_size = sizeof(llvm::MachO::segment_command);
+ }
+ llvm::MachO::segment_command_64 segment = {
+ cmd_type, // uint32_t cmd;
+ segment_size, // uint32_t cmdsize;
+ {0}, // char segname[16];
+ obj.addr, // uint64_t vmaddr; // uint32_t for 32-bit
+ // Mach-O
+ obj.size, // uint64_t vmsize; // uint32_t for 32-bit
+ // Mach-O
+ 0, // uint64_t fileoff; // uint32_t for 32-bit Mach-O
+ obj.size, // uint64_t filesize; // uint32_t for 32-bit
+ // Mach-O
+ obj.prot, // uint32_t maxprot;
+ obj.prot, // uint32_t initprot;
+ 0, // uint32_t nsects;
+ 0}; // uint32_t flags;
+ segment_load_commands.push_back(segment);
+ }
+
StreamString buffer(Stream::eBinary, addr_byte_size, byte_order);
- mach_header_64 mach_header;
+ llvm::MachO::mach_header_64 mach_header;
if (addr_byte_size == 8) {
mach_header.magic = MH_MAGIC_64;
} else {
@@ -6290,11 +6682,11 @@
// The size of the load command is the size of the segments...
if (addr_byte_size == 8) {
- mach_header.sizeofcmds =
- segment_load_commands.size() * sizeof(struct segment_command_64);
+ mach_header.sizeofcmds = segment_load_commands.size() *
+ sizeof(llvm::MachO::segment_command_64);
} else {
- mach_header.sizeofcmds =
- segment_load_commands.size() * sizeof(struct segment_command);
+ mach_header.sizeofcmds = segment_load_commands.size() *
+ sizeof(llvm::MachO::segment_command);
}
// and the size of all LC_THREAD load command
@@ -6303,6 +6695,19 @@
mach_header.sizeofcmds += 8 + LC_THREAD_data.GetSize();
}
+ // Bits will be set to indicate which bits are NOT used in
+ // addressing in this process or 0 for unknown.
+ uint64_t address_mask = process_sp->GetCodeAddressMask();
+ if (address_mask != 0) {
+ // LC_NOTE "addrable bits"
+ mach_header.ncmds++;
+ mach_header.sizeofcmds += sizeof(llvm::MachO::note_command);
+ }
+
+ // LC_NOTE "all image infos"
+ mach_header.ncmds++;
+ mach_header.sizeofcmds += sizeof(llvm::MachO::note_command);
+
// Write the mach header
buffer.PutHex32(mach_header.magic);
buffer.PutHex32(mach_header.cputype);
@@ -6318,11 +6723,54 @@
// Skip the mach header and all load commands and align to the next
// 0x1000 byte boundary
addr_t file_offset = buffer.GetSize() + mach_header.sizeofcmds;
- if (file_offset & 0x00000fff) {
- file_offset += 0x00001000ull;
- file_offset &= (~0x00001000ull + 1);
+
+ file_offset = llvm::alignTo(file_offset, 16);
+ std::vector<std::unique_ptr<LCNoteEntry>> lc_notes;
+
+ // Add "addrable bits" LC_NOTE when an address mask is available
+ if (address_mask != 0) {
+ std::unique_ptr<LCNoteEntry> addrable_bits_lcnote_up(
+ new LCNoteEntry(addr_byte_size, byte_order));
+ addrable_bits_lcnote_up->name = "addrable bits";
+ addrable_bits_lcnote_up->payload_file_offset = file_offset;
+ int bits = std::bitset<64>(~address_mask).count();
+ addrable_bits_lcnote_up->payload.PutHex32(3); // version
+ addrable_bits_lcnote_up->payload.PutHex32(
+ bits); // # of bits used for addressing
+ addrable_bits_lcnote_up->payload.PutHex64(0); // unused
+
+ file_offset += addrable_bits_lcnote_up->payload.GetSize();
+
+ lc_notes.push_back(std::move(addrable_bits_lcnote_up));
}
+ // Add "all image infos" LC_NOTE
+ std::unique_ptr<LCNoteEntry> all_image_infos_lcnote_up(
+ new LCNoteEntry(addr_byte_size, byte_order));
+ all_image_infos_lcnote_up->name = "all image infos";
+ all_image_infos_lcnote_up->payload_file_offset = file_offset;
+ file_offset = CreateAllImageInfosPayload(
+ process_sp, file_offset, all_image_infos_lcnote_up->payload);
+ lc_notes.push_back(std::move(all_image_infos_lcnote_up));
+
+ // Add LC_NOTE load commands
+ for (auto &lcnote : lc_notes) {
+ // Add the LC_NOTE load command to the file.
+ buffer.PutHex32(LC_NOTE);
+ buffer.PutHex32(sizeof(llvm::MachO::note_command));
+ char namebuf[16];
+ memset(namebuf, 0, sizeof(namebuf));
+ // this is the uncommon case where strncpy is exactly
+ // the right one, doesn't need to be nul terminated.
+ strncpy(namebuf, lcnote->name.c_str(), sizeof(namebuf));
+ buffer.PutRawBytes(namebuf, sizeof(namebuf));
+ buffer.PutHex64(lcnote->payload_file_offset);
+ buffer.PutHex64(lcnote->payload.GetSize());
+ }
+
+ // Align to 4096-byte page boundary for the LC_SEGMENTs.
+ file_offset = llvm::alignTo(file_offset, 4096);
+
for (auto &segment : segment_load_commands) {
segment.fileoff = file_offset;
file_offset += segment.filesize;
@@ -6338,14 +6786,6 @@
// Write out all of the segment load commands
for (const auto &segment : segment_load_commands) {
- printf("0x%8.8x 0x%8.8x [0x%16.16" PRIx64 " - 0x%16.16" PRIx64
- ") [0x%16.16" PRIx64 " 0x%16.16" PRIx64
- ") 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x]\n",
- segment.cmd, segment.cmdsize, segment.vmaddr,
- segment.vmaddr + segment.vmsize, segment.fileoff,
- segment.filesize, segment.maxprot, segment.initprot,
- segment.nsects, segment.flags);
-
buffer.PutHex32(segment.cmd);
buffer.PutHex32(segment.cmdsize);
buffer.PutRawBytes(segment.segname, sizeof(segment.segname));
@@ -6380,6 +6820,22 @@
error =
core_file.get()->Write(buffer.GetString().data(), bytes_written);
if (error.Success()) {
+
+ for (auto &lcnote : lc_notes) {
+ if (core_file.get()->SeekFromStart(lcnote->payload_file_offset) ==
+ -1) {
+ error.SetErrorStringWithFormat("Unable to seek to corefile pos "
+ "to write '%s' LC_NOTE payload",
+ lcnote->name.c_str());
+ return false;
+ }
+ bytes_written = lcnote->payload.GetSize();
+ error = core_file.get()->Write(lcnote->payload.GetData(),
+ bytes_written);
+ if (!error.Success())
+ return false;
+ }
+
// Now write the file data for all memory segments in the process
for (const auto &segment : segment_load_commands) {
if (core_file.get()->SeekFromStart(segment.fileoff) == -1) {
@@ -6389,9 +6845,10 @@
break;
}
- printf("Saving %" PRId64
- " bytes of data for memory region at 0x%" PRIx64 "\n",
- segment.vmsize, segment.vmaddr);
+ target.GetDebugger().GetAsyncOutputStream()->Printf(
+ "Saving %" PRId64
+ " bytes of data for memory region at 0x%" PRIx64 "\n",
+ segment.vmsize, segment.vmaddr);
addr_t bytes_left = segment.vmsize;
addr_t addr = segment.vmaddr;
Status memory_read_error;
@@ -6433,3 +6890,121 @@
}
return false;
}
+
+ObjectFileMachO::MachOCorefileAllImageInfos
+ObjectFileMachO::GetCorefileAllImageInfos() {
+ MachOCorefileAllImageInfos image_infos;
+
+ // Look for an "all image infos" LC_NOTE.
+ lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
+ for (uint32_t i = 0; i < m_header.ncmds; ++i) {
+ const uint32_t cmd_offset = offset;
+ llvm::MachO::load_command lc;
+ if (m_data.GetU32(&offset, &lc.cmd, 2) == nullptr)
+ break;
+ if (lc.cmd == LC_NOTE) {
+ char data_owner[17];
+ m_data.CopyData(offset, 16, data_owner);
+ data_owner[16] = '\0';
+ offset += 16;
+ uint64_t fileoff = m_data.GetU64_unchecked(&offset);
+ offset += 4; /* size unused */
+
+ if (strcmp("all image infos", data_owner) == 0) {
+ offset = fileoff;
+ // Read the struct all_image_infos_header.
+ uint32_t version = m_data.GetU32(&offset);
+ if (version != 1) {
+ return image_infos;
+ }
+ uint32_t imgcount = m_data.GetU32(&offset);
+ uint64_t entries_fileoff = m_data.GetU64(&offset);
+ offset += 4; // uint32_t entries_size;
+ offset += 4; // uint32_t unused;
+
+ offset = entries_fileoff;
+ for (uint32_t i = 0; i < imgcount; i++) {
+ // Read the struct image_entry.
+ offset_t filepath_offset = m_data.GetU64(&offset);
+ uuid_t uuid;
+ memcpy(&uuid, m_data.GetData(&offset, sizeof(uuid_t)),
+ sizeof(uuid_t));
+ uint64_t load_address = m_data.GetU64(&offset);
+ offset_t seg_addrs_offset = m_data.GetU64(&offset);
+ uint32_t segment_count = m_data.GetU32(&offset);
+ uint32_t currently_executing = m_data.GetU32(&offset);
+
+ MachOCorefileImageEntry image_entry;
+ image_entry.filename = (const char *)m_data.GetCStr(&filepath_offset);
+ image_entry.uuid = UUID::fromData(uuid, sizeof(uuid_t));
+ image_entry.load_address = load_address;
+ image_entry.currently_executing = currently_executing;
+
+ offset_t seg_vmaddrs_offset = seg_addrs_offset;
+ for (uint32_t j = 0; j < segment_count; j++) {
+ char segname[17];
+ m_data.CopyData(seg_vmaddrs_offset, 16, segname);
+ segname[16] = '\0';
+ seg_vmaddrs_offset += 16;
+ uint64_t vmaddr = m_data.GetU64(&seg_vmaddrs_offset);
+ seg_vmaddrs_offset += 8; /* unused */
+
+ std::tuple<ConstString, addr_t> new_seg{ConstString(segname),
+ vmaddr};
+ image_entry.segment_load_addresses.push_back(new_seg);
+ }
+ image_infos.all_image_infos.push_back(image_entry);
+ }
+ }
+ }
+ offset = cmd_offset + lc.cmdsize;
+ }
+
+ return image_infos;
+}
+
+bool ObjectFileMachO::LoadCoreFileImages(lldb_private::Process &process) {
+ MachOCorefileAllImageInfos image_infos = GetCorefileAllImageInfos();
+ bool added_images = false;
+ if (image_infos.IsValid()) {
+ for (const MachOCorefileImageEntry &image : image_infos.all_image_infos) {
+ ModuleSpec module_spec;
+ module_spec.GetUUID() = image.uuid;
+ module_spec.GetFileSpec() = FileSpec(image.filename.c_str());
+ if (image.currently_executing) {
+ Symbols::DownloadObjectAndSymbolFile(module_spec, true);
+ if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) {
+ process.GetTarget().GetOrCreateModule(module_spec, false);
+ }
+ }
+ Status error;
+ ModuleSP module_sp =
+ process.GetTarget().GetOrCreateModule(module_spec, false, &error);
+ if (!module_sp.get() || !module_sp->GetObjectFile()) {
+ if (image.load_address != LLDB_INVALID_ADDRESS) {
+ module_sp = process.ReadModuleFromMemory(module_spec.GetFileSpec(),
+ image.load_address);
+ }
+ }
+ if (module_sp.get() && module_sp->GetObjectFile()) {
+ added_images = true;
+ if (module_sp->GetObjectFile()->GetType() ==
+ ObjectFile::eTypeExecutable) {
+ process.GetTarget().SetExecutableModule(module_sp, eLoadDependentsNo);
+ }
+ for (auto name_vmaddr_tuple : image.segment_load_addresses) {
+ SectionList *sectlist = module_sp->GetObjectFile()->GetSectionList();
+ if (sectlist) {
+ SectionSP sect_sp =
+ sectlist->FindSectionByName(std::get<0>(name_vmaddr_tuple));
+ if (sect_sp) {
+ process.GetTarget().SetSectionLoadAddress(
+ sect_sp, std::get<1>(name_vmaddr_tuple));
+ }
+ }
+ }
+ }
+ }
+ }
+ return added_images;
+}
diff --git a/src/llvm-project/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h b/src/llvm-project/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
index 2308c49..3e8c84f 100644
--- a/src/llvm-project/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
+++ b/src/llvm-project/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
@@ -15,6 +15,7 @@
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/RangeMap.h"
+#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/UUID.h"
// This class needs to be hidden as eventually belongs in a plugin that
@@ -58,6 +59,7 @@
static bool SaveCore(const lldb::ProcessSP &process_sp,
const lldb_private::FileSpec &outfile,
+ lldb::SaveCoreStyle &core_style,
lldb_private::Status &error);
static bool MagicBytesMatch(lldb::DataBufferSP &data_sp, lldb::addr_t offset,
@@ -112,10 +114,14 @@
std::string GetIdentifierString() override;
+ lldb::addr_t GetAddressMask() override;
+
bool GetCorefileMainBinaryInfo(lldb::addr_t &address,
lldb_private::UUID &uuid,
ObjectFile::BinaryType &type) override;
+ bool LoadCoreFileImages(lldb_private::Process &process) override;
+
lldb::RegisterContextSP
GetThreadContextAtIndex(uint32_t idx, lldb_private::Thread &thread) override;
@@ -209,6 +215,40 @@
bool SectionIsLoadable(const lldb_private::Section *section);
+ /// A corefile may include metadata about all of the binaries that were
+ /// present in the process when the corefile was taken. This is only
+ /// implemented for Mach-O files for now; we'll generalize it when we
+ /// have other systems that can include the same.
+ struct MachOCorefileImageEntry {
+ std::string filename;
+ lldb_private::UUID uuid;
+ lldb::addr_t load_address = LLDB_INVALID_ADDRESS;
+ bool currently_executing;
+ std::vector<std::tuple<lldb_private::ConstString, lldb::addr_t>>
+ segment_load_addresses;
+ };
+
+ struct LCNoteEntry {
+ LCNoteEntry(uint32_t addr_byte_size, lldb::ByteOrder byte_order)
+ : payload(lldb_private::Stream::eBinary, addr_byte_size, byte_order) {}
+
+ std::string name;
+ lldb::addr_t payload_file_offset = 0;
+ lldb_private::StreamString payload;
+ };
+
+ struct MachOCorefileAllImageInfos {
+ std::vector<MachOCorefileImageEntry> all_image_infos;
+ bool IsValid() { return all_image_infos.size() > 0; }
+ };
+
+ /// Get the list of binary images that were present in the process
+ /// when the corefile was produced.
+ /// \return
+ /// The MachOCorefileAllImageInfos object returned will have
+ /// IsValid() == false if the information is unavailable.
+ MachOCorefileAllImageInfos GetCorefileAllImageInfos();
+
llvm::MachO::mach_header m_header;
static lldb_private::ConstString GetSegmentNameTEXT();
static lldb_private::ConstString GetSegmentNameDATA();
diff --git a/src/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp b/src/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp
index 35a823e..cb7bbee 100644
--- a/src/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp
@@ -173,7 +173,7 @@
if (ec || magic != llvm::file_magic::pdb)
return nullptr;
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ErrorOrBuffer =
- llvm::MemoryBuffer::getFile(PdbPath, /*FileSize=*/-1,
+ llvm::MemoryBuffer::getFile(PdbPath, /*IsText=*/false,
/*RequiresNullTerminator=*/false);
if (!ErrorOrBuffer)
return nullptr;
diff --git a/src/llvm-project/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/src/llvm-project/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
index 4e2598c..9eb1c25 100644
--- a/src/llvm-project/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
@@ -189,7 +189,9 @@
bool ObjectFilePECOFF::SaveCore(const lldb::ProcessSP &process_sp,
const lldb_private::FileSpec &outfile,
+ lldb::SaveCoreStyle &core_style,
lldb_private::Status &error) {
+ core_style = eSaveCoreFull;
return SaveMiniDump(process_sp, outfile, error);
}
@@ -261,7 +263,7 @@
::memset(&m_coff_header, 0, sizeof(m_coff_header));
}
-ObjectFilePECOFF::~ObjectFilePECOFF() {}
+ObjectFilePECOFF::~ObjectFilePECOFF() = default;
bool ObjectFilePECOFF::ParseHeader() {
ModuleSP module_sp(GetModule());
diff --git a/src/llvm-project/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h b/src/llvm-project/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
index fdcacbe..9fe4a13 100644
--- a/src/llvm-project/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
+++ b/src/llvm-project/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
@@ -79,6 +79,7 @@
static bool SaveCore(const lldb::ProcessSP &process_sp,
const lldb_private::FileSpec &outfile,
+ lldb::SaveCoreStyle &core_style,
lldb_private::Status &error);
static bool MagicBytesMatch(lldb::DataBufferSP &data_sp);
diff --git a/src/llvm-project/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp b/src/llvm-project/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
index 6c29c23..5272da9 100644
--- a/src/llvm-project/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
@@ -196,7 +196,7 @@
m_sect_infos.push_back(section_info{*offset_ptr + c.tell(), section_length,
section_id, *sect_name});
*offset_ptr += (c.tell() + section_length);
- } else if (section_id <= llvm::wasm::WASM_SEC_EVENT) {
+ } else if (section_id <= llvm::wasm::WASM_SEC_TAG) {
m_sect_infos.push_back(section_info{*offset_ptr + c.tell(),
static_cast<uint32_t>(payload_len),
section_id, ConstString()});
diff --git a/src/llvm-project/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/src/llvm-project/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
index 4350010..730c88f 100644
--- a/src/llvm-project/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
+++ b/src/llvm-project/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
@@ -91,13 +91,13 @@
std::string os_plugin_class_name(
python_module_path.GetFilename().AsCString(""));
if (!os_plugin_class_name.empty()) {
- const bool init_session = false;
+ LoadScriptOptions options;
char python_module_path_cstr[PATH_MAX];
python_module_path.GetPath(python_module_path_cstr,
sizeof(python_module_path_cstr));
Status error;
- if (m_interpreter->LoadScriptingModule(python_module_path_cstr,
- init_session, error)) {
+ if (m_interpreter->LoadScriptingModule(python_module_path_cstr, options,
+ error)) {
// Strip the ".py" extension if there is one
size_t py_extension_pos = os_plugin_class_name.rfind(".py");
if (py_extension_pos != std::string::npos)
@@ -115,7 +115,7 @@
}
}
-OperatingSystemPython::~OperatingSystemPython() {}
+OperatingSystemPython::~OperatingSystemPython() = default;
DynamicRegisterInfo *OperatingSystemPython::GetDynamicRegisterInfo() {
if (m_register_info_up == nullptr) {
diff --git a/src/llvm-project/lldb/source/Plugins/Platform/Android/AdbClient.cpp b/src/llvm-project/lldb/source/Plugins/Platform/Android/AdbClient.cpp
index ffccd6d..ed2d56f 100644
--- a/src/llvm-project/lldb/source/Plugins/Platform/Android/AdbClient.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Platform/Android/AdbClient.cpp
@@ -24,7 +24,7 @@
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timeout.h"
-#include <limits.h>
+#include <climits>
#include <algorithm>
#include <cstdlib>
@@ -118,11 +118,11 @@
return error;
}
-AdbClient::AdbClient() {}
+AdbClient::AdbClient() = default;
AdbClient::AdbClient(const std::string &device_id) : m_device_id(device_id) {}
-AdbClient::~AdbClient() {}
+AdbClient::~AdbClient() = default;
void AdbClient::SetDeviceID(const std::string &device_id) {
m_device_id = device_id;
@@ -583,7 +583,7 @@
return error;
}
-AdbClient::SyncService::~SyncService() {}
+AdbClient::SyncService::~SyncService() = default;
Status AdbClient::SyncService::SendSyncRequest(const char *request_id,
const uint32_t data_len,
diff --git a/src/llvm-project/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp b/src/llvm-project/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp
index 6dd5306..77690b4 100644
--- a/src/llvm-project/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp
@@ -73,7 +73,7 @@
return error;
}
-PlatformAndroidRemoteGDBServer::PlatformAndroidRemoteGDBServer() {}
+PlatformAndroidRemoteGDBServer::PlatformAndroidRemoteGDBServer() = default;
PlatformAndroidRemoteGDBServer::~PlatformAndroidRemoteGDBServer() {
for (const auto &it : m_port_forwards)
diff --git a/src/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp b/src/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
index f4d44eb..7b3d8a3 100644
--- a/src/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
@@ -9,7 +9,7 @@
#include "PlatformFreeBSD.h"
#include "lldb/Host/Config.h"
-#include <stdio.h>
+#include <cstdio>
#if LLDB_ENABLE_POSIX
#include <sys/utsname.h>
#endif
@@ -214,55 +214,9 @@
#endif
}
-size_t
-PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode(Target &target,
- BreakpointSite *bp_site) {
- switch (target.GetArchitecture().GetMachine()) {
- case llvm::Triple::arm: {
- lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetOwnerAtIndex(0));
- AddressClass addr_class = AddressClass::eUnknown;
-
- if (bp_loc_sp) {
- addr_class = bp_loc_sp->GetAddress().GetAddressClass();
- if (addr_class == AddressClass::eUnknown &&
- (bp_loc_sp->GetAddress().GetFileAddress() & 1))
- addr_class = AddressClass::eCodeAlternateISA;
- }
-
- if (addr_class == AddressClass::eCodeAlternateISA) {
- // TODO: Enable when FreeBSD supports thumb breakpoints.
- // FreeBSD kernel as of 10.x, does not support thumb breakpoints
- return 0;
- }
-
- static const uint8_t g_arm_breakpoint_opcode[] = {0xFE, 0xDE, 0xFF, 0xE7};
- size_t trap_opcode_size = sizeof(g_arm_breakpoint_opcode);
- assert(bp_site);
- if (bp_site->SetTrapOpcode(g_arm_breakpoint_opcode, trap_opcode_size))
- return trap_opcode_size;
- }
- LLVM_FALLTHROUGH;
- default:
- return Platform::GetSoftwareBreakpointTrapOpcode(target, bp_site);
- }
-}
-
bool PlatformFreeBSD::CanDebugProcess() {
if (IsHost()) {
- llvm::Triple host_triple{llvm::sys::getProcessTriple()};
- bool use_legacy_plugin;
-
- switch (host_triple.getArch()) {
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- // FreeBSDRemote plugin supports x86 only at the moment
- use_legacy_plugin = !!getenv("FREEBSD_LEGACY_PLUGIN");
- break;
- default:
- use_legacy_plugin = true;
- }
-
- return !use_legacy_plugin;
+ return true;
} else {
// If we're connected, we can debug.
return IsConnected();
diff --git a/src/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h b/src/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
index c198ea1..4fd10fb 100644
--- a/src/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
+++ b/src/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
@@ -44,9 +44,6 @@
bool CanDebugProcess() override;
- size_t GetSoftwareBreakpointTrapOpcode(Target &target,
- BreakpointSite *bp_site) override;
-
void CalculateTrapHandlerSymbolNames() override;
MmapArgList GetMmapArgumentList(const ArchSpec &arch, lldb::addr_t addr,
diff --git a/src/llvm-project/lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp b/src/llvm-project/lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp
index 2cb671f..314730c 100644
--- a/src/llvm-project/lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp
@@ -9,7 +9,7 @@
#include "PlatformLinux.h"
#include "lldb/Host/Config.h"
-#include <stdio.h>
+#include <cstdio>
#if LLDB_ENABLE_POSIX
#include <sys/utsname.h>
#endif
diff --git a/src/llvm-project/lldb/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp b/src/llvm-project/lldb/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp
index 342f7c2..925a3d1 100644
--- a/src/llvm-project/lldb/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp
@@ -50,7 +50,7 @@
///
/// The destructor is virtual since this class is designed to be
/// inherited from by the plug-in instance.
-PlatformAppleSimulator::~PlatformAppleSimulator() {}
+PlatformAppleSimulator::~PlatformAppleSimulator() = default;
lldb_private::Status PlatformAppleSimulator::LaunchProcess(
lldb_private::ProcessLaunchInfo &launch_info) {
@@ -505,6 +505,16 @@
return process_infos.size();
}
+/// Whether to skip creating a simulator platform.
+static bool shouldSkipSimulatorPlatform(bool force, const ArchSpec *arch) {
+ // If the arch is known not to specify a simulator environment, skip creating
+ // the simulator platform (we can create it later if there's a matching arch).
+ // This avoids very slow xcrun queries for non-simulator archs (the slowness
+ // is due to xcrun not caching negative queries (rdar://74882205)).
+ return !force && arch && arch->IsValid() &&
+ !arch->TripleEnvironmentWasSpecified();
+}
+
static llvm::StringRef GetXcodeSDKDir(std::string preferred,
std::string secondary) {
llvm::StringRef sdk;
@@ -530,6 +540,8 @@
}
static PlatformSP CreateInstance(bool force, const ArchSpec *arch) {
+ if (shouldSkipSimulatorPlatform(force, arch))
+ return nullptr;
llvm::StringRef sdk;
sdk = HostInfo::GetXcodeSDKPath(XcodeSDK("iPhoneSimulator.Internal.sdk"));
if (sdk.empty())
@@ -578,6 +590,8 @@
}
static PlatformSP CreateInstance(bool force, const ArchSpec *arch) {
+ if (shouldSkipSimulatorPlatform(force, arch))
+ return nullptr;
return PlatformAppleSimulator::CreateInstance(
"PlatformAppleTVSimulator", g_tvos_description,
ConstString(g_tvos_plugin_name),
@@ -619,6 +633,8 @@
}
static PlatformSP CreateInstance(bool force, const ArchSpec *arch) {
+ if (shouldSkipSimulatorPlatform(force, arch))
+ return nullptr;
return PlatformAppleSimulator::CreateInstance(
"PlatformAppleWatchSimulator", g_watchos_description,
ConstString(g_watchos_plugin_name),
diff --git a/src/llvm-project/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/src/llvm-project/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
index f1ca859..51ff2a6 100644
--- a/src/llvm-project/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
@@ -8,7 +8,7 @@
#include "PlatformDarwin.h"
-#include <string.h>
+#include <cstring>
#include <algorithm>
#include <memory>
@@ -54,7 +54,7 @@
///
/// The destructor is virtual since this class is designed to be
/// inherited from by the plug-in instance.
-PlatformDarwin::~PlatformDarwin() {}
+PlatformDarwin::~PlatformDarwin() = default;
lldb_private::Status
PlatformDarwin::PutFile(const lldb_private::FileSpec &source,
diff --git a/src/llvm-project/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp b/src/llvm-project/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
index 76ce500..ee8850f 100644
--- a/src/llvm-project/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
@@ -197,7 +197,7 @@
m_collection_sp->Initialize(g_platformdarwinkernel_properties);
}
- virtual ~PlatformDarwinKernelProperties() {}
+ virtual ~PlatformDarwinKernelProperties() = default;
FileSpecList GetKextDirectories() const {
const uint32_t idx = ePropertyKextDirectories;
@@ -250,7 +250,7 @@
///
/// The destructor is virtual since this class is designed to be
/// inherited from by the plug-in instance.
-PlatformDarwinKernel::~PlatformDarwinKernel() {}
+PlatformDarwinKernel::~PlatformDarwinKernel() = default;
void PlatformDarwinKernel::GetStatus(Stream &strm) {
Platform::GetStatus(strm);
@@ -791,21 +791,6 @@
return error;
}
- // Lastly, look through the kext binarys without dSYMs
- if (m_name_to_kext_path_map_without_dsyms.count(kext_bundle) > 0) {
- for (BundleIDToKextIterator it =
- m_name_to_kext_path_map_without_dsyms.begin();
- it != m_name_to_kext_path_map_without_dsyms.end(); ++it) {
- if (it->first == kext_bundle) {
- error = ExamineKextForMatchingUUID(it->second, module_spec.GetUUID(),
- module_spec.GetArchitecture(),
- module_sp);
- if (module_sp.get()) {
- return error;
- }
- }
- }
- }
return error;
}
@@ -884,33 +869,6 @@
return error;
}
- // Lastly, try all kernel binaries that don't have a dSYM
- for (auto possible_kernel : m_kernel_binaries_without_dsyms) {
- if (FileSystem::Instance().Exists(possible_kernel)) {
- ModuleSpec kern_spec(possible_kernel);
- kern_spec.GetUUID() = module_spec.GetUUID();
- module_sp.reset(new Module(kern_spec));
- if (module_sp && module_sp->GetObjectFile() &&
- module_sp->MatchesModuleSpec(kern_spec)) {
- // module_sp is an actual kernel binary we want to add.
- if (process) {
- process->GetTarget().GetImages().AppendIfNeeded(module_sp);
- error.Clear();
- return error;
- } else {
- error = ModuleList::GetSharedModule(kern_spec, module_sp, nullptr,
- nullptr, nullptr);
- if (module_sp && module_sp->GetObjectFile() &&
- module_sp->GetObjectFile()->GetType() !=
- ObjectFile::Type::eTypeCoreFile) {
- return error;
- }
- module_sp.reset();
- }
- }
- }
- }
-
return error;
}
diff --git a/src/llvm-project/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp b/src/llvm-project/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp
index 8a11f40..79cbd1c 100644
--- a/src/llvm-project/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp
@@ -39,15 +39,13 @@
PlatformRemoteDarwinDevice::PlatformRemoteDarwinDevice()
: PlatformDarwin(false), // This is a remote platform
m_sdk_directory_infos(), m_device_support_directory(),
- m_device_support_directory_for_os_version(), m_build_update(),
- m_last_module_sdk_idx(UINT32_MAX),
- m_connected_module_sdk_idx(UINT32_MAX) {}
+ m_device_support_directory_for_os_version(), m_build_update() {}
/// Destructor.
///
/// The destructor is virtual since this class is designed to be
/// inherited from by the plug-in instance.
-PlatformRemoteDarwinDevice::~PlatformRemoteDarwinDevice() {}
+PlatformRemoteDarwinDevice::~PlatformRemoteDarwinDevice() = default;
void PlatformRemoteDarwinDevice::GetStatus(Stream &strm) {
Platform::GetStatus(strm);
diff --git a/src/llvm-project/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h b/src/llvm-project/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h
index 6f6ede7..3b578a3 100644
--- a/src/llvm-project/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h
+++ b/src/llvm-project/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h
@@ -64,8 +64,8 @@
std::string m_device_support_directory;
std::string m_device_support_directory_for_os_version;
std::string m_build_update;
- uint32_t m_last_module_sdk_idx;
- uint32_t m_connected_module_sdk_idx;
+ uint32_t m_last_module_sdk_idx = UINT32_MAX;
+ uint32_t m_connected_module_sdk_idx = UINT32_MAX;
bool UpdateSDKDirectoryInfosIfNeeded();
diff --git a/src/llvm-project/lldb/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.h b/src/llvm-project/lldb/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.h
index 5104e48..a35efd5 100644
--- a/src/llvm-project/lldb/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.h
+++ b/src/llvm-project/lldb/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.h
@@ -93,7 +93,7 @@
ProductFamilyID GetProductFamilyID();
private:
- id m_dev;
+ id m_dev = nullptr;
llvm::Optional<ModelIdentifier> m_model_identifier;
};
@@ -129,7 +129,7 @@
bool IsAvailable();
private:
- id m_dev;
+ id m_dev = nullptr;
llvm::Optional<OSVersion> m_os_version;
};
@@ -169,7 +169,7 @@
Process Spawn(lldb_private::ProcessLaunchInfo &launch_info);
private:
- id m_dev;
+ id m_dev = nullptr;
llvm::Optional<DeviceType> m_dev_type;
llvm::Optional<DeviceRuntime> m_dev_runtime;
diff --git a/src/llvm-project/lldb/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm b/src/llvm-project/lldb/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm
index 66fe569..91d6252 100644
--- a/src/llvm-project/lldb/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm
+++ b/src/llvm-project/lldb/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm
@@ -66,8 +66,7 @@
CoreSimulatorSupport::Process::Process(lldb::pid_t p, Status error)
: m_pid(p), m_error(error) {}
-CoreSimulatorSupport::DeviceType::DeviceType()
- : m_dev(nil), m_model_identifier() {}
+CoreSimulatorSupport::DeviceType::DeviceType() : m_model_identifier() {}
CoreSimulatorSupport::DeviceType::DeviceType(id d)
: m_dev(d), m_model_identifier() {}
@@ -87,8 +86,7 @@
return ProductFamilyID([m_dev productFamilyID]);
}
-CoreSimulatorSupport::DeviceRuntime::DeviceRuntime()
- : m_dev(nil), m_os_version() {}
+CoreSimulatorSupport::DeviceRuntime::DeviceRuntime() : m_os_version() {}
CoreSimulatorSupport::DeviceRuntime::DeviceRuntime(id d)
: m_dev(d), m_os_version() {}
@@ -99,8 +97,7 @@
return [m_dev available];
}
-CoreSimulatorSupport::Device::Device()
- : m_dev(nil), m_dev_type(), m_dev_runtime() {}
+CoreSimulatorSupport::Device::Device() : m_dev_type(), m_dev_runtime() {}
CoreSimulatorSupport::Device::Device(id d)
: m_dev(d), m_dev_type(), m_dev_runtime() {}
diff --git a/src/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp b/src/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp
index a5d73c9..e3682b4 100644
--- a/src/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp
@@ -9,7 +9,7 @@
#include "PlatformNetBSD.h"
#include "lldb/Host/Config.h"
-#include <stdio.h>
+#include <cstdio>
#if LLDB_ENABLE_POSIX
#include <sys/utsname.h>
#endif
diff --git a/src/llvm-project/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp b/src/llvm-project/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp
index 2cd024f..012b688 100644
--- a/src/llvm-project/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp
@@ -9,7 +9,7 @@
#include "PlatformOpenBSD.h"
#include "lldb/Host/Config.h"
-#include <stdio.h>
+#include <cstdio>
#if LLDB_ENABLE_POSIX
#include <sys/utsname.h>
#endif
diff --git a/src/llvm-project/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/src/llvm-project/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
index 3628b0a..7353132 100644
--- a/src/llvm-project/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
@@ -46,7 +46,7 @@
///
/// The destructor is virtual since this class is designed to be
/// inherited from by the plug-in instance.
-PlatformPOSIX::~PlatformPOSIX() {}
+PlatformPOSIX::~PlatformPOSIX() = default;
lldb_private::OptionGroupOptions *PlatformPOSIX::GetConnectionOptions(
lldb_private::CommandInterpreter &interpreter) {
@@ -578,7 +578,19 @@
// __lldb_dlopen_result for consistency. The wrapper returns a void * but
// doesn't use it because UtilityFunctions don't work with void returns at
// present.
+ //
+ // Use lazy binding so as to not make dlopen()'s success conditional on
+ // forcing every symbol in the library.
+ //
+ // In general, the debugger should allow programs to load & run with
+ // libraries as far as they can, instead of defaulting to being super-picky
+ // about unavailable symbols.
+ //
+ // The value "1" appears to imply lazy binding (RTLD_LAZY) on both Darwin
+ // and other POSIX OSes.
static const char *dlopen_wrapper_code = R"(
+ const int RTLD_LAZY = 1;
+
struct __lldb_dlopen_result {
void *image_ptr;
const char *error_str;
@@ -595,7 +607,7 @@
{
// This is the case where the name is the full path:
if (!path_strings) {
- result_ptr->image_ptr = dlopen(name, 2);
+ result_ptr->image_ptr = dlopen(name, RTLD_LAZY);
if (result_ptr->image_ptr)
result_ptr->error_str = nullptr;
return nullptr;
@@ -609,7 +621,7 @@
buffer[path_len] = '/';
char *target_ptr = buffer+path_len+1;
memcpy((void *) target_ptr, (void *) name, name_len + 1);
- result_ptr->image_ptr = dlopen(buffer, 2);
+ result_ptr->image_ptr = dlopen(buffer, RTLD_LAZY);
if (result_ptr->image_ptr) {
result_ptr->error_str = nullptr;
break;
@@ -659,7 +671,7 @@
// We are passing four arguments, the basename, the list of places to look,
// a buffer big enough for all the path + name combos, and
// a pointer to the storage we've made for the result:
- value.SetValueType(Value::eValueTypeScalar);
+ value.SetValueType(Value::ValueType::Scalar);
value.SetCompilerType(clang_void_pointer_type);
arguments.PushValue(value);
value.SetCompilerType(clang_char_pointer_type);
@@ -994,13 +1006,6 @@
)";
}
-size_t PlatformPOSIX::ConnectToWaitingProcesses(Debugger &debugger,
- Status &error) {
- if (m_remote_platform_sp)
- return m_remote_platform_sp->ConnectToWaitingProcesses(debugger, error);
- return Platform::ConnectToWaitingProcesses(debugger, error);
-}
-
ConstString PlatformPOSIX::GetFullNameForDylib(ConstString basename) {
if (basename.IsEmpty())
return basename;
diff --git a/src/llvm-project/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.h b/src/llvm-project/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.h
index 72c54f4..1cba4c5 100644
--- a/src/llvm-project/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.h
+++ b/src/llvm-project/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.h
@@ -71,9 +71,6 @@
lldb_private::Status UnloadImage(lldb_private::Process *process,
uint32_t image_token) override;
- size_t ConnectToWaitingProcesses(lldb_private::Debugger &debugger,
- lldb_private::Status &error) override;
-
lldb_private::ConstString GetFullNameForDylib(lldb_private::ConstString basename) override;
protected:
diff --git a/src/llvm-project/lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp b/src/llvm-project/lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp
index 3527fb1..fd28eec 100644
--- a/src/llvm-project/lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp
@@ -8,7 +8,7 @@
#include "PlatformWindows.h"
-#include <stdio.h>
+#include <cstdio>
#if defined(_WIN32)
#include "lldb/Host/windows/windows.h"
#include <winsock2.h>
diff --git a/src/llvm-project/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/src/llvm-project/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
index 6a4275d..5282086 100644
--- a/src/llvm-project/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
@@ -30,6 +30,7 @@
#include "lldb/Utility/UriParser.h"
#include "Plugins/Process/Utility/GDBRemoteSignals.h"
+#include "Plugins/Process/gdb-remote/ProcessGDBRemote.h"
using namespace lldb;
using namespace lldb_private;
@@ -202,13 +203,16 @@
/// Default Constructor
PlatformRemoteGDBServer::PlatformRemoteGDBServer()
: Platform(false), // This is a remote platform
- m_gdb_client() {}
+ m_gdb_client() {
+ m_gdb_client.SetPacketTimeout(
+ process_gdb_remote::ProcessGDBRemote::GetPacketTimeout());
+}
/// Destructor.
///
/// The destructor is virtual since this class is designed to be
/// inherited from by the plug-in instance.
-PlatformRemoteGDBServer::~PlatformRemoteGDBServer() {}
+PlatformRemoteGDBServer::~PlatformRemoteGDBServer() = default;
bool PlatformRemoteGDBServer::GetSupportedArchitectureAtIndex(uint32_t idx,
ArchSpec &arch) {
@@ -736,8 +740,8 @@
m_remote_signals_sp = UnixSignals::Create(GetRemoteSystemArchitecture());
StringExtractorGDBRemote response;
- auto result = m_gdb_client.SendPacketAndWaitForResponse("jSignalsInfo",
- response, false);
+ auto result =
+ m_gdb_client.SendPacketAndWaitForResponse("jSignalsInfo", response);
if (result != decltype(result)::Success ||
response.GetResponseType() != response.eResponse)
@@ -839,7 +843,7 @@
GetPendingGdbServerList(connection_urls);
for (size_t i = 0; i < connection_urls.size(); ++i) {
- ConnectProcess(connection_urls[i].c_str(), "", debugger, nullptr, error);
+ ConnectProcess(connection_urls[i].c_str(), "gdb-remote", debugger, nullptr, error);
if (error.Fail())
return i; // We already connected to i process succsessfully
}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/CMakeLists.txt b/src/llvm-project/lldb/source/Plugins/Process/CMakeLists.txt
index 91f20ec..bea5bac 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/CMakeLists.txt
+++ b/src/llvm-project/lldb/source/Plugins/Process/CMakeLists.txt
@@ -2,7 +2,6 @@
add_subdirectory(Linux)
add_subdirectory(POSIX)
elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
- add_subdirectory(FreeBSDRemote)
add_subdirectory(FreeBSD)
add_subdirectory(POSIX)
elseif (CMAKE_SYSTEM_NAME MATCHES "NetBSD")
@@ -13,6 +12,7 @@
elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin")
add_subdirectory(MacOSX-Kernel)
endif()
+add_subdirectory(scripted)
add_subdirectory(gdb-remote)
add_subdirectory(Utility)
add_subdirectory(elf-core)
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/CMakeLists.txt b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/CMakeLists.txt
index c8301f3..598911c 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/CMakeLists.txt
+++ b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/CMakeLists.txt
@@ -1,24 +1,20 @@
-add_lldb_library(lldbPluginProcessFreeBSD PLUGIN
- ProcessFreeBSD.cpp
- FreeBSDThread.cpp
- ProcessMonitor.cpp
-
- POSIXStopInfo.cpp
- RegisterContextPOSIXProcessMonitor_arm.cpp
- RegisterContextPOSIXProcessMonitor_arm64.cpp
- RegisterContextPOSIXProcessMonitor_powerpc.cpp
- RegisterContextPOSIXProcessMonitor_x86.cpp
- RegisterContextPOSIXProcessMonitor_mips64.cpp
+add_lldb_library(lldbPluginProcessFreeBSD
+ NativeProcessFreeBSD.cpp
+ NativeRegisterContextFreeBSD.cpp
+ NativeRegisterContextFreeBSD_arm.cpp
+ NativeRegisterContextFreeBSD_arm64.cpp
+ NativeRegisterContextFreeBSD_mips64.cpp
+ NativeRegisterContextFreeBSD_powerpc.cpp
+ NativeRegisterContextFreeBSD_x86_64.cpp
+ NativeThreadFreeBSD.cpp
LINK_LIBS
- lldbBreakpoint
- lldbCore
lldbHost
lldbSymbol
lldbTarget
lldbUtility
- lldbPluginProcessUtility
lldbPluginProcessPOSIX
+ lldbPluginProcessUtility
LINK_COMPONENTS
Support
)
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
deleted file mode 100644
index 3accc9c..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
+++ /dev/null
@@ -1,616 +0,0 @@
-//===-- FreeBSDThread.cpp -------------------------------------------------===//
-//
-// 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 <errno.h>
-#include <pthread.h>
-#include <pthread_np.h>
-#include <stdlib.h>
-#include <sys/sysctl.h>
-#include <sys/types.h>
-#include <sys/user.h>
-
-#include "FreeBSDThread.h"
-#include "POSIXStopInfo.h"
-#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
-#include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h"
-#include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h"
-#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h"
-#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
-#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h"
-#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
-#include "ProcessFreeBSD.h"
-#include "ProcessMonitor.h"
-#include "RegisterContextPOSIXProcessMonitor_arm.h"
-#include "RegisterContextPOSIXProcessMonitor_arm64.h"
-#include "RegisterContextPOSIXProcessMonitor_mips64.h"
-#include "RegisterContextPOSIXProcessMonitor_powerpc.h"
-#include "RegisterContextPOSIXProcessMonitor_x86.h"
-#include "lldb/Breakpoint/BreakpointLocation.h"
-#include "lldb/Breakpoint/Watchpoint.h"
-#include "lldb/Core/Debugger.h"
-#include "lldb/Host/Host.h"
-#include "lldb/Host/HostInfo.h"
-#include "lldb/Host/HostNativeThread.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/StopInfo.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Target/ThreadSpec.h"
-#include "lldb/Target/UnixSignals.h"
-#include "lldb/Target/Unwind.h"
-#include "lldb/Utility/State.h"
-#include "llvm/ADT/SmallString.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-FreeBSDThread::FreeBSDThread(Process &process, lldb::tid_t tid)
- : Thread(process, tid), m_frame_up(), m_breakpoint(),
- m_thread_name_valid(false), m_thread_name(), m_posix_thread(nullptr) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
- LLDB_LOGV(log, "tid = {0}", tid);
-
- // Set the current watchpoints for this thread.
- Target &target = GetProcess()->GetTarget();
- const WatchpointList &wp_list = target.GetWatchpointList();
- size_t wp_size = wp_list.GetSize();
-
- for (uint32_t wp_idx = 0; wp_idx < wp_size; wp_idx++) {
- lldb::WatchpointSP wp = wp_list.GetByIndex(wp_idx);
- if (wp.get() && wp->IsEnabled()) {
- // This watchpoint as been enabled; obviously this "new" thread has been
- // created since that watchpoint was enabled. Since the
- // POSIXBreakpointProtocol has yet to be initialized, its
- // m_watchpoints_initialized member will be FALSE. Attempting to read
- // the debug status register to determine if a watchpoint has been hit
- // would result in the zeroing of that register. Since the active debug
- // registers would have been cloned when this thread was created, simply
- // force the m_watchpoints_initized member to TRUE and avoid resetting
- // dr6 and dr7.
- GetPOSIXBreakpointProtocol()->ForceWatchpointsInitialized();
- }
- }
-}
-
-FreeBSDThread::~FreeBSDThread() { DestroyThread(); }
-
-ProcessMonitor &FreeBSDThread::GetMonitor() {
- ProcessSP base = GetProcess();
- ProcessFreeBSD &process = static_cast<ProcessFreeBSD &>(*base);
- return process.GetMonitor();
-}
-
-void FreeBSDThread::RefreshStateAfterStop() {
- // Invalidate all registers in our register context. We don't set "force" to
- // true because the stop reply packet might have had some register values
- // that were expedited and these will already be copied into the register
- // context by the time this function gets called. The KDPRegisterContext
- // class has been made smart enough to detect when it needs to invalidate
- // which registers are valid by putting hooks in the register read and
- // register supply functions where they check the process stop ID and do the
- // right thing. if (StateIsStoppedState(GetState())
- {
- const bool force = false;
- GetRegisterContext()->InvalidateIfNeeded(force);
- }
-}
-
-const char *FreeBSDThread::GetInfo() { return nullptr; }
-
-void FreeBSDThread::SetName(const char *name) {
- m_thread_name_valid = (name && name[0]);
- if (m_thread_name_valid)
- m_thread_name.assign(name);
- else
- m_thread_name.clear();
-}
-
-const char *FreeBSDThread::GetName() {
- if (!m_thread_name_valid) {
- m_thread_name.clear();
- int pid = GetProcess()->GetID();
-
- struct kinfo_proc *kp = nullptr, *nkp;
- size_t len = 0;
- int error;
- int ctl[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID | KERN_PROC_INC_THREAD,
- pid};
-
- while (1) {
- error = sysctl(ctl, 4, kp, &len, nullptr, 0);
- if (kp == nullptr || (error != 0 && errno == ENOMEM)) {
- // Add extra space in case threads are added before next call.
- len += sizeof(*kp) + len / 10;
- nkp = (struct kinfo_proc *)realloc(kp, len);
- if (nkp == nullptr) {
- free(kp);
- return nullptr;
- }
- kp = nkp;
- continue;
- }
- if (error != 0)
- len = 0;
- break;
- }
-
- for (size_t i = 0; i < len / sizeof(*kp); i++) {
- if (kp[i].ki_tid == (lwpid_t)GetID()) {
- m_thread_name.append(kp[i].ki_tdname,
- kp[i].ki_tdname + strlen(kp[i].ki_tdname));
- break;
- }
- }
- free(kp);
- m_thread_name_valid = true;
- }
-
- if (m_thread_name.empty())
- return nullptr;
- return m_thread_name.c_str();
-}
-
-lldb::RegisterContextSP FreeBSDThread::GetRegisterContext() {
- if (!m_reg_context_sp) {
- m_posix_thread = nullptr;
-
- RegisterInfoInterface *reg_interface = nullptr;
- const ArchSpec &target_arch = GetProcess()->GetTarget().GetArchitecture();
-
- assert(target_arch.GetTriple().getOS() == llvm::Triple::FreeBSD);
- switch (target_arch.GetMachine()) {
- case llvm::Triple::aarch64:
- case llvm::Triple::arm:
- break;
- case llvm::Triple::ppc:
-#ifndef __powerpc64__
- reg_interface = new RegisterContextFreeBSD_powerpc32(target_arch);
- break;
-#endif
- case llvm::Triple::ppc64:
- reg_interface = new RegisterContextFreeBSD_powerpc64(target_arch);
- break;
- case llvm::Triple::mips64:
- reg_interface = new RegisterContextFreeBSD_mips64(target_arch);
- break;
- case llvm::Triple::x86:
- reg_interface = new RegisterContextFreeBSD_i386(target_arch);
- break;
- case llvm::Triple::x86_64:
- reg_interface = new RegisterContextFreeBSD_x86_64(target_arch);
- break;
- default:
- llvm_unreachable("CPU not supported");
- }
-
- switch (target_arch.GetMachine()) {
- case llvm::Triple::aarch64: {
- RegisterContextPOSIXProcessMonitor_arm64 *reg_ctx =
- new RegisterContextPOSIXProcessMonitor_arm64(
- *this, std::make_unique<RegisterInfoPOSIX_arm64>(target_arch));
- m_posix_thread = reg_ctx;
- m_reg_context_sp.reset(reg_ctx);
- break;
- }
- case llvm::Triple::arm: {
- RegisterContextPOSIXProcessMonitor_arm *reg_ctx =
- new RegisterContextPOSIXProcessMonitor_arm(
- *this, std::make_unique<RegisterInfoPOSIX_arm>(target_arch));
- m_posix_thread = reg_ctx;
- m_reg_context_sp.reset(reg_ctx);
- break;
- }
- case llvm::Triple::mips64: {
- RegisterContextPOSIXProcessMonitor_mips64 *reg_ctx =
- new RegisterContextPOSIXProcessMonitor_mips64(*this, 0,
- reg_interface);
- m_posix_thread = reg_ctx;
- m_reg_context_sp.reset(reg_ctx);
- break;
- }
- case llvm::Triple::ppc:
- case llvm::Triple::ppc64: {
- RegisterContextPOSIXProcessMonitor_powerpc *reg_ctx =
- new RegisterContextPOSIXProcessMonitor_powerpc(*this, 0,
- reg_interface);
- m_posix_thread = reg_ctx;
- m_reg_context_sp.reset(reg_ctx);
- break;
- }
- case llvm::Triple::x86:
- case llvm::Triple::x86_64: {
- RegisterContextPOSIXProcessMonitor_x86_64 *reg_ctx =
- new RegisterContextPOSIXProcessMonitor_x86_64(*this, 0,
- reg_interface);
- m_posix_thread = reg_ctx;
- m_reg_context_sp.reset(reg_ctx);
- break;
- }
- default:
- break;
- }
- }
- return m_reg_context_sp;
-}
-
-lldb::RegisterContextSP
-FreeBSDThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) {
- lldb::RegisterContextSP reg_ctx_sp;
- uint32_t concrete_frame_idx = 0;
-
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
- LLDB_LOGV(log, "called");
-
- if (frame)
- concrete_frame_idx = frame->GetConcreteFrameIndex();
-
- if (concrete_frame_idx == 0)
- reg_ctx_sp = GetRegisterContext();
- else {
- reg_ctx_sp = GetUnwinder().CreateRegisterContextForFrame(frame);
- }
-
- return reg_ctx_sp;
-}
-
-lldb::addr_t FreeBSDThread::GetThreadPointer() {
- ProcessMonitor &monitor = GetMonitor();
- addr_t addr;
- if (monitor.ReadThreadPointer(GetID(), addr))
- return addr;
- else
- return LLDB_INVALID_ADDRESS;
-}
-
-bool FreeBSDThread::CalculateStopInfo() {
- SetStopInfo(m_stop_info_sp);
- return true;
-}
-
-void FreeBSDThread::DidStop() {
- // Don't set the thread state to stopped unless we really stopped.
-}
-
-void FreeBSDThread::WillResume(lldb::StateType resume_state) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
- LLDB_LOGF(log, "tid %lu resume_state = %s", GetID(),
- lldb_private::StateAsCString(resume_state));
- ProcessSP process_sp(GetProcess());
- ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(process_sp.get());
- int signo = GetResumeSignal();
- bool signo_valid = process->GetUnixSignals()->SignalIsValid(signo);
-
- switch (resume_state) {
- case eStateSuspended:
- case eStateStopped:
- process->m_suspend_tids.push_back(GetID());
- break;
- case eStateRunning:
- process->m_run_tids.push_back(GetID());
- if (signo_valid)
- process->m_resume_signo = signo;
- break;
- case eStateStepping:
- process->m_step_tids.push_back(GetID());
- if (signo_valid)
- process->m_resume_signo = signo;
- break;
- default:
- break;
- }
-}
-
-bool FreeBSDThread::Resume() {
- lldb::StateType resume_state = GetResumeState();
- ProcessMonitor &monitor = GetMonitor();
- bool status;
-
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
- LLDB_LOGF(log, "FreeBSDThread::%s (), resume_state = %s", __FUNCTION__,
- StateAsCString(resume_state));
-
- switch (resume_state) {
- default:
- assert(false && "Unexpected state for resume!");
- status = false;
- break;
-
- case lldb::eStateRunning:
- SetState(resume_state);
- status = monitor.Resume(GetID(), GetResumeSignal());
- break;
-
- case lldb::eStateStepping:
- SetState(resume_state);
- status = monitor.SingleStep(GetID(), GetResumeSignal());
- break;
- case lldb::eStateStopped:
- case lldb::eStateSuspended:
- status = true;
- break;
- }
-
- return status;
-}
-
-void FreeBSDThread::Notify(const ProcessMessage &message) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
- LLDB_LOGF(log, "FreeBSDThread::%s () message kind = '%s' for tid %" PRIu64,
- __FUNCTION__, message.PrintKind(), GetID());
-
- switch (message.GetKind()) {
- default:
- assert(false && "Unexpected message kind!");
- break;
-
- case ProcessMessage::eExitMessage:
- // Nothing to be done.
- break;
-
- case ProcessMessage::eLimboMessage:
- LimboNotify(message);
- break;
-
- case ProcessMessage::eCrashMessage:
- case ProcessMessage::eSignalMessage:
- SignalNotify(message);
- break;
-
- case ProcessMessage::eSignalDeliveredMessage:
- SignalDeliveredNotify(message);
- break;
-
- case ProcessMessage::eTraceMessage:
- TraceNotify(message);
- break;
-
- case ProcessMessage::eBreakpointMessage:
- BreakNotify(message);
- break;
-
- case ProcessMessage::eWatchpointMessage:
- WatchNotify(message);
- break;
-
- case ProcessMessage::eExecMessage:
- ExecNotify(message);
- break;
- }
-}
-
-bool FreeBSDThread::EnableHardwareWatchpoint(Watchpoint *wp) {
- bool wp_set = false;
- if (wp) {
- addr_t wp_addr = wp->GetLoadAddress();
- size_t wp_size = wp->GetByteSize();
- bool wp_read = wp->WatchpointRead();
- bool wp_write = wp->WatchpointWrite();
- uint32_t wp_hw_index = wp->GetHardwareIndex();
- POSIXBreakpointProtocol *reg_ctx = GetPOSIXBreakpointProtocol();
- if (reg_ctx)
- wp_set = reg_ctx->SetHardwareWatchpointWithIndex(
- wp_addr, wp_size, wp_read, wp_write, wp_hw_index);
- }
- return wp_set;
-}
-
-bool FreeBSDThread::DisableHardwareWatchpoint(Watchpoint *wp) {
- bool result = false;
- if (wp) {
- lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext();
- if (reg_ctx_sp.get())
- result = reg_ctx_sp->ClearHardwareWatchpoint(wp->GetHardwareIndex());
- }
- return result;
-}
-
-uint32_t FreeBSDThread::NumSupportedHardwareWatchpoints() {
- lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext();
- if (reg_ctx_sp.get())
- return reg_ctx_sp->NumSupportedHardwareWatchpoints();
- return 0;
-}
-
-uint32_t FreeBSDThread::FindVacantWatchpointIndex() {
- uint32_t hw_index = LLDB_INVALID_INDEX32;
- uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
- uint32_t wp_idx;
- POSIXBreakpointProtocol *reg_ctx = GetPOSIXBreakpointProtocol();
- if (reg_ctx) {
- for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) {
- if (reg_ctx->IsWatchpointVacant(wp_idx)) {
- hw_index = wp_idx;
- break;
- }
- }
- }
- return hw_index;
-}
-
-void FreeBSDThread::BreakNotify(const ProcessMessage &message) {
- bool status;
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
-
- assert(GetRegisterContext());
- status = GetPOSIXBreakpointProtocol()->UpdateAfterBreakpoint();
- assert(status && "Breakpoint update failed!");
-
- // With our register state restored, resolve the breakpoint object
- // corresponding to our current PC.
- assert(GetRegisterContext());
- lldb::addr_t pc = GetRegisterContext()->GetPC();
- LLDB_LOGF(log, "FreeBSDThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc);
- lldb::BreakpointSiteSP bp_site(
- GetProcess()->GetBreakpointSiteList().FindByAddress(pc));
-
- // If the breakpoint is for this thread, then we'll report the hit, but if it
- // is for another thread, we create a stop reason with should_stop=false. If
- // there is no breakpoint location, then report an invalid stop reason. We
- // don't need to worry about stepping over the breakpoint here, that will be
- // taken care of when the thread resumes and notices that there's a
- // breakpoint under the pc.
- if (bp_site) {
- lldb::break_id_t bp_id = bp_site->GetID();
- // If we have an operating system plug-in, we might have set a thread
- // specific breakpoint using the operating system thread ID, so we can't
- // make any assumptions about the thread ID so we must always report the
- // breakpoint regardless of the thread.
- if (bp_site->ValidForThisThread(this) ||
- GetProcess()->GetOperatingSystem() != nullptr)
- SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id));
- else {
- const bool should_stop = false;
- SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id,
- should_stop));
- }
- } else
- SetStopInfo(StopInfoSP());
-}
-
-void FreeBSDThread::WatchNotify(const ProcessMessage &message) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
-
- lldb::addr_t halt_addr = message.GetHWAddress();
- LLDB_LOGF(log,
- "FreeBSDThread::%s () Hardware Watchpoint Address = 0x%8.8" PRIx64,
- __FUNCTION__, halt_addr);
-
- POSIXBreakpointProtocol *reg_ctx = GetPOSIXBreakpointProtocol();
- if (reg_ctx) {
- uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints();
- uint32_t wp_idx;
- for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) {
- if (reg_ctx->IsWatchpointHit(wp_idx)) {
- // Clear the watchpoint hit here
- reg_ctx->ClearWatchpointHits();
- break;
- }
- }
-
- if (wp_idx == num_hw_wps)
- return;
-
- Target &target = GetProcess()->GetTarget();
- lldb::addr_t wp_monitor_addr = reg_ctx->GetWatchpointAddress(wp_idx);
- const WatchpointList &wp_list = target.GetWatchpointList();
- lldb::WatchpointSP wp_sp = wp_list.FindByAddress(wp_monitor_addr);
-
- assert(wp_sp.get() && "No watchpoint found");
- SetStopInfo(
- StopInfo::CreateStopReasonWithWatchpointID(*this, wp_sp->GetID()));
- }
-}
-
-void FreeBSDThread::TraceNotify(const ProcessMessage &message) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
-
- // Try to resolve the breakpoint object corresponding to the current PC.
- assert(GetRegisterContext());
- lldb::addr_t pc = GetRegisterContext()->GetPC();
- LLDB_LOGF(log, "FreeBSDThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc);
- lldb::BreakpointSiteSP bp_site(
- GetProcess()->GetBreakpointSiteList().FindByAddress(pc));
-
- // If the current pc is a breakpoint site then set the StopInfo to
- // Breakpoint. Otherwise, set the StopInfo to Watchpoint or Trace. If we have
- // an operating system plug-in, we might have set a thread specific
- // breakpoint using the operating system thread ID, so we can't make any
- // assumptions about the thread ID so we must always report the breakpoint
- // regardless of the thread.
- if (bp_site && (bp_site->ValidForThisThread(this) ||
- GetProcess()->GetOperatingSystem() != nullptr))
- SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID(
- *this, bp_site->GetID()));
- else {
- POSIXBreakpointProtocol *reg_ctx = GetPOSIXBreakpointProtocol();
- if (reg_ctx) {
- uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints();
- uint32_t wp_idx;
- for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) {
- if (reg_ctx->IsWatchpointHit(wp_idx)) {
- WatchNotify(message);
- return;
- }
- }
- }
- SetStopInfo(StopInfo::CreateStopReasonToTrace(*this));
- }
-}
-
-void FreeBSDThread::LimboNotify(const ProcessMessage &message) {
- SetStopInfo(lldb::StopInfoSP(new POSIXLimboStopInfo(*this)));
-}
-
-void FreeBSDThread::SignalNotify(const ProcessMessage &message) {
- int signo = message.GetSignal();
- if (message.GetKind() == ProcessMessage::eCrashMessage) {
- std::string stop_description = GetCrashReasonString(
- message.GetCrashReason(), message.GetFaultAddress());
- SetStopInfo(StopInfo::CreateStopReasonWithSignal(
- *this, signo, stop_description.c_str()));
- } else {
- SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, signo));
- }
-}
-
-void FreeBSDThread::SignalDeliveredNotify(const ProcessMessage &message) {
- int signo = message.GetSignal();
- SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, signo));
-}
-
-unsigned FreeBSDThread::GetRegisterIndexFromOffset(unsigned offset) {
- unsigned reg = LLDB_INVALID_REGNUM;
- ArchSpec arch = HostInfo::GetArchitecture();
-
- switch (arch.GetMachine()) {
- default:
- llvm_unreachable("CPU type not supported!");
- break;
-
- case llvm::Triple::aarch64:
- case llvm::Triple::arm:
- case llvm::Triple::mips64:
- case llvm::Triple::ppc:
- case llvm::Triple::ppc64:
- case llvm::Triple::x86:
- case llvm::Triple::x86_64: {
- POSIXBreakpointProtocol *reg_ctx = GetPOSIXBreakpointProtocol();
- reg = reg_ctx->GetRegisterIndexFromOffset(offset);
- } break;
- }
- return reg;
-}
-
-void FreeBSDThread::ExecNotify(const ProcessMessage &message) {
- SetStopInfo(StopInfo::CreateStopReasonWithExec(*this));
-}
-
-const char *FreeBSDThread::GetRegisterName(unsigned reg) {
- const char *name = nullptr;
- ArchSpec arch = HostInfo::GetArchitecture();
-
- switch (arch.GetMachine()) {
- default:
- assert(false && "CPU type not supported!");
- break;
-
- case llvm::Triple::aarch64:
- case llvm::Triple::arm:
- case llvm::Triple::mips64:
- case llvm::Triple::ppc:
- case llvm::Triple::ppc64:
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- name = GetRegisterContext()->GetRegisterName(reg);
- break;
- }
- return name;
-}
-
-const char *FreeBSDThread::GetRegisterNameFromOffset(unsigned offset) {
- return GetRegisterName(GetRegisterIndexFromOffset(offset));
-}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.h b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.h
deleted file mode 100644
index 774ffb5..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/FreeBSDThread.h
+++ /dev/null
@@ -1,111 +0,0 @@
-//===-- FreeBSDThread.h -----------------------------------------*- 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_FreeBSDThread_H_
-#define liblldb_FreeBSDThread_H_
-
-#include <memory>
-#include <string>
-
-#include "RegisterContextPOSIX.h"
-#include "lldb/Target/Thread.h"
-
-class ProcessMessage;
-class ProcessMonitor;
-class POSIXBreakpointProtocol;
-
-// @class FreeBSDThread
-// Abstraction of a FreeBSD thread.
-class FreeBSDThread : public lldb_private::Thread {
-public:
- // Constructors and destructors
- FreeBSDThread(lldb_private::Process &process, lldb::tid_t tid);
-
- virtual ~FreeBSDThread();
-
- // POSIXThread
- void RefreshStateAfterStop() override;
-
- // This notifies the thread when a private stop occurs.
- void DidStop() override;
-
- const char *GetInfo() override;
-
- void SetName(const char *name) override;
-
- const char *GetName() override;
-
- lldb::RegisterContextSP GetRegisterContext() override;
-
- lldb::RegisterContextSP
- CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;
-
- lldb::addr_t GetThreadPointer() override;
-
- // These functions provide a mapping from the register offset
- // back to the register index or name for use in debugging or log
- // output.
-
- unsigned GetRegisterIndexFromOffset(unsigned offset);
-
- const char *GetRegisterName(unsigned reg);
-
- const char *GetRegisterNameFromOffset(unsigned offset);
-
- // These methods form a specialized interface to POSIX threads.
- //
- bool Resume();
-
- void Notify(const ProcessMessage &message);
-
- // These methods provide an interface to watchpoints
- //
- bool EnableHardwareWatchpoint(lldb_private::Watchpoint *wp);
-
- bool DisableHardwareWatchpoint(lldb_private::Watchpoint *wp);
-
- uint32_t NumSupportedHardwareWatchpoints();
-
- uint32_t FindVacantWatchpointIndex();
-
-protected:
- POSIXBreakpointProtocol *GetPOSIXBreakpointProtocol() {
- if (!m_reg_context_sp)
- m_reg_context_sp = GetRegisterContext();
- return m_posix_thread;
- }
-
- std::unique_ptr<lldb_private::StackFrame> m_frame_up;
-
- lldb::BreakpointSiteSP m_breakpoint;
-
- bool m_thread_name_valid;
- std::string m_thread_name;
- POSIXBreakpointProtocol *m_posix_thread;
-
- ProcessMonitor &GetMonitor();
-
- bool CalculateStopInfo() override;
-
- void BreakNotify(const ProcessMessage &message);
- void WatchNotify(const ProcessMessage &message);
- virtual void TraceNotify(const ProcessMessage &message);
- void LimboNotify(const ProcessMessage &message);
- void SignalNotify(const ProcessMessage &message);
- void SignalDeliveredNotify(const ProcessMessage &message);
- void CrashNotify(const ProcessMessage &message);
- void ExitNotify(const ProcessMessage &message);
- void ExecNotify(const ProcessMessage &message);
-
- // FreeBSDThread internal API.
-
- // POSIXThread override
- virtual void WillResume(lldb::StateType resume_state) override;
-};
-
-#endif // #ifndef liblldb_FreeBSDThread_H_
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.cpp b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp
similarity index 84%
rename from src/llvm-project/lldb/source/Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.cpp
rename to src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp
index 163093c..d6426b3 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp
@@ -128,13 +128,20 @@
return std::move(process_up);
}
+NativeProcessFreeBSD::Extension
+NativeProcessFreeBSD::Factory::GetSupportedExtensions() const {
+ return Extension::multiprocess | Extension::fork | Extension::vfork |
+ Extension::pass_signals | Extension::auxv | Extension::libraries_svr4;
+}
+
// Public Instance Methods
NativeProcessFreeBSD::NativeProcessFreeBSD(::pid_t pid, int terminal_fd,
NativeDelegate &delegate,
const ArchSpec &arch,
MainLoop &mainloop)
- : NativeProcessELF(pid, terminal_fd, delegate), m_arch(arch) {
+ : NativeProcessELF(pid, terminal_fd, delegate), m_arch(arch),
+ m_main_loop(mainloop) {
if (m_terminal_fd != -1) {
Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK);
assert(status.Success());
@@ -213,8 +220,9 @@
llvm::Error error = t.CopyWatchpointsFrom(
static_cast<NativeThreadFreeBSD &>(*GetCurrentThread()));
if (error) {
- LLDB_LOG(log, "failed to copy watchpoints to new thread {0}: {1}",
- info.pl_lwpid, llvm::toString(std::move(error)));
+ LLDB_LOG_ERROR(log, std::move(error),
+ "failed to copy watchpoints to new thread {1}: {0}",
+ info.pl_lwpid);
SetState(StateType::eStateInvalid);
return;
}
@@ -257,6 +265,26 @@
info.pl_lwpid);
}
+ if (info.pl_flags & PL_FLAG_FORKED) {
+ assert(thread);
+ MonitorClone(info.pl_child_pid, info.pl_flags & PL_FLAG_VFORKED, *thread);
+ return;
+ }
+
+ if (info.pl_flags & PL_FLAG_VFORK_DONE) {
+ assert(thread);
+ if ((m_enabled_extensions & Extension::vfork) == Extension::vfork) {
+ thread->SetStoppedByVForkDone();
+ SetState(StateType::eStateStopped, true);
+ } else {
+ Status error =
+ PtraceWrapper(PT_CONTINUE, pid, reinterpret_cast<void *>(1), 0);
+ if (error.Fail())
+ SetState(StateType::eStateInvalid);
+ }
+ return;
+ }
+
if (info.pl_flags & PL_FLAG_SI) {
assert(info.pl_siginfo.si_signo == SIGTRAP);
LLDB_LOG(log, "SIGTRAP siginfo: si_code = {0}, pid = {1}",
@@ -264,19 +292,35 @@
switch (info.pl_siginfo.si_code) {
case TRAP_BRKPT:
+ LLDB_LOG(log, "SIGTRAP/TRAP_BRKPT: si_addr: {0}",
+ info.pl_siginfo.si_addr);
+
if (thread) {
- thread->SetStoppedByBreakpoint();
+ auto thread_info =
+ m_threads_stepping_with_breakpoint.find(thread->GetID());
+ if (thread_info != m_threads_stepping_with_breakpoint.end()) {
+ thread->SetStoppedByTrace();
+ Status brkpt_error = RemoveBreakpoint(thread_info->second);
+ if (brkpt_error.Fail())
+ LLDB_LOG(log, "pid = {0} remove stepping breakpoint: {1}",
+ thread_info->first, brkpt_error);
+ m_threads_stepping_with_breakpoint.erase(thread_info);
+ } else
+ thread->SetStoppedByBreakpoint();
FixupBreakpointPCAsNeeded(*thread);
}
SetState(StateType::eStateStopped, true);
return;
case TRAP_TRACE:
+ LLDB_LOG(log, "SIGTRAP/TRAP_TRACE: si_addr: {0}",
+ info.pl_siginfo.si_addr);
+
if (thread) {
auto ®ctx = static_cast<NativeRegisterContextFreeBSD &>(
thread->GetRegisterContext());
uint32_t wp_index = LLDB_INVALID_INDEX32;
- Status error =
- regctx.GetWatchpointHitIndex(wp_index, LLDB_INVALID_ADDRESS);
+ Status error = regctx.GetWatchpointHitIndex(
+ wp_index, reinterpret_cast<uintptr_t>(info.pl_siginfo.si_addr));
if (error.Fail())
LLDB_LOG(log,
"received error while checking for watchpoint hits, pid = "
@@ -354,6 +398,27 @@
return error;
}
+llvm::Expected<llvm::ArrayRef<uint8_t>>
+NativeProcessFreeBSD::GetSoftwareBreakpointTrapOpcode(size_t size_hint) {
+ static const uint8_t g_arm_opcode[] = {0xfe, 0xde, 0xff, 0xe7};
+ static const uint8_t g_thumb_opcode[] = {0x01, 0xde};
+
+ switch (GetArchitecture().GetMachine()) {
+ case llvm::Triple::arm:
+ switch (size_hint) {
+ case 2:
+ return llvm::makeArrayRef(g_thumb_opcode);
+ case 4:
+ return llvm::makeArrayRef(g_arm_opcode);
+ default:
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Unrecognised trap opcode size hint!");
+ }
+ default:
+ return NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode(size_hint);
+ }
+}
+
Status NativeProcessFreeBSD::Resume(const ResumeActionList &resume_actions) {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
LLDB_LOG(log, "pid {0}", GetID());
@@ -623,9 +688,8 @@
Status NativeProcessFreeBSD::SetBreakpoint(lldb::addr_t addr, uint32_t size,
bool hardware) {
if (hardware)
- return Status("NativeProcessFreeBSD does not support hardware breakpoints");
- else
- return SetSoftwareBreakpoint(addr, size);
+ return SetHardwareBreakpoint(addr, size);
+ return SetSoftwareBreakpoint(addr, size);
}
Status NativeProcessFreeBSD::GetLoadedModuleFileSpec(const char *module_path,
@@ -668,17 +732,17 @@
void NativeProcessFreeBSD::SigchldHandler() {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
- // Process all pending waitpid notifications.
int status;
::pid_t wait_pid =
llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status, WNOHANG);
if (wait_pid == 0)
- return; // We are done.
+ return;
if (wait_pid == -1) {
Status error(errno, eErrorTypePOSIX);
LLDB_LOG(log, "waitpid ({0}, &status, _) failed: {1}", GetID(), error);
+ return;
}
WaitStatus wait_status = WaitStatus::Decode(status);
@@ -848,7 +912,7 @@
PtraceWrapper(PT_GET_EVENT_MASK, GetID(), &events, sizeof(events));
if (status.Fail())
return status;
- events |= PTRACE_LWP;
+ events |= PTRACE_LWP | PTRACE_FORK | PTRACE_VFORK;
status = PtraceWrapper(PT_SET_EVENT_MASK, GetID(), &events, sizeof(events));
if (status.Fail())
return status;
@@ -878,3 +942,70 @@
return error;
}
+
+bool NativeProcessFreeBSD::SupportHardwareSingleStepping() const {
+ return !m_arch.IsMIPS();
+}
+
+void NativeProcessFreeBSD::MonitorClone(::pid_t child_pid, bool is_vfork,
+ NativeThreadFreeBSD &parent_thread) {
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ LLDB_LOG(log, "fork, child_pid={0}", child_pid);
+
+ int status;
+ ::pid_t wait_pid =
+ llvm::sys::RetryAfterSignal(-1, ::waitpid, child_pid, &status, 0);
+ if (wait_pid != child_pid) {
+ LLDB_LOG(log,
+ "waiting for pid {0} failed. Assuming the pid has "
+ "disappeared in the meantime",
+ child_pid);
+ return;
+ }
+ if (WIFEXITED(status)) {
+ LLDB_LOG(log,
+ "waiting for pid {0} returned an 'exited' event. Not "
+ "tracking it.",
+ child_pid);
+ return;
+ }
+
+ struct ptrace_lwpinfo info;
+ const auto siginfo_err = PtraceWrapper(PT_LWPINFO, child_pid, &info, sizeof(info));
+ if (siginfo_err.Fail()) {
+ LLDB_LOG(log, "PT_LWPINFO failed {0}", siginfo_err);
+ return;
+ }
+ assert(info.pl_event == PL_EVENT_SIGNAL);
+ lldb::tid_t child_tid = info.pl_lwpid;
+
+ std::unique_ptr<NativeProcessFreeBSD> child_process{
+ new NativeProcessFreeBSD(static_cast<::pid_t>(child_pid), m_terminal_fd,
+ m_delegate, m_arch, m_main_loop)};
+ if (!is_vfork)
+ child_process->m_software_breakpoints = m_software_breakpoints;
+
+ Extension expected_ext = is_vfork ? Extension::vfork : Extension::fork;
+ if ((m_enabled_extensions & expected_ext) == expected_ext) {
+ child_process->SetupTrace();
+ for (const auto &thread : child_process->m_threads)
+ static_cast<NativeThreadFreeBSD &>(*thread).SetStoppedBySignal(SIGSTOP);
+ child_process->SetState(StateType::eStateStopped, false);
+
+ m_delegate.NewSubprocess(this, std::move(child_process));
+ if (is_vfork)
+ parent_thread.SetStoppedByVFork(child_pid, child_tid);
+ else
+ parent_thread.SetStoppedByFork(child_pid, child_tid);
+ SetState(StateType::eStateStopped, true);
+ } else {
+ child_process->Detach();
+ Status pt_error =
+ PtraceWrapper(PT_CONTINUE, GetID(), reinterpret_cast<void *>(1), 0);
+ if (pt_error.Fail()) {
+ LLDB_LOG_ERROR(log, pt_error.ToError(),
+ "unable to resume parent process {1}: {0}", GetID());
+ SetState(StateType::eStateInvalid);
+ }
+ }
+}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.h b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.h
similarity index 88%
rename from src/llvm-project/lldb/source/Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.h
rename to src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.h
index 3c7a940..7ec9d17 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.h
@@ -10,6 +10,8 @@
#define liblldb_NativeProcessFreeBSD_H_
#include "Plugins/Process/POSIX/NativeProcessELF.h"
+#include "Plugins/Process/Utility/NativeProcessSoftwareSingleStep.h"
+
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/FileSpec.h"
@@ -25,7 +27,8 @@
/// for debugging.
///
/// Changes in the inferior process state are broadcasted.
-class NativeProcessFreeBSD : public NativeProcessELF {
+class NativeProcessFreeBSD : public NativeProcessELF,
+ private NativeProcessSoftwareSingleStep {
public:
class Factory : public NativeProcessProtocol::Factory {
public:
@@ -36,6 +39,8 @@
llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Attach(lldb::pid_t pid, NativeDelegate &native_delegate,
MainLoop &mainloop) const override;
+
+ Extension GetSupportedExtensions() const override;
};
// NativeProcessProtocol Interface
@@ -84,9 +89,16 @@
static Status PtraceWrapper(int req, lldb::pid_t pid, void *addr = nullptr,
int data = 0, int *result = nullptr);
+ bool SupportHardwareSingleStepping() const;
+
+protected:
+ llvm::Expected<llvm::ArrayRef<uint8_t>>
+ GetSoftwareBreakpointTrapOpcode(size_t size_hint) override;
+
private:
MainLoop::SignalHandleUP m_sigchld_handle;
ArchSpec m_arch;
+ MainLoop& m_main_loop;
LazyBool m_supports_mem_region = eLazyBoolCalculate;
std::vector<std::pair<MemoryRegionInfo, FileSpec>> m_mem_region_cache;
@@ -104,6 +116,8 @@
void MonitorSIGSTOP(lldb::pid_t pid);
void MonitorSIGTRAP(lldb::pid_t pid);
void MonitorSignal(lldb::pid_t pid, int signal);
+ void MonitorClone(::pid_t child_pid, bool is_vfork,
+ NativeThreadFreeBSD &parent_thread);
Status PopulateMemoryRegionCache();
void SigchldHandler();
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD.cpp b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.cpp
similarity index 92%
rename from src/llvm-project/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD.cpp
rename to src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.cpp
index ac3cc4f..3d744f7 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.cpp
@@ -8,7 +8,7 @@
#include "NativeRegisterContextFreeBSD.h"
-#include "Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.h"
+#include "Plugins/Process/FreeBSD/NativeProcessFreeBSD.h"
#include "lldb/Host/common/NativeProcessProtocol.h"
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD.h b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h
similarity index 100%
rename from src/llvm-project/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD.h
rename to src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm.cpp b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm.cpp
new file mode 100644
index 0000000..c4ee377
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm.cpp
@@ -0,0 +1,202 @@
+//===-- NativeRegisterContextFreeBSD_arm.cpp ------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__arm__)
+
+#include "NativeRegisterContextFreeBSD_arm.h"
+
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Status.h"
+
+#include "Plugins/Process/FreeBSD/NativeProcessFreeBSD.h"
+#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h"
+
+// clang-format off
+#include <sys/param.h>
+#include <sys/ptrace.h>
+#include <sys/types.h>
+// clang-format on
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::process_freebsd;
+
+NativeRegisterContextFreeBSD *
+NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD(
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
+ return new NativeRegisterContextFreeBSD_arm(target_arch, native_thread);
+}
+
+NativeRegisterContextFreeBSD_arm::NativeRegisterContextFreeBSD_arm(
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
+ : NativeRegisterContextRegisterInfo(
+ native_thread, new RegisterInfoPOSIX_arm(target_arch)) {}
+
+RegisterInfoPOSIX_arm &
+NativeRegisterContextFreeBSD_arm::GetRegisterInfo() const {
+ return static_cast<RegisterInfoPOSIX_arm &>(*m_register_info_interface_up);
+}
+
+uint32_t NativeRegisterContextFreeBSD_arm::GetRegisterSetCount() const {
+ return GetRegisterInfo().GetRegisterSetCount();
+}
+
+const RegisterSet *
+NativeRegisterContextFreeBSD_arm::GetRegisterSet(uint32_t set_index) const {
+ return GetRegisterInfo().GetRegisterSet(set_index);
+}
+
+uint32_t NativeRegisterContextFreeBSD_arm::GetUserRegisterCount() const {
+ uint32_t count = 0;
+ for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)
+ count += GetRegisterSet(set_index)->num_registers;
+ return count;
+}
+
+Status NativeRegisterContextFreeBSD_arm::ReadRegisterSet(uint32_t set) {
+ switch (set) {
+ case RegisterInfoPOSIX_arm::GPRegSet:
+ return NativeProcessFreeBSD::PtraceWrapper(PT_GETREGS, m_thread.GetID(),
+ m_reg_data.data());
+ case RegisterInfoPOSIX_arm::FPRegSet:
+ return NativeProcessFreeBSD::PtraceWrapper(
+ PT_GETVFPREGS, m_thread.GetID(),
+ m_reg_data.data() + sizeof(RegisterInfoPOSIX_arm::GPR));
+ }
+ llvm_unreachable("NativeRegisterContextFreeBSD_arm::ReadRegisterSet");
+}
+
+Status NativeRegisterContextFreeBSD_arm::WriteRegisterSet(uint32_t set) {
+ switch (set) {
+ case RegisterInfoPOSIX_arm::GPRegSet:
+ return NativeProcessFreeBSD::PtraceWrapper(PT_SETREGS, m_thread.GetID(),
+ m_reg_data.data());
+ case RegisterInfoPOSIX_arm::FPRegSet:
+ return NativeProcessFreeBSD::PtraceWrapper(
+ PT_SETVFPREGS, m_thread.GetID(),
+ m_reg_data.data() + sizeof(RegisterInfoPOSIX_arm::GPR));
+ }
+ llvm_unreachable("NativeRegisterContextFreeBSD_arm::WriteRegisterSet");
+}
+
+Status
+NativeRegisterContextFreeBSD_arm::ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue ®_value) {
+ Status error;
+
+ if (!reg_info) {
+ error.SetErrorString("reg_info NULL");
+ return error;
+ }
+
+ const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+
+ if (reg == LLDB_INVALID_REGNUM)
+ return Status("no lldb regnum for %s", reg_info && reg_info->name
+ ? reg_info->name
+ : "<unknown register>");
+
+ uint32_t set = GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg);
+ error = ReadRegisterSet(set);
+ if (error.Fail())
+ return error;
+
+ assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());
+ reg_value.SetBytes(m_reg_data.data() + reg_info->byte_offset,
+ reg_info->byte_size, endian::InlHostByteOrder());
+ return error;
+}
+
+Status NativeRegisterContextFreeBSD_arm::WriteRegister(
+ const RegisterInfo *reg_info, const RegisterValue ®_value) {
+ Status error;
+
+ if (!reg_info)
+ return Status("reg_info NULL");
+
+ const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+
+ if (reg == LLDB_INVALID_REGNUM)
+ return Status("no lldb regnum for %s", reg_info && reg_info->name
+ ? reg_info->name
+ : "<unknown register>");
+
+ uint32_t set = GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg);
+ error = ReadRegisterSet(set);
+ if (error.Fail())
+ return error;
+
+ assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());
+ ::memcpy(m_reg_data.data() + reg_info->byte_offset, reg_value.GetBytes(),
+ reg_info->byte_size);
+
+ return WriteRegisterSet(set);
+}
+
+Status NativeRegisterContextFreeBSD_arm::ReadAllRegisterValues(
+ lldb::DataBufferSP &data_sp) {
+ Status error;
+
+ error = ReadRegisterSet(RegisterInfoPOSIX_arm::GPRegSet);
+ if (error.Fail())
+ return error;
+
+ error = ReadRegisterSet(RegisterInfoPOSIX_arm::FPRegSet);
+ if (error.Fail())
+ return error;
+
+ data_sp.reset(new DataBufferHeap(m_reg_data.size(), 0));
+ uint8_t *dst = data_sp->GetBytes();
+ ::memcpy(dst, m_reg_data.data(), m_reg_data.size());
+
+ return error;
+}
+
+Status NativeRegisterContextFreeBSD_arm::WriteAllRegisterValues(
+ const lldb::DataBufferSP &data_sp) {
+ Status error;
+
+ if (!data_sp) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextFreeBSD_arm::%s invalid data_sp provided",
+ __FUNCTION__);
+ return error;
+ }
+
+ if (data_sp->GetByteSize() != m_reg_data.size()) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextFreeBSD_arm::%s data_sp contained mismatched "
+ "data size, expected %" PRIu64 ", actual %" PRIu64,
+ __FUNCTION__, m_reg_data.size(), data_sp->GetByteSize());
+ return error;
+ }
+
+ uint8_t *src = data_sp->GetBytes();
+ if (src == nullptr) {
+ error.SetErrorStringWithFormat("NativeRegisterContextFreeBSD_arm::%s "
+ "DataBuffer::GetBytes() returned a null "
+ "pointer",
+ __FUNCTION__);
+ return error;
+ }
+ ::memcpy(m_reg_data.data(), src, m_reg_data.size());
+
+ error = WriteRegisterSet(RegisterInfoPOSIX_arm::GPRegSet);
+ if (error.Fail())
+ return error;
+
+ return WriteRegisterSet(RegisterInfoPOSIX_arm::FPRegSet);
+}
+
+llvm::Error NativeRegisterContextFreeBSD_arm::CopyHardwareWatchpointsFrom(
+ NativeRegisterContextFreeBSD &source) {
+ return llvm::Error::success();
+}
+
+#endif // defined (__arm__)
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm.h b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm.h
new file mode 100644
index 0000000..4be75b9
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm.h
@@ -0,0 +1,68 @@
+//===-- NativeRegisterContextFreeBSD_arm.h ----------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__arm__)
+
+#ifndef lldb_NativeRegisterContextFreeBSD_arm_h
+#define lldb_NativeRegisterContextFreeBSD_arm_h
+
+// clang-format off
+#include <sys/types.h>
+#include <machine/reg.h>
+#include <machine/vfp.h>
+// clang-format on
+
+#include "Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h"
+#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h"
+
+#include <array>
+
+namespace lldb_private {
+namespace process_freebsd {
+
+class NativeProcessFreeBSD;
+
+class NativeRegisterContextFreeBSD_arm : public NativeRegisterContextFreeBSD {
+public:
+ NativeRegisterContextFreeBSD_arm(const ArchSpec &target_arch,
+ NativeThreadProtocol &native_thread);
+
+ uint32_t GetRegisterSetCount() const override;
+
+ uint32_t GetUserRegisterCount() const override;
+
+ const RegisterSet *GetRegisterSet(uint32_t set_index) const override;
+
+ Status ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue ®_value) override;
+
+ Status WriteRegister(const RegisterInfo *reg_info,
+ const RegisterValue ®_value) override;
+
+ Status ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+
+ Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
+
+ llvm::Error
+ CopyHardwareWatchpointsFrom(NativeRegisterContextFreeBSD &source) override;
+
+private:
+ std::array<uint8_t, sizeof(reg) + sizeof(vfp_state)> m_reg_data;
+
+ Status ReadRegisterSet(uint32_t set);
+ Status WriteRegisterSet(uint32_t set);
+
+ RegisterInfoPOSIX_arm &GetRegisterInfo() const;
+};
+
+} // namespace process_freebsd
+} // namespace lldb_private
+
+#endif // #ifndef lldb_NativeRegisterContextFreeBSD_arm_h
+
+#endif // defined (__arm__)
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp
new file mode 100644
index 0000000..4578138
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp
@@ -0,0 +1,282 @@
+//===-- NativeRegisterContextFreeBSD_arm64.cpp ----------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__aarch64__)
+
+#include "NativeRegisterContextFreeBSD_arm64.h"
+
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Status.h"
+
+#include "Plugins/Process/FreeBSD/NativeProcessFreeBSD.h"
+#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
+#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
+
+// clang-format off
+#include <sys/param.h>
+#include <sys/ptrace.h>
+#include <sys/types.h>
+// clang-format on
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::process_freebsd;
+
+NativeRegisterContextFreeBSD *
+NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD(
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
+ return new NativeRegisterContextFreeBSD_arm64(target_arch, native_thread);
+}
+
+NativeRegisterContextFreeBSD_arm64::NativeRegisterContextFreeBSD_arm64(
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
+ : NativeRegisterContextRegisterInfo(
+ native_thread, new RegisterInfoPOSIX_arm64(target_arch, 0))
+#ifdef LLDB_HAS_FREEBSD_WATCHPOINT
+ ,
+ m_read_dbreg(false)
+#endif
+{
+ ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs));
+ ::memset(&m_hbp_regs, 0, sizeof(m_hbp_regs));
+}
+
+RegisterInfoPOSIX_arm64 &
+NativeRegisterContextFreeBSD_arm64::GetRegisterInfo() const {
+ return static_cast<RegisterInfoPOSIX_arm64 &>(*m_register_info_interface_up);
+}
+
+uint32_t NativeRegisterContextFreeBSD_arm64::GetRegisterSetCount() const {
+ return GetRegisterInfo().GetRegisterSetCount();
+}
+
+const RegisterSet *
+NativeRegisterContextFreeBSD_arm64::GetRegisterSet(uint32_t set_index) const {
+ return GetRegisterInfo().GetRegisterSet(set_index);
+}
+
+uint32_t NativeRegisterContextFreeBSD_arm64::GetUserRegisterCount() const {
+ uint32_t count = 0;
+ for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)
+ count += GetRegisterSet(set_index)->num_registers;
+ return count;
+}
+
+Status NativeRegisterContextFreeBSD_arm64::ReadRegisterSet(uint32_t set) {
+ switch (set) {
+ case RegisterInfoPOSIX_arm64::GPRegSet:
+ return NativeProcessFreeBSD::PtraceWrapper(PT_GETREGS, m_thread.GetID(),
+ m_reg_data.data());
+ case RegisterInfoPOSIX_arm64::FPRegSet:
+ return NativeProcessFreeBSD::PtraceWrapper(
+ PT_GETFPREGS, m_thread.GetID(),
+ m_reg_data.data() + sizeof(RegisterInfoPOSIX_arm64::GPR));
+ }
+ llvm_unreachable("NativeRegisterContextFreeBSD_arm64::ReadRegisterSet");
+}
+
+Status NativeRegisterContextFreeBSD_arm64::WriteRegisterSet(uint32_t set) {
+ switch (set) {
+ case RegisterInfoPOSIX_arm64::GPRegSet:
+ return NativeProcessFreeBSD::PtraceWrapper(PT_SETREGS, m_thread.GetID(),
+ m_reg_data.data());
+ case RegisterInfoPOSIX_arm64::FPRegSet:
+ return NativeProcessFreeBSD::PtraceWrapper(
+ PT_SETFPREGS, m_thread.GetID(),
+ m_reg_data.data() + sizeof(RegisterInfoPOSIX_arm64::GPR));
+ }
+ llvm_unreachable("NativeRegisterContextFreeBSD_arm64::WriteRegisterSet");
+}
+
+Status
+NativeRegisterContextFreeBSD_arm64::ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue ®_value) {
+ Status error;
+
+ if (!reg_info) {
+ error.SetErrorString("reg_info NULL");
+ return error;
+ }
+
+ const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+
+ if (reg == LLDB_INVALID_REGNUM)
+ return Status("no lldb regnum for %s", reg_info && reg_info->name
+ ? reg_info->name
+ : "<unknown register>");
+
+ uint32_t set = GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg);
+ error = ReadRegisterSet(set);
+ if (error.Fail())
+ return error;
+
+ assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());
+ reg_value.SetBytes(m_reg_data.data() + reg_info->byte_offset,
+ reg_info->byte_size, endian::InlHostByteOrder());
+ return error;
+}
+
+Status NativeRegisterContextFreeBSD_arm64::WriteRegister(
+ const RegisterInfo *reg_info, const RegisterValue ®_value) {
+ Status error;
+
+ if (!reg_info)
+ return Status("reg_info NULL");
+
+ const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+
+ if (reg == LLDB_INVALID_REGNUM)
+ return Status("no lldb regnum for %s", reg_info && reg_info->name
+ ? reg_info->name
+ : "<unknown register>");
+
+ uint32_t set = GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg);
+ error = ReadRegisterSet(set);
+ if (error.Fail())
+ return error;
+
+ assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());
+ ::memcpy(m_reg_data.data() + reg_info->byte_offset, reg_value.GetBytes(),
+ reg_info->byte_size);
+
+ return WriteRegisterSet(set);
+}
+
+Status NativeRegisterContextFreeBSD_arm64::ReadAllRegisterValues(
+ lldb::DataBufferSP &data_sp) {
+ Status error;
+
+ error = ReadRegisterSet(RegisterInfoPOSIX_arm64::GPRegSet);
+ if (error.Fail())
+ return error;
+
+ error = ReadRegisterSet(RegisterInfoPOSIX_arm64::FPRegSet);
+ if (error.Fail())
+ return error;
+
+ data_sp.reset(new DataBufferHeap(m_reg_data.size(), 0));
+ uint8_t *dst = data_sp->GetBytes();
+ ::memcpy(dst, m_reg_data.data(), m_reg_data.size());
+
+ return error;
+}
+
+Status NativeRegisterContextFreeBSD_arm64::WriteAllRegisterValues(
+ const lldb::DataBufferSP &data_sp) {
+ Status error;
+
+ if (!data_sp) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextFreeBSD_arm64::%s invalid data_sp provided",
+ __FUNCTION__);
+ return error;
+ }
+
+ if (data_sp->GetByteSize() != m_reg_data.size()) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextFreeBSD_arm64::%s data_sp contained mismatched "
+ "data size, expected %" PRIu64 ", actual %" PRIu64,
+ __FUNCTION__, m_reg_data.size(), data_sp->GetByteSize());
+ return error;
+ }
+
+ uint8_t *src = data_sp->GetBytes();
+ if (src == nullptr) {
+ error.SetErrorStringWithFormat("NativeRegisterContextFreeBSD_arm64::%s "
+ "DataBuffer::GetBytes() returned a null "
+ "pointer",
+ __FUNCTION__);
+ return error;
+ }
+ ::memcpy(m_reg_data.data(), src, m_reg_data.size());
+
+ error = WriteRegisterSet(RegisterInfoPOSIX_arm64::GPRegSet);
+ if (error.Fail())
+ return error;
+
+ return WriteRegisterSet(RegisterInfoPOSIX_arm64::FPRegSet);
+}
+
+llvm::Error NativeRegisterContextFreeBSD_arm64::CopyHardwareWatchpointsFrom(
+ NativeRegisterContextFreeBSD &source) {
+#ifdef LLDB_HAS_FREEBSD_WATCHPOINT
+ auto &r_source = static_cast<NativeRegisterContextFreeBSD_arm64 &>(source);
+ llvm::Error error = r_source.ReadHardwareDebugInfo();
+ if (error)
+ return error;
+
+ m_dbreg = r_source.m_dbreg;
+ m_hbp_regs = r_source.m_hbp_regs;
+ m_hwp_regs = r_source.m_hwp_regs;
+ m_max_hbp_supported = r_source.m_max_hbp_supported;
+ m_max_hwp_supported = r_source.m_max_hwp_supported;
+ m_read_dbreg = true;
+
+ // on FreeBSD this writes both breakpoints and watchpoints
+ return WriteHardwareDebugRegs(eDREGTypeWATCH);
+#else
+ return llvm::Error::success();
+#endif
+}
+
+llvm::Error NativeRegisterContextFreeBSD_arm64::ReadHardwareDebugInfo() {
+#ifdef LLDB_HAS_FREEBSD_WATCHPOINT
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_REGISTERS));
+
+ // we're fully stateful, so no need to reread control registers ever
+ if (m_read_dbreg)
+ return llvm::Error::success();
+
+ Status res = NativeProcessFreeBSD::PtraceWrapper(PT_GETDBREGS,
+ m_thread.GetID(), &m_dbreg);
+ if (res.Fail())
+ return res.ToError();
+
+ LLDB_LOG(log, "m_dbreg read: debug_ver={0}, nbkpts={1}, nwtpts={2}",
+ m_dbreg.db_debug_ver, m_dbreg.db_nbkpts, m_dbreg.db_nwtpts);
+ m_max_hbp_supported = m_dbreg.db_nbkpts;
+ m_max_hwp_supported = m_dbreg.db_nwtpts;
+ assert(m_max_hbp_supported <= m_hbp_regs.size());
+ assert(m_max_hwp_supported <= m_hwp_regs.size());
+
+ m_read_dbreg = true;
+ return llvm::Error::success();
+#else
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "Hardware breakpoints/watchpoints require FreeBSD 14.0");
+#endif
+}
+
+llvm::Error
+NativeRegisterContextFreeBSD_arm64::WriteHardwareDebugRegs(DREGType) {
+#ifdef LLDB_HAS_FREEBSD_WATCHPOINT
+ assert(m_read_dbreg && "dbregs must be read before writing them back");
+
+ // copy data from m_*_regs to m_dbreg before writing it back
+ for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
+ m_dbreg.db_breakregs[i].dbr_addr = m_hbp_regs[i].address;
+ m_dbreg.db_breakregs[i].dbr_ctrl = m_hbp_regs[i].control;
+ }
+ for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
+ m_dbreg.db_watchregs[i].dbw_addr = m_hwp_regs[i].address;
+ m_dbreg.db_watchregs[i].dbw_ctrl = m_hwp_regs[i].control;
+ }
+
+ return NativeProcessFreeBSD::PtraceWrapper(PT_SETDBREGS, m_thread.GetID(),
+ &m_dbreg)
+ .ToError();
+#else
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "Hardware breakpoints/watchpoints require FreeBSD 14.0");
+#endif
+}
+
+#endif // defined (__aarch64__)
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.h b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.h
new file mode 100644
index 0000000..a230f8f
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.h
@@ -0,0 +1,86 @@
+//===-- NativeRegisterContextFreeBSD_arm64.h --------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__aarch64__)
+
+#ifndef lldb_NativeRegisterContextFreeBSD_arm64_h
+#define lldb_NativeRegisterContextFreeBSD_arm64_h
+
+// clang-format off
+#include <sys/types.h>
+#include <sys/param.h>
+#include <machine/reg.h>
+// clang-format on
+
+#include "Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h"
+#include "Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.h"
+#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
+
+#include <array>
+
+#if __FreeBSD_version >= 1300139
+# define LLDB_HAS_FREEBSD_WATCHPOINT 1
+#endif
+
+namespace lldb_private {
+namespace process_freebsd {
+
+class NativeProcessFreeBSD;
+
+class NativeRegisterContextFreeBSD_arm64
+ : public NativeRegisterContextFreeBSD,
+ public NativeRegisterContextDBReg_arm64 {
+public:
+ NativeRegisterContextFreeBSD_arm64(const ArchSpec &target_arch,
+ NativeThreadProtocol &native_thread);
+
+ uint32_t GetRegisterSetCount() const override;
+
+ uint32_t GetUserRegisterCount() const override;
+
+ const RegisterSet *GetRegisterSet(uint32_t set_index) const override;
+
+ Status ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue ®_value) override;
+
+ Status WriteRegister(const RegisterInfo *reg_info,
+ const RegisterValue ®_value) override;
+
+ Status ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+
+ Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
+
+ llvm::Error
+ CopyHardwareWatchpointsFrom(NativeRegisterContextFreeBSD &source) override;
+
+private:
+ // Due to alignment, FreeBSD reg/fpreg are a few bytes larger than
+ // LLDB's GPR/FPU structs. However, all fields have matching offsets
+ // and sizes, so we do not have to worry about these (and we have
+ // a unittest to assert that).
+ std::array<uint8_t, sizeof(reg) + sizeof(fpreg)> m_reg_data;
+#ifdef LLDB_HAS_FREEBSD_WATCHPOINT
+ dbreg m_dbreg;
+ bool m_read_dbreg;
+#endif
+
+ Status ReadRegisterSet(uint32_t set);
+ Status WriteRegisterSet(uint32_t set);
+
+ llvm::Error ReadHardwareDebugInfo() override;
+ llvm::Error WriteHardwareDebugRegs(DREGType hwbType) override;
+
+ RegisterInfoPOSIX_arm64 &GetRegisterInfo() const;
+};
+
+} // namespace process_freebsd
+} // namespace lldb_private
+
+#endif // #ifndef lldb_NativeRegisterContextFreeBSD_arm64_h
+
+#endif // defined (__aarch64__)
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.cpp b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.cpp
new file mode 100644
index 0000000..8e722c0
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.cpp
@@ -0,0 +1,186 @@
+//===-- NativeRegisterContextFreeBSD_mips64.cpp ---------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__mips64__)
+
+#include "NativeRegisterContextFreeBSD_mips64.h"
+
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Status.h"
+
+#include "Plugins/Process/FreeBSD/NativeProcessFreeBSD.h"
+
+// clang-format off
+#include <sys/param.h>
+#include <sys/ptrace.h>
+#include <sys/types.h>
+// clang-format on
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::process_freebsd;
+
+NativeRegisterContextFreeBSD *
+NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD(
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
+ return new NativeRegisterContextFreeBSD_mips64(target_arch, native_thread);
+}
+
+NativeRegisterContextFreeBSD_mips64::NativeRegisterContextFreeBSD_mips64(
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
+ : NativeRegisterContextRegisterInfo(
+ native_thread, new RegisterContextFreeBSD_mips64(target_arch)) {}
+
+RegisterContextFreeBSD_mips64 &
+NativeRegisterContextFreeBSD_mips64::GetRegisterInfo() const {
+ return static_cast<RegisterContextFreeBSD_mips64 &>(
+ *m_register_info_interface_up);
+}
+
+uint32_t NativeRegisterContextFreeBSD_mips64::GetRegisterSetCount() const {
+ return GetRegisterInfo().GetRegisterSetCount();
+}
+
+const RegisterSet *
+NativeRegisterContextFreeBSD_mips64::GetRegisterSet(uint32_t set_index) const {
+ return GetRegisterInfo().GetRegisterSet(set_index);
+}
+
+uint32_t NativeRegisterContextFreeBSD_mips64::GetUserRegisterCount() const {
+ uint32_t count = 0;
+ for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)
+ count += GetRegisterSet(set_index)->num_registers;
+ return count;
+}
+
+Status NativeRegisterContextFreeBSD_mips64::ReadRegisterSet(RegSetKind set) {
+ switch (set) {
+ case GPRegSet:
+ return NativeProcessFreeBSD::PtraceWrapper(PT_GETREGS, m_thread.GetID(),
+ m_reg_data.data());
+ }
+ llvm_unreachable("NativeRegisterContextFreeBSD_mips64::ReadRegisterSet");
+}
+
+Status NativeRegisterContextFreeBSD_mips64::WriteRegisterSet(RegSetKind set) {
+ switch (set) {
+ case GPRegSet:
+ return NativeProcessFreeBSD::PtraceWrapper(PT_SETREGS, m_thread.GetID(),
+ m_reg_data.data());
+ }
+ llvm_unreachable("NativeRegisterContextFreeBSD_mips64::WriteRegisterSet");
+}
+
+Status
+NativeRegisterContextFreeBSD_mips64::ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue ®_value) {
+ Status error;
+
+ if (!reg_info) {
+ error.SetErrorString("reg_info NULL");
+ return error;
+ }
+
+ const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+
+ if (reg == LLDB_INVALID_REGNUM)
+ return Status("no lldb regnum for %s", reg_info && reg_info->name
+ ? reg_info->name
+ : "<unknown register>");
+
+ RegSetKind set = GPRegSet;
+ error = ReadRegisterSet(set);
+ if (error.Fail())
+ return error;
+
+ assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());
+ reg_value.SetBytes(m_reg_data.data() + reg_info->byte_offset,
+ reg_info->byte_size, endian::InlHostByteOrder());
+ return error;
+}
+
+Status NativeRegisterContextFreeBSD_mips64::WriteRegister(
+ const RegisterInfo *reg_info, const RegisterValue ®_value) {
+ Status error;
+
+ if (!reg_info)
+ return Status("reg_info NULL");
+
+ const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+
+ if (reg == LLDB_INVALID_REGNUM)
+ return Status("no lldb regnum for %s", reg_info && reg_info->name
+ ? reg_info->name
+ : "<unknown register>");
+
+ RegSetKind set = GPRegSet;
+ error = ReadRegisterSet(set);
+ if (error.Fail())
+ return error;
+
+ assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());
+ ::memcpy(m_reg_data.data() + reg_info->byte_offset, reg_value.GetBytes(),
+ reg_info->byte_size);
+
+ return WriteRegisterSet(set);
+}
+
+Status NativeRegisterContextFreeBSD_mips64::ReadAllRegisterValues(
+ lldb::DataBufferSP &data_sp) {
+ Status error;
+
+ error = ReadRegisterSet(GPRegSet);
+ if (error.Fail())
+ return error;
+
+ data_sp.reset(new DataBufferHeap(m_reg_data.size(), 0));
+ uint8_t *dst = data_sp->GetBytes();
+ ::memcpy(dst, m_reg_data.data(), m_reg_data.size());
+
+ return error;
+}
+
+Status NativeRegisterContextFreeBSD_mips64::WriteAllRegisterValues(
+ const lldb::DataBufferSP &data_sp) {
+ Status error;
+
+ if (!data_sp) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextFreeBSD_mips64::%s invalid data_sp provided",
+ __FUNCTION__);
+ return error;
+ }
+
+ if (data_sp->GetByteSize() != m_reg_data.size()) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextFreeBSD_mips64::%s data_sp contained mismatched "
+ "data size, expected %" PRIu64 ", actual %" PRIu64,
+ __FUNCTION__, m_reg_data.size(), data_sp->GetByteSize());
+ return error;
+ }
+
+ uint8_t *src = data_sp->GetBytes();
+ if (src == nullptr) {
+ error.SetErrorStringWithFormat("NativeRegisterContextFreeBSD_mips64::%s "
+ "DataBuffer::GetBytes() returned a null "
+ "pointer",
+ __FUNCTION__);
+ return error;
+ }
+ ::memcpy(m_reg_data.data(), src, m_reg_data.size());
+
+ return WriteRegisterSet(GPRegSet);
+}
+
+llvm::Error NativeRegisterContextFreeBSD_mips64::CopyHardwareWatchpointsFrom(
+ NativeRegisterContextFreeBSD &source) {
+ return llvm::Error::success();
+}
+
+#endif // defined (__mips64__)
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.h b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.h
new file mode 100644
index 0000000..6a3eb86
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_mips64.h
@@ -0,0 +1,71 @@
+//===-- NativeRegisterContextFreeBSD_mips64.h -------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__mips64__)
+
+#ifndef lldb_NativeRegisterContextFreeBSD_mips64_h
+#define lldb_NativeRegisterContextFreeBSD_mips64_h
+
+// clang-format off
+#include <sys/types.h>
+#include <machine/reg.h>
+// clang-format on
+
+#include "Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h"
+#include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h"
+
+#include <array>
+
+namespace lldb_private {
+namespace process_freebsd {
+
+class NativeProcessFreeBSD;
+
+class NativeRegisterContextFreeBSD_mips64
+ : public NativeRegisterContextFreeBSD {
+public:
+ NativeRegisterContextFreeBSD_mips64(const ArchSpec &target_arch,
+ NativeThreadProtocol &native_thread);
+
+ uint32_t GetRegisterSetCount() const override;
+
+ uint32_t GetUserRegisterCount() const override;
+
+ const RegisterSet *GetRegisterSet(uint32_t set_index) const override;
+
+ Status ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue ®_value) override;
+
+ Status WriteRegister(const RegisterInfo *reg_info,
+ const RegisterValue ®_value) override;
+
+ Status ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+
+ Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
+
+ llvm::Error
+ CopyHardwareWatchpointsFrom(NativeRegisterContextFreeBSD &source) override;
+
+private:
+ enum RegSetKind {
+ GPRegSet,
+ };
+ std::array<uint8_t, sizeof(reg)> m_reg_data;
+
+ Status ReadRegisterSet(RegSetKind set);
+ Status WriteRegisterSet(RegSetKind set);
+
+ RegisterContextFreeBSD_mips64 &GetRegisterInfo() const;
+};
+
+} // namespace process_freebsd
+} // namespace lldb_private
+
+#endif // #ifndef lldb_NativeRegisterContextFreeBSD_mips64_h
+
+#endif // defined (__mips64__)
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.cpp b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.cpp
new file mode 100644
index 0000000..5b5d44a
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.cpp
@@ -0,0 +1,289 @@
+//===-- NativeRegisterContextFreeBSD_powerpc.cpp --------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__powerpc__)
+
+#include "NativeRegisterContextFreeBSD_powerpc.h"
+
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Status.h"
+
+#include "Plugins/Process/FreeBSD/NativeProcessFreeBSD.h"
+// for register enum definitions
+#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"
+
+// clang-format off
+#include <sys/param.h>
+#include <sys/ptrace.h>
+#include <sys/types.h>
+// clang-format on
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::process_freebsd;
+
+static const uint32_t g_gpr_regnums[] = {
+ gpr_r0_powerpc, gpr_r1_powerpc, gpr_r2_powerpc, gpr_r3_powerpc,
+ gpr_r4_powerpc, gpr_r5_powerpc, gpr_r6_powerpc, gpr_r7_powerpc,
+ gpr_r8_powerpc, gpr_r9_powerpc, gpr_r10_powerpc, gpr_r11_powerpc,
+ gpr_r12_powerpc, gpr_r13_powerpc, gpr_r14_powerpc, gpr_r15_powerpc,
+ gpr_r16_powerpc, gpr_r17_powerpc, gpr_r18_powerpc, gpr_r19_powerpc,
+ gpr_r20_powerpc, gpr_r21_powerpc, gpr_r22_powerpc, gpr_r23_powerpc,
+ gpr_r24_powerpc, gpr_r25_powerpc, gpr_r26_powerpc, gpr_r27_powerpc,
+ gpr_r28_powerpc, gpr_r29_powerpc, gpr_r30_powerpc, gpr_r31_powerpc,
+ gpr_lr_powerpc, gpr_cr_powerpc, gpr_xer_powerpc, gpr_ctr_powerpc,
+ gpr_pc_powerpc,
+};
+
+static const uint32_t g_fpr_regnums[] = {
+ fpr_f0_powerpc, fpr_f1_powerpc, fpr_f2_powerpc, fpr_f3_powerpc,
+ fpr_f4_powerpc, fpr_f5_powerpc, fpr_f6_powerpc, fpr_f7_powerpc,
+ fpr_f8_powerpc, fpr_f9_powerpc, fpr_f10_powerpc, fpr_f11_powerpc,
+ fpr_f12_powerpc, fpr_f13_powerpc, fpr_f14_powerpc, fpr_f15_powerpc,
+ fpr_f16_powerpc, fpr_f17_powerpc, fpr_f18_powerpc, fpr_f19_powerpc,
+ fpr_f20_powerpc, fpr_f21_powerpc, fpr_f22_powerpc, fpr_f23_powerpc,
+ fpr_f24_powerpc, fpr_f25_powerpc, fpr_f26_powerpc, fpr_f27_powerpc,
+ fpr_f28_powerpc, fpr_f29_powerpc, fpr_f30_powerpc, fpr_f31_powerpc,
+ fpr_fpscr_powerpc,
+};
+
+// Number of register sets provided by this context.
+enum { k_num_register_sets = 2 };
+
+static const RegisterSet g_reg_sets_powerpc[k_num_register_sets] = {
+ {"General Purpose Registers", "gpr", k_num_gpr_registers_powerpc,
+ g_gpr_regnums},
+ {"Floating Point Registers", "fpr", k_num_fpr_registers_powerpc,
+ g_fpr_regnums},
+};
+
+NativeRegisterContextFreeBSD *
+NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD(
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
+ return new NativeRegisterContextFreeBSD_powerpc(target_arch, native_thread);
+}
+
+static RegisterInfoInterface *
+CreateRegisterInfoInterface(const ArchSpec &target_arch) {
+ if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) {
+ return new RegisterContextFreeBSD_powerpc32(target_arch);
+ } else {
+ assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
+ "Register setting path assumes this is a 64-bit host");
+ return new RegisterContextFreeBSD_powerpc64(target_arch);
+ }
+}
+
+NativeRegisterContextFreeBSD_powerpc::NativeRegisterContextFreeBSD_powerpc(
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
+ : NativeRegisterContextRegisterInfo(
+ native_thread, CreateRegisterInfoInterface(target_arch)) {}
+
+RegisterContextFreeBSD_powerpc &
+NativeRegisterContextFreeBSD_powerpc::GetRegisterInfo() const {
+ return static_cast<RegisterContextFreeBSD_powerpc &>(
+ *m_register_info_interface_up);
+}
+
+uint32_t NativeRegisterContextFreeBSD_powerpc::GetRegisterSetCount() const {
+ return k_num_register_sets;
+}
+
+const RegisterSet *
+NativeRegisterContextFreeBSD_powerpc::GetRegisterSet(uint32_t set_index) const {
+ switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
+ case llvm::Triple::ppc:
+ return &g_reg_sets_powerpc[set_index];
+ default:
+ llvm_unreachable("Unhandled target architecture.");
+ }
+}
+
+llvm::Optional<NativeRegisterContextFreeBSD_powerpc::RegSetKind>
+NativeRegisterContextFreeBSD_powerpc::GetSetForNativeRegNum(
+ uint32_t reg_num) const {
+ switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
+ case llvm::Triple::ppc:
+ if (reg_num >= k_first_gpr_powerpc && reg_num <= k_last_gpr_powerpc)
+ return GPRegSet;
+ if (reg_num >= k_first_fpr && reg_num <= k_last_fpr)
+ return FPRegSet;
+ break;
+ default:
+ llvm_unreachable("Unhandled target architecture.");
+ }
+
+ llvm_unreachable("Register does not belong to any register set");
+}
+
+uint32_t NativeRegisterContextFreeBSD_powerpc::GetUserRegisterCount() const {
+ uint32_t count = 0;
+ for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)
+ count += GetRegisterSet(set_index)->num_registers;
+ return count;
+}
+
+Status NativeRegisterContextFreeBSD_powerpc::ReadRegisterSet(RegSetKind set) {
+ switch (set) {
+ case GPRegSet:
+ return NativeProcessFreeBSD::PtraceWrapper(PT_GETREGS, m_thread.GetID(),
+ m_reg_data.data());
+ case FPRegSet:
+ return NativeProcessFreeBSD::PtraceWrapper(PT_GETFPREGS, m_thread.GetID(),
+ m_reg_data.data() + sizeof(reg));
+ }
+ llvm_unreachable("NativeRegisterContextFreeBSD_powerpc::ReadRegisterSet");
+}
+
+Status NativeRegisterContextFreeBSD_powerpc::WriteRegisterSet(RegSetKind set) {
+ switch (set) {
+ case GPRegSet:
+ return NativeProcessFreeBSD::PtraceWrapper(PT_SETREGS, m_thread.GetID(),
+ m_reg_data.data());
+ case FPRegSet:
+ return NativeProcessFreeBSD::PtraceWrapper(PT_SETFPREGS, m_thread.GetID(),
+ m_reg_data.data() + sizeof(reg));
+ }
+ llvm_unreachable("NativeRegisterContextFreeBSD_powerpc::WriteRegisterSet");
+}
+
+Status
+NativeRegisterContextFreeBSD_powerpc::ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue ®_value) {
+ Status error;
+
+ if (!reg_info) {
+ error.SetErrorString("reg_info NULL");
+ return error;
+ }
+
+ const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+
+ if (reg == LLDB_INVALID_REGNUM)
+ return Status("no lldb regnum for %s", reg_info && reg_info->name
+ ? reg_info->name
+ : "<unknown register>");
+
+ llvm::Optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg);
+ if (!opt_set) {
+ // This is likely an internal register for lldb use only and should not be
+ // directly queried.
+ error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",
+ reg_info->name);
+ return error;
+ }
+
+ RegSetKind set = opt_set.getValue();
+ error = ReadRegisterSet(set);
+ if (error.Fail())
+ return error;
+
+ assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());
+ reg_value.SetBytes(m_reg_data.data() + reg_info->byte_offset,
+ reg_info->byte_size, endian::InlHostByteOrder());
+ return error;
+}
+
+Status NativeRegisterContextFreeBSD_powerpc::WriteRegister(
+ const RegisterInfo *reg_info, const RegisterValue ®_value) {
+ Status error;
+
+ if (!reg_info)
+ return Status("reg_info NULL");
+
+ const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+
+ if (reg == LLDB_INVALID_REGNUM)
+ return Status("no lldb regnum for %s", reg_info && reg_info->name
+ ? reg_info->name
+ : "<unknown register>");
+
+ llvm::Optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg);
+ if (!opt_set) {
+ // This is likely an internal register for lldb use only and should not be
+ // directly queried.
+ error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",
+ reg_info->name);
+ return error;
+ }
+
+ RegSetKind set = opt_set.getValue();
+ error = ReadRegisterSet(set);
+ if (error.Fail())
+ return error;
+
+ assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());
+ ::memcpy(m_reg_data.data() + reg_info->byte_offset, reg_value.GetBytes(),
+ reg_info->byte_size);
+
+ return WriteRegisterSet(set);
+}
+
+Status NativeRegisterContextFreeBSD_powerpc::ReadAllRegisterValues(
+ lldb::DataBufferSP &data_sp) {
+ Status error;
+
+ error = ReadRegisterSet(GPRegSet);
+ if (error.Fail())
+ return error;
+
+ error = ReadRegisterSet(FPRegSet);
+ if (error.Fail())
+ return error;
+
+ data_sp.reset(new DataBufferHeap(m_reg_data.size(), 0));
+ uint8_t *dst = data_sp->GetBytes();
+ ::memcpy(dst, m_reg_data.data(), m_reg_data.size());
+
+ return error;
+}
+
+Status NativeRegisterContextFreeBSD_powerpc::WriteAllRegisterValues(
+ const lldb::DataBufferSP &data_sp) {
+ Status error;
+
+ if (!data_sp) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextFreeBSD_powerpc::%s invalid data_sp provided",
+ __FUNCTION__);
+ return error;
+ }
+
+ if (data_sp->GetByteSize() != m_reg_data.size()) {
+ error.SetErrorStringWithFormat(
+ "NativeRegisterContextFreeBSD_powerpc::%s data_sp contained mismatched "
+ "data size, expected %zu, actual %" PRIu64,
+ __FUNCTION__, m_reg_data.size(), data_sp->GetByteSize());
+ return error;
+ }
+
+ uint8_t *src = data_sp->GetBytes();
+ if (src == nullptr) {
+ error.SetErrorStringWithFormat("NativeRegisterContextFreeBSD_powerpc::%s "
+ "DataBuffer::GetBytes() returned a null "
+ "pointer",
+ __FUNCTION__);
+ return error;
+ }
+ ::memcpy(m_reg_data.data(), src, m_reg_data.size());
+
+ error = WriteRegisterSet(GPRegSet);
+ if (error.Fail())
+ return error;
+
+ return WriteRegisterSet(FPRegSet);
+}
+
+llvm::Error NativeRegisterContextFreeBSD_powerpc::CopyHardwareWatchpointsFrom(
+ NativeRegisterContextFreeBSD &source) {
+ return llvm::Error::success();
+}
+
+#endif // defined (__powerpc__)
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.h b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.h
new file mode 100644
index 0000000..884c259
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.h
@@ -0,0 +1,74 @@
+//===-- NativeRegisterContextFreeBSD_powerpc.h ------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__powerpc__)
+
+#ifndef lldb_NativeRegisterContextFreeBSD_powerpc_h
+#define lldb_NativeRegisterContextFreeBSD_powerpc_h
+
+// clang-format off
+#include <sys/types.h>
+#include <machine/reg.h>
+// clang-format on
+
+#include "Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h"
+#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h"
+
+#include <array>
+
+namespace lldb_private {
+namespace process_freebsd {
+
+class NativeProcessFreeBSD;
+
+class NativeRegisterContextFreeBSD_powerpc
+ : public NativeRegisterContextFreeBSD {
+public:
+ NativeRegisterContextFreeBSD_powerpc(const ArchSpec &target_arch,
+ NativeThreadProtocol &native_thread);
+
+ uint32_t GetRegisterSetCount() const override;
+
+ uint32_t GetUserRegisterCount() const override;
+
+ const RegisterSet *GetRegisterSet(uint32_t set_index) const override;
+
+ Status ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue ®_value) override;
+
+ Status WriteRegister(const RegisterInfo *reg_info,
+ const RegisterValue ®_value) override;
+
+ Status ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+
+ Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
+
+ llvm::Error
+ CopyHardwareWatchpointsFrom(NativeRegisterContextFreeBSD &source) override;
+
+private:
+ enum RegSetKind {
+ GPRegSet,
+ FPRegSet,
+ };
+ std::array<uint8_t, sizeof(reg) + sizeof(fpreg)> m_reg_data;
+
+ llvm::Optional<RegSetKind> GetSetForNativeRegNum(uint32_t reg_num) const;
+
+ Status ReadRegisterSet(RegSetKind set);
+ Status WriteRegisterSet(RegSetKind set);
+
+ RegisterContextFreeBSD_powerpc &GetRegisterInfo() const;
+};
+
+} // namespace process_freebsd
+} // namespace lldb_private
+
+#endif // #ifndef lldb_NativeRegisterContextFreeBSD_powerpc_h
+
+#endif // defined (__powerpc__)
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.cpp b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.cpp
similarity index 99%
rename from src/llvm-project/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.cpp
rename to src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.cpp
index d5052e7..9328d60 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.cpp
@@ -260,7 +260,7 @@
const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
: NativeRegisterContextRegisterInfo(
native_thread, CreateRegisterInfoInterface(target_arch)),
- m_regset_offsets({0}) {
+ NativeRegisterContextDBReg_x86(native_thread), m_regset_offsets({0}) {
assert(m_gpr.size() == GetRegisterInfoInterface().GetGPRSize());
std::array<uint32_t, MaxRegSet + 1> first_regnos;
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.h b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.h
similarity index 93%
rename from src/llvm-project/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.h
rename to src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.h
index 673cffd..efd0f91 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.h
@@ -20,9 +20,9 @@
#include <array>
-#include "Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD.h"
+#include "Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h"
#include "Plugins/Process/Utility/RegisterContext_x86.h"
-#include "Plugins/Process/Utility/NativeRegisterContextWatchpoint_x86.h"
+#include "Plugins/Process/Utility/NativeRegisterContextDBReg_x86.h"
#include "Plugins/Process/Utility/lldb-x86-register-enums.h"
#define LLDB_INVALID_XSAVE_OFFSET UINT32_MAX
@@ -34,7 +34,7 @@
class NativeRegisterContextFreeBSD_x86_64
: public NativeRegisterContextFreeBSD,
- public NativeRegisterContextWatchpoint_x86 {
+ public NativeRegisterContextDBReg_x86 {
public:
NativeRegisterContextFreeBSD_x86_64(const ArchSpec &target_arch,
NativeThreadProtocol &native_thread);
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSDRemote/NativeThreadFreeBSD.cpp b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.cpp
similarity index 89%
rename from src/llvm-project/lldb/source/Plugins/Process/FreeBSDRemote/NativeThreadFreeBSD.cpp
rename to src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.cpp
index 4349487..80b3527 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/FreeBSDRemote/NativeThreadFreeBSD.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.cpp
@@ -46,6 +46,11 @@
if (!ret.Success())
return ret;
ret = NativeProcessFreeBSD::PtraceWrapper(PT_CLEARSTEP, GetID());
+ // we can get EINVAL if the architecture in question does not support
+ // hardware single-stepping -- that's fine, we have nothing to clear
+ // then
+ if (ret.GetError() == EINVAL)
+ ret.Clear();
if (ret.Success())
SetRunning();
return ret;
@@ -125,6 +130,30 @@
m_stop_info.details.signal.signo = SIGTRAP;
}
+void NativeThreadFreeBSD::SetStoppedByFork(lldb::pid_t child_pid,
+ lldb::tid_t child_tid) {
+ SetStopped();
+
+ m_stop_info.reason = StopReason::eStopReasonFork;
+ m_stop_info.details.fork.child_pid = child_pid;
+ m_stop_info.details.fork.child_tid = child_tid;
+}
+
+void NativeThreadFreeBSD::SetStoppedByVFork(lldb::pid_t child_pid,
+ lldb::tid_t child_tid) {
+ SetStopped();
+
+ m_stop_info.reason = StopReason::eStopReasonVFork;
+ m_stop_info.details.fork.child_pid = child_pid;
+ m_stop_info.details.fork.child_tid = child_tid;
+}
+
+void NativeThreadFreeBSD::SetStoppedByVForkDone() {
+ SetStopped();
+
+ m_stop_info.reason = StopReason::eStopReasonVForkDone;
+}
+
void NativeThreadFreeBSD::SetStoppedWithNoReason() {
SetStopped();
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSDRemote/NativeThreadFreeBSD.h b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.h
similarity index 90%
rename from src/llvm-project/lldb/source/Plugins/Process/FreeBSDRemote/NativeThreadFreeBSD.h
rename to src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.h
index 4e997b3..3ec6daa 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/FreeBSDRemote/NativeThreadFreeBSD.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.h
@@ -11,7 +11,7 @@
#include "lldb/Host/common/NativeThreadProtocol.h"
-#include "Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD.h"
+#include "Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h"
#include <csignal>
#include <map>
@@ -59,6 +59,9 @@
void SetStoppedByTrace();
void SetStoppedByExec();
void SetStoppedByWatchpoint(uint32_t wp_index);
+ void SetStoppedByFork(lldb::pid_t child_pid, lldb::tid_t child_tid);
+ void SetStoppedByVFork(lldb::pid_t child_pid, lldb::tid_t child_tid);
+ void SetStoppedByVForkDone();
void SetStoppedWithNoReason();
void SetStopped();
void SetRunning();
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp
deleted file mode 100644
index 4e6f3af..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-//===-- POSIXStopInfo.cpp -------------------------------------------------===//
-//
-// 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 "POSIXStopInfo.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-//===----------------------------------------------------------------------===//
-// POSIXLimboStopInfo
-
-POSIXLimboStopInfo::~POSIXLimboStopInfo() {}
-
-lldb::StopReason POSIXLimboStopInfo::GetStopReason() const {
- return lldb::eStopReasonThreadExiting;
-}
-
-const char *POSIXLimboStopInfo::GetDescription() { return "thread exiting"; }
-
-bool POSIXLimboStopInfo::ShouldStop(Event *event_ptr) { return false; }
-
-bool POSIXLimboStopInfo::ShouldNotify(Event *event_ptr) { return false; }
-
-//===----------------------------------------------------------------------===//
-// POSIXNewThreadStopInfo
-
-POSIXNewThreadStopInfo::~POSIXNewThreadStopInfo() {}
-
-lldb::StopReason POSIXNewThreadStopInfo::GetStopReason() const {
- return lldb::eStopReasonNone;
-}
-
-const char *POSIXNewThreadStopInfo::GetDescription() {
- return "thread spawned";
-}
-
-bool POSIXNewThreadStopInfo::ShouldStop(Event *event_ptr) { return false; }
-
-bool POSIXNewThreadStopInfo::ShouldNotify(Event *event_ptr) { return false; }
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.h b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.h
deleted file mode 100644
index 5a022c4..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/POSIXStopInfo.h
+++ /dev/null
@@ -1,66 +0,0 @@
-//===-- POSIXStopInfo.h -----------------------------------------*- 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_POSIXStopInfo_H_
-#define liblldb_POSIXStopInfo_H_
-
-#include "FreeBSDThread.h"
-#include "Plugins/Process/POSIX/CrashReason.h"
-#include "lldb/Target/StopInfo.h"
-#include <string>
-
-//===----------------------------------------------------------------------===//
-/// \class POSIXStopInfo
-/// Simple base class for all POSIX-specific StopInfo objects.
-///
-class POSIXStopInfo : public lldb_private::StopInfo {
-public:
- POSIXStopInfo(lldb_private::Thread &thread, uint32_t status)
- : StopInfo(thread, status) {}
-};
-
-//===----------------------------------------------------------------------===//
-/// \class POSIXLimboStopInfo
-/// Represents the stop state of a process ready to exit.
-///
-class POSIXLimboStopInfo : public POSIXStopInfo {
-public:
- POSIXLimboStopInfo(FreeBSDThread &thread) : POSIXStopInfo(thread, 0) {}
-
- ~POSIXLimboStopInfo();
-
- lldb::StopReason GetStopReason() const override;
-
- const char *GetDescription() override;
-
- bool ShouldStop(lldb_private::Event *event_ptr) override;
-
- bool ShouldNotify(lldb_private::Event *event_ptr) override;
-};
-
-//===----------------------------------------------------------------------===//
-/// \class POSIXNewThreadStopInfo
-/// Represents the stop state of process when a new thread is spawned.
-///
-
-class POSIXNewThreadStopInfo : public POSIXStopInfo {
-public:
- POSIXNewThreadStopInfo(FreeBSDThread &thread) : POSIXStopInfo(thread, 0) {}
-
- ~POSIXNewThreadStopInfo();
-
- lldb::StopReason GetStopReason() const override;
-
- const char *GetDescription() override;
-
- bool ShouldStop(lldb_private::Event *event_ptr) override;
-
- bool ShouldNotify(lldb_private::Event *event_ptr) override;
-};
-
-#endif
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
deleted file mode 100644
index a1fe45b..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
+++ /dev/null
@@ -1,1080 +0,0 @@
-//===-- ProcessFreeBSD.cpp ------------------------------------------------===//
-//
-// 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 <errno.h>
-#include <pthread.h>
-#include <pthread_np.h>
-#include <stdlib.h>
-#include <sys/sysctl.h>
-#include <sys/types.h>
-#include <sys/user.h>
-#include <machine/elf.h>
-
-#include <mutex>
-#include <unordered_map>
-
-#include "lldb/Core/PluginManager.h"
-#include "lldb/Host/FileSystem.h"
-#include "lldb/Host/Host.h"
-#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Target/DynamicLoader.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Utility/RegisterValue.h"
-#include "lldb/Utility/State.h"
-
-#include "FreeBSDThread.h"
-#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
-#include "Plugins/Process/Utility/FreeBSDSignals.h"
-#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
-#include "ProcessFreeBSD.h"
-#include "ProcessMonitor.h"
-
-#include "lldb/Breakpoint/BreakpointLocation.h"
-#include "lldb/Breakpoint/Watchpoint.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Core/ModuleSpec.h"
-#include "lldb/Core/PluginManager.h"
-#include "lldb/Host/Host.h"
-#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Target/DynamicLoader.h"
-#include "lldb/Target/Platform.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Utility/DataBufferHeap.h"
-#include "lldb/Utility/FileSpec.h"
-#include "lldb/Utility/State.h"
-
-#include "lldb/Host/posix/Fcntl.h"
-
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Threading.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-LLDB_PLUGIN_DEFINE(ProcessFreeBSD)
-
-namespace {
-UnixSignalsSP &GetFreeBSDSignals() {
- static UnixSignalsSP s_freebsd_signals_sp(new FreeBSDSignals());
- return s_freebsd_signals_sp;
-}
-}
-
-// Static functions.
-
-lldb::ProcessSP
-ProcessFreeBSD::CreateInstance(lldb::TargetSP target_sp,
- lldb::ListenerSP listener_sp,
- const FileSpec *crash_file_path,
- bool can_connect) {
- lldb::ProcessSP process_sp;
- if (crash_file_path == NULL && !can_connect)
- process_sp.reset(
- new ProcessFreeBSD(target_sp, listener_sp, GetFreeBSDSignals()));
- return process_sp;
-}
-
-void ProcessFreeBSD::Initialize() {
- static llvm::once_flag g_once_flag;
-
- llvm::call_once(g_once_flag, []() {
- PluginManager::RegisterPlugin(GetPluginNameStatic(),
- GetPluginDescriptionStatic(), CreateInstance);
- });
-}
-
-lldb_private::ConstString ProcessFreeBSD::GetPluginNameStatic() {
- static ConstString g_name("freebsd");
- return g_name;
-}
-
-const char *ProcessFreeBSD::GetPluginDescriptionStatic() {
- return "Process plugin for FreeBSD";
-}
-
-// ProcessInterface protocol.
-
-lldb_private::ConstString ProcessFreeBSD::GetPluginName() {
- return GetPluginNameStatic();
-}
-
-uint32_t ProcessFreeBSD::GetPluginVersion() { return 1; }
-
-void ProcessFreeBSD::Terminate() {}
-
-Status ProcessFreeBSD::DoDetach(bool keep_stopped) {
- Status error;
- if (keep_stopped) {
- error.SetErrorString("Detaching with keep_stopped true is not currently "
- "supported on FreeBSD.");
- return error;
- }
-
- error = m_monitor->Detach(GetID());
-
- if (error.Success())
- SetPrivateState(eStateDetached);
-
- return error;
-}
-
-Status ProcessFreeBSD::DoResume() {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
-
- SetPrivateState(eStateRunning);
-
- std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex());
- bool do_step = false;
- bool software_single_step = !SupportHardwareSingleStepping();
-
- for (tid_collection::const_iterator t_pos = m_run_tids.begin(),
- t_end = m_run_tids.end();
- t_pos != t_end; ++t_pos) {
- m_monitor->ThreadSuspend(*t_pos, false);
- }
- for (tid_collection::const_iterator t_pos = m_step_tids.begin(),
- t_end = m_step_tids.end();
- t_pos != t_end; ++t_pos) {
- m_monitor->ThreadSuspend(*t_pos, false);
- do_step = true;
- if (software_single_step) {
- Status error = SetupSoftwareSingleStepping(*t_pos);
- if (error.Fail())
- return error;
- }
- }
- for (tid_collection::const_iterator t_pos = m_suspend_tids.begin(),
- t_end = m_suspend_tids.end();
- t_pos != t_end; ++t_pos) {
- m_monitor->ThreadSuspend(*t_pos, true);
- // XXX Cannot PT_CONTINUE properly with suspended threads.
- do_step = true;
- }
-
- LLDB_LOGF(log, "process %" PRIu64 " resuming (%s)", GetID(),
- do_step ? "step" : "continue");
- if (do_step && !software_single_step)
- m_monitor->SingleStep(GetID(), m_resume_signo);
- else
- m_monitor->Resume(GetID(), m_resume_signo);
-
- return Status();
-}
-
-bool ProcessFreeBSD::DoUpdateThreadList(ThreadList &old_thread_list,
- ThreadList &new_thread_list) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
- LLDB_LOGF(log, "ProcessFreeBSD::%s (pid = %" PRIu64 ")", __FUNCTION__,
- GetID());
-
- std::vector<lldb::pid_t> tds;
- if (!GetMonitor().GetCurrentThreadIDs(tds)) {
- return false;
- }
-
- ThreadList old_thread_list_copy(old_thread_list);
- for (size_t i = 0; i < tds.size(); ++i) {
- tid_t tid = tds[i];
- ThreadSP thread_sp(old_thread_list_copy.RemoveThreadByID(tid, false));
- if (!thread_sp) {
- thread_sp.reset(new FreeBSDThread(*this, tid));
- LLDB_LOGF(log, "ProcessFreeBSD::%s new tid = %" PRIu64, __FUNCTION__,
- tid);
- } else {
- LLDB_LOGF(log, "ProcessFreeBSD::%s existing tid = %" PRIu64, __FUNCTION__,
- tid);
- }
- new_thread_list.AddThread(thread_sp);
- }
- for (size_t i = 0; i < old_thread_list_copy.GetSize(false); ++i) {
- ThreadSP old_thread_sp(old_thread_list_copy.GetThreadAtIndex(i, false));
- if (old_thread_sp) {
- LLDB_LOGF(log, "ProcessFreeBSD::%s remove tid", __FUNCTION__);
- }
- }
-
- return true;
-}
-
-Status ProcessFreeBSD::WillResume() {
- m_resume_signo = 0;
- m_suspend_tids.clear();
- m_run_tids.clear();
- m_step_tids.clear();
- return Process::WillResume();
-}
-
-void ProcessFreeBSD::SendMessage(const ProcessMessage &message) {
- std::lock_guard<std::recursive_mutex> guard(m_message_mutex);
-
- switch (message.GetKind()) {
- case ProcessMessage::eInvalidMessage:
- return;
-
- case ProcessMessage::eAttachMessage:
- SetPrivateState(eStateStopped);
- return;
-
- case ProcessMessage::eLimboMessage:
- case ProcessMessage::eExitMessage:
- SetExitStatus(message.GetExitStatus(), NULL);
- break;
-
- case ProcessMessage::eSignalMessage:
- case ProcessMessage::eSignalDeliveredMessage:
- case ProcessMessage::eBreakpointMessage:
- case ProcessMessage::eTraceMessage:
- case ProcessMessage::eWatchpointMessage:
- case ProcessMessage::eCrashMessage:
- SetPrivateState(eStateStopped);
- break;
-
- case ProcessMessage::eNewThreadMessage:
- llvm_unreachable("eNewThreadMessage unexpected on FreeBSD");
- break;
-
- case ProcessMessage::eExecMessage:
- SetPrivateState(eStateStopped);
- break;
- }
-
- m_message_queue.push(message);
-}
-
-// Constructors and destructors.
-
-ProcessFreeBSD::ProcessFreeBSD(lldb::TargetSP target_sp,
- lldb::ListenerSP listener_sp,
- UnixSignalsSP &unix_signals_sp)
- : Process(target_sp, listener_sp, unix_signals_sp),
- m_byte_order(endian::InlHostByteOrder()), m_monitor(NULL), m_module(NULL),
- m_message_mutex(), m_exit_now(false), m_seen_initial_stop(),
- m_resume_signo(0) {
- // FIXME: Putting this code in the ctor and saving the byte order in a
- // member variable is a hack to avoid const qual issues in GetByteOrder.
- lldb::ModuleSP module = GetTarget().GetExecutableModule();
- if (module && module->GetObjectFile())
- m_byte_order = module->GetObjectFile()->GetByteOrder();
-}
-
-ProcessFreeBSD::~ProcessFreeBSD() { delete m_monitor; }
-
-// Process protocol.
-void ProcessFreeBSD::Finalize() {
- Process::Finalize();
-
- if (m_monitor)
- m_monitor->StopMonitor();
-}
-
-bool ProcessFreeBSD::CanDebug(lldb::TargetSP target_sp,
- bool plugin_specified_by_name) {
- // For now we are just making sure the file exists for a given module
- ModuleSP exe_module_sp(target_sp->GetExecutableModule());
- if (exe_module_sp.get())
- return FileSystem::Instance().Exists(exe_module_sp->GetFileSpec());
- // If there is no executable module, we return true since we might be
- // preparing to attach.
- return true;
-}
-
-Status
-ProcessFreeBSD::DoAttachToProcessWithID(lldb::pid_t pid,
- const ProcessAttachInfo &attach_info) {
- Status error;
- assert(m_monitor == NULL);
-
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
- LLDB_LOGV(log, "pid = {0}", GetID());
-
- m_monitor = new ProcessMonitor(this, pid, error);
-
- if (!error.Success())
- return error;
-
- PlatformSP platform_sp(GetTarget().GetPlatform());
- assert(platform_sp.get());
- if (!platform_sp)
- return error; // FIXME: Detatch?
-
- // Find out what we can about this process
- ProcessInstanceInfo process_info;
- platform_sp->GetProcessInfo(pid, process_info);
-
- // Resolve the executable module
- ModuleSP exe_module_sp;
- FileSpecList executable_search_paths(
- Target::GetDefaultExecutableSearchPaths());
- ModuleSpec exe_module_spec(process_info.GetExecutableFile(),
- GetTarget().GetArchitecture());
- error = platform_sp->ResolveExecutable(
- exe_module_spec, exe_module_sp,
- executable_search_paths.GetSize() ? &executable_search_paths : NULL);
- if (!error.Success())
- return error;
-
- // Fix the target architecture if necessary
- const ArchSpec &module_arch = exe_module_sp->GetArchitecture();
- if (module_arch.IsValid() &&
- !GetTarget().GetArchitecture().IsExactMatch(module_arch))
- GetTarget().SetArchitecture(module_arch);
-
- // Initialize the target module list
- GetTarget().SetExecutableModule(exe_module_sp, eLoadDependentsYes);
-
- SetSTDIOFileDescriptor(m_monitor->GetTerminalFD());
-
- SetID(pid);
-
- return error;
-}
-
-Status ProcessFreeBSD::WillLaunch(Module *module) {
- Status error;
- return error;
-}
-
-FileSpec
-ProcessFreeBSD::GetFileSpec(const lldb_private::FileAction *file_action,
- const FileSpec &default_file_spec,
- const FileSpec &dbg_pts_file_spec) {
- FileSpec file_spec{};
-
- if (file_action && file_action->GetAction() == FileAction::eFileActionOpen) {
- file_spec = file_action->GetFileSpec();
- // By default the stdio paths passed in will be pseudo-terminal (/dev/pts).
- // If so, convert to using a different default path instead to redirect I/O
- // to the debugger console. This should also handle user overrides to
- // /dev/null or a different file.
- if (!file_spec || file_spec == dbg_pts_file_spec)
- file_spec = default_file_spec;
- }
- return file_spec;
-}
-
-Status ProcessFreeBSD::DoLaunch(Module *module,
- ProcessLaunchInfo &launch_info) {
- Status error;
- assert(m_monitor == NULL);
-
- FileSpec working_dir = launch_info.GetWorkingDirectory();
- if (working_dir) {
- FileSystem::Instance().Resolve(working_dir);
- if (!FileSystem::Instance().IsDirectory(working_dir.GetPath())) {
- error.SetErrorStringWithFormat("No such file or directory: %s",
- working_dir.GetCString());
- return error;
- }
- }
-
- SetPrivateState(eStateLaunching);
-
- const lldb_private::FileAction *file_action;
-
- // Default of empty will mean to use existing open file descriptors
- FileSpec stdin_file_spec{};
- FileSpec stdout_file_spec{};
- FileSpec stderr_file_spec{};
-
- const FileSpec dbg_pts_file_spec{launch_info.GetPTY().GetSecondaryName()};
-
- file_action = launch_info.GetFileActionForFD(STDIN_FILENO);
- stdin_file_spec =
- GetFileSpec(file_action, stdin_file_spec, dbg_pts_file_spec);
-
- file_action = launch_info.GetFileActionForFD(STDOUT_FILENO);
- stdout_file_spec =
- GetFileSpec(file_action, stdout_file_spec, dbg_pts_file_spec);
-
- file_action = launch_info.GetFileActionForFD(STDERR_FILENO);
- stderr_file_spec =
- GetFileSpec(file_action, stderr_file_spec, dbg_pts_file_spec);
-
- m_monitor = new ProcessMonitor(
- this, module, launch_info.GetArguments().GetConstArgumentVector(),
- launch_info.GetEnvironment(), stdin_file_spec, stdout_file_spec,
- stderr_file_spec, working_dir, launch_info, error);
-
- m_module = module;
-
- if (!error.Success())
- return error;
-
- int terminal = m_monitor->GetTerminalFD();
- if (terminal >= 0) {
-// The reader thread will close the file descriptor when done, so we pass it a
-// copy.
-#ifdef F_DUPFD_CLOEXEC
- int stdio = fcntl(terminal, F_DUPFD_CLOEXEC, 0);
- if (stdio == -1) {
- error.SetErrorToErrno();
- return error;
- }
-#else
- // Special case when F_DUPFD_CLOEXEC does not exist (Debian kFreeBSD)
- int stdio = fcntl(terminal, F_DUPFD, 0);
- if (stdio == -1) {
- error.SetErrorToErrno();
- return error;
- }
- stdio = fcntl(terminal, F_SETFD, FD_CLOEXEC);
- if (stdio == -1) {
- error.SetErrorToErrno();
- return error;
- }
-#endif
- SetSTDIOFileDescriptor(stdio);
- }
-
- SetID(m_monitor->GetPID());
- return error;
-}
-
-void ProcessFreeBSD::DidLaunch() {}
-
-addr_t ProcessFreeBSD::GetImageInfoAddress() {
- Target *target = &GetTarget();
- ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
- Address addr = obj_file->GetImageInfoAddress(target);
-
- if (addr.IsValid())
- return addr.GetLoadAddress(target);
- return LLDB_INVALID_ADDRESS;
-}
-
-Status ProcessFreeBSD::DoHalt(bool &caused_stop) {
- Status error;
-
- if (IsStopped()) {
- caused_stop = false;
- } else if (kill(GetID(), SIGSTOP)) {
- caused_stop = false;
- error.SetErrorToErrno();
- } else {
- caused_stop = true;
- }
- return error;
-}
-
-Status ProcessFreeBSD::DoSignal(int signal) {
- Status error;
-
- if (kill(GetID(), signal))
- error.SetErrorToErrno();
-
- return error;
-}
-
-Status ProcessFreeBSD::DoDestroy() {
- Status error;
-
- if (!HasExited()) {
- assert(m_monitor);
- m_exit_now = true;
- if (GetID() == LLDB_INVALID_PROCESS_ID) {
- error.SetErrorString("invalid process id");
- return error;
- }
- if (!m_monitor->Kill()) {
- error.SetErrorToErrno();
- return error;
- }
-
- SetPrivateState(eStateExited);
- }
-
- return error;
-}
-
-void ProcessFreeBSD::DoDidExec() {
- Target *target = &GetTarget();
- if (target) {
- PlatformSP platform_sp(target->GetPlatform());
- assert(platform_sp.get());
- if (platform_sp) {
- ProcessInstanceInfo process_info;
- platform_sp->GetProcessInfo(GetID(), process_info);
- ModuleSP exe_module_sp;
- ModuleSpec exe_module_spec(process_info.GetExecutableFile(),
- target->GetArchitecture());
- FileSpecList executable_search_paths(
- Target::GetDefaultExecutableSearchPaths());
- Status error = platform_sp->ResolveExecutable(
- exe_module_spec, exe_module_sp,
- executable_search_paths.GetSize() ? &executable_search_paths : NULL);
- if (!error.Success())
- return;
- target->SetExecutableModule(exe_module_sp, eLoadDependentsYes);
- }
- }
-}
-
-bool ProcessFreeBSD::AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid) {
- bool added_to_set = false;
- ThreadStopSet::iterator it = m_seen_initial_stop.find(stop_tid);
- if (it == m_seen_initial_stop.end()) {
- m_seen_initial_stop.insert(stop_tid);
- added_to_set = true;
- }
- return added_to_set;
-}
-
-bool ProcessFreeBSD::WaitingForInitialStop(lldb::tid_t stop_tid) {
- return (m_seen_initial_stop.find(stop_tid) == m_seen_initial_stop.end());
-}
-
-FreeBSDThread *
-ProcessFreeBSD::CreateNewFreeBSDThread(lldb_private::Process &process,
- lldb::tid_t tid) {
- return new FreeBSDThread(process, tid);
-}
-
-void ProcessFreeBSD::RefreshStateAfterStop() {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
- LLDB_LOGV(log, "message_queue size = {0}", m_message_queue.size());
-
- std::lock_guard<std::recursive_mutex> guard(m_message_mutex);
-
- // This method used to only handle one message. Changing it to loop allows
- // it to handle the case where we hit a breakpoint while handling a different
- // breakpoint.
- while (!m_message_queue.empty()) {
- ProcessMessage &message = m_message_queue.front();
-
- // Resolve the thread this message corresponds to and pass it along.
- lldb::tid_t tid = message.GetTID();
- LLDB_LOGV(log, " message_queue size = {0}, pid = {1}",
- m_message_queue.size(), tid);
-
- m_thread_list.RefreshStateAfterStop();
-
- FreeBSDThread *thread = static_cast<FreeBSDThread *>(
- GetThreadList().FindThreadByID(tid, false).get());
- if (thread)
- thread->Notify(message);
-
- if (message.GetKind() == ProcessMessage::eExitMessage) {
- // FIXME: We should tell the user about this, but the limbo message is
- // probably better for that.
- LLDB_LOG(log, "removing thread, tid = {0}", tid);
- std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex());
-
- ThreadSP thread_sp = m_thread_list.RemoveThreadByID(tid, false);
- thread_sp.reset();
- m_seen_initial_stop.erase(tid);
- }
-
- m_message_queue.pop();
- }
-}
-
-bool ProcessFreeBSD::IsAlive() {
- StateType state = GetPrivateState();
- return state != eStateDetached && state != eStateExited &&
- state != eStateInvalid && state != eStateUnloaded;
-}
-
-size_t ProcessFreeBSD::DoReadMemory(addr_t vm_addr, void *buf, size_t size,
- Status &error) {
- assert(m_monitor);
- return m_monitor->ReadMemory(vm_addr, buf, size, error);
-}
-
-size_t ProcessFreeBSD::DoWriteMemory(addr_t vm_addr, const void *buf,
- size_t size, Status &error) {
- assert(m_monitor);
- return m_monitor->WriteMemory(vm_addr, buf, size, error);
-}
-
-addr_t ProcessFreeBSD::DoAllocateMemory(size_t size, uint32_t permissions,
- Status &error) {
- addr_t allocated_addr = LLDB_INVALID_ADDRESS;
-
- unsigned prot = 0;
- if (permissions & lldb::ePermissionsReadable)
- prot |= eMmapProtRead;
- if (permissions & lldb::ePermissionsWritable)
- prot |= eMmapProtWrite;
- if (permissions & lldb::ePermissionsExecutable)
- prot |= eMmapProtExec;
-
- if (InferiorCallMmap(this, allocated_addr, 0, size, prot,
- eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) {
- m_addr_to_mmap_size[allocated_addr] = size;
- error.Clear();
- } else {
- allocated_addr = LLDB_INVALID_ADDRESS;
- error.SetErrorStringWithFormat(
- "unable to allocate %zu bytes of memory with permissions %s", size,
- GetPermissionsAsCString(permissions));
- }
-
- return allocated_addr;
-}
-
-Status ProcessFreeBSD::DoDeallocateMemory(lldb::addr_t addr) {
- Status error;
- MMapMap::iterator pos = m_addr_to_mmap_size.find(addr);
- if (pos != m_addr_to_mmap_size.end() &&
- InferiorCallMunmap(this, addr, pos->second))
- m_addr_to_mmap_size.erase(pos);
- else
- error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" PRIx64,
- addr);
-
- return error;
-}
-
-size_t
-ProcessFreeBSD::GetSoftwareBreakpointTrapOpcode(BreakpointSite *bp_site) {
- static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x20, 0xD4};
- static const uint8_t g_i386_opcode[] = {0xCC};
-
- ArchSpec arch = GetTarget().GetArchitecture();
- const uint8_t *opcode = NULL;
- size_t opcode_size = 0;
-
- switch (arch.GetMachine()) {
- default:
- assert(false && "CPU type not supported!");
- break;
-
- case llvm::Triple::arm: {
- // The ARM reference recommends the use of 0xe7fddefe and 0xdefe but the
- // linux kernel does otherwise.
- static const uint8_t g_arm_breakpoint_opcode[] = {0xf0, 0x01, 0xf0, 0xe7};
- static const uint8_t g_thumb_breakpoint_opcode[] = {0x01, 0xde};
-
- lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetOwnerAtIndex(0));
- AddressClass addr_class = AddressClass::eUnknown;
-
- if (bp_loc_sp)
- addr_class = bp_loc_sp->GetAddress().GetAddressClass();
-
- if (addr_class == AddressClass::eCodeAlternateISA ||
- (addr_class == AddressClass::eUnknown &&
- bp_loc_sp->GetAddress().GetOffset() & 1)) {
- opcode = g_thumb_breakpoint_opcode;
- opcode_size = sizeof(g_thumb_breakpoint_opcode);
- } else {
- opcode = g_arm_breakpoint_opcode;
- opcode_size = sizeof(g_arm_breakpoint_opcode);
- }
- } break;
- case llvm::Triple::aarch64:
- opcode = g_aarch64_opcode;
- opcode_size = sizeof(g_aarch64_opcode);
- break;
-
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- opcode = g_i386_opcode;
- opcode_size = sizeof(g_i386_opcode);
- break;
- }
-
- bp_site->SetTrapOpcode(opcode, opcode_size);
- return opcode_size;
-}
-
-Status ProcessFreeBSD::EnableBreakpointSite(BreakpointSite *bp_site) {
- if (bp_site->HardwareRequired())
- return Status("Hardware breakpoints are not supported.");
-
- return EnableSoftwareBreakpoint(bp_site);
-}
-
-Status ProcessFreeBSD::DisableBreakpointSite(BreakpointSite *bp_site) {
- return DisableSoftwareBreakpoint(bp_site);
-}
-
-Status ProcessFreeBSD::EnableWatchpoint(Watchpoint *wp, bool notify) {
- Status error;
- if (wp) {
- user_id_t watchID = wp->GetID();
- addr_t addr = wp->GetLoadAddress();
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
- LLDB_LOGF(log, "ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64 ")",
- watchID);
- if (wp->IsEnabled()) {
- LLDB_LOGF(log,
- "ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64
- ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.",
- watchID, (uint64_t)addr);
- return error;
- }
-
- // Try to find a vacant watchpoint slot in the inferiors' main thread
- uint32_t wp_hw_index = LLDB_INVALID_INDEX32;
- std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex());
- FreeBSDThread *thread = static_cast<FreeBSDThread *>(
- m_thread_list.GetThreadAtIndex(0, false).get());
-
- if (thread)
- wp_hw_index = thread->FindVacantWatchpointIndex();
-
- if (wp_hw_index == LLDB_INVALID_INDEX32) {
- error.SetErrorString("Setting hardware watchpoint failed.");
- } else {
- wp->SetHardwareIndex(wp_hw_index);
- bool wp_enabled = true;
- uint32_t thread_count = m_thread_list.GetSize(false);
- for (uint32_t i = 0; i < thread_count; ++i) {
- thread = static_cast<FreeBSDThread *>(
- m_thread_list.GetThreadAtIndex(i, false).get());
- if (thread)
- wp_enabled &= thread->EnableHardwareWatchpoint(wp);
- else
- wp_enabled = false;
- }
- if (wp_enabled) {
- wp->SetEnabled(true, notify);
- return error;
- } else {
- // Watchpoint enabling failed on at least one of the threads so roll
- // back all of them
- DisableWatchpoint(wp, false);
- error.SetErrorString("Setting hardware watchpoint failed");
- }
- }
- } else
- error.SetErrorString("Watchpoint argument was NULL.");
- return error;
-}
-
-Status ProcessFreeBSD::DisableWatchpoint(Watchpoint *wp, bool notify) {
- Status error;
- if (wp) {
- user_id_t watchID = wp->GetID();
- addr_t addr = wp->GetLoadAddress();
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
- LLDB_LOGF(log, "ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64 ")",
- watchID);
- if (!wp->IsEnabled()) {
- LLDB_LOGF(log,
- "ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64
- ") addr = 0x%8.8" PRIx64 ": watchpoint already disabled.",
- watchID, (uint64_t)addr);
- // This is needed (for now) to keep watchpoints disabled correctly
- wp->SetEnabled(false, notify);
- return error;
- }
-
- if (wp->IsHardware()) {
- bool wp_disabled = true;
- std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex());
- uint32_t thread_count = m_thread_list.GetSize(false);
- for (uint32_t i = 0; i < thread_count; ++i) {
- FreeBSDThread *thread = static_cast<FreeBSDThread *>(
- m_thread_list.GetThreadAtIndex(i, false).get());
- if (thread)
- wp_disabled &= thread->DisableHardwareWatchpoint(wp);
- else
- wp_disabled = false;
- }
- if (wp_disabled) {
- wp->SetHardwareIndex(LLDB_INVALID_INDEX32);
- wp->SetEnabled(false, notify);
- return error;
- } else
- error.SetErrorString("Disabling hardware watchpoint failed");
- }
- } else
- error.SetErrorString("Watchpoint argument was NULL.");
- return error;
-}
-
-Status ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num) {
- Status error;
- std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex());
- FreeBSDThread *thread = static_cast<FreeBSDThread *>(
- m_thread_list.GetThreadAtIndex(0, false).get());
- if (thread)
- num = thread->NumSupportedHardwareWatchpoints();
- else
- error.SetErrorString("Process does not exist.");
- return error;
-}
-
-Status ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num, bool &after) {
- Status error = GetWatchpointSupportInfo(num);
- // Watchpoints trigger and halt the inferior after the corresponding
- // instruction has been executed.
- after = true;
- return error;
-}
-
-uint32_t ProcessFreeBSD::UpdateThreadListIfNeeded() {
- std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex());
- // Do not allow recursive updates.
- return m_thread_list.GetSize(false);
-}
-
-ByteOrder ProcessFreeBSD::GetByteOrder() const {
- // FIXME: We should be able to extract this value directly. See comment in
- // ProcessFreeBSD().
- return m_byte_order;
-}
-
-size_t ProcessFreeBSD::PutSTDIN(const char *buf, size_t len, Status &error) {
- ssize_t status;
- if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0) {
- error.SetErrorToErrno();
- return 0;
- }
- return status;
-}
-
-// Utility functions.
-
-bool ProcessFreeBSD::HasExited() {
- switch (GetPrivateState()) {
- default:
- break;
-
- case eStateDetached:
- case eStateExited:
- return true;
- }
-
- return false;
-}
-
-bool ProcessFreeBSD::IsStopped() {
- switch (GetPrivateState()) {
- default:
- break;
-
- case eStateStopped:
- case eStateCrashed:
- case eStateSuspended:
- return true;
- }
-
- return false;
-}
-
-bool ProcessFreeBSD::IsAThreadRunning() {
- bool is_running = false;
- std::lock_guard<std::recursive_mutex> guard(m_thread_list.GetMutex());
- uint32_t thread_count = m_thread_list.GetSize(false);
- for (uint32_t i = 0; i < thread_count; ++i) {
- FreeBSDThread *thread = static_cast<FreeBSDThread *>(
- m_thread_list.GetThreadAtIndex(i, false).get());
- StateType thread_state = thread->GetState();
- if (thread_state == eStateRunning || thread_state == eStateStepping) {
- is_running = true;
- break;
- }
- }
- return is_running;
-}
-
-lldb_private::DataExtractor ProcessFreeBSD::GetAuxvData() {
- // If we're the local platform, we can ask the host for auxv data.
- PlatformSP platform_sp = GetTarget().GetPlatform();
- assert(platform_sp && platform_sp->IsHost());
-
- int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_AUXV, (int)m_process->GetID()};
- size_t auxv_size = AT_COUNT * sizeof(Elf_Auxinfo);
- DataBufferSP buf_sp(new DataBufferHeap(auxv_size, 0));
-
- if (::sysctl(mib, 4, buf_sp->GetBytes(), &auxv_size, NULL, 0) != 0) {
- perror("sysctl failed on auxv");
- buf_sp.reset();
- }
-
- return DataExtractor(buf_sp, GetByteOrder(), GetAddressByteSize());
-}
-
-struct EmulatorBaton {
- ProcessFreeBSD *m_process;
- RegisterContext *m_reg_context;
-
- // eRegisterKindDWARF -> RegisterValue
- std::unordered_map<uint32_t, RegisterValue> m_register_values;
-
- EmulatorBaton(ProcessFreeBSD *process, RegisterContext *reg_context)
- : m_process(process), m_reg_context(reg_context) {}
-};
-
-static size_t ReadMemoryCallback(EmulateInstruction *instruction, void *baton,
- const EmulateInstruction::Context &context,
- lldb::addr_t addr, void *dst, size_t length) {
- EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
-
- Status error;
- size_t bytes_read =
- emulator_baton->m_process->DoReadMemory(addr, dst, length, error);
- if (!error.Success())
- bytes_read = 0;
- return bytes_read;
-}
-
-static bool ReadRegisterCallback(EmulateInstruction *instruction, void *baton,
- const RegisterInfo *reg_info,
- RegisterValue ®_value) {
- EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
-
- auto it = emulator_baton->m_register_values.find(
- reg_info->kinds[eRegisterKindDWARF]);
- if (it != emulator_baton->m_register_values.end()) {
- reg_value = it->second;
- return true;
- }
-
- // The emulator only fills in the dwarf register numbers (and in some cases
- // the generic register numbers). Get the full register info from the
- // register context based on the dwarf register numbers.
- const RegisterInfo *full_reg_info =
- emulator_baton->m_reg_context->GetRegisterInfo(
- eRegisterKindDWARF, reg_info->kinds[eRegisterKindDWARF]);
-
- bool error =
- emulator_baton->m_reg_context->ReadRegister(full_reg_info, reg_value);
- return error;
-}
-
-static bool WriteRegisterCallback(EmulateInstruction *instruction, void *baton,
- const EmulateInstruction::Context &context,
- const RegisterInfo *reg_info,
- const RegisterValue ®_value) {
- EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
- emulator_baton->m_register_values[reg_info->kinds[eRegisterKindDWARF]] =
- reg_value;
- return true;
-}
-
-static size_t WriteMemoryCallback(EmulateInstruction *instruction, void *baton,
- const EmulateInstruction::Context &context,
- lldb::addr_t addr, const void *dst,
- size_t length) {
- return length;
-}
-
-bool ProcessFreeBSD::SingleStepBreakpointHit(
- void *baton, lldb_private::StoppointCallbackContext *context,
- lldb::user_id_t break_id, lldb::user_id_t break_loc_id) {
- return false;
-}
-
-Status ProcessFreeBSD::SetSoftwareSingleStepBreakpoint(lldb::tid_t tid,
- lldb::addr_t addr) {
- Status error;
-
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
- if (log) {
- LLDB_LOGF(log, "ProcessFreeBSD::%s addr = 0x%" PRIx64, __FUNCTION__, addr);
- LLDB_LOGF(log, "SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__,
- addr);
- }
-
- // Validate the address.
- if (addr == LLDB_INVALID_ADDRESS)
- return Status("ProcessFreeBSD::%s invalid load address specified.",
- __FUNCTION__);
-
- Breakpoint *const sw_step_break =
- m_process->GetTarget().CreateBreakpoint(addr, true, false).get();
- sw_step_break->SetCallback(SingleStepBreakpointHit, this, true);
- sw_step_break->SetBreakpointKind("software-single-step");
-
- LLDB_LOGF(log, "ProcessFreeBSD::%s addr = 0x%" PRIx64 " -- SUCCESS",
- __FUNCTION__, addr);
-
- m_threads_stepping_with_breakpoint.insert({tid, sw_step_break->GetID()});
- return Status();
-}
-
-bool ProcessFreeBSD::IsSoftwareStepBreakpoint(lldb::tid_t tid) {
- ThreadSP thread = GetThreadList().FindThreadByID(tid);
- if (!thread)
- return false;
-
- assert(thread->GetRegisterContext());
- lldb::addr_t stop_pc = thread->GetRegisterContext()->GetPC();
-
- const auto &iter = m_threads_stepping_with_breakpoint.find(tid);
- if (iter == m_threads_stepping_with_breakpoint.end())
- return false;
-
- lldb::break_id_t bp_id = iter->second;
- BreakpointSP bp = GetTarget().GetBreakpointByID(bp_id);
- if (!bp)
- return false;
-
- BreakpointLocationSP bp_loc = bp->FindLocationByAddress(stop_pc);
- if (!bp_loc)
- return false;
-
- GetTarget().RemoveBreakpointByID(bp_id);
- m_threads_stepping_with_breakpoint.erase(tid);
- return true;
-}
-
-bool ProcessFreeBSD::SupportHardwareSingleStepping() const {
- lldb_private::ArchSpec arch = GetTarget().GetArchitecture();
- if (arch.GetMachine() == llvm::Triple::arm || arch.IsMIPS())
- return false;
- return true;
-}
-
-Status ProcessFreeBSD::SetupSoftwareSingleStepping(lldb::tid_t tid) {
- std::unique_ptr<EmulateInstruction> emulator_up(
- EmulateInstruction::FindPlugin(GetTarget().GetArchitecture(),
- eInstructionTypePCModifying, nullptr));
-
- if (emulator_up == nullptr)
- return Status("Instruction emulator not found!");
-
- FreeBSDThread *thread = static_cast<FreeBSDThread *>(
- m_thread_list.FindThreadByID(tid, false).get());
- if (thread == NULL)
- return Status("Thread not found not found!");
-
- lldb::RegisterContextSP register_context_sp = thread->GetRegisterContext();
-
- EmulatorBaton baton(this, register_context_sp.get());
- emulator_up->SetBaton(&baton);
- emulator_up->SetReadMemCallback(&ReadMemoryCallback);
- emulator_up->SetReadRegCallback(&ReadRegisterCallback);
- emulator_up->SetWriteMemCallback(&WriteMemoryCallback);
- emulator_up->SetWriteRegCallback(&WriteRegisterCallback);
-
- if (!emulator_up->ReadInstruction())
- return Status("Read instruction failed!");
-
- bool emulation_result =
- emulator_up->EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC);
- const RegisterInfo *reg_info_pc = register_context_sp->GetRegisterInfo(
- eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
- auto pc_it =
- baton.m_register_values.find(reg_info_pc->kinds[eRegisterKindDWARF]);
-
- lldb::addr_t next_pc;
- if (emulation_result) {
- assert(pc_it != baton.m_register_values.end() &&
- "Emulation was successful but PC wasn't updated");
- next_pc = pc_it->second.GetAsUInt64();
- } else if (pc_it == baton.m_register_values.end()) {
- // Emulate instruction failed and it haven't changed PC. Advance PC with
- // the size of the current opcode because the emulation of all
- // PC modifying instruction should be successful. The failure most
- // likely caused by a not supported instruction which don't modify PC.
- next_pc =
- register_context_sp->GetPC() + emulator_up->GetOpcode().GetByteSize();
- } else {
- // The instruction emulation failed after it modified the PC. It is an
- // unknown error where we can't continue because the next instruction is
- // modifying the PC but we don't know how.
- return Status("Instruction emulation failed unexpectedly");
- }
-
- SetSoftwareSingleStepBreakpoint(tid, next_pc);
- return Status();
-}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
deleted file mode 100644
index b60bcd2..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
+++ /dev/null
@@ -1,221 +0,0 @@
-//===-- ProcessFreeBSD.h ------------------------------------------*- 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_ProcessFreeBSD_H_
-#define liblldb_ProcessFreeBSD_H_
-
-#include "Plugins/Process/POSIX/ProcessMessage.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/ThreadList.h"
-#include <mutex>
-#include <queue>
-#include <set>
-
-class ProcessMonitor;
-class FreeBSDThread;
-
-class ProcessFreeBSD : public lldb_private::Process {
-
-public:
- // Static functions.
- static lldb::ProcessSP
- CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
- const lldb_private::FileSpec *crash_file_path,
- bool can_connect);
-
- static void Initialize();
-
- static void Terminate();
-
- static lldb_private::ConstString GetPluginNameStatic();
-
- static const char *GetPluginDescriptionStatic();
-
- // Constructors and destructors
- ProcessFreeBSD(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
- lldb::UnixSignalsSP &unix_signals_sp);
-
- ~ProcessFreeBSD();
-
- virtual lldb_private::Status WillResume() override;
-
- // PluginInterface protocol
- virtual lldb_private::ConstString GetPluginName() override;
-
- virtual uint32_t GetPluginVersion() override;
-
-public:
- // Process protocol.
- void Finalize() override;
-
- bool CanDebug(lldb::TargetSP target_sp,
- bool plugin_specified_by_name) override;
-
- lldb_private::Status WillLaunch(lldb_private::Module *module) override;
-
- lldb_private::Status DoAttachToProcessWithID(
- lldb::pid_t pid,
- const lldb_private::ProcessAttachInfo &attach_info) override;
-
- lldb_private::Status
- DoLaunch(lldb_private::Module *exe_module,
- lldb_private::ProcessLaunchInfo &launch_info) override;
-
- void DidLaunch() override;
-
- lldb_private::Status DoResume() override;
-
- lldb_private::Status DoHalt(bool &caused_stop) override;
-
- lldb_private::Status DoDetach(bool keep_stopped) override;
-
- lldb_private::Status DoSignal(int signal) override;
-
- lldb_private::Status DoDestroy() override;
-
- void DoDidExec() override;
-
- void RefreshStateAfterStop() override;
-
- bool IsAlive() override;
-
- size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
- lldb_private::Status &error) override;
-
- size_t DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
- lldb_private::Status &error) override;
-
- lldb::addr_t DoAllocateMemory(size_t size, uint32_t permissions,
- lldb_private::Status &error) override;
-
- lldb_private::Status DoDeallocateMemory(lldb::addr_t ptr) override;
-
- virtual size_t
- GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite *bp_site);
-
- lldb_private::Status
- EnableBreakpointSite(lldb_private::BreakpointSite *bp_site) override;
-
- lldb_private::Status
- DisableBreakpointSite(lldb_private::BreakpointSite *bp_site) override;
-
- lldb_private::Status EnableWatchpoint(lldb_private::Watchpoint *wp,
- bool notify = true) override;
-
- lldb_private::Status DisableWatchpoint(lldb_private::Watchpoint *wp,
- bool notify = true) override;
-
- lldb_private::Status GetWatchpointSupportInfo(uint32_t &num) override;
-
- lldb_private::Status GetWatchpointSupportInfo(uint32_t &num,
- bool &after) override;
-
- virtual uint32_t UpdateThreadListIfNeeded();
-
- bool DoUpdateThreadList(lldb_private::ThreadList &old_thread_list,
- lldb_private::ThreadList &new_thread_list) override;
-
- virtual lldb::ByteOrder GetByteOrder() const;
-
- lldb::addr_t GetImageInfoAddress() override;
-
- size_t PutSTDIN(const char *buf, size_t len,
- lldb_private::Status &error) override;
-
- lldb_private::DataExtractor GetAuxvData() override;
-
- // ProcessFreeBSD internal API.
-
- /// Registers the given message with this process.
- virtual void SendMessage(const ProcessMessage &message);
-
- ProcessMonitor &GetMonitor() {
- assert(m_monitor);
- return *m_monitor;
- }
-
- lldb_private::FileSpec
- GetFileSpec(const lldb_private::FileAction *file_action,
- const lldb_private::FileSpec &default_file_spec,
- const lldb_private::FileSpec &dbg_pts_file_spec);
-
- /// Adds the thread to the list of threads for which we have received the
- /// initial stopping signal.
- /// The \p stop_tid parameter indicates the thread which the stop happened
- /// for.
- bool AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid);
-
- bool WaitingForInitialStop(lldb::tid_t stop_tid);
-
- virtual FreeBSDThread *CreateNewFreeBSDThread(lldb_private::Process &process,
- lldb::tid_t tid);
-
- static bool SingleStepBreakpointHit(
- void *baton, lldb_private::StoppointCallbackContext *context,
- lldb::user_id_t break_id, lldb::user_id_t break_loc_id);
-
- lldb_private::Status SetupSoftwareSingleStepping(lldb::tid_t tid);
-
- lldb_private::Status SetSoftwareSingleStepBreakpoint(lldb::tid_t tid,
- lldb::addr_t addr);
-
- bool IsSoftwareStepBreakpoint(lldb::tid_t tid);
-
- bool SupportHardwareSingleStepping() const;
-
- typedef std::vector<lldb::tid_t> tid_collection;
- tid_collection &GetStepTids() { return m_step_tids; }
-
-protected:
- static const size_t MAX_TRAP_OPCODE_SIZE = 8;
-
- /// Target byte order.
- lldb::ByteOrder m_byte_order;
-
- /// Process monitor;
- ProcessMonitor *m_monitor;
-
- /// The module we are executing.
- lldb_private::Module *m_module;
-
- /// Message queue notifying this instance of inferior process state changes.
- std::recursive_mutex m_message_mutex;
- std::queue<ProcessMessage> m_message_queue;
-
- /// Drive any exit events to completion.
- bool m_exit_now;
-
- /// Returns true if the process has exited.
- bool HasExited();
-
- /// Returns true if the process is stopped.
- bool IsStopped();
-
- /// Returns true if at least one running is currently running
- bool IsAThreadRunning();
-
- typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap;
- MMapMap m_addr_to_mmap_size;
-
- typedef std::set<lldb::tid_t> ThreadStopSet;
- /// Every thread begins with a stop signal. This keeps track
- /// of the threads for which we have received the stop signal.
- ThreadStopSet m_seen_initial_stop;
-
- friend class FreeBSDThread;
-
- tid_collection m_suspend_tids;
- tid_collection m_run_tids;
- tid_collection m_step_tids;
- std::map<lldb::tid_t, lldb::break_id_t> m_threads_stepping_with_breakpoint;
-
- int m_resume_signo;
-};
-
-#endif // liblldb_ProcessFreeBSD_H_
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
deleted file mode 100644
index 4637458..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
+++ /dev/null
@@ -1,1424 +0,0 @@
-//===-- ProcessMonitor.cpp ------------------------------------------------===//
-//
-// 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 <errno.h>
-#include <poll.h>
-#include <signal.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/ptrace.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include "lldb/Host/Host.h"
-#include "lldb/Host/PseudoTerminal.h"
-#include "lldb/Host/ThreadLauncher.h"
-#include "lldb/Target/RegisterContext.h"
-#include "lldb/Target/Thread.h"
-#include "lldb/Target/UnixSignals.h"
-#include "lldb/Utility/RegisterValue.h"
-#include "lldb/Utility/Scalar.h"
-#include "lldb/Utility/Status.h"
-#include "llvm/Support/Errno.h"
-
-#include "FreeBSDThread.h"
-#include "Plugins/Process/POSIX/CrashReason.h"
-#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
-#include "ProcessFreeBSD.h"
-#include "ProcessMonitor.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-// Wrapper for ptrace to catch errors and log calls.
-
-const char *Get_PT_IO_OP(int op) {
- switch (op) {
- case PIOD_READ_D:
- return "READ_D";
- case PIOD_WRITE_D:
- return "WRITE_D";
- case PIOD_READ_I:
- return "READ_I";
- case PIOD_WRITE_I:
- return "WRITE_I";
- default:
- return "Unknown op";
- }
-}
-
-// Wrapper for ptrace to catch errors and log calls. Note that ptrace sets
-// errno on error because -1 is reserved as a valid result.
-extern long PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data,
- const char *reqName, const char *file, int line) {
- long int result;
-
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
-
- if (log) {
- LLDB_LOGF(log,
- "ptrace(%s, %" PRIu64 ", %p, %x) called from file %s line %d",
- reqName, pid, addr, data, file, line);
- if (req == PT_IO) {
- struct ptrace_io_desc *pi = (struct ptrace_io_desc *)addr;
-
- LLDB_LOGF(log, "PT_IO: op=%s offs=%zx size=%zu",
- Get_PT_IO_OP(pi->piod_op), (size_t)pi->piod_offs, pi->piod_len);
- }
- }
-
- // PtraceDisplayBytes(req, data);
-
- errno = 0;
- result = ptrace(req, pid, (caddr_t)addr, data);
-
- // PtraceDisplayBytes(req, data);
-
- if (log && errno != 0) {
- const char *str;
- switch (errno) {
- case ESRCH:
- str = "ESRCH";
- break;
- case EINVAL:
- str = "EINVAL";
- break;
- case EBUSY:
- str = "EBUSY";
- break;
- case EPERM:
- str = "EPERM";
- break;
- default:
- str = "<unknown>";
- }
- LLDB_LOGF(log, "ptrace() failed; errno=%d (%s)", errno, str);
- }
-
- if (log) {
-#ifdef __amd64__
- if (req == PT_GETREGS) {
- struct reg *r = (struct reg *)addr;
-
- LLDB_LOGF(log, "PT_GETREGS: rip=0x%lx rsp=0x%lx rbp=0x%lx rax=0x%lx",
- r->r_rip, r->r_rsp, r->r_rbp, r->r_rax);
- }
- if (req == PT_GETDBREGS || req == PT_SETDBREGS) {
- struct dbreg *r = (struct dbreg *)addr;
- char setget = (req == PT_GETDBREGS) ? 'G' : 'S';
-
- for (int i = 0; i <= 7; i++)
- LLDB_LOGF(log, "PT_%cETDBREGS: dr[%d]=0x%lx", setget, i, r->dr[i]);
- }
-#endif
- }
-
- return result;
-}
-
-// Wrapper for ptrace when logging is not required. Sets errno to 0 prior to
-// calling ptrace.
-extern long PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data) {
- long result = 0;
- errno = 0;
- result = ptrace(req, pid, (caddr_t)addr, data);
- return result;
-}
-
-#define PTRACE(req, pid, addr, data) \
- PtraceWrapper((req), (pid), (addr), (data), #req, __FILE__, __LINE__)
-
-// Static implementations of ProcessMonitor::ReadMemory and
-// ProcessMonitor::WriteMemory. This enables mutual recursion between these
-// functions without needed to go thru the thread funnel.
-
-static size_t DoReadMemory(lldb::pid_t pid, lldb::addr_t vm_addr, void *buf,
- size_t size, Status &error) {
- struct ptrace_io_desc pi_desc;
-
- pi_desc.piod_op = PIOD_READ_D;
- pi_desc.piod_offs = (void *)vm_addr;
- pi_desc.piod_addr = buf;
- pi_desc.piod_len = size;
-
- if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0) {
- error.SetErrorToErrno();
- return 0;
- }
- return pi_desc.piod_len;
-}
-
-static size_t DoWriteMemory(lldb::pid_t pid, lldb::addr_t vm_addr,
- const void *buf, size_t size, Status &error) {
- struct ptrace_io_desc pi_desc;
-
- pi_desc.piod_op = PIOD_WRITE_D;
- pi_desc.piod_offs = (void *)vm_addr;
- pi_desc.piod_addr = const_cast<void *>(buf);
- pi_desc.piod_len = size;
-
- if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0) {
- error.SetErrorToErrno();
- return 0;
- }
- return pi_desc.piod_len;
-}
-
-// Simple helper function to ensure flags are enabled on the given file
-// descriptor.
-static bool EnsureFDFlags(int fd, int flags, Status &error) {
- int status;
-
- if ((status = fcntl(fd, F_GETFL)) == -1) {
- error.SetErrorToErrno();
- return false;
- }
-
- if (fcntl(fd, F_SETFL, status | flags) == -1) {
- error.SetErrorToErrno();
- return false;
- }
-
- return true;
-}
-
-/// \class Operation
-/// Represents a ProcessMonitor operation.
-///
-/// Under FreeBSD, it is not possible to ptrace() from any other thread but
-/// the one that spawned or attached to the process from the start.
-/// Therefore, when a ProcessMonitor is asked to deliver or change the state
-/// of an inferior process the operation must be "funneled" to a specific
-/// thread to perform the task. The Operation class provides an abstract base
-/// for all services the ProcessMonitor must perform via the single virtual
-/// function Execute, thus encapsulating the code that needs to run in the
-/// privileged context.
-class Operation {
-public:
- virtual ~Operation() {}
- virtual void Execute(ProcessMonitor *monitor) = 0;
-};
-
-/// \class ReadOperation
-/// Implements ProcessMonitor::ReadMemory.
-class ReadOperation : public Operation {
-public:
- ReadOperation(lldb::addr_t addr, void *buff, size_t size, Status &error,
- size_t &result)
- : m_addr(addr), m_buff(buff), m_size(size), m_error(error),
- m_result(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- lldb::addr_t m_addr;
- void *m_buff;
- size_t m_size;
- Status &m_error;
- size_t &m_result;
-};
-
-void ReadOperation::Execute(ProcessMonitor *monitor) {
- lldb::pid_t pid = monitor->GetPID();
-
- m_result = DoReadMemory(pid, m_addr, m_buff, m_size, m_error);
-}
-
-/// \class WriteOperation
-/// Implements ProcessMonitor::WriteMemory.
-class WriteOperation : public Operation {
-public:
- WriteOperation(lldb::addr_t addr, const void *buff, size_t size,
- Status &error, size_t &result)
- : m_addr(addr), m_buff(buff), m_size(size), m_error(error),
- m_result(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- lldb::addr_t m_addr;
- const void *m_buff;
- size_t m_size;
- Status &m_error;
- size_t &m_result;
-};
-
-void WriteOperation::Execute(ProcessMonitor *monitor) {
- lldb::pid_t pid = monitor->GetPID();
-
- m_result = DoWriteMemory(pid, m_addr, m_buff, m_size, m_error);
-}
-
-/// \class ReadRegOperation
-/// Implements ProcessMonitor::ReadRegisterValue.
-class ReadRegOperation : public Operation {
-public:
- ReadRegOperation(lldb::tid_t tid, unsigned offset, unsigned size,
- RegisterValue &value, bool &result)
- : m_tid(tid), m_offset(offset), m_size(size), m_value(value),
- m_result(result) {}
-
- void Execute(ProcessMonitor *monitor);
-
-private:
- lldb::tid_t m_tid;
- unsigned m_offset;
- unsigned m_size;
- RegisterValue &m_value;
- bool &m_result;
-};
-
-void ReadRegOperation::Execute(ProcessMonitor *monitor) {
- struct reg regs;
- int rc;
-
- if ((rc = PTRACE(PT_GETREGS, m_tid, (caddr_t)®s, 0)) < 0) {
- m_result = false;
- } else {
- // 'struct reg' contains only 32- or 64-bit register values. Punt on
- // others. Also, not all entries may be uintptr_t sized, such as 32-bit
- // processes on powerpc64 (probably the same for i386 on amd64)
- if (m_size == sizeof(uint32_t))
- m_value = *(uint32_t *)(((caddr_t)®s) + m_offset);
- else if (m_size == sizeof(uint64_t))
- m_value = *(uint64_t *)(((caddr_t)®s) + m_offset);
- else
- memcpy((void *)&m_value, (((caddr_t)®s) + m_offset), m_size);
- m_result = true;
- }
-}
-
-/// \class WriteRegOperation
-/// Implements ProcessMonitor::WriteRegisterValue.
-class WriteRegOperation : public Operation {
-public:
- WriteRegOperation(lldb::tid_t tid, unsigned offset,
- const RegisterValue &value, bool &result)
- : m_tid(tid), m_offset(offset), m_value(value), m_result(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- lldb::tid_t m_tid;
- unsigned m_offset;
- const RegisterValue &m_value;
- bool &m_result;
-};
-
-void WriteRegOperation::Execute(ProcessMonitor *monitor) {
- struct reg regs;
-
- if (PTRACE(PT_GETREGS, m_tid, (caddr_t)®s, 0) < 0) {
- m_result = false;
- return;
- }
- *(uintptr_t *)(((caddr_t)®s) + m_offset) =
- (uintptr_t)m_value.GetAsUInt64();
- if (PTRACE(PT_SETREGS, m_tid, (caddr_t)®s, 0) < 0)
- m_result = false;
- else
- m_result = true;
-}
-
-/// \class ReadDebugRegOperation
-/// Implements ProcessMonitor::ReadDebugRegisterValue.
-class ReadDebugRegOperation : public Operation {
-public:
- ReadDebugRegOperation(lldb::tid_t tid, unsigned offset, unsigned size,
- RegisterValue &value, bool &result)
- : m_tid(tid), m_offset(offset), m_size(size), m_value(value),
- m_result(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- lldb::tid_t m_tid;
- unsigned m_offset;
- unsigned m_size;
- RegisterValue &m_value;
- bool &m_result;
-};
-
-void ReadDebugRegOperation::Execute(ProcessMonitor *monitor) {
- struct dbreg regs;
- int rc;
-
- if ((rc = PTRACE(PT_GETDBREGS, m_tid, (caddr_t)®s, 0)) < 0) {
- m_result = false;
- } else {
- if (m_size == sizeof(uintptr_t))
- m_value = *(uintptr_t *)(((caddr_t)®s) + m_offset);
- else
- memcpy((void *)&m_value, (((caddr_t)®s) + m_offset), m_size);
- m_result = true;
- }
-}
-
-/// \class WriteDebugRegOperation
-/// Implements ProcessMonitor::WriteDebugRegisterValue.
-class WriteDebugRegOperation : public Operation {
-public:
- WriteDebugRegOperation(lldb::tid_t tid, unsigned offset,
- const RegisterValue &value, bool &result)
- : m_tid(tid), m_offset(offset), m_value(value), m_result(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- lldb::tid_t m_tid;
- unsigned m_offset;
- const RegisterValue &m_value;
- bool &m_result;
-};
-
-void WriteDebugRegOperation::Execute(ProcessMonitor *monitor) {
- struct dbreg regs;
-
- if (PTRACE(PT_GETDBREGS, m_tid, (caddr_t)®s, 0) < 0) {
- m_result = false;
- return;
- }
- *(uintptr_t *)(((caddr_t)®s) + m_offset) =
- (uintptr_t)m_value.GetAsUInt64();
- if (PTRACE(PT_SETDBREGS, m_tid, (caddr_t)®s, 0) < 0)
- m_result = false;
- else
- m_result = true;
-}
-
-/// \class ReadGPROperation
-/// Implements ProcessMonitor::ReadGPR.
-class ReadGPROperation : public Operation {
-public:
- ReadGPROperation(lldb::tid_t tid, void *buf, bool &result)
- : m_tid(tid), m_buf(buf), m_result(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- lldb::tid_t m_tid;
- void *m_buf;
- bool &m_result;
-};
-
-void ReadGPROperation::Execute(ProcessMonitor *monitor) {
- int rc;
-
- errno = 0;
- rc = PTRACE(PT_GETREGS, m_tid, (caddr_t)m_buf, 0);
- if (errno != 0)
- m_result = false;
- else
- m_result = true;
-}
-
-/// \class ReadFPROperation
-/// Implements ProcessMonitor::ReadFPR.
-class ReadFPROperation : public Operation {
-public:
- ReadFPROperation(lldb::tid_t tid, void *buf, bool &result)
- : m_tid(tid), m_buf(buf), m_result(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- lldb::tid_t m_tid;
- void *m_buf;
- bool &m_result;
-};
-
-void ReadFPROperation::Execute(ProcessMonitor *monitor) {
- if (PTRACE(PT_GETFPREGS, m_tid, (caddr_t)m_buf, 0) < 0)
- m_result = false;
- else
- m_result = true;
-}
-
-/// \class WriteGPROperation
-/// Implements ProcessMonitor::WriteGPR.
-class WriteGPROperation : public Operation {
-public:
- WriteGPROperation(lldb::tid_t tid, void *buf, bool &result)
- : m_tid(tid), m_buf(buf), m_result(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- lldb::tid_t m_tid;
- void *m_buf;
- bool &m_result;
-};
-
-void WriteGPROperation::Execute(ProcessMonitor *monitor) {
- if (PTRACE(PT_SETREGS, m_tid, (caddr_t)m_buf, 0) < 0)
- m_result = false;
- else
- m_result = true;
-}
-
-/// \class WriteFPROperation
-/// Implements ProcessMonitor::WriteFPR.
-class WriteFPROperation : public Operation {
-public:
- WriteFPROperation(lldb::tid_t tid, void *buf, bool &result)
- : m_tid(tid), m_buf(buf), m_result(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- lldb::tid_t m_tid;
- void *m_buf;
- bool &m_result;
-};
-
-void WriteFPROperation::Execute(ProcessMonitor *monitor) {
- if (PTRACE(PT_SETFPREGS, m_tid, (caddr_t)m_buf, 0) < 0)
- m_result = false;
- else
- m_result = true;
-}
-
-/// \class ResumeOperation
-/// Implements ProcessMonitor::Resume.
-class ResumeOperation : public Operation {
-public:
- ResumeOperation(uint32_t signo, bool &result)
- : m_signo(signo), m_result(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- uint32_t m_signo;
- bool &m_result;
-};
-
-void ResumeOperation::Execute(ProcessMonitor *monitor) {
- lldb::pid_t pid = monitor->GetPID();
- int data = 0;
-
- if (m_signo != LLDB_INVALID_SIGNAL_NUMBER)
- data = m_signo;
-
- if (PTRACE(PT_CONTINUE, pid, (caddr_t)1, data)) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
- LLDB_LOG(log, "ResumeOperation ({0}) failed: {1}", pid,
- llvm::sys::StrError(errno));
- m_result = false;
- } else
- m_result = true;
-}
-
-/// \class SingleStepOperation
-/// Implements ProcessMonitor::SingleStep.
-class SingleStepOperation : public Operation {
-public:
- SingleStepOperation(uint32_t signo, bool &result)
- : m_signo(signo), m_result(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- uint32_t m_signo;
- bool &m_result;
-};
-
-void SingleStepOperation::Execute(ProcessMonitor *monitor) {
- lldb::pid_t pid = monitor->GetPID();
- int data = 0;
-
- if (m_signo != LLDB_INVALID_SIGNAL_NUMBER)
- data = m_signo;
-
- if (PTRACE(PT_STEP, pid, NULL, data))
- m_result = false;
- else
- m_result = true;
-}
-
-/// \class LwpInfoOperation
-/// Implements ProcessMonitor::GetLwpInfo.
-class LwpInfoOperation : public Operation {
-public:
- LwpInfoOperation(lldb::tid_t tid, void *info, bool &result, int &ptrace_err)
- : m_tid(tid), m_info(info), m_result(result), m_err(ptrace_err) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- lldb::tid_t m_tid;
- void *m_info;
- bool &m_result;
- int &m_err;
-};
-
-void LwpInfoOperation::Execute(ProcessMonitor *monitor) {
- struct ptrace_lwpinfo plwp;
-
- if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp))) {
- m_result = false;
- m_err = errno;
- } else {
- memcpy(m_info, &plwp, sizeof(plwp));
- m_result = true;
- }
-}
-
-/// \class ThreadSuspendOperation
-/// Implements ProcessMonitor::ThreadSuspend.
-class ThreadSuspendOperation : public Operation {
-public:
- ThreadSuspendOperation(lldb::tid_t tid, bool suspend, bool &result)
- : m_tid(tid), m_suspend(suspend), m_result(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- lldb::tid_t m_tid;
- bool m_suspend;
- bool &m_result;
-};
-
-void ThreadSuspendOperation::Execute(ProcessMonitor *monitor) {
- m_result = !PTRACE(m_suspend ? PT_SUSPEND : PT_RESUME, m_tid, NULL, 0);
-}
-
-/// \class EventMessageOperation
-/// Implements ProcessMonitor::GetEventMessage.
-class EventMessageOperation : public Operation {
-public:
- EventMessageOperation(lldb::tid_t tid, unsigned long *message, bool &result)
- : m_tid(tid), m_message(message), m_result(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- lldb::tid_t m_tid;
- unsigned long *m_message;
- bool &m_result;
-};
-
-void EventMessageOperation::Execute(ProcessMonitor *monitor) {
- struct ptrace_lwpinfo plwp;
-
- if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp)))
- m_result = false;
- else {
- if (plwp.pl_flags & PL_FLAG_FORKED) {
- *m_message = plwp.pl_child_pid;
- m_result = true;
- } else
- m_result = false;
- }
-}
-
-/// \class KillOperation
-/// Implements ProcessMonitor::Kill.
-class KillOperation : public Operation {
-public:
- KillOperation(bool &result) : m_result(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- bool &m_result;
-};
-
-void KillOperation::Execute(ProcessMonitor *monitor) {
- lldb::pid_t pid = monitor->GetPID();
-
- if (PTRACE(PT_KILL, pid, NULL, 0))
- m_result = false;
- else
- m_result = true;
-}
-
-/// \class DetachOperation
-/// Implements ProcessMonitor::Detach.
-class DetachOperation : public Operation {
-public:
- DetachOperation(Status &result) : m_error(result) {}
-
- void Execute(ProcessMonitor *monitor) override;
-
-private:
- Status &m_error;
-};
-
-void DetachOperation::Execute(ProcessMonitor *monitor) {
- lldb::pid_t pid = monitor->GetPID();
-
- if (PTRACE(PT_DETACH, pid, NULL, 0) < 0)
- m_error.SetErrorToErrno();
-}
-
-ProcessMonitor::OperationArgs::OperationArgs(ProcessMonitor *monitor)
- : m_monitor(monitor) {
- sem_init(&m_semaphore, 0, 0);
-}
-
-ProcessMonitor::OperationArgs::~OperationArgs() { sem_destroy(&m_semaphore); }
-
-ProcessMonitor::LaunchArgs::LaunchArgs(ProcessMonitor *monitor,
- lldb_private::Module *module,
- char const **argv, Environment env,
- const FileSpec &stdin_file_spec,
- const FileSpec &stdout_file_spec,
- const FileSpec &stderr_file_spec,
- const FileSpec &working_dir)
- : OperationArgs(monitor), m_module(module), m_argv(argv),
- m_env(std::move(env)), m_stdin_file_spec(stdin_file_spec),
- m_stdout_file_spec(stdout_file_spec),
- m_stderr_file_spec(stderr_file_spec), m_working_dir(working_dir) {}
-
-ProcessMonitor::LaunchArgs::~LaunchArgs() {}
-
-ProcessMonitor::AttachArgs::AttachArgs(ProcessMonitor *monitor, lldb::pid_t pid)
- : OperationArgs(monitor), m_pid(pid) {}
-
-ProcessMonitor::AttachArgs::~AttachArgs() {}
-
-/// The basic design of the ProcessMonitor is built around two threads.
-///
-/// One thread (@see SignalThread) simply blocks on a call to waitpid()
-/// looking for changes in the debugee state. When a change is detected a
-/// ProcessMessage is sent to the associated ProcessFreeBSD instance. This
-/// thread "drives" state changes in the debugger.
-///
-/// The second thread (@see OperationThread) is responsible for two things 1)
-/// launching or attaching to the inferior process, and then 2) servicing
-/// operations such as register reads/writes, stepping, etc. See the comments
-/// on the Operation class for more info as to why this is needed.
-ProcessMonitor::ProcessMonitor(
- ProcessFreeBSD *process, Module *module, const char *argv[],
- Environment env, const FileSpec &stdin_file_spec,
- const FileSpec &stdout_file_spec, const FileSpec &stderr_file_spec,
- const FileSpec &working_dir,
- const lldb_private::ProcessLaunchInfo & /* launch_info */,
- lldb_private::Status &error)
- : m_process(static_cast<ProcessFreeBSD *>(process)),
- m_operation_thread(), m_monitor_thread(), m_pid(LLDB_INVALID_PROCESS_ID), m_terminal_fd(-1), m_operation(0) {
- using namespace std::placeholders;
-
- std::unique_ptr<LaunchArgs> args(
- new LaunchArgs(this, module, argv, std::move(env), stdin_file_spec,
- stdout_file_spec, stderr_file_spec, working_dir));
-
- sem_init(&m_operation_pending, 0, 0);
- sem_init(&m_operation_done, 0, 0);
-
- StartLaunchOpThread(args.get(), error);
- if (!error.Success())
- return;
-
- if (llvm::sys::RetryAfterSignal(-1, sem_wait, &args->m_semaphore) == -1) {
- error.SetErrorToErrno();
- return;
- }
-
- // Check that the launch was a success.
- if (!args->m_error.Success()) {
- StopOpThread();
- error = args->m_error;
- return;
- }
-
- // Finally, start monitoring the child process for change in state.
- llvm::Expected<lldb_private::HostThread> monitor_thread =
- Host::StartMonitoringChildProcess(
- std::bind(&ProcessMonitor::MonitorCallback, this, _1, _2, _3, _4),
- GetPID(), true);
- if (!monitor_thread || !monitor_thread->IsJoinable()) {
- error.SetErrorToGenericError();
- error.SetErrorString("Process launch failed.");
- return;
- }
- m_monitor_thread = *monitor_thread;
-}
-
-ProcessMonitor::ProcessMonitor(ProcessFreeBSD *process, lldb::pid_t pid,
- lldb_private::Status &error)
- : m_process(static_cast<ProcessFreeBSD *>(process)),
- m_operation_thread(), m_monitor_thread(), m_pid(pid), m_terminal_fd(-1), m_operation(0) {
- using namespace std::placeholders;
-
- sem_init(&m_operation_pending, 0, 0);
- sem_init(&m_operation_done, 0, 0);
-
- std::unique_ptr<AttachArgs> args(new AttachArgs(this, pid));
-
- StartAttachOpThread(args.get(), error);
- if (!error.Success())
- return;
-
- if (llvm::sys::RetryAfterSignal(-1, sem_wait, &args->m_semaphore) == -1) {
- error.SetErrorToErrno();
- return;
- }
-
- // Check that the attach was a success.
- if (!args->m_error.Success()) {
- StopOpThread();
- error = args->m_error;
- return;
- }
-
- // Finally, start monitoring the child process for change in state.
- llvm::Expected<lldb_private::HostThread> monitor_thread =
- Host::StartMonitoringChildProcess(
- std::bind(&ProcessMonitor::MonitorCallback, this, _1, _2, _3, _4),
- GetPID(), true);
- if (!monitor_thread || !monitor_thread->IsJoinable()) {
- error.SetErrorToGenericError();
- error.SetErrorString("Process attach failed.");
- return;
- }
- m_monitor_thread = *monitor_thread;
-}
-
-ProcessMonitor::~ProcessMonitor() { StopMonitor(); }
-
-// Thread setup and tear down.
-void ProcessMonitor::StartLaunchOpThread(LaunchArgs *args, Status &error) {
- static const char *g_thread_name = "lldb.process.freebsd.operation";
-
- if (m_operation_thread && m_operation_thread->IsJoinable())
- return;
-
- llvm::Expected<lldb_private::HostThread> operation_thread =
- ThreadLauncher::LaunchThread(g_thread_name, LaunchOpThread, args);
- if (operation_thread)
- m_operation_thread = *operation_thread;
- else
- error = operation_thread.takeError();
-}
-
-void *ProcessMonitor::LaunchOpThread(void *arg) {
- LaunchArgs *args = static_cast<LaunchArgs *>(arg);
-
- if (!Launch(args)) {
- sem_post(&args->m_semaphore);
- return NULL;
- }
-
- ServeOperation(args);
- return NULL;
-}
-
-bool ProcessMonitor::Launch(LaunchArgs *args) {
- ProcessMonitor *monitor = args->m_monitor;
- ProcessFreeBSD &process = monitor->GetProcess();
- const char **argv = args->m_argv;
- const FileSpec &stdin_file_spec = args->m_stdin_file_spec;
- const FileSpec &stdout_file_spec = args->m_stdout_file_spec;
- const FileSpec &stderr_file_spec = args->m_stderr_file_spec;
- const FileSpec &working_dir = args->m_working_dir;
-
- PseudoTerminal terminal;
-
- // Propagate the environment if one is not supplied.
- Environment::Envp envp =
- (args->m_env.empty() ? Host::GetEnvironment() : args->m_env).getEnvp();
-
- llvm::Expected<lldb::pid_t> pid = terminal.Fork();
- if (!pid) {
- args->m_error = pid.takeError();
- goto FINISH;
- }
-
- // Recognized child exit status codes.
- enum {
- ePtraceFailed = 1,
- eDupStdinFailed,
- eDupStdoutFailed,
- eDupStderrFailed,
- eChdirFailed,
- eExecFailed,
- eSetGidFailed
- };
-
- // Child process.
- if (*pid == 0) {
- // Trace this process.
- if (PTRACE(PT_TRACE_ME, 0, NULL, 0) < 0)
- exit(ePtraceFailed);
-
- // terminal has already dupped the tty descriptors to stdin/out/err. This
- // closes original fd from which they were copied (and avoids leaking
- // descriptors to the debugged process.
- terminal.CloseSecondaryFileDescriptor();
-
- // Do not inherit setgid powers.
- if (setgid(getgid()) != 0)
- exit(eSetGidFailed);
-
- // Let us have our own process group.
- setpgid(0, 0);
-
- // Dup file descriptors if needed.
- //
- // FIXME: If two or more of the paths are the same we needlessly open
- // the same file multiple times.
- if (stdin_file_spec)
- if (!DupDescriptor(stdin_file_spec, STDIN_FILENO, O_RDONLY))
- exit(eDupStdinFailed);
-
- if (stdout_file_spec)
- if (!DupDescriptor(stdout_file_spec, STDOUT_FILENO, O_WRONLY | O_CREAT))
- exit(eDupStdoutFailed);
-
- if (stderr_file_spec)
- if (!DupDescriptor(stderr_file_spec, STDERR_FILENO, O_WRONLY | O_CREAT))
- exit(eDupStderrFailed);
-
- // Change working directory
- if (working_dir && 0 != ::chdir(working_dir.GetCString()))
- exit(eChdirFailed);
-
- // Execute. We should never return.
- execve(argv[0], const_cast<char *const *>(argv), envp);
- exit(eExecFailed);
- }
-
- // Wait for the child process to to trap on its call to execve.
- ::pid_t wpid;
- int status;
- if ((wpid = waitpid(*pid, &status, 0)) < 0) {
- args->m_error.SetErrorToErrno();
- goto FINISH;
- } else if (WIFEXITED(status)) {
- // open, dup or execve likely failed for some reason.
- args->m_error.SetErrorToGenericError();
- switch (WEXITSTATUS(status)) {
- case ePtraceFailed:
- args->m_error.SetErrorString("Child ptrace failed.");
- break;
- case eDupStdinFailed:
- args->m_error.SetErrorString("Child open stdin failed.");
- break;
- case eDupStdoutFailed:
- args->m_error.SetErrorString("Child open stdout failed.");
- break;
- case eDupStderrFailed:
- args->m_error.SetErrorString("Child open stderr failed.");
- break;
- case eChdirFailed:
- args->m_error.SetErrorString("Child failed to set working directory.");
- break;
- case eExecFailed:
- args->m_error.SetErrorString("Child exec failed.");
- break;
- case eSetGidFailed:
- args->m_error.SetErrorString("Child setgid failed.");
- break;
- default:
- args->m_error.SetErrorString("Child returned unknown exit status.");
- break;
- }
- goto FINISH;
- }
- assert(WIFSTOPPED(status) && wpid == (::pid_t)*pid &&
- "Could not sync with inferior process.");
-
-#ifdef notyet
- // Have the child raise an event on exit. This is used to keep the child in
- // limbo until it is destroyed.
- if (PTRACE(PTRACE_SETOPTIONS, *pid, NULL, PTRACE_O_TRACEEXIT) < 0) {
- args->m_error.SetErrorToErrno();
- goto FINISH;
- }
-#endif
- // Release the master terminal descriptor and pass it off to the
- // ProcessMonitor instance. Similarly stash the inferior pid.
- monitor->m_terminal_fd = terminal.ReleasePrimaryFileDescriptor();
- monitor->m_pid = *pid;
-
- // Set the terminal fd to be in non blocking mode (it simplifies the
- // implementation of ProcessFreeBSD::GetSTDOUT to have a non-blocking
- // descriptor to read from).
- if (!EnsureFDFlags(monitor->m_terminal_fd, O_NONBLOCK, args->m_error))
- goto FINISH;
-
- process.SendMessage(ProcessMessage::Attach(*pid));
-
-FINISH:
- return args->m_error.Success();
-}
-
-void ProcessMonitor::StartAttachOpThread(AttachArgs *args,
- lldb_private::Status &error) {
- static const char *g_thread_name = "lldb.process.freebsd.operation";
-
- if (m_operation_thread && m_operation_thread->IsJoinable())
- return;
-
- llvm::Expected<lldb_private::HostThread> operation_thread =
- ThreadLauncher::LaunchThread(g_thread_name, AttachOpThread, args);
- if (operation_thread)
- m_operation_thread = *operation_thread;
- else
- error = operation_thread.takeError();
-}
-
-void *ProcessMonitor::AttachOpThread(void *arg) {
- AttachArgs *args = static_cast<AttachArgs *>(arg);
-
- Attach(args);
-
- ServeOperation(args);
- return NULL;
-}
-
-void ProcessMonitor::Attach(AttachArgs *args) {
- lldb::pid_t pid = args->m_pid;
-
- ProcessMonitor *monitor = args->m_monitor;
- ProcessFreeBSD &process = monitor->GetProcess();
-
- if (pid <= 1) {
- args->m_error.SetErrorToGenericError();
- args->m_error.SetErrorString("Attaching to process 1 is not allowed.");
- return;
- }
-
- // Attach to the requested process.
- if (PTRACE(PT_ATTACH, pid, NULL, 0) < 0) {
- args->m_error.SetErrorToErrno();
- return;
- }
-
- int status;
- if ((status = waitpid(pid, NULL, 0)) < 0) {
- args->m_error.SetErrorToErrno();
- return;
- }
-
- process.SendMessage(ProcessMessage::Attach(pid));
-}
-
-size_t
-ProcessMonitor::GetCurrentThreadIDs(std::vector<lldb::tid_t> &thread_ids) {
- lwpid_t *tids;
- int tdcnt;
-
- thread_ids.clear();
-
- tdcnt = PTRACE(PT_GETNUMLWPS, m_pid, NULL, 0);
- if (tdcnt <= 0)
- return 0;
- tids = (lwpid_t *)malloc(tdcnt * sizeof(*tids));
- if (tids == NULL)
- return 0;
- if (PTRACE(PT_GETLWPLIST, m_pid, (void *)tids, tdcnt) < 0) {
- free(tids);
- return 0;
- }
- thread_ids = std::vector<lldb::tid_t>(tids, tids + tdcnt);
- free(tids);
- return thread_ids.size();
-}
-
-bool ProcessMonitor::MonitorCallback(ProcessMonitor *monitor, lldb::pid_t pid,
- bool exited, int signal, int status) {
- ProcessMessage message;
- ProcessFreeBSD *process = monitor->m_process;
- assert(process);
- bool stop_monitoring;
- struct ptrace_lwpinfo plwp;
- int ptrace_err;
-
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
-
- if (exited) {
- LLDB_LOGF(log, "ProcessMonitor::%s() got exit signal, tid = %" PRIu64,
- __FUNCTION__, pid);
- message = ProcessMessage::Exit(pid, status);
- process->SendMessage(message);
- return pid == process->GetID();
- }
-
- if (!monitor->GetLwpInfo(pid, &plwp, ptrace_err))
- stop_monitoring = true; // pid is gone. Bail.
- else {
- switch (plwp.pl_siginfo.si_signo) {
- case SIGTRAP:
- message = MonitorSIGTRAP(monitor, &plwp.pl_siginfo, plwp.pl_lwpid);
- break;
-
- default:
- message = MonitorSignal(monitor, &plwp.pl_siginfo, plwp.pl_lwpid);
- break;
- }
-
- process->SendMessage(message);
- stop_monitoring = message.GetKind() == ProcessMessage::eExitMessage;
- }
-
- return stop_monitoring;
-}
-
-ProcessMessage ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor,
- const siginfo_t *info,
- lldb::tid_t tid) {
- ProcessMessage message;
-
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
-
- assert(monitor);
- assert(info && info->si_signo == SIGTRAP && "Unexpected child signal!");
-
- switch (info->si_code) {
- default:
- assert(false && "Unexpected SIGTRAP code!");
- break;
-
- case (SIGTRAP /* | (PTRACE_EVENT_EXIT << 8) */): {
- // The inferior process is about to exit. Maintain the process in a state
- // of "limbo" until we are explicitly commanded to detach, destroy, resume,
- // etc.
- unsigned long data = 0;
- if (!monitor->GetEventMessage(tid, &data))
- data = -1;
- LLDB_LOGF(log,
- "ProcessMonitor::%s() received exit? event, data = %lx, tid "
- "= %" PRIu64,
- __FUNCTION__, data, tid);
- message = ProcessMessage::Limbo(tid, (data >> 8));
- break;
- }
-
- case 0:
- case TRAP_TRACE:
-#ifdef TRAP_CAP
- // Map TRAP_CAP to a trace trap in the absense of a more specific handler.
- case TRAP_CAP:
-#endif
- LLDB_LOGF(log,
- "ProcessMonitor::%s() received trace event, tid = %" PRIu64
- " : si_code = %d",
- __FUNCTION__, tid, info->si_code);
- message = ProcessMessage::Trace(tid);
- break;
-
- case SI_KERNEL:
- case TRAP_BRKPT:
- if (monitor->m_process->IsSoftwareStepBreakpoint(tid)) {
- LLDB_LOGF(log,
- "ProcessMonitor::%s() received sw single step breakpoint "
- "event, tid = %" PRIu64,
- __FUNCTION__, tid);
- message = ProcessMessage::Trace(tid);
- } else {
- LLDB_LOGF(
- log, "ProcessMonitor::%s() received breakpoint event, tid = %" PRIu64,
- __FUNCTION__, tid);
- message = ProcessMessage::Break(tid);
- }
- break;
- }
-
- return message;
-}
-
-ProcessMessage ProcessMonitor::MonitorSignal(ProcessMonitor *monitor,
- const siginfo_t *info,
- lldb::tid_t tid) {
- ProcessMessage message;
- int signo = info->si_signo;
-
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
-
- // POSIX says that process behaviour is undefined after it ignores a SIGFPE,
- // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a kill(2)
- // or raise(3). Similarly for tgkill(2) on FreeBSD.
- //
- // IOW, user generated signals never generate what we consider to be a
- // "crash".
- //
- // Similarly, ACK signals generated by this monitor.
- if (info->si_code == SI_USER) {
- LLDB_LOGF(log,
- "ProcessMonitor::%s() received signal %s with code %s, pid = %d",
- __FUNCTION__,
- monitor->m_process->GetUnixSignals()->GetSignalAsCString(signo),
- "SI_USER", info->si_pid);
- if (info->si_pid == getpid())
- return ProcessMessage::SignalDelivered(tid, signo);
- else
- return ProcessMessage::Signal(tid, signo);
- }
-
- LLDB_LOGF(log, "ProcessMonitor::%s() received signal %s", __FUNCTION__,
- monitor->m_process->GetUnixSignals()->GetSignalAsCString(signo));
-
- switch (signo) {
- case SIGSEGV:
- case SIGILL:
- case SIGFPE:
- case SIGBUS:
- lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr);
- const auto reason = GetCrashReason(*info);
- if (reason != CrashReason::eInvalidCrashReason) {
- return ProcessMessage::Crash(tid, reason, signo, fault_addr);
- } // else; Use atleast si_signo info for other si_code
- }
-
- // Everything else is "normal" and does not require any special action on our
- // part.
- return ProcessMessage::Signal(tid, signo);
-}
-
-void ProcessMonitor::ServeOperation(OperationArgs *args) {
- ProcessMonitor *monitor = args->m_monitor;
-
- // We are finised with the arguments and are ready to go. Sync with the
- // parent thread and start serving operations on the inferior.
- sem_post(&args->m_semaphore);
-
- for (;;) {
- // wait for next pending operation
- sem_wait(&monitor->m_operation_pending);
-
- monitor->m_operation->Execute(monitor);
-
- // notify calling thread that operation is complete
- sem_post(&monitor->m_operation_done);
- }
-}
-
-void ProcessMonitor::DoOperation(Operation *op) {
- std::lock_guard<std::mutex> guard(m_operation_mutex);
-
- m_operation = op;
-
- // notify operation thread that an operation is ready to be processed
- sem_post(&m_operation_pending);
-
- // wait for operation to complete
- sem_wait(&m_operation_done);
-}
-
-size_t ProcessMonitor::ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
- Status &error) {
- size_t result;
- ReadOperation op(vm_addr, buf, size, error, result);
- DoOperation(&op);
- return result;
-}
-
-size_t ProcessMonitor::WriteMemory(lldb::addr_t vm_addr, const void *buf,
- size_t size, lldb_private::Status &error) {
- size_t result;
- WriteOperation op(vm_addr, buf, size, error, result);
- DoOperation(&op);
- return result;
-}
-
-bool ProcessMonitor::ReadRegisterValue(lldb::tid_t tid, unsigned offset,
- const char *reg_name, unsigned size,
- RegisterValue &value) {
- bool result;
- ReadRegOperation op(tid, offset, size, value, result);
- DoOperation(&op);
- return result;
-}
-
-bool ProcessMonitor::WriteRegisterValue(lldb::tid_t tid, unsigned offset,
- const char *reg_name,
- const RegisterValue &value) {
- bool result;
- WriteRegOperation op(tid, offset, value, result);
- DoOperation(&op);
- return result;
-}
-
-bool ProcessMonitor::ReadDebugRegisterValue(
- lldb::tid_t tid, unsigned offset, const char *reg_name, unsigned size,
- lldb_private::RegisterValue &value) {
- bool result;
- ReadDebugRegOperation op(tid, offset, size, value, result);
- DoOperation(&op);
- return result;
-}
-
-bool ProcessMonitor::WriteDebugRegisterValue(
- lldb::tid_t tid, unsigned offset, const char *reg_name,
- const lldb_private::RegisterValue &value) {
- bool result;
- WriteDebugRegOperation op(tid, offset, value, result);
- DoOperation(&op);
- return result;
-}
-
-bool ProcessMonitor::ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size) {
- bool result;
- ReadGPROperation op(tid, buf, result);
- DoOperation(&op);
- return result;
-}
-
-bool ProcessMonitor::ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size) {
- bool result;
- ReadFPROperation op(tid, buf, result);
- DoOperation(&op);
- return result;
-}
-
-bool ProcessMonitor::ReadRegisterSet(lldb::tid_t tid, void *buf,
- size_t buf_size, unsigned int regset) {
- return false;
-}
-
-bool ProcessMonitor::WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size) {
- bool result;
- WriteGPROperation op(tid, buf, result);
- DoOperation(&op);
- return result;
-}
-
-bool ProcessMonitor::WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size) {
- bool result;
- WriteFPROperation op(tid, buf, result);
- DoOperation(&op);
- return result;
-}
-
-bool ProcessMonitor::WriteRegisterSet(lldb::tid_t tid, void *buf,
- size_t buf_size, unsigned int regset) {
- return false;
-}
-
-bool ProcessMonitor::ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value) {
- return false;
-}
-
-bool ProcessMonitor::Resume(lldb::tid_t unused, uint32_t signo) {
- bool result;
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
-
- if (log) {
- const char *signame =
- m_process->GetUnixSignals()->GetSignalAsCString(signo);
- if (signame == nullptr)
- signame = "<none>";
- LLDB_LOGF(log,
- "ProcessMonitor::%s() resuming pid %" PRIu64 " with signal %s",
- __FUNCTION__, GetPID(), signame);
- }
- ResumeOperation op(signo, result);
- DoOperation(&op);
- LLDB_LOGF(log, "ProcessMonitor::%s() resuming result = %s", __FUNCTION__,
- result ? "true" : "false");
- return result;
-}
-
-bool ProcessMonitor::SingleStep(lldb::tid_t unused, uint32_t signo) {
- bool result;
- SingleStepOperation op(signo, result);
- DoOperation(&op);
- return result;
-}
-
-bool ProcessMonitor::Kill() {
- bool result;
- KillOperation op(result);
- DoOperation(&op);
- return result;
-}
-
-bool ProcessMonitor::GetLwpInfo(lldb::tid_t tid, void *lwpinfo,
- int &ptrace_err) {
- bool result;
- LwpInfoOperation op(tid, lwpinfo, result, ptrace_err);
- DoOperation(&op);
- return result;
-}
-
-bool ProcessMonitor::ThreadSuspend(lldb::tid_t tid, bool suspend) {
- bool result;
- ThreadSuspendOperation op(tid, suspend, result);
- DoOperation(&op);
- return result;
-}
-
-bool ProcessMonitor::GetEventMessage(lldb::tid_t tid, unsigned long *message) {
- bool result;
- EventMessageOperation op(tid, message, result);
- DoOperation(&op);
- return result;
-}
-
-lldb_private::Status ProcessMonitor::Detach(lldb::tid_t tid) {
- lldb_private::Status error;
- if (tid != LLDB_INVALID_THREAD_ID) {
- DetachOperation op(error);
- DoOperation(&op);
- }
- return error;
-}
-
-bool ProcessMonitor::DupDescriptor(const FileSpec &file_spec, int fd,
- int flags) {
- int target_fd = llvm::sys::RetryAfterSignal(-1, open,
- file_spec.GetCString(), flags, 0666);
-
- if (target_fd == -1)
- return false;
-
- if (dup2(target_fd, fd) == -1)
- return false;
-
- return (close(target_fd) == -1) ? false : true;
-}
-
-void ProcessMonitor::StopMonitoringChildProcess() {
- if (m_monitor_thread && m_monitor_thread->IsJoinable()) {
- m_monitor_thread->Cancel();
- m_monitor_thread->Join(nullptr);
- m_monitor_thread->Reset();
- }
-}
-
-void ProcessMonitor::StopMonitor() {
- StopMonitoringChildProcess();
- StopOpThread();
- sem_destroy(&m_operation_pending);
- sem_destroy(&m_operation_done);
- if (m_terminal_fd >= 0) {
- close(m_terminal_fd);
- m_terminal_fd = -1;
- }
-}
-
-// FIXME: On Linux, when a new thread is created, we receive to notifications,
-// (1) a SIGTRAP|PTRACE_EVENT_CLONE from the main process thread with the child
-// thread id as additional information, and (2) a SIGSTOP|SI_USER from the new
-// child thread indicating that it has is stopped because we attached. We have
-// no guarantee of the order in which these arrive, but we need both before we
-// are ready to proceed. We currently keep a list of threads which have sent
-// the initial SIGSTOP|SI_USER event. Then when we receive the
-// SIGTRAP|PTRACE_EVENT_CLONE notification, if the initial stop has not
-// occurred we call ProcessMonitor::WaitForInitialTIDStop() to wait for it.
-//
-// Right now, the above logic is in ProcessPOSIX, so we need a definition of
-// this function in the FreeBSD ProcessMonitor implementation even if it isn't
-// logically needed.
-//
-// We really should figure out what actually happens on FreeBSD and move the
-// Linux-specific logic out of ProcessPOSIX as needed.
-
-bool ProcessMonitor::WaitForInitialTIDStop(lldb::tid_t tid) { return true; }
-
-void ProcessMonitor::StopOpThread() {
- if (m_operation_thread && m_operation_thread->IsJoinable()) {
- m_operation_thread->Cancel();
- m_operation_thread->Join(nullptr);
- m_operation_thread->Reset();
- }
-}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h
deleted file mode 100644
index c5edfc0..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.h
+++ /dev/null
@@ -1,279 +0,0 @@
-//===-- ProcessMonitor.h -------------------------------------- -*- 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_ProcessMonitor_H_
-#define liblldb_ProcessMonitor_H_
-
-#include <semaphore.h>
-#include <signal.h>
-
-#include <mutex>
-
-#include "lldb/Host/HostThread.h"
-#include "lldb/Utility/FileSpec.h"
-#include "lldb/lldb-types.h"
-
-namespace lldb_private {
-class Status;
-class Module;
-class Scalar;
-} // End lldb_private namespace.
-
-class ProcessFreeBSD;
-class Operation;
-
-/// \class ProcessMonitor
-/// Manages communication with the inferior (debugee) process.
-///
-/// Upon construction, this class prepares and launches an inferior process
-/// for debugging.
-///
-/// Changes in the inferior process state are propagated to the associated
-/// ProcessFreeBSD instance by calling ProcessFreeBSD::SendMessage with the
-/// appropriate ProcessMessage events.
-///
-/// A purposely minimal set of operations are provided to interrogate and change
-/// the inferior process state.
-class ProcessMonitor {
-public:
- /// Launches an inferior process ready for debugging. Forms the
- /// implementation of Process::DoLaunch.
- ProcessMonitor(ProcessFreeBSD *process, lldb_private::Module *module,
- char const *argv[], lldb_private::Environment env,
- const lldb_private::FileSpec &stdin_file_spec,
- const lldb_private::FileSpec &stdout_file_spec,
- const lldb_private::FileSpec &stderr_file_spec,
- const lldb_private::FileSpec &working_dir,
- const lldb_private::ProcessLaunchInfo &launch_info,
- lldb_private::Status &error);
-
- ProcessMonitor(ProcessFreeBSD *process, lldb::pid_t pid,
- lldb_private::Status &error);
-
- ~ProcessMonitor();
-
- /// Provides the process number of debugee.
- lldb::pid_t GetPID() const { return m_pid; }
-
- /// Returns the process associated with this ProcessMonitor.
- ProcessFreeBSD &GetProcess() { return *m_process; }
-
- /// Returns a file descriptor to the controlling terminal of the inferior
- /// process.
- ///
- /// Reads from this file descriptor yield both the standard output and
- /// standard error of this debugee. Even if stderr and stdout were
- /// redirected on launch it may still happen that data is available on this
- /// descriptor (if the inferior process opens /dev/tty, for example). This
- /// descriptor is closed after a call to StopMonitor().
- ///
- /// If this monitor was attached to an existing process this method returns
- /// -1.
- int GetTerminalFD() const { return m_terminal_fd; }
-
- /// Reads \p size bytes from address @vm_adder in the inferior process
- /// address space.
- ///
- /// This method is provided to implement Process::DoReadMemory.
- size_t ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
- lldb_private::Status &error);
-
- /// Writes \p size bytes from address \p vm_adder in the inferior process
- /// address space.
- ///
- /// This method is provided to implement Process::DoWriteMemory.
- size_t WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
- lldb_private::Status &error);
-
- /// Reads the contents from the register identified by the given
- /// (architecture dependent) offset.
- ///
- /// This method is provided for use by RegisterContextFreeBSD derivatives.
- bool ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
- unsigned size, lldb_private::RegisterValue &value);
-
- /// Writes the given value to the register identified by the given
- /// (architecture dependent) offset.
- ///
- /// This method is provided for use by RegisterContextFreeBSD derivatives.
- bool WriteRegisterValue(lldb::tid_t tid, unsigned offset,
- const char *reg_name,
- const lldb_private::RegisterValue &value);
-
- /// Reads the contents from the debug register identified by the given
- /// (architecture dependent) offset.
- ///
- /// This method is provided for use by RegisterContextFreeBSD derivatives.
- bool ReadDebugRegisterValue(lldb::tid_t tid, unsigned offset,
- const char *reg_name, unsigned size,
- lldb_private::RegisterValue &value);
-
- /// Writes the given value to the debug register identified by the given
- /// (architecture dependent) offset.
- ///
- /// This method is provided for use by RegisterContextFreeBSD derivatives.
- bool WriteDebugRegisterValue(lldb::tid_t tid, unsigned offset,
- const char *reg_name,
- const lldb_private::RegisterValue &value);
- /// Reads all general purpose registers into the specified buffer.
- bool ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size);
-
- /// Reads all floating point registers into the specified buffer.
- bool ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size);
-
- /// Reads the specified register set into the specified buffer.
- ///
- /// This method is provided for use by RegisterContextFreeBSD derivatives.
- bool ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size,
- unsigned int regset);
-
- /// Writes all general purpose registers into the specified buffer.
- bool WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size);
-
- /// Writes all floating point registers into the specified buffer.
- bool WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size);
-
- /// Writes the specified register set into the specified buffer.
- ///
- /// This method is provided for use by RegisterContextFreeBSD derivatives.
- bool WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size,
- unsigned int regset);
-
- /// Reads the value of the thread-specific pointer for a given thread ID.
- bool ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value);
-
- /// Returns current thread IDs in process
- size_t GetCurrentThreadIDs(std::vector<lldb::tid_t> &thread_ids);
-
- /// Writes a ptrace_lwpinfo structure corresponding to the given thread ID
- /// to the memory region pointed to by \p lwpinfo.
- bool GetLwpInfo(lldb::tid_t tid, void *lwpinfo, int &error_no);
-
- /// Suspends or unsuspends a thread prior to process resume or step.
- bool ThreadSuspend(lldb::tid_t tid, bool suspend);
-
- /// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG)
- /// corresponding to the given thread IDto the memory pointed to by @p
- /// message.
- bool GetEventMessage(lldb::tid_t tid, unsigned long *message);
-
- /// Resumes the process. If \p signo is anything but
- /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the process.
- bool Resume(lldb::tid_t unused, uint32_t signo);
-
- /// Single steps the process. If \p signo is anything but
- /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the process.
- bool SingleStep(lldb::tid_t unused, uint32_t signo);
-
- /// Terminate the traced process.
- bool Kill();
-
- lldb_private::Status Detach(lldb::tid_t tid);
-
- void StopMonitor();
-
- // Waits for the initial stop message from a new thread.
- bool WaitForInitialTIDStop(lldb::tid_t tid);
-
-private:
- ProcessFreeBSD *m_process;
-
- llvm::Optional<lldb_private::HostThread> m_operation_thread;
- llvm::Optional<lldb_private::HostThread> m_monitor_thread;
- lldb::pid_t m_pid;
-
- int m_terminal_fd;
-
- // current operation which must be executed on the privileged thread
- Operation *m_operation;
- std::mutex m_operation_mutex;
-
- // semaphores notified when Operation is ready to be processed and when
- // the operation is complete.
- sem_t m_operation_pending;
- sem_t m_operation_done;
-
- struct OperationArgs {
- OperationArgs(ProcessMonitor *monitor);
-
- ~OperationArgs();
-
- ProcessMonitor *m_monitor; // The monitor performing the attach.
- sem_t m_semaphore; // Posted to once operation complete.
- lldb_private::Status m_error; // Set if process operation failed.
- };
-
- /// \class LauchArgs
- ///
- /// Simple structure to pass data to the thread responsible for launching a
- /// child process.
- struct LaunchArgs : OperationArgs {
- LaunchArgs(ProcessMonitor *monitor, lldb_private::Module *module,
- char const **argv, lldb_private::Environment env,
- const lldb_private::FileSpec &stdin_file_spec,
- const lldb_private::FileSpec &stdout_file_spec,
- const lldb_private::FileSpec &stderr_file_spec,
- const lldb_private::FileSpec &working_dir);
-
- ~LaunchArgs();
-
- lldb_private::Module *m_module; // The executable image to launch.
- char const **m_argv; // Process arguments.
- lldb_private::Environment m_env; // Process environment.
- const lldb_private::FileSpec m_stdin_file_spec; // Redirect stdin or empty.
- const lldb_private::FileSpec
- m_stdout_file_spec; // Redirect stdout or empty.
- const lldb_private::FileSpec
- m_stderr_file_spec; // Redirect stderr or empty.
- const lldb_private::FileSpec m_working_dir; // Working directory or empty.
- };
-
- void StartLaunchOpThread(LaunchArgs *args, lldb_private::Status &error);
-
- static void *LaunchOpThread(void *arg);
-
- static bool Launch(LaunchArgs *args);
-
- struct AttachArgs : OperationArgs {
- AttachArgs(ProcessMonitor *monitor, lldb::pid_t pid);
-
- ~AttachArgs();
-
- lldb::pid_t m_pid; // pid of the process to be attached.
- };
-
- void StartAttachOpThread(AttachArgs *args, lldb_private::Status &error);
-
- static void *AttachOpThread(void *args);
-
- static void Attach(AttachArgs *args);
-
- static void ServeOperation(OperationArgs *args);
-
- static bool DupDescriptor(const lldb_private::FileSpec &file_spec, int fd,
- int flags);
-
- static bool MonitorCallback(ProcessMonitor *monitor, lldb::pid_t pid,
- bool exited, int signal, int status);
-
- static ProcessMessage MonitorSIGTRAP(ProcessMonitor *monitor,
- const siginfo_t *info, lldb::pid_t pid);
-
- static ProcessMessage MonitorSignal(ProcessMonitor *monitor,
- const siginfo_t *info, lldb::pid_t pid);
-
- void DoOperation(Operation *op);
-
- /// Stops the child monitor thread.
- void StopMonitoringChildProcess();
-
- /// Stops the operation thread used to attach/launch a process.
- void StopOpThread();
-};
-
-#endif // #ifndef liblldb_ProcessMonitor_H_
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h
deleted file mode 100644
index cf52a06..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h
+++ /dev/null
@@ -1,63 +0,0 @@
-//===-- RegisterContextPOSIX.h --------------------------------*- 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_RegisterContextPOSIX_H_
-#define liblldb_RegisterContextPOSIX_H_
-
-#include "Plugins/Process/Utility/RegisterInfoInterface.h"
-#include "lldb/Target/RegisterContext.h"
-#include "lldb/Utility/ArchSpec.h"
-
-/// \class POSIXBreakpointProtocol
-///
-/// Extends RegisterClass with a few virtual operations useful on POSIX.
-class POSIXBreakpointProtocol {
-public:
- POSIXBreakpointProtocol() { m_watchpoints_initialized = false; }
- virtual ~POSIXBreakpointProtocol() {}
-
- /// Updates the register state of the associated thread after hitting a
- /// breakpoint (if that make sense for the architecture). Default
- /// implementation simply returns true for architectures which do not
- /// require any update.
- ///
- /// \return
- /// True if the operation succeeded and false otherwise.
- virtual bool UpdateAfterBreakpoint() = 0;
-
- /// Determines the index in lldb's register file given a kernel byte offset.
- virtual unsigned GetRegisterIndexFromOffset(unsigned offset) = 0;
-
- // Checks to see if a watchpoint specified by hw_index caused the inferior
- // to stop.
- virtual bool IsWatchpointHit(uint32_t hw_index) = 0;
-
- // Resets any watchpoints that have been hit.
- virtual bool ClearWatchpointHits() = 0;
-
- // Returns the watchpoint address associated with a watchpoint hardware
- // index.
- virtual lldb::addr_t GetWatchpointAddress(uint32_t hw_index) = 0;
-
- virtual bool IsWatchpointVacant(uint32_t hw_index) = 0;
-
- virtual bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size,
- bool read, bool write,
- uint32_t hw_index) = 0;
-
- // From lldb_private::RegisterContext
- virtual uint32_t NumSupportedHardwareWatchpoints() = 0;
-
- // Force m_watchpoints_initialized to TRUE
- void ForceWatchpointsInitialized() { m_watchpoints_initialized = true; }
-
-protected:
- bool m_watchpoints_initialized;
-};
-
-#endif // #ifndef liblldb_RegisterContextPOSIX_H_
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp
deleted file mode 100644
index afb92e8..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp
+++ /dev/null
@@ -1,260 +0,0 @@
-//===-- RegisterContextPOSIXProcessMonitor_arm.cpp ------------------------===//
-//
-// 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 "lldb/Target/Thread.h"
-#include "lldb/Utility/DataBufferHeap.h"
-#include "lldb/Utility/RegisterValue.h"
-
-#include "ProcessFreeBSD.h"
-#include "ProcessMonitor.h"
-#include "RegisterContextPOSIXProcessMonitor_arm.h"
-#include "Plugins/Process/Utility/RegisterContextPOSIX_arm.h"
-#include "Plugins/Process/Utility/lldb-arm-register-enums.h"
-
-using namespace lldb_private;
-using namespace lldb;
-
-#define REG_CONTEXT_SIZE (GetGPRSize())
-
-RegisterContextPOSIXProcessMonitor_arm::RegisterContextPOSIXProcessMonitor_arm(
- lldb_private::Thread &thread,
- std::unique_ptr<RegisterInfoPOSIX_arm> register_info)
- : RegisterContextPOSIX_arm(thread, std::move(register_info)) {}
-
-ProcessMonitor &RegisterContextPOSIXProcessMonitor_arm::GetMonitor() {
- ProcessSP base = CalculateProcess();
- ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(base.get());
- return process->GetMonitor();
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::ReadGPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadGPR(m_thread.GetID(), &m_gpr_arm, GetGPRSize());
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::ReadFPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadFPR(m_thread.GetID(), &m_fpr, sizeof(m_fpr));
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::WriteGPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteGPR(m_thread.GetID(), &m_gpr_arm, GetGPRSize());
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::WriteFPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteFPR(m_thread.GetID(), &m_fpr, sizeof(m_fpr));
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::ReadRegister(
- const unsigned reg, RegisterValue &value) {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg),
- GetRegisterName(reg), GetRegisterSize(reg),
- value);
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::WriteRegister(
- const unsigned reg, const RegisterValue &value) {
- unsigned reg_to_write = reg;
- RegisterValue value_to_write = value;
-
- // Check if this is a subregister of a full register.
- const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
- if (reg_info->invalidate_regs &&
- (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) {
- RegisterValue full_value;
- uint32_t full_reg = reg_info->invalidate_regs[0];
- const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
-
- // Read the full register.
- if (ReadRegister(full_reg_info, full_value)) {
- Status error;
- ByteOrder byte_order = GetByteOrder();
- uint8_t dst[RegisterValue::kMaxRegisterByteSize];
-
- // Get the bytes for the full register.
- const uint32_t dest_size = full_value.GetAsMemoryData(
- full_reg_info, dst, sizeof(dst), byte_order, error);
- if (error.Success() && dest_size) {
- uint8_t src[RegisterValue::kMaxRegisterByteSize];
-
- // Get the bytes for the source data.
- const uint32_t src_size = value.GetAsMemoryData(
- reg_info, src, sizeof(src), byte_order, error);
- if (error.Success() && src_size && (src_size < dest_size)) {
- // Copy the src bytes to the destination.
- memcpy(dst + (reg_info->byte_offset & 0x1), src, src_size);
- // Set this full register as the value to write.
- value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
- value_to_write.SetType(full_reg_info);
- reg_to_write = full_reg;
- }
- }
- }
- }
-
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteRegisterValue(
- m_thread.GetID(), GetRegisterOffset(reg_to_write),
- GetRegisterName(reg_to_write), value_to_write);
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::ReadRegister(
- const RegisterInfo *reg_info, RegisterValue &value) {
- if (!reg_info)
- return false;
-
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
-
- if (IsFPR(reg)) {
- if (!ReadFPR())
- return false;
- } else {
- return ReadRegister(reg, value);
- }
-
- // Get pointer to m_fpr variable and set the data from it.
- assert(reg_info->byte_offset < sizeof m_fpr);
- uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset;
- switch (reg_info->byte_size) {
- case 2:
- value.SetUInt16(*(uint16_t *)src);
- return true;
- case 4:
- value.SetUInt32(*(uint32_t *)src);
- return true;
- case 8:
- value.SetUInt64(*(uint64_t *)src);
- return true;
- default:
- assert(false && "Unhandled data size.");
- return false;
- }
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::WriteRegister(
- const RegisterInfo *reg_info, const RegisterValue &value) {
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
-
- if (IsGPR(reg)) {
- return WriteRegister(reg, value);
- } else if (IsFPR(reg)) {
- return WriteFPR();
- }
-
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::ReadAllRegisterValues(
- DataBufferSP &data_sp) {
- bool success = false;
- data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
- if (ReadGPR() && ReadFPR()) {
- uint8_t *dst = data_sp->GetBytes();
- success = dst != 0;
-
- if (success) {
- ::memcpy(dst, &m_gpr_arm, GetGPRSize());
- dst += GetGPRSize();
- ::memcpy(dst, &m_fpr, sizeof(m_fpr));
- }
- }
- return success;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::WriteAllRegisterValues(
- const DataBufferSP &data_sp) {
- bool success = false;
- if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
- uint8_t *src = data_sp->GetBytes();
- if (src) {
- ::memcpy(&m_gpr_arm, src, GetGPRSize());
-
- if (WriteGPR()) {
- src += GetGPRSize();
- ::memcpy(&m_fpr, src, sizeof(m_fpr));
-
- success = WriteFPR();
- }
- }
- }
- return success;
-}
-
-uint32_t RegisterContextPOSIXProcessMonitor_arm::SetHardwareWatchpoint(
- addr_t addr, size_t size, bool read, bool write) {
- const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
- uint32_t hw_index;
-
- for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) {
- if (IsWatchpointVacant(hw_index))
- return SetHardwareWatchpointWithIndex(addr, size, read, write, hw_index);
- }
-
- return LLDB_INVALID_INDEX32;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::ClearHardwareWatchpoint(
- uint32_t hw_index) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::HardwareSingleStep(bool enable) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::UpdateAfterBreakpoint() {
- lldb::addr_t pc;
-
- if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
- return false;
-
- return true;
-}
-
-unsigned RegisterContextPOSIXProcessMonitor_arm::GetRegisterIndexFromOffset(
- unsigned offset) {
- unsigned reg;
- for (reg = 0; reg < k_num_registers_arm; reg++) {
- if (GetRegisterInfo()[reg].byte_offset == offset)
- break;
- }
- assert(reg < k_num_registers_arm && "Invalid register offset.");
- return reg;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::IsWatchpointHit(
- uint32_t hw_index) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::ClearWatchpointHits() {
- return false;
-}
-
-addr_t RegisterContextPOSIXProcessMonitor_arm::GetWatchpointAddress(
- uint32_t hw_index) {
- return LLDB_INVALID_ADDRESS;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::IsWatchpointVacant(
- uint32_t hw_index) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm::SetHardwareWatchpointWithIndex(
- addr_t addr, size_t size, bool read, bool write, uint32_t hw_index) {
- return false;
-}
-
-uint32_t
-RegisterContextPOSIXProcessMonitor_arm::NumSupportedHardwareWatchpoints() {
- return 0;
-}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h
deleted file mode 100644
index bb45584..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h
+++ /dev/null
@@ -1,80 +0,0 @@
-//===-- RegisterContextPOSIXProcessMonitor_arm.h --------------*- 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_RegisterContextPOSIXProcessMonitor_arm_H_
-#define liblldb_RegisterContextPOSIXProcessMonitor_arm_H_
-
-#include "Plugins/Process/Utility/RegisterContextPOSIX_arm.h"
-#include "RegisterContextPOSIX.h"
-
-class RegisterContextPOSIXProcessMonitor_arm : public RegisterContextPOSIX_arm,
- public POSIXBreakpointProtocol {
-public:
- RegisterContextPOSIXProcessMonitor_arm(
- lldb_private::Thread &thread,
- std::unique_ptr<RegisterInfoPOSIX_arm> register_info);
-
-protected:
- bool ReadGPR() override;
-
- bool ReadFPR() override;
-
- bool WriteGPR() override;
-
- bool WriteFPR() override;
-
- // lldb_private::RegisterContext
- bool ReadRegister(const unsigned reg, lldb_private::RegisterValue &value);
-
- bool WriteRegister(const unsigned reg,
- const lldb_private::RegisterValue &value);
-
- bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
- lldb_private::RegisterValue &value) override;
-
- bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &value) override;
-
- bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
-
- bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
-
- uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read,
- bool write) override;
-
- bool ClearHardwareWatchpoint(uint32_t hw_index) override;
-
- bool HardwareSingleStep(bool enable) override;
-
- // POSIXBreakpointProtocol
- bool UpdateAfterBreakpoint() override;
-
- unsigned GetRegisterIndexFromOffset(unsigned offset) override;
-
- bool IsWatchpointHit(uint32_t hw_index) override;
-
- bool ClearWatchpointHits() override;
-
- lldb::addr_t GetWatchpointAddress(uint32_t hw_index) override;
-
- bool IsWatchpointVacant(uint32_t hw_index) override;
-
- bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read,
- bool write, uint32_t hw_index) override;
-
- uint32_t NumSupportedHardwareWatchpoints() override;
-
-private:
- RegisterInfoPOSIX_arm::GPR m_gpr_arm;
-
- RegisterInfoPOSIX_arm::FPU m_fpr;
-
- ProcessMonitor &GetMonitor();
-};
-
-#endif
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp
deleted file mode 100644
index 39ae0b9..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp
+++ /dev/null
@@ -1,267 +0,0 @@
-//===-- RegisterContextPOSIXProcessMonitor_arm64.cpp ----------------------===//
-//
-// 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 "lldb/Target/Thread.h"
-#include "lldb/Utility/DataBufferHeap.h"
-#include "lldb/Utility/RegisterValue.h"
-
-#include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h"
-#include "ProcessFreeBSD.h"
-#include "ProcessMonitor.h"
-#include "RegisterContextPOSIXProcessMonitor_arm64.h"
-
-#define REG_CONTEXT_SIZE (GetGPRSize())
-
-using namespace lldb;
-using namespace lldb_private;
-
-RegisterContextPOSIXProcessMonitor_arm64::
- RegisterContextPOSIXProcessMonitor_arm64(
- lldb_private::Thread &thread,
- std::unique_ptr<RegisterInfoPOSIX_arm64> register_info)
- : RegisterContextPOSIX_arm64(thread, std::move(register_info)) {
- ::memset(&m_gpr_arm64, 0, sizeof m_gpr_arm64);
- ::memset(&m_fpr, 0, sizeof m_fpr);
-}
-
-ProcessMonitor &RegisterContextPOSIXProcessMonitor_arm64::GetMonitor() {
- lldb::ProcessSP base = CalculateProcess();
- ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(base.get());
- return process->GetMonitor();
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::ReadGPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadGPR(m_thread.GetID(), &m_gpr_arm64, GetGPRSize());
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::ReadFPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadFPR(m_thread.GetID(), &m_fpr, sizeof m_fpr);
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::WriteGPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteGPR(m_thread.GetID(), &m_gpr_arm64, GetGPRSize());
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::WriteFPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteFPR(m_thread.GetID(), &m_fpr, sizeof m_fpr);
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::ReadRegister(
- const unsigned reg, lldb_private::RegisterValue &value) {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg),
- GetRegisterName(reg), GetRegisterSize(reg),
- value);
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::WriteRegister(
- const unsigned reg, const lldb_private::RegisterValue &value) {
- unsigned reg_to_write = reg;
- lldb_private::RegisterValue value_to_write = value;
-
- // Check if this is a subregister of a full register.
- const lldb_private::RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
- if (reg_info->invalidate_regs &&
- (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) {
- lldb_private::RegisterValue full_value;
- uint32_t full_reg = reg_info->invalidate_regs[0];
- const lldb_private::RegisterInfo *full_reg_info =
- GetRegisterInfoAtIndex(full_reg);
-
- // Read the full register.
- if (ReadRegister(full_reg_info, full_value)) {
- lldb_private::Status error;
- lldb::ByteOrder byte_order = GetByteOrder();
- uint8_t dst[lldb_private::RegisterValue::kMaxRegisterByteSize];
-
- // Get the bytes for the full register.
- const uint32_t dest_size = full_value.GetAsMemoryData(
- full_reg_info, dst, sizeof(dst), byte_order, error);
- if (error.Success() && dest_size) {
- uint8_t src[lldb_private::RegisterValue::kMaxRegisterByteSize];
-
- // Get the bytes for the source data.
- const uint32_t src_size = value.GetAsMemoryData(
- reg_info, src, sizeof(src), byte_order, error);
- if (error.Success() && src_size && (src_size < dest_size)) {
- // Copy the src bytes to the destination.
- ::memcpy(dst + (reg_info->byte_offset & 0x1), src, src_size);
- // Set this full register as the value to write.
- value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
- value_to_write.SetType(full_reg_info);
- reg_to_write = full_reg;
- }
- }
- }
- }
-
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteRegisterValue(
- m_thread.GetID(), GetRegisterOffset(reg_to_write),
- GetRegisterName(reg_to_write), value_to_write);
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::ReadRegister(
- const lldb_private::RegisterInfo *reg_info,
- lldb_private::RegisterValue &value) {
- if (!reg_info)
- return false;
-
- const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
-
- if (IsFPR(reg)) {
- if (!ReadFPR())
- return false;
- } else {
- uint32_t full_reg = reg;
- bool is_subreg = reg_info->invalidate_regs &&
- (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
-
- if (is_subreg) {
- // Read the full aligned 64-bit register.
- full_reg = reg_info->invalidate_regs[0];
- }
- return ReadRegister(full_reg, value);
- }
-
- // Get pointer to m_fpr variable and set the data from it.
- assert(reg_info->byte_offset < sizeof m_fpr);
- uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset;
- switch (reg_info->byte_size) {
- case 2:
- value.SetUInt16(*(uint16_t *)src);
- return true;
- case 4:
- value.SetUInt32(*(uint32_t *)src);
- return true;
- case 8:
- value.SetUInt64(*(uint64_t *)src);
- return true;
- default:
- assert(false && "Unhandled data size.");
- return false;
- }
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::WriteRegister(
- const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &value) {
- const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
-
- if (IsGPR(reg))
- return WriteRegister(reg, value);
-
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::ReadAllRegisterValues(
- lldb::DataBufferSP &data_sp) {
- bool success = false;
- data_sp.reset(new lldb_private::DataBufferHeap(REG_CONTEXT_SIZE, 0));
- if (ReadGPR() && ReadFPR()) {
- uint8_t *dst = data_sp->GetBytes();
- success = dst != 0;
-
- if (success) {
- ::memcpy(dst, &m_gpr_arm64, GetGPRSize());
- dst += GetGPRSize();
- ::memcpy(dst, &m_fpr, sizeof m_fpr);
- }
- }
- return success;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::WriteAllRegisterValues(
- const lldb::DataBufferSP &data_sp) {
- bool success = false;
- if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
- uint8_t *src = data_sp->GetBytes();
- if (src) {
- ::memcpy(&m_gpr_arm64, src, GetGPRSize());
- if (WriteGPR()) {
- src += GetGPRSize();
- ::memcpy(&m_fpr, src, sizeof m_fpr);
- success = WriteFPR();
- }
- }
- }
- return success;
-}
-
-uint32_t RegisterContextPOSIXProcessMonitor_arm64::SetHardwareWatchpoint(
- lldb::addr_t addr, size_t size, bool read, bool write) {
- const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
- uint32_t hw_index;
-
- for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) {
- if (IsWatchpointVacant(hw_index))
- return SetHardwareWatchpointWithIndex(addr, size, read, write, hw_index);
- }
-
- return LLDB_INVALID_INDEX32;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::ClearHardwareWatchpoint(
- uint32_t hw_index) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::HardwareSingleStep(bool enable) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::UpdateAfterBreakpoint() {
- if (GetPC() == LLDB_INVALID_ADDRESS)
- return false;
-
- return true;
-}
-
-unsigned RegisterContextPOSIXProcessMonitor_arm64::GetRegisterIndexFromOffset(
- unsigned offset) {
- unsigned reg;
- for (reg = 0; reg < GetRegisterCount(); reg++) {
- if (GetRegisterInfo()[reg].byte_offset == offset)
- break;
- }
- assert(reg < GetRegisterCount() && "Invalid register offset.");
- return reg;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::IsWatchpointHit(
- uint32_t hw_index) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::ClearWatchpointHits() {
- return false;
-}
-
-lldb::addr_t RegisterContextPOSIXProcessMonitor_arm64::GetWatchpointAddress(
- uint32_t hw_index) {
- return LLDB_INVALID_ADDRESS;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::IsWatchpointVacant(
- uint32_t hw_index) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_arm64::SetHardwareWatchpointWithIndex(
- lldb::addr_t addr, size_t size, bool read, bool write, uint32_t hw_index) {
- return false;
-}
-
-uint32_t
-RegisterContextPOSIXProcessMonitor_arm64::NumSupportedHardwareWatchpoints() {
- return 0;
-}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h
deleted file mode 100644
index dcae1d4..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h
+++ /dev/null
@@ -1,82 +0,0 @@
-//===-- RegisterContextPOSIXProcessMonitor_arm64.h --------------*- 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_RegisterContextPOSIXProcessMonitor_arm64_H_
-#define liblldb_RegisterContextPOSIXProcessMonitor_arm64_H_
-
-#include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h"
-#include "RegisterContextPOSIX.h"
-
-class RegisterContextPOSIXProcessMonitor_arm64
- : public RegisterContextPOSIX_arm64,
- public POSIXBreakpointProtocol {
-public:
- RegisterContextPOSIXProcessMonitor_arm64(
- lldb_private::Thread &thread,
- std::unique_ptr<RegisterInfoPOSIX_arm64> register_info);
-
-protected:
- bool ReadGPR() override;
-
- bool ReadFPR() override;
-
- bool WriteGPR() override;
-
- bool WriteFPR() override;
-
- // lldb_private::RegisterContext
- bool ReadRegister(const unsigned reg, lldb_private::RegisterValue &value);
-
- bool WriteRegister(const unsigned reg,
- const lldb_private::RegisterValue &value);
-
- bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
- lldb_private::RegisterValue &value) override;
-
- bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &value) override;
-
- bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
-
- bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
-
- uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read,
- bool write) override;
-
- bool ClearHardwareWatchpoint(uint32_t hw_index) override;
-
- bool HardwareSingleStep(bool enable) override;
-
- // POSIXBreakpointProtocol
- bool UpdateAfterBreakpoint() override;
-
- unsigned GetRegisterIndexFromOffset(unsigned offset) override;
-
- bool IsWatchpointHit(uint32_t hw_index) override;
-
- bool ClearWatchpointHits() override;
-
- lldb::addr_t GetWatchpointAddress(uint32_t hw_index) override;
-
- bool IsWatchpointVacant(uint32_t hw_index) override;
-
- bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read,
- bool write, uint32_t hw_index) override;
-
- uint32_t NumSupportedHardwareWatchpoints() override;
-
-private:
- RegisterInfoPOSIX_arm64::GPR m_gpr_arm64; // 64-bit general purpose registers.
-
- RegisterInfoPOSIX_arm64::FPU
- m_fpr; // floating-point registers including extended register sets.
-
- ProcessMonitor &GetMonitor();
-};
-
-#endif
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp
deleted file mode 100644
index 23c76f2..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp
+++ /dev/null
@@ -1,262 +0,0 @@
-//===-- RegisterContextPOSIXProcessMonitor_mips64.cpp ---------------------===//
-//
-// 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 "lldb/Target/Thread.h"
-#include "lldb/Utility/DataBufferHeap.h"
-#include "lldb/Utility/RegisterValue.h"
-
-#include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h"
-#include "ProcessFreeBSD.h"
-#include "ProcessMonitor.h"
-#include "RegisterContextPOSIXProcessMonitor_mips64.h"
-
-using namespace lldb_private;
-using namespace lldb;
-
-#define REG_CONTEXT_SIZE (GetGPRSize())
-
-RegisterContextPOSIXProcessMonitor_mips64::
- RegisterContextPOSIXProcessMonitor_mips64(
- Thread &thread, uint32_t concrete_frame_idx,
- lldb_private::RegisterInfoInterface *register_info)
- : RegisterContextPOSIX_mips64(thread, concrete_frame_idx, register_info) {}
-
-ProcessMonitor &RegisterContextPOSIXProcessMonitor_mips64::GetMonitor() {
- ProcessSP base = CalculateProcess();
- ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(base.get());
- return process->GetMonitor();
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::ReadGPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadGPR(m_thread.GetID(), &m_gpr_mips64, GetGPRSize());
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::ReadFPR() {
- // XXX not yet implemented
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::WriteGPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteGPR(m_thread.GetID(), &m_gpr_mips64, GetGPRSize());
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::WriteFPR() {
- // XXX not yet implemented
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::ReadRegister(
- const unsigned reg, RegisterValue &value) {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg),
- GetRegisterName(reg), GetRegisterSize(reg),
- value);
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::WriteRegister(
- const unsigned reg, const RegisterValue &value) {
- unsigned reg_to_write = reg;
- RegisterValue value_to_write = value;
-
- // Check if this is a subregister of a full register.
- const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
- if (reg_info->invalidate_regs &&
- (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) {
- RegisterValue full_value;
- uint32_t full_reg = reg_info->invalidate_regs[0];
- const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
-
- // Read the full register.
- if (ReadRegister(full_reg_info, full_value)) {
- Status error;
- ByteOrder byte_order = GetByteOrder();
- uint8_t dst[RegisterValue::kMaxRegisterByteSize];
-
- // Get the bytes for the full register.
- const uint32_t dest_size = full_value.GetAsMemoryData(
- full_reg_info, dst, sizeof(dst), byte_order, error);
- if (error.Success() && dest_size) {
- uint8_t src[RegisterValue::kMaxRegisterByteSize];
-
- // Get the bytes for the source data.
- const uint32_t src_size = value.GetAsMemoryData(
- reg_info, src, sizeof(src), byte_order, error);
- if (error.Success() && src_size && (src_size < dest_size)) {
- // Copy the src bytes to the destination.
- memcpy(dst + (reg_info->byte_offset & 0x1), src, src_size);
- // Set this full register as the value to write.
- value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
- value_to_write.SetType(full_reg_info);
- reg_to_write = full_reg;
- }
- }
- }
- }
-
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteRegisterValue(
- m_thread.GetID(), GetRegisterOffset(reg_to_write),
- GetRegisterName(reg_to_write), value_to_write);
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::ReadRegister(
- const RegisterInfo *reg_info, RegisterValue &value) {
- if (!reg_info)
- return false;
-
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
-
- if (IsFPR(reg)) {
- if (!ReadFPR())
- return false;
- } else {
- uint32_t full_reg = reg;
- bool is_subreg = reg_info->invalidate_regs &&
- (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
-
- if (is_subreg) {
- // Read the full aligned 64-bit register.
- full_reg = reg_info->invalidate_regs[0];
- }
-
- bool success = ReadRegister(full_reg, value);
-
- if (success) {
- // If our read was not aligned (for ah,bh,ch,dh), shift our returned
- // value one byte to the right.
- if (is_subreg && (reg_info->byte_offset & 0x1))
- value.SetUInt64(value.GetAsUInt64() >> 8);
-
- // If our return byte size was greater than the return value reg size,
- // then use the type specified by reg_info rather than the uint64_t
- // default
- if (value.GetByteSize() > reg_info->byte_size)
- value.SetType(reg_info);
- }
- return success;
- }
-
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::WriteRegister(
- const RegisterInfo *reg_info, const RegisterValue &value) {
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
-
- if (IsGPR(reg))
- return WriteRegister(reg, value);
-
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::ReadAllRegisterValues(
- DataBufferSP &data_sp) {
- bool success = false;
- data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
- if (ReadGPR() && ReadFPR()) {
- uint8_t *dst = data_sp->GetBytes();
- success = dst != 0;
-
- if (success) {
- ::memcpy(dst, &m_gpr_mips64, GetGPRSize());
- }
- }
- return success;
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::WriteAllRegisterValues(
- const DataBufferSP &data_sp) {
- bool success = false;
- if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
- uint8_t *src = data_sp->GetBytes();
- if (src) {
- ::memcpy(&m_gpr_mips64, src, GetGPRSize());
-
- if (WriteGPR()) {
- src += GetGPRSize();
- }
- }
- }
- return success;
-}
-
-uint32_t RegisterContextPOSIXProcessMonitor_mips64::SetHardwareWatchpoint(
- addr_t addr, size_t size, bool read, bool write) {
- const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
- uint32_t hw_index;
-
- for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) {
- if (IsWatchpointVacant(hw_index))
- return SetHardwareWatchpointWithIndex(addr, size, read, write, hw_index);
- }
-
- return LLDB_INVALID_INDEX32;
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::ClearHardwareWatchpoint(
- uint32_t hw_index) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::HardwareSingleStep(
- bool enable) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::UpdateAfterBreakpoint() {
- // PC points one byte past the int3 responsible for the breakpoint.
- lldb::addr_t pc;
-
- if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
- return false;
-
- SetPC(pc - 1);
- return true;
-}
-
-unsigned RegisterContextPOSIXProcessMonitor_mips64::GetRegisterIndexFromOffset(
- unsigned offset) {
- unsigned reg;
- for (reg = 0; reg < k_num_registers_mips64; reg++) {
- if (GetRegisterInfo()[reg].byte_offset == offset)
- break;
- }
- assert(reg < k_num_registers_mips64 && "Invalid register offset.");
- return reg;
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::IsWatchpointHit(
- uint32_t hw_index) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::ClearWatchpointHits() {
- return false;
-}
-
-addr_t RegisterContextPOSIXProcessMonitor_mips64::GetWatchpointAddress(
- uint32_t hw_index) {
- return LLDB_INVALID_ADDRESS;
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::IsWatchpointVacant(
- uint32_t hw_index) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_mips64::SetHardwareWatchpointWithIndex(
- addr_t addr, size_t size, bool read, bool write, uint32_t hw_index) {
- return false;
-}
-
-uint32_t
-RegisterContextPOSIXProcessMonitor_mips64::NumSupportedHardwareWatchpoints() {
- return 0;
-}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h
deleted file mode 100644
index be404cc..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h
+++ /dev/null
@@ -1,82 +0,0 @@
-//===-- RegisterContextPOSIXProcessMonitor_mips64.h -------------*- 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_RegisterContextPOSIXProcessMonitor_mips64_H_
-#define liblldb_RegisterContextPOSIXProcessMonitor_mips64_H_
-
-#include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h"
-#include "Plugins/Process/Utility/lldb-mips-freebsd-register-enums.h"
-#include "RegisterContextPOSIX.h"
-
-class ProcessMonitor;
-
-class RegisterContextPOSIXProcessMonitor_mips64
- : public RegisterContextPOSIX_mips64,
- public POSIXBreakpointProtocol {
-public:
- RegisterContextPOSIXProcessMonitor_mips64(
- lldb_private::Thread &thread, uint32_t concrete_frame_idx,
- lldb_private::RegisterInfoInterface *register_info);
-
-protected:
- bool ReadGPR() override;
-
- bool ReadFPR() override;
-
- bool WriteGPR() override;
-
- bool WriteFPR() override;
-
- // lldb_private::RegisterContext
- bool ReadRegister(const unsigned reg, lldb_private::RegisterValue &value);
-
- bool WriteRegister(const unsigned reg,
- const lldb_private::RegisterValue &value);
-
- bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
- lldb_private::RegisterValue &value) override;
-
- bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &value) override;
-
- bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
-
- bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
-
- uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read,
- bool write) override;
-
- bool ClearHardwareWatchpoint(uint32_t hw_index) override;
-
- bool HardwareSingleStep(bool enable) override;
-
- // POSIXBreakpointProtocol
- bool UpdateAfterBreakpoint() override;
-
- unsigned GetRegisterIndexFromOffset(unsigned offset) override;
-
- bool IsWatchpointHit(uint32_t hw_index) override;
-
- bool ClearWatchpointHits() override;
-
- lldb::addr_t GetWatchpointAddress(uint32_t hw_index) override;
-
- bool IsWatchpointVacant(uint32_t hw_index) override;
-
- bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read,
- bool write, uint32_t hw_index) override;
-
- uint32_t NumSupportedHardwareWatchpoints() override;
-
-private:
- uint64_t
- m_gpr_mips64[lldb_private::k_num_gpr_registers_mips64]; // general purpose registers.
- ProcessMonitor &GetMonitor();
-};
-
-#endif
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp
deleted file mode 100644
index f834277..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp
+++ /dev/null
@@ -1,274 +0,0 @@
-//===-- RegisterContextPOSIXProcessMonitor_powerpc.cpp --------------------===//
-//
-// 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 "lldb/Target/Thread.h"
-#include "lldb/Utility/DataBufferHeap.h"
-#include "lldb/Utility/RegisterValue.h"
-
-#include "ProcessFreeBSD.h"
-#include "ProcessMonitor.h"
-#include "RegisterContextPOSIXProcessMonitor_powerpc.h"
-#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"
-
-using namespace lldb_private;
-using namespace lldb;
-
-#define REG_CONTEXT_SIZE (GetGPRSize())
-
-RegisterContextPOSIXProcessMonitor_powerpc::
- RegisterContextPOSIXProcessMonitor_powerpc(
- Thread &thread, uint32_t concrete_frame_idx,
- lldb_private::RegisterInfoInterface *register_info)
- : RegisterContextPOSIX_powerpc(thread, concrete_frame_idx, register_info) {}
-
-ProcessMonitor &RegisterContextPOSIXProcessMonitor_powerpc::GetMonitor() {
- ProcessSP base = CalculateProcess();
- ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(base.get());
- return process->GetMonitor();
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::ReadGPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize());
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::ReadFPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadFPR(m_thread.GetID(), &m_fpr_powerpc,
- sizeof(m_fpr_powerpc));
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::ReadVMX() {
- // XXX: Need a way to read/write process VMX registers with ptrace.
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::WriteGPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize());
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::WriteFPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteFPR(m_thread.GetID(), &m_fpr_powerpc,
- sizeof(m_fpr_powerpc));
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::WriteVMX() {
- // XXX: Need a way to read/write process VMX registers with ptrace.
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::ReadRegister(
- const unsigned reg, RegisterValue &value) {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg),
- GetRegisterName(reg), GetRegisterSize(reg),
- value);
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::WriteRegister(
- const unsigned reg, const RegisterValue &value) {
- unsigned reg_to_write = reg;
- RegisterValue value_to_write = value;
-
- // Check if this is a subregister of a full register.
- const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
- if (reg_info->invalidate_regs &&
- (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) {
- RegisterValue full_value;
- uint32_t full_reg = reg_info->invalidate_regs[0];
- const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
-
- // Read the full register.
- if (ReadRegister(full_reg_info, full_value)) {
- Status error;
- ByteOrder byte_order = GetByteOrder();
- uint8_t dst[RegisterValue::kMaxRegisterByteSize];
-
- // Get the bytes for the full register.
- const uint32_t dest_size = full_value.GetAsMemoryData(
- full_reg_info, dst, sizeof(dst), byte_order, error);
- if (error.Success() && dest_size) {
- uint8_t src[RegisterValue::kMaxRegisterByteSize];
-
- // Get the bytes for the source data.
- const uint32_t src_size = value.GetAsMemoryData(
- reg_info, src, sizeof(src), byte_order, error);
- if (error.Success() && src_size && (src_size < dest_size)) {
- // Copy the src bytes to the destination.
- memcpy(dst + (reg_info->byte_offset & 0x1), src, src_size);
- // Set this full register as the value to write.
- value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
- value_to_write.SetType(full_reg_info);
- reg_to_write = full_reg;
- }
- }
- }
- }
-
- ProcessMonitor &monitor = GetMonitor();
- // Account for the fact that 32-bit targets on powerpc64 really use 64-bit
- // registers in ptrace, but expose here 32-bit registers with a higher
- // offset.
- uint64_t offset = GetRegisterOffset(reg_to_write);
- offset &= ~(sizeof(uintptr_t) - 1);
- return monitor.WriteRegisterValue(
- m_thread.GetID(), offset, GetRegisterName(reg_to_write), value_to_write);
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::ReadRegister(
- const RegisterInfo *reg_info, RegisterValue &value) {
- if (!reg_info)
- return false;
-
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
-
- if (IsFPR(reg)) {
- if (!ReadFPR())
- return false;
- uint8_t *src = (uint8_t *)&m_fpr_powerpc + reg_info->byte_offset;
- value.SetUInt64(*(uint64_t *)src);
- } else if (IsGPR(reg)) {
- bool success = ReadRegister(reg, value);
-
- if (success) {
- // If our return byte size was greater than the return value reg size,
- // then use the type specified by reg_info rather than the uint64_t
- // default
- if (value.GetByteSize() > reg_info->byte_size)
- value.SetType(reg_info);
- }
- return success;
- }
-
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::WriteRegister(
- const RegisterInfo *reg_info, const RegisterValue &value) {
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
-
- if (IsGPR(reg)) {
- return WriteRegister(reg, value);
- } else if (IsFPR(reg)) {
- assert(reg_info->byte_offset < sizeof(m_fpr_powerpc));
- uint8_t *dst = (uint8_t *)&m_fpr_powerpc + reg_info->byte_offset;
- *(uint64_t *)dst = value.GetAsUInt64();
- return WriteFPR();
- }
-
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::ReadAllRegisterValues(
- DataBufferSP &data_sp) {
- bool success = false;
- data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
- if (ReadGPR() && ReadFPR()) {
- uint8_t *dst = data_sp->GetBytes();
- success = dst != 0;
-
- if (success) {
- ::memcpy(dst, &m_gpr_powerpc, GetGPRSize());
- dst += GetGPRSize();
- }
- }
- return success;
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::WriteAllRegisterValues(
- const DataBufferSP &data_sp) {
- bool success = false;
- if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
- uint8_t *src = data_sp->GetBytes();
- if (src) {
- ::memcpy(&m_gpr_powerpc, src, GetGPRSize());
-
- if (WriteGPR()) {
- src += GetGPRSize();
- ::memcpy(&m_fpr_powerpc, src, sizeof(m_fpr_powerpc));
-
- success = WriteFPR();
- }
- }
- }
- return success;
-}
-
-uint32_t RegisterContextPOSIXProcessMonitor_powerpc::SetHardwareWatchpoint(
- addr_t addr, size_t size, bool read, bool write) {
- const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
- uint32_t hw_index;
-
- for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) {
- if (IsWatchpointVacant(hw_index))
- return SetHardwareWatchpointWithIndex(addr, size, read, write, hw_index);
- }
-
- return LLDB_INVALID_INDEX32;
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::ClearHardwareWatchpoint(
- uint32_t hw_index) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::HardwareSingleStep(
- bool enable) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::UpdateAfterBreakpoint() {
- lldb::addr_t pc;
-
- if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
- return false;
-
- return true;
-}
-
-unsigned RegisterContextPOSIXProcessMonitor_powerpc::GetRegisterIndexFromOffset(
- unsigned offset) {
- unsigned reg;
- for (reg = 0; reg < k_num_registers_powerpc; reg++) {
- if (GetRegisterInfo()[reg].byte_offset == offset)
- break;
- }
- assert(reg < k_num_registers_powerpc && "Invalid register offset.");
- return reg;
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::IsWatchpointHit(
- uint32_t hw_index) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::ClearWatchpointHits() {
- return false;
-}
-
-addr_t RegisterContextPOSIXProcessMonitor_powerpc::GetWatchpointAddress(
- uint32_t hw_index) {
- return LLDB_INVALID_ADDRESS;
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::IsWatchpointVacant(
- uint32_t hw_index) {
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_powerpc::SetHardwareWatchpointWithIndex(
- addr_t addr, size_t size, bool read, bool write, uint32_t hw_index) {
- return false;
-}
-
-uint32_t
-RegisterContextPOSIXProcessMonitor_powerpc::NumSupportedHardwareWatchpoints() {
- return 0;
-}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h
deleted file mode 100644
index 328db44..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h
+++ /dev/null
@@ -1,84 +0,0 @@
-//===-- RegisterContextPOSIXProcessMonitor_powerpc.h -------------*- 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_RegisterContextPOSIXProcessMonitor_powerpc_H_
-#define liblldb_RegisterContextPOSIXProcessMonitor_powerpc_H_
-
-#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"
-#include "RegisterContextPOSIX.h"
-
-class RegisterContextPOSIXProcessMonitor_powerpc
- : public RegisterContextPOSIX_powerpc,
- public POSIXBreakpointProtocol {
-public:
- RegisterContextPOSIXProcessMonitor_powerpc(
- lldb_private::Thread &thread, uint32_t concrete_frame_idx,
- lldb_private::RegisterInfoInterface *register_info);
-
-protected:
- bool IsVMX();
-
- bool ReadGPR() override;
-
- bool ReadFPR() override;
-
- bool ReadVMX() override;
-
- bool WriteGPR() override;
-
- bool WriteFPR() override;
-
- bool WriteVMX() override;
-
- // lldb_private::RegisterContext
- bool ReadRegister(const unsigned reg, lldb_private::RegisterValue &value);
-
- bool WriteRegister(const unsigned reg,
- const lldb_private::RegisterValue &value);
-
- bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
- lldb_private::RegisterValue &value) override;
-
- bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &value) override;
-
- bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
-
- bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
-
- uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read,
- bool write) override;
-
- bool ClearHardwareWatchpoint(uint32_t hw_index) override;
-
- bool HardwareSingleStep(bool enable) override;
-
- // POSIXBreakpointProtocol
- bool UpdateAfterBreakpoint() override;
-
- unsigned GetRegisterIndexFromOffset(unsigned offset) override;
-
- bool IsWatchpointHit(uint32_t hw_index) override;
-
- bool ClearWatchpointHits() override;
-
- lldb::addr_t GetWatchpointAddress(uint32_t hw_index) override;
-
- bool IsWatchpointVacant(uint32_t hw_index) override;
-
- bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read,
- bool write, uint32_t hw_index) override;
-
- uint32_t NumSupportedHardwareWatchpoints() override;
-
-private:
- ProcessMonitor &GetMonitor();
-};
-
-#endif
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp
deleted file mode 100644
index b1739e1..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp
+++ /dev/null
@@ -1,613 +0,0 @@
-//===-- RegisterContextPOSIXProcessMonitor_x86.cpp ------------------------===//
-//
-// 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 "lldb/Target/Thread.h"
-#include "lldb/Utility/DataBufferHeap.h"
-#include "lldb/Utility/RegisterValue.h"
-
-#include "Plugins/Process/FreeBSD/ProcessFreeBSD.h"
-#include "Plugins/Process/FreeBSD/ProcessMonitor.h"
-#include "RegisterContextPOSIXProcessMonitor_x86.h"
-
-using namespace lldb_private;
-using namespace lldb;
-
-// Support ptrace extensions even when compiled without required kernel support
-#ifndef NT_X86_XSTATE
-#define NT_X86_XSTATE 0x202
-#endif
-
-#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof(FPR))
-
-static uint32_t size_and_rw_bits(size_t size, bool read, bool write) {
- uint32_t rw;
-
- if (read)
- rw = 0x3; // READ or READ/WRITE
- else if (write)
- rw = 0x1; // WRITE
- else
- assert(0 && "read and write cannot both be false");
-
- switch (size) {
- case 1:
- return rw;
- case 2:
- return (0x1 << 2) | rw;
- case 4:
- return (0x3 << 2) | rw;
- case 8:
- return (0x2 << 2) | rw;
- default:
- assert(0 && "invalid size, must be one of 1, 2, 4, or 8");
- return 0; // Unreachable. Just to silence compiler.
- }
-}
-
-RegisterContextPOSIXProcessMonitor_x86_64::
- RegisterContextPOSIXProcessMonitor_x86_64(
- Thread &thread, uint32_t concrete_frame_idx,
- lldb_private::RegisterInfoInterface *register_info)
- : RegisterContextPOSIX_x86(thread, concrete_frame_idx, register_info) {
- // Store byte offset of fctrl (i.e. first register of FPR) wrt 'UserArea'
- const RegisterInfo *reg_info_fctrl = GetRegisterInfoByName("fctrl");
- m_fctrl_offset_in_userarea = reg_info_fctrl->byte_offset;
-
- m_iovec.iov_base = &m_fpr.xsave;
- m_iovec.iov_len = sizeof(m_fpr.xsave);
-}
-
-ProcessMonitor &RegisterContextPOSIXProcessMonitor_x86_64::GetMonitor() {
- ProcessSP base = CalculateProcess();
- ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(base.get());
- return process->GetMonitor();
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::ReadGPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.ReadGPR(m_thread.GetID(), &m_gpr_x86_64, GetGPRSize());
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::ReadFPR() {
- ProcessMonitor &monitor = GetMonitor();
- if (GetFPRType() == eFXSAVE)
- return monitor.ReadFPR(m_thread.GetID(), &m_fpr.fxsave,
- sizeof(m_fpr.fxsave));
-
- if (GetFPRType() == eXSAVE)
- return monitor.ReadRegisterSet(m_thread.GetID(), &m_iovec,
- sizeof(m_fpr.xsave), NT_X86_XSTATE);
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::WriteGPR() {
- ProcessMonitor &monitor = GetMonitor();
- return monitor.WriteGPR(m_thread.GetID(), &m_gpr_x86_64, GetGPRSize());
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::WriteFPR() {
- ProcessMonitor &monitor = GetMonitor();
- if (GetFPRType() == eFXSAVE)
- return monitor.WriteFPR(m_thread.GetID(), &m_fpr.fxsave,
- sizeof(m_fpr.fxsave));
-
- if (GetFPRType() == eXSAVE)
- return monitor.WriteRegisterSet(m_thread.GetID(), &m_iovec,
- sizeof(m_fpr.xsave), NT_X86_XSTATE);
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister(
- const unsigned reg, RegisterValue &value) {
- ProcessMonitor &monitor = GetMonitor();
-
-#if defined(__FreeBSD__)
- if (reg >= m_reg_info.first_dr)
- return monitor.ReadDebugRegisterValue(
- m_thread.GetID(), GetRegisterOffset(reg), GetRegisterName(reg),
- GetRegisterSize(reg), value);
-#endif
- return monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg),
- GetRegisterName(reg), GetRegisterSize(reg),
- value);
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::WriteRegister(
- const unsigned reg, const RegisterValue &value) {
- unsigned reg_to_write = reg;
- RegisterValue value_to_write = value;
-
- // Check if this is a subregister of a full register.
- const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
- if (reg_info->invalidate_regs &&
- (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) {
- RegisterValue full_value;
- uint32_t full_reg = reg_info->invalidate_regs[0];
- const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
-
- // Read the full register.
- if (ReadRegister(full_reg_info, full_value)) {
- Status error;
- ByteOrder byte_order = GetByteOrder();
- uint8_t dst[RegisterValue::kMaxRegisterByteSize];
-
- // Get the bytes for the full register.
- const uint32_t dest_size = full_value.GetAsMemoryData(
- full_reg_info, dst, sizeof(dst), byte_order, error);
- if (error.Success() && dest_size) {
- uint8_t src[RegisterValue::kMaxRegisterByteSize];
-
- // Get the bytes for the source data.
- const uint32_t src_size = value.GetAsMemoryData(
- reg_info, src, sizeof(src), byte_order, error);
- if (error.Success() && src_size && (src_size < dest_size)) {
- // Copy the src bytes to the destination.
- memcpy(dst + (reg_info->byte_offset & 0x1), src, src_size);
- // Set this full register as the value to write.
- value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
- value_to_write.SetType(full_reg_info);
- reg_to_write = full_reg;
- }
- }
- }
- }
-
- ProcessMonitor &monitor = GetMonitor();
-#if defined(__FreeBSD__)
- if (reg >= m_reg_info.first_dr)
- return monitor.WriteDebugRegisterValue(
- m_thread.GetID(), GetRegisterOffset(reg_to_write),
- GetRegisterName(reg_to_write), value_to_write);
-#endif
- return monitor.WriteRegisterValue(
- m_thread.GetID(), GetRegisterOffset(reg_to_write),
- GetRegisterName(reg_to_write), value_to_write);
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister(
- const RegisterInfo *reg_info, RegisterValue &value) {
- if (!reg_info)
- return false;
-
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
-
- if (IsFPR(reg, GetFPRType())) {
- if (!ReadFPR())
- return false;
- } else {
- uint32_t full_reg = reg;
- bool is_subreg = reg_info->invalidate_regs &&
- (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
-
- if (is_subreg) {
- // Read the full aligned 64-bit register.
- full_reg = reg_info->invalidate_regs[0];
- }
-
- bool success = ReadRegister(full_reg, value);
-
- if (success) {
- // If our read was not aligned (for ah,bh,ch,dh), shift our returned
- // value one byte to the right.
- if (is_subreg && (reg_info->byte_offset & 0x1))
- value.SetUInt64(value.GetAsUInt64() >> 8);
-
- // If our return byte size was greater than the return value reg size,
- // then use the type specified by reg_info rather than the uint64_t
- // default
- if (value.GetByteSize() > reg_info->byte_size)
- value.SetType(reg_info);
- }
- return success;
- }
-
- if (reg_info->encoding == eEncodingVector) {
- ByteOrder byte_order = GetByteOrder();
-
- if (byte_order != ByteOrder::eByteOrderInvalid) {
- if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st)
- value.SetBytes(m_fpr.fxsave.stmm[reg - m_reg_info.first_st].bytes,
- reg_info->byte_size, byte_order);
- if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm)
- value.SetBytes(m_fpr.fxsave.stmm[reg - m_reg_info.first_mm].bytes,
- reg_info->byte_size, byte_order);
- if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm)
- value.SetBytes(m_fpr.fxsave.xmm[reg - m_reg_info.first_xmm].bytes,
- reg_info->byte_size, byte_order);
- if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) {
- // Concatenate ymm using the register halves in xmm.bytes and
- // ymmh.bytes
- if (GetFPRType() == eXSAVE && CopyXSTATEtoYMM(reg, byte_order))
- value.SetBytes(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes,
- reg_info->byte_size, byte_order);
- else
- return false;
- }
- return value.GetType() == RegisterValue::eTypeBytes;
- }
- return false;
- }
-
- // Get pointer to m_fpr.fxsave variable and set the data from it. Byte
- // offsets of all registers are calculated wrt 'UserArea' structure. However,
- // ReadFPR() reads fpu registers {using ptrace(PT_GETFPREGS,..)} and stores
- // them in 'm_fpr' (of type FPR structure). To extract values of fpu
- // registers, m_fpr should be read at byte offsets calculated wrt to FPR
- // structure.
-
- // Since, FPR structure is also one of the member of UserArea structure.
- // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) -
- // byte_offset(fctrl wrt UserArea)
- assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(m_fpr));
- uint8_t *src =
- (uint8_t *)&m_fpr + reg_info->byte_offset - m_fctrl_offset_in_userarea;
- switch (reg_info->byte_size) {
- case 1:
- value.SetUInt8(*(uint8_t *)src);
- return true;
- case 2:
- value.SetUInt16(*(uint16_t *)src);
- return true;
- case 4:
- value.SetUInt32(*(uint32_t *)src);
- return true;
- case 8:
- value.SetUInt64(*(uint64_t *)src);
- return true;
- default:
- assert(false && "Unhandled data size.");
- return false;
- }
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::WriteRegister(
- const RegisterInfo *reg_info, const RegisterValue &value) {
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
-
- if (IsGPR(reg))
- return WriteRegister(reg, value);
-
- if (IsFPR(reg, GetFPRType())) {
- if (reg_info->encoding == eEncodingVector) {
- if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st)
- ::memcpy(m_fpr.fxsave.stmm[reg - m_reg_info.first_st].bytes,
- value.GetBytes(), value.GetByteSize());
-
- if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm)
- ::memcpy(m_fpr.fxsave.stmm[reg - m_reg_info.first_mm].bytes,
- value.GetBytes(), value.GetByteSize());
-
- if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm)
- ::memcpy(m_fpr.fxsave.xmm[reg - m_reg_info.first_xmm].bytes,
- value.GetBytes(), value.GetByteSize());
-
- if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) {
- if (GetFPRType() != eXSAVE)
- return false; // the target processor does not support AVX
-
- // Store ymm register content, and split into the register halves in
- // xmm.bytes and ymmh.bytes
- ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes,
- value.GetBytes(), value.GetByteSize());
- if (false == CopyYMMtoXSTATE(reg, GetByteOrder()))
- return false;
- }
- } else {
- // Get pointer to m_fpr.fxsave variable and set the data to it. Byte
- // offsets of all registers are calculated wrt 'UserArea' structure.
- // However, WriteFPR() takes m_fpr (of type FPR structure) and writes
- // only fpu registers using ptrace(PT_SETFPREGS,..) API. Hence fpu
- // registers should be written in m_fpr at byte offsets calculated wrt
- // FPR structure.
-
- // Since, FPR structure is also one of the member of UserArea structure.
- // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) -
- // byte_offset(fctrl wrt UserArea)
- assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) <
- sizeof(m_fpr));
- uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset -
- m_fctrl_offset_in_userarea;
- switch (reg_info->byte_size) {
- case 1:
- *(uint8_t *)dst = value.GetAsUInt8();
- break;
- case 2:
- *(uint16_t *)dst = value.GetAsUInt16();
- break;
- case 4:
- *(uint32_t *)dst = value.GetAsUInt32();
- break;
- case 8:
- *(uint64_t *)dst = value.GetAsUInt64();
- break;
- default:
- assert(false && "Unhandled data size.");
- return false;
- }
- }
-
- if (WriteFPR()) {
- if (IsAVX(reg))
- return CopyYMMtoXSTATE(reg, GetByteOrder());
- return true;
- }
- }
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::ReadAllRegisterValues(
- DataBufferSP &data_sp) {
- bool success = false;
- data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
- if (ReadGPR() && ReadFPR()) {
- uint8_t *dst = data_sp->GetBytes();
- success = dst != 0;
-
- if (success) {
- ::memcpy(dst, &m_gpr_x86_64, GetGPRSize());
- dst += GetGPRSize();
- if (GetFPRType() == eFXSAVE)
- ::memcpy(dst, &m_fpr.fxsave, sizeof(m_fpr.fxsave));
- }
-
- if (GetFPRType() == eXSAVE) {
- ByteOrder byte_order = GetByteOrder();
-
- // Assemble the YMM register content from the register halves.
- for (uint32_t reg = m_reg_info.first_ymm;
- success && reg <= m_reg_info.last_ymm; ++reg)
- success = CopyXSTATEtoYMM(reg, byte_order);
-
- if (success) {
- // Copy the extended register state including the assembled ymm
- // registers.
- ::memcpy(dst, &m_fpr, sizeof(m_fpr));
- }
- }
- }
- return success;
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::WriteAllRegisterValues(
- const DataBufferSP &data_sp) {
- bool success = false;
- if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
- uint8_t *src = data_sp->GetBytes();
- if (src) {
- ::memcpy(&m_gpr_x86_64, src, GetGPRSize());
-
- if (WriteGPR()) {
- src += GetGPRSize();
- if (GetFPRType() == eFXSAVE)
- ::memcpy(&m_fpr.fxsave, src, sizeof(m_fpr.fxsave));
- if (GetFPRType() == eXSAVE)
- ::memcpy(&m_fpr.xsave, src, sizeof(m_fpr.xsave));
-
- success = WriteFPR();
- if (success) {
- if (GetFPRType() == eXSAVE) {
- ByteOrder byte_order = GetByteOrder();
-
- // Parse the YMM register content from the register halves.
- for (uint32_t reg = m_reg_info.first_ymm;
- success && reg <= m_reg_info.last_ymm; ++reg)
- success = CopyYMMtoXSTATE(reg, byte_order);
- }
- }
- }
- }
- }
- return success;
-}
-
-uint32_t RegisterContextPOSIXProcessMonitor_x86_64::SetHardwareWatchpoint(
- addr_t addr, size_t size, bool read, bool write) {
- const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
- uint32_t hw_index;
-
- for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) {
- if (IsWatchpointVacant(hw_index))
- return SetHardwareWatchpointWithIndex(addr, size, read, write, hw_index);
- }
-
- return LLDB_INVALID_INDEX32;
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::ClearHardwareWatchpoint(
- uint32_t hw_index) {
- if (hw_index < NumSupportedHardwareWatchpoints()) {
- RegisterValue current_dr7_bits;
-
- if (ReadRegister(m_reg_info.first_dr + 7, current_dr7_bits)) {
- uint64_t new_dr7_bits =
- current_dr7_bits.GetAsUInt64() & ~(3 << (2 * hw_index));
-
- if (WriteRegister(m_reg_info.first_dr + 7, RegisterValue(new_dr7_bits)))
- return true;
- }
- }
-
- return false;
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::HardwareSingleStep(
- bool enable) {
- enum { TRACE_BIT = 0x100 };
- uint64_t rflags;
-
- if ((rflags = ReadRegisterAsUnsigned(m_reg_info.gpr_flags, -1UL)) == -1UL)
- return false;
-
- if (enable) {
- if (rflags & TRACE_BIT)
- return true;
-
- rflags |= TRACE_BIT;
- } else {
- if (!(rflags & TRACE_BIT))
- return false;
-
- rflags &= ~TRACE_BIT;
- }
-
- return WriteRegisterFromUnsigned(m_reg_info.gpr_flags, rflags);
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::UpdateAfterBreakpoint() {
- // PC points one byte past the int3 responsible for the breakpoint.
- lldb::addr_t pc;
-
- if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
- return false;
-
- SetPC(pc - 1);
- return true;
-}
-
-unsigned RegisterContextPOSIXProcessMonitor_x86_64::GetRegisterIndexFromOffset(
- unsigned offset) {
- unsigned reg;
- for (reg = 0; reg < m_reg_info.num_registers; reg++) {
- if (GetRegisterInfo()[reg].byte_offset == offset)
- break;
- }
- assert(reg < m_reg_info.num_registers && "Invalid register offset.");
- return reg;
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::IsWatchpointHit(
- uint32_t hw_index) {
- bool is_hit = false;
-
- if (m_watchpoints_initialized == false) {
- // Reset the debug status and debug control registers
- RegisterValue zero_bits = RegisterValue(uint64_t(0));
- if (!WriteRegister(m_reg_info.first_dr + 6, zero_bits) ||
- !WriteRegister(m_reg_info.first_dr + 7, zero_bits))
- assert(false && "Could not initialize watchpoint registers");
- m_watchpoints_initialized = true;
- }
-
- if (hw_index < NumSupportedHardwareWatchpoints()) {
- RegisterValue value;
-
- if (ReadRegister(m_reg_info.first_dr + 6, value)) {
- uint64_t val = value.GetAsUInt64();
- is_hit = val & (1 << hw_index);
- }
- }
-
- return is_hit;
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::ClearWatchpointHits() {
- return WriteRegister(m_reg_info.first_dr + 6, RegisterValue((uint64_t)0));
-}
-
-addr_t RegisterContextPOSIXProcessMonitor_x86_64::GetWatchpointAddress(
- uint32_t hw_index) {
- addr_t wp_monitor_addr = LLDB_INVALID_ADDRESS;
-
- if (hw_index < NumSupportedHardwareWatchpoints()) {
- if (!IsWatchpointVacant(hw_index)) {
- RegisterValue value;
-
- if (ReadRegister(m_reg_info.first_dr + hw_index, value))
- wp_monitor_addr = value.GetAsUInt64();
- }
- }
-
- return wp_monitor_addr;
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::IsWatchpointVacant(
- uint32_t hw_index) {
- bool is_vacant = false;
- RegisterValue value;
-
- assert(hw_index < NumSupportedHardwareWatchpoints());
-
- if (m_watchpoints_initialized == false) {
- // Reset the debug status and debug control registers
- RegisterValue zero_bits = RegisterValue(uint64_t(0));
- if (!WriteRegister(m_reg_info.first_dr + 6, zero_bits) ||
- !WriteRegister(m_reg_info.first_dr + 7, zero_bits))
- assert(false && "Could not initialize watchpoint registers");
- m_watchpoints_initialized = true;
- }
-
- if (ReadRegister(m_reg_info.first_dr + 7, value)) {
- uint64_t val = value.GetAsUInt64();
- is_vacant = (val & (3 << 2 * hw_index)) == 0;
- }
-
- return is_vacant;
-}
-
-bool RegisterContextPOSIXProcessMonitor_x86_64::SetHardwareWatchpointWithIndex(
- addr_t addr, size_t size, bool read, bool write, uint32_t hw_index) {
- const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
-
- if (num_hw_watchpoints == 0 || hw_index >= num_hw_watchpoints)
- return false;
-
- if (!(size == 1 || size == 2 || size == 4 || size == 8))
- return false;
-
- if (read == false && write == false)
- return false;
-
- if (!IsWatchpointVacant(hw_index))
- return false;
-
- // Set both dr7 (debug control register) and dri (debug address register).
-
- // dr7{7-0} encodes the local/global enable bits:
- // global enable --. .-- local enable
- // | |
- // v v
- // dr0 -> bits{1-0}
- // dr1 -> bits{3-2}
- // dr2 -> bits{5-4}
- // dr3 -> bits{7-6}
- //
- // dr7{31-16} encodes the rw/len bits:
- // b_x+3, b_x+2, b_x+1, b_x
- // where bits{x+1, x} => rw
- // 0b00: execute, 0b01: write, 0b11: read-or-write,
- // 0b10: io read-or-write (unused)
- // and bits{x+3, x+2} => len
- // 0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte
- //
- // dr0 -> bits{19-16}
- // dr1 -> bits{23-20}
- // dr2 -> bits{27-24}
- // dr3 -> bits{31-28}
- if (hw_index < num_hw_watchpoints) {
- RegisterValue current_dr7_bits;
-
- if (ReadRegister(m_reg_info.first_dr + 7, current_dr7_bits)) {
- uint64_t new_dr7_bits =
- current_dr7_bits.GetAsUInt64() |
- (1 << (2 * hw_index) |
- size_and_rw_bits(size, read, write) << (16 + 4 * hw_index));
-
- if (WriteRegister(m_reg_info.first_dr + hw_index, RegisterValue(addr)) &&
- WriteRegister(m_reg_info.first_dr + 7, RegisterValue(new_dr7_bits)))
- return true;
- }
- }
-
- return false;
-}
-
-uint32_t
-RegisterContextPOSIXProcessMonitor_x86_64::NumSupportedHardwareWatchpoints() {
- // Available debug address registers: dr0, dr1, dr2, dr3
- return 4;
-}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h b/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h
deleted file mode 100644
index 1afb366..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h
+++ /dev/null
@@ -1,81 +0,0 @@
-//===-- RegisterContextPOSIXProcessMonitor_x86.h ----------------*- 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_RegisterContextPOSIXProcessMonitor_x86_H_
-#define liblldb_RegisterContextPOSIXProcessMonitor_x86_H_
-
-#include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h"
-#include "RegisterContextPOSIX.h"
-#include <sys/uio.h>
-
-class RegisterContextPOSIXProcessMonitor_x86_64
- : public RegisterContextPOSIX_x86,
- public POSIXBreakpointProtocol {
-public:
- RegisterContextPOSIXProcessMonitor_x86_64(
- lldb_private::Thread &thread, uint32_t concrete_frame_idx,
- lldb_private::RegisterInfoInterface *register_info);
-
-protected:
- bool ReadGPR() override;
-
- bool ReadFPR() override;
-
- bool WriteGPR() override;
-
- bool WriteFPR() override;
-
- // lldb_private::RegisterContext
- bool ReadRegister(const unsigned reg, lldb_private::RegisterValue &value);
-
- bool WriteRegister(const unsigned reg,
- const lldb_private::RegisterValue &value);
-
- bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
- lldb_private::RegisterValue &value) override;
-
- bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &value) override;
-
- bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
-
- bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
-
- uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read,
- bool write) override;
-
- bool ClearHardwareWatchpoint(uint32_t hw_index) override;
-
- bool HardwareSingleStep(bool enable) override;
-
- // POSIXBreakpointProtocol
- bool UpdateAfterBreakpoint() override;
-
- unsigned GetRegisterIndexFromOffset(unsigned offset) override;
-
- bool IsWatchpointHit(uint32_t hw_index) override;
-
- bool ClearWatchpointHits() override;
-
- lldb::addr_t GetWatchpointAddress(uint32_t hw_index) override;
-
- bool IsWatchpointVacant(uint32_t hw_index) override;
-
- bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read,
- bool write, uint32_t hw_index) override;
-
- uint32_t NumSupportedHardwareWatchpoints() override;
-
-private:
- ProcessMonitor &GetMonitor();
- uint32_t
- m_fctrl_offset_in_userarea; // Offset of 'fctrl' in 'UserArea' Structure
- struct iovec m_iovec;
-};
-
-#endif
diff --git a/src/llvm-project/lldb/source/Plugins/Process/FreeBSDRemote/CMakeLists.txt b/src/llvm-project/lldb/source/Plugins/Process/FreeBSDRemote/CMakeLists.txt
deleted file mode 100644
index 8c1cec5..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/FreeBSDRemote/CMakeLists.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-add_lldb_library(lldbPluginProcessFreeBSDRemote
- NativeProcessFreeBSD.cpp
- NativeRegisterContextFreeBSD.cpp
- NativeRegisterContextFreeBSD_x86_64.cpp
- NativeThreadFreeBSD.cpp
-
- LINK_LIBS
- lldbHost
- lldbSymbol
- lldbTarget
- lldbUtility
- lldbPluginProcessPOSIX
- lldbPluginProcessUtility
- LINK_COMPONENTS
- Support
- )
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Linux/CMakeLists.txt b/src/llvm-project/lldb/source/Plugins/Process/Linux/CMakeLists.txt
index dd2a889..c4edc57 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Linux/CMakeLists.txt
+++ b/src/llvm-project/lldb/source/Plugins/Process/Linux/CMakeLists.txt
@@ -1,14 +1,13 @@
add_lldb_library(lldbPluginProcessLinux
+ IntelPTManager.cpp
NativeProcessLinux.cpp
NativeRegisterContextLinux.cpp
NativeRegisterContextLinux_arm.cpp
NativeRegisterContextLinux_arm64.cpp
- NativeRegisterContextLinux_mips64.cpp
NativeRegisterContextLinux_ppc64le.cpp
NativeRegisterContextLinux_s390x.cpp
NativeRegisterContextLinux_x86_64.cpp
NativeThreadLinux.cpp
- ProcessorTrace.cpp
SingleStepCheck.cpp
LINK_LIBS
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Linux/IntelPTManager.cpp b/src/llvm-project/lldb/source/Plugins/Process/Linux/IntelPTManager.cpp
new file mode 100644
index 0000000..0bd4893
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Process/Linux/IntelPTManager.cpp
@@ -0,0 +1,685 @@
+//===-- IntelPTManager.cpp ------------------------------------------------===//
+//
+// 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 <algorithm>
+#include <fstream>
+#include <sstream>
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MathExtras.h"
+
+#include "IntelPTManager.h"
+#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
+#include "lldb/Host/linux/Support.h"
+#include "lldb/Utility/StreamString.h"
+
+#include <sys/ioctl.h>
+#include <sys/syscall.h>
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace process_linux;
+using namespace llvm;
+
+const char *kOSEventIntelPTTypeFile =
+ "/sys/bus/event_source/devices/intel_pt/type";
+
+const char *kPSBPeriodCapFile =
+ "/sys/bus/event_source/devices/intel_pt/caps/psb_cyc";
+
+const char *kPSBPeriodValidValuesFile =
+ "/sys/bus/event_source/devices/intel_pt/caps/psb_periods";
+
+const char *kTSCBitOffsetFile =
+ "/sys/bus/event_source/devices/intel_pt/format/tsc";
+
+const char *kPSBPeriodBitOffsetFile =
+ "/sys/bus/event_source/devices/intel_pt/format/psb_period";
+
+enum IntelPTConfigFileType {
+ Hex = 0,
+ // 0 or 1
+ ZeroOne,
+ Decimal,
+ // a bit index file always starts with the prefix config: following by an int,
+ // which represents the offset of the perf_event_attr.config value where to
+ // store a given configuration.
+ BitOffset
+};
+
+static Expected<uint32_t> ReadIntelPTConfigFile(const char *file,
+ IntelPTConfigFileType type) {
+ ErrorOr<std::unique_ptr<MemoryBuffer>> stream =
+ MemoryBuffer::getFileAsStream(file);
+
+ if (!stream)
+ return createStringError(inconvertibleErrorCode(),
+ "Can't open the file '%s'", file);
+
+ uint32_t value = 0;
+ StringRef text_buffer = stream.get()->getBuffer();
+
+ if (type == BitOffset) {
+ const char *prefix = "config:";
+ if (!text_buffer.startswith(prefix))
+ return createStringError(inconvertibleErrorCode(),
+ "The file '%s' contents doesn't start with '%s'",
+ file, prefix);
+ text_buffer = text_buffer.substr(strlen(prefix));
+ }
+
+ auto getRadix = [&]() {
+ switch (type) {
+ case Hex:
+ return 16;
+ case ZeroOne:
+ case Decimal:
+ case BitOffset:
+ return 10;
+ }
+ };
+
+ auto createError = [&](const char *expected_value_message) {
+ return createStringError(
+ inconvertibleErrorCode(),
+ "The file '%s' has an invalid value. It should be %s.", file,
+ expected_value_message);
+ };
+
+ if (text_buffer.trim().consumeInteger(getRadix(), value) ||
+ (type == ZeroOne && value != 0 && value != 1)) {
+ switch (type) {
+ case Hex:
+ return createError("an unsigned hexadecimal int");
+ case ZeroOne:
+ return createError("0 or 1");
+ case Decimal:
+ case BitOffset:
+ return createError("an unsigned decimal int");
+ }
+ }
+ return value;
+}
+/// Return the Linux perf event type for Intel PT.
+static Expected<uint32_t> GetOSEventType() {
+ return ReadIntelPTConfigFile(kOSEventIntelPTTypeFile,
+ IntelPTConfigFileType::Decimal);
+}
+
+static Error CheckPsbPeriod(size_t psb_period) {
+ Expected<uint32_t> cap =
+ ReadIntelPTConfigFile(kPSBPeriodCapFile, IntelPTConfigFileType::ZeroOne);
+ if (!cap)
+ return cap.takeError();
+ if (*cap == 0)
+ return createStringError(inconvertibleErrorCode(),
+ "psb_period is unsupported in the system.");
+
+ Expected<uint32_t> valid_values = ReadIntelPTConfigFile(
+ kPSBPeriodValidValuesFile, IntelPTConfigFileType::Hex);
+ if (!valid_values)
+ return valid_values.takeError();
+
+ if (valid_values.get() & (1 << psb_period))
+ return Error::success();
+
+ std::ostringstream error;
+ // 0 is always a valid value
+ error << "Invalid psb_period. Valid values are: 0";
+ uint32_t mask = valid_values.get();
+ while (mask) {
+ int index = __builtin_ctz(mask);
+ if (index > 0)
+ error << ", " << index;
+ // clear the lowest bit
+ mask &= mask - 1;
+ }
+ error << ".";
+ return createStringError(inconvertibleErrorCode(), error.str().c_str());
+}
+
+size_t IntelPTThreadTrace::GetTraceBufferSize() const {
+ return m_mmap_meta->aux_size;
+}
+
+static Expected<uint64_t>
+GeneratePerfEventConfigValue(bool enable_tsc, Optional<size_t> psb_period) {
+ uint64_t config = 0;
+ // tsc is always supported
+ if (enable_tsc) {
+ if (Expected<uint32_t> offset = ReadIntelPTConfigFile(
+ kTSCBitOffsetFile, IntelPTConfigFileType::BitOffset))
+ config |= 1 << *offset;
+ else
+ return offset.takeError();
+ }
+ if (psb_period) {
+ if (Error error = CheckPsbPeriod(*psb_period))
+ return std::move(error);
+
+ if (Expected<uint32_t> offset = ReadIntelPTConfigFile(
+ kPSBPeriodBitOffsetFile, IntelPTConfigFileType::BitOffset))
+ config |= *psb_period << *offset;
+ else
+ return offset.takeError();
+ }
+ return config;
+}
+
+Error IntelPTThreadTrace::StartTrace(lldb::pid_t pid, lldb::tid_t tid,
+ uint64_t buffer_size, bool enable_tsc,
+ Optional<size_t> psb_period) {
+#ifndef PERF_ATTR_SIZE_VER5
+ llvm_unreachable("Intel PT Linux perf event not supported");
+#else
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
+
+ m_tid = tid;
+ LLDB_LOG(log, "called thread id {0}", tid);
+ uint64_t page_size = getpagesize();
+
+ if (__builtin_popcount(buffer_size) != 1 || buffer_size < 4096) {
+ return createStringError(
+ inconvertibleErrorCode(),
+ "The trace buffer size must be a power of 2 greater than or equal to "
+ "4096 (2^12) bytes. It was %" PRIu64 ".",
+ buffer_size);
+ }
+ uint64_t numpages = static_cast<uint64_t>(
+ llvm::PowerOf2Floor((buffer_size + page_size - 1) / page_size));
+ numpages = std::max<uint64_t>(1, numpages);
+ buffer_size = page_size * numpages;
+
+ perf_event_attr attr;
+ memset(&attr, 0, sizeof(attr));
+ attr.size = sizeof(attr);
+ attr.exclude_kernel = 1;
+ attr.sample_type = PERF_SAMPLE_TIME;
+ attr.sample_id_all = 1;
+ attr.exclude_hv = 1;
+ attr.exclude_idle = 1;
+ attr.mmap = 1;
+
+ if (Expected<uint64_t> config_value =
+ GeneratePerfEventConfigValue(enable_tsc, psb_period)) {
+ attr.config = *config_value;
+ LLDB_LOG(log, "intel pt config {0}", attr.config);
+ } else {
+ return config_value.takeError();
+ }
+
+ if (Expected<uint32_t> intel_pt_type = GetOSEventType()) {
+ attr.type = *intel_pt_type;
+ LLDB_LOG(log, "intel pt type {0}", attr.type);
+ } else {
+ return intel_pt_type.takeError();
+ }
+
+ LLDB_LOG(log, "buffer size {0} ", buffer_size);
+
+ errno = 0;
+ auto fd =
+ syscall(SYS_perf_event_open, &attr, static_cast<::tid_t>(tid), -1, -1, 0);
+ if (fd == -1) {
+ LLDB_LOG(log, "syscall error {0}", errno);
+ return createStringError(inconvertibleErrorCode(),
+ "perf event syscall failed");
+ }
+
+ m_fd = std::unique_ptr<int, file_close>(new int(fd), file_close());
+
+ errno = 0;
+ auto base =
+ mmap(nullptr, (buffer_size + page_size), PROT_WRITE, MAP_SHARED, fd, 0);
+
+ if (base == MAP_FAILED) {
+ LLDB_LOG(log, "mmap base error {0}", errno);
+ return createStringError(inconvertibleErrorCode(),
+ "Meta buffer allocation failed");
+ }
+
+ m_mmap_meta = std::unique_ptr<perf_event_mmap_page, munmap_delete>(
+ reinterpret_cast<perf_event_mmap_page *>(base),
+ munmap_delete(buffer_size + page_size));
+
+ m_mmap_meta->aux_offset = m_mmap_meta->data_offset + m_mmap_meta->data_size;
+ m_mmap_meta->aux_size = buffer_size;
+
+ errno = 0;
+ auto mmap_aux = mmap(nullptr, buffer_size, PROT_READ, MAP_SHARED, fd,
+ static_cast<long int>(m_mmap_meta->aux_offset));
+
+ if (mmap_aux == MAP_FAILED) {
+ LLDB_LOG(log, "second mmap done {0}", errno);
+ return createStringError(inconvertibleErrorCode(),
+ "Trace buffer allocation failed");
+ }
+ m_mmap_aux = std::unique_ptr<uint8_t, munmap_delete>(
+ reinterpret_cast<uint8_t *>(mmap_aux), munmap_delete(buffer_size));
+ return Error::success();
+#endif
+}
+
+llvm::MutableArrayRef<uint8_t> IntelPTThreadTrace::GetDataBuffer() const {
+#ifndef PERF_ATTR_SIZE_VER5
+ llvm_unreachable("Intel PT Linux perf event not supported");
+#else
+ return MutableArrayRef<uint8_t>(
+ (reinterpret_cast<uint8_t *>(m_mmap_meta.get()) +
+ m_mmap_meta->data_offset),
+ m_mmap_meta->data_size);
+#endif
+}
+
+llvm::MutableArrayRef<uint8_t> IntelPTThreadTrace::GetAuxBuffer() const {
+#ifndef PERF_ATTR_SIZE_VER5
+ llvm_unreachable("Intel PT Linux perf event not supported");
+#else
+ return MutableArrayRef<uint8_t>(m_mmap_aux.get(), m_mmap_meta->aux_size);
+#endif
+}
+
+Expected<ArrayRef<uint8_t>> IntelPTThreadTrace::GetCPUInfo() {
+ static llvm::Optional<std::vector<uint8_t>> cpu_info;
+ if (!cpu_info) {
+ auto buffer_or_error = getProcFile("cpuinfo");
+ if (!buffer_or_error)
+ return Status(buffer_or_error.getError()).ToError();
+ MemoryBuffer &buffer = **buffer_or_error;
+ cpu_info = std::vector<uint8_t>(
+ reinterpret_cast<const uint8_t *>(buffer.getBufferStart()),
+ reinterpret_cast<const uint8_t *>(buffer.getBufferEnd()));
+ }
+ return *cpu_info;
+}
+
+llvm::Expected<IntelPTThreadTraceUP>
+IntelPTThreadTrace::Create(lldb::pid_t pid, lldb::tid_t tid, size_t buffer_size,
+ bool enable_tsc, Optional<size_t> psb_period) {
+ IntelPTThreadTraceUP thread_trace_up(new IntelPTThreadTrace());
+
+ if (llvm::Error err = thread_trace_up->StartTrace(pid, tid, buffer_size,
+ enable_tsc, psb_period))
+ return std::move(err);
+
+ return std::move(thread_trace_up);
+}
+
+Expected<std::vector<uint8_t>>
+IntelPTThreadTrace::GetIntelPTBuffer(size_t offset, size_t size) const {
+ std::vector<uint8_t> data(size, 0);
+ MutableArrayRef<uint8_t> buffer_ref(data);
+ Status error = ReadPerfTraceAux(buffer_ref, 0);
+ if (error.Fail())
+ return error.ToError();
+ return data;
+}
+
+Status
+IntelPTThreadTrace::ReadPerfTraceAux(llvm::MutableArrayRef<uint8_t> &buffer,
+ size_t offset) const {
+#ifndef PERF_ATTR_SIZE_VER5
+ llvm_unreachable("perf event not supported");
+#else
+ // Disable the perf event to force a flush out of the CPU's internal buffer.
+ // Besides, we can guarantee that the CPU won't override any data as we are
+ // reading the buffer.
+ //
+ // The Intel documentation says:
+ //
+ // Packets are first buffered internally and then written out asynchronously.
+ // To collect packet output for postprocessing, a collector needs first to
+ // ensure that all packet data has been flushed from internal buffers.
+ // Software can ensure this by stopping packet generation by clearing
+ // IA32_RTIT_CTL.TraceEn (see “Disabling Packet Generation” in
+ // Section 35.2.7.2).
+ //
+ // This is achieved by the PERF_EVENT_IOC_DISABLE ioctl request, as mentioned
+ // in the man page of perf_event_open.
+ ioctl(*m_fd, PERF_EVENT_IOC_DISABLE);
+
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
+ Status error;
+ uint64_t head = m_mmap_meta->aux_head;
+
+ LLDB_LOG(log, "Aux size -{0} , Head - {1}", m_mmap_meta->aux_size, head);
+
+ /**
+ * When configured as ring buffer, the aux buffer keeps wrapping around
+ * the buffer and its not possible to detect how many times the buffer
+ * wrapped. Initially the buffer is filled with zeros,as shown below
+ * so in order to get complete buffer we first copy firstpartsize, followed
+ * by any left over part from beginning to aux_head
+ *
+ * aux_offset [d,d,d,d,d,d,d,d,0,0,0,0,0,0,0,0,0,0,0] aux_size
+ * aux_head->||<- firstpartsize ->|
+ *
+ * */
+
+ ReadCyclicBuffer(buffer, GetAuxBuffer(), static_cast<size_t>(head), offset);
+ LLDB_LOG(log, "ReadCyclic BUffer Done");
+
+ // Reenable tracing now we have read the buffer
+ ioctl(*m_fd, PERF_EVENT_IOC_ENABLE);
+ return error;
+#endif
+}
+
+Status
+IntelPTThreadTrace::ReadPerfTraceData(llvm::MutableArrayRef<uint8_t> &buffer,
+ size_t offset) const {
+#ifndef PERF_ATTR_SIZE_VER5
+ llvm_unreachable("perf event not supported");
+#else
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
+ uint64_t bytes_remaining = buffer.size();
+ Status error;
+
+ uint64_t head = m_mmap_meta->data_head;
+
+ /*
+ * The data buffer and aux buffer have different implementations
+ * with respect to their definition of head pointer. In the case
+ * of Aux data buffer the head always wraps around the aux buffer
+ * and we don't need to care about it, whereas the data_head keeps
+ * increasing and needs to be wrapped by modulus operator
+ */
+
+ LLDB_LOG(log, "bytes_remaining - {0}", bytes_remaining);
+
+ auto data_buffer = GetDataBuffer();
+
+ if (head > data_buffer.size()) {
+ head = head % data_buffer.size();
+ LLDB_LOG(log, "Data size -{0} Head - {1}", m_mmap_meta->data_size, head);
+
+ ReadCyclicBuffer(buffer, data_buffer, static_cast<size_t>(head), offset);
+ bytes_remaining -= buffer.size();
+ } else {
+ LLDB_LOG(log, "Head - {0}", head);
+ if (offset >= head) {
+ LLDB_LOG(log, "Invalid Offset ");
+ error.SetErrorString("invalid offset");
+ buffer = buffer.slice(buffer.size());
+ return error;
+ }
+
+ auto data = data_buffer.slice(offset, (head - offset));
+ auto remaining = std::copy(data.begin(), data.end(), buffer.begin());
+ bytes_remaining -= (remaining - buffer.begin());
+ }
+ buffer = buffer.drop_back(bytes_remaining);
+ return error;
+#endif
+}
+
+void IntelPTThreadTrace::ReadCyclicBuffer(llvm::MutableArrayRef<uint8_t> &dst,
+ llvm::MutableArrayRef<uint8_t> src,
+ size_t src_cyc_index, size_t offset) {
+
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
+
+ if (dst.empty() || src.empty()) {
+ dst = dst.drop_back(dst.size());
+ return;
+ }
+
+ if (dst.data() == nullptr || src.data() == nullptr) {
+ dst = dst.drop_back(dst.size());
+ return;
+ }
+
+ if (src_cyc_index > src.size()) {
+ dst = dst.drop_back(dst.size());
+ return;
+ }
+
+ if (offset >= src.size()) {
+ LLDB_LOG(log, "Too Big offset ");
+ dst = dst.drop_back(dst.size());
+ return;
+ }
+
+ llvm::SmallVector<MutableArrayRef<uint8_t>, 2> parts = {
+ src.slice(src_cyc_index), src.take_front(src_cyc_index)};
+
+ if (offset > parts[0].size()) {
+ parts[1] = parts[1].slice(offset - parts[0].size());
+ parts[0] = parts[0].drop_back(parts[0].size());
+ } else if (offset == parts[0].size()) {
+ parts[0] = parts[0].drop_back(parts[0].size());
+ } else {
+ parts[0] = parts[0].slice(offset);
+ }
+ auto next = dst.begin();
+ auto bytes_left = dst.size();
+ for (auto part : parts) {
+ size_t chunk_size = std::min(part.size(), bytes_left);
+ next = std::copy_n(part.begin(), chunk_size, next);
+ bytes_left -= chunk_size;
+ }
+ dst = dst.drop_back(bytes_left);
+}
+
+TraceThreadState IntelPTThreadTrace::GetState() const {
+ return {static_cast<int64_t>(m_tid),
+ {TraceBinaryData{"threadTraceBuffer",
+ static_cast<int64_t>(GetTraceBufferSize())}}};
+}
+
+/// IntelPTThreadTraceCollection
+
+bool IntelPTThreadTraceCollection::TracesThread(lldb::tid_t tid) const {
+ return m_thread_traces.count(tid);
+}
+
+Error IntelPTThreadTraceCollection::TraceStop(lldb::tid_t tid) {
+ auto it = m_thread_traces.find(tid);
+ if (it == m_thread_traces.end())
+ return createStringError(inconvertibleErrorCode(),
+ "Thread %" PRIu64 " not currently traced", tid);
+ m_total_buffer_size -= it->second->GetTraceBufferSize();
+ m_thread_traces.erase(tid);
+ return Error::success();
+}
+
+Error IntelPTThreadTraceCollection::TraceStart(
+ lldb::tid_t tid, const TraceIntelPTStartRequest &request) {
+ if (TracesThread(tid))
+ return createStringError(inconvertibleErrorCode(),
+ "Thread %" PRIu64 " already traced", tid);
+
+ Expected<IntelPTThreadTraceUP> trace_up = IntelPTThreadTrace::Create(
+ m_pid, tid, request.threadBufferSize, request.enableTsc,
+ request.psbPeriod.map([](int64_t period) { return (size_t)period; }));
+ if (!trace_up)
+ return trace_up.takeError();
+
+ m_total_buffer_size += (*trace_up)->GetTraceBufferSize();
+ m_thread_traces.try_emplace(tid, std::move(*trace_up));
+ return Error::success();
+}
+
+size_t IntelPTThreadTraceCollection::GetTotalBufferSize() const {
+ return m_total_buffer_size;
+}
+
+std::vector<TraceThreadState>
+IntelPTThreadTraceCollection::GetThreadStates() const {
+ std::vector<TraceThreadState> states;
+ for (const auto &it : m_thread_traces)
+ states.push_back(it.second->GetState());
+ return states;
+}
+
+Expected<const IntelPTThreadTrace &>
+IntelPTThreadTraceCollection::GetTracedThread(lldb::tid_t tid) const {
+ auto it = m_thread_traces.find(tid);
+ if (it == m_thread_traces.end())
+ return createStringError(inconvertibleErrorCode(),
+ "Thread %" PRIu64 " not currently traced", tid);
+ return *it->second.get();
+}
+
+void IntelPTThreadTraceCollection::Clear() {
+ m_thread_traces.clear();
+ m_total_buffer_size = 0;
+}
+
+/// IntelPTProcessTrace
+
+bool IntelPTProcessTrace::TracesThread(lldb::tid_t tid) const {
+ return m_thread_traces.TracesThread(tid);
+}
+
+Error IntelPTProcessTrace::TraceStop(lldb::tid_t tid) {
+ return m_thread_traces.TraceStop(tid);
+}
+
+Error IntelPTProcessTrace::TraceStart(lldb::tid_t tid) {
+ if (m_thread_traces.GetTotalBufferSize() + m_tracing_params.threadBufferSize >
+ static_cast<size_t>(*m_tracing_params.processBufferSizeLimit))
+ return createStringError(
+ inconvertibleErrorCode(),
+ "Thread %" PRIu64 " can't be traced as the process trace size limit "
+ "has been reached. Consider retracing with a higher "
+ "limit.",
+ tid);
+
+ return m_thread_traces.TraceStart(tid, m_tracing_params);
+}
+
+const IntelPTThreadTraceCollection &
+IntelPTProcessTrace::GetThreadTraces() const {
+ return m_thread_traces;
+}
+
+/// IntelPTManager
+
+Error IntelPTManager::TraceStop(lldb::tid_t tid) {
+ if (IsProcessTracingEnabled() && m_process_trace->TracesThread(tid))
+ return m_process_trace->TraceStop(tid);
+ return m_thread_traces.TraceStop(tid);
+}
+
+Error IntelPTManager::TraceStop(const TraceStopRequest &request) {
+ if (request.IsProcessTracing()) {
+ Clear();
+ return Error::success();
+ } else {
+ Error error = Error::success();
+ for (int64_t tid : *request.tids)
+ error = joinErrors(std::move(error),
+ TraceStop(static_cast<lldb::tid_t>(tid)));
+ return error;
+ }
+}
+
+Error IntelPTManager::TraceStart(
+ const TraceIntelPTStartRequest &request,
+ const std::vector<lldb::tid_t> &process_threads) {
+ if (request.IsProcessTracing()) {
+ if (IsProcessTracingEnabled()) {
+ return createStringError(
+ inconvertibleErrorCode(),
+ "Process currently traced. Stop process tracing first");
+ }
+ m_process_trace = IntelPTProcessTrace(m_pid, request);
+
+ Error error = Error::success();
+ for (lldb::tid_t tid : process_threads)
+ error = joinErrors(std::move(error), m_process_trace->TraceStart(tid));
+ return error;
+ } else {
+ Error error = Error::success();
+ for (int64_t tid : *request.tids)
+ error = joinErrors(std::move(error),
+ m_thread_traces.TraceStart(tid, request));
+ return error;
+ }
+}
+
+Error IntelPTManager::OnThreadCreated(lldb::tid_t tid) {
+ if (!IsProcessTracingEnabled())
+ return Error::success();
+ return m_process_trace->TraceStart(tid);
+}
+
+Error IntelPTManager::OnThreadDestroyed(lldb::tid_t tid) {
+ if (IsProcessTracingEnabled() && m_process_trace->TracesThread(tid))
+ return m_process_trace->TraceStop(tid);
+ else if (m_thread_traces.TracesThread(tid))
+ return m_thread_traces.TraceStop(tid);
+ return Error::success();
+}
+
+Expected<json::Value> IntelPTManager::GetState() const {
+ Expected<ArrayRef<uint8_t>> cpu_info = IntelPTThreadTrace::GetCPUInfo();
+ if (!cpu_info)
+ return cpu_info.takeError();
+
+ TraceGetStateResponse state;
+ state.processBinaryData.push_back(
+ {"cpuInfo", static_cast<int64_t>(cpu_info->size())});
+
+ std::vector<TraceThreadState> thread_states =
+ m_thread_traces.GetThreadStates();
+ state.tracedThreads.insert(state.tracedThreads.end(), thread_states.begin(),
+ thread_states.end());
+
+ if (IsProcessTracingEnabled()) {
+ thread_states = m_process_trace->GetThreadTraces().GetThreadStates();
+ state.tracedThreads.insert(state.tracedThreads.end(), thread_states.begin(),
+ thread_states.end());
+ }
+ return toJSON(state);
+}
+
+Expected<const IntelPTThreadTrace &>
+IntelPTManager::GetTracedThread(lldb::tid_t tid) const {
+ if (IsProcessTracingEnabled() && m_process_trace->TracesThread(tid))
+ return m_process_trace->GetThreadTraces().GetTracedThread(tid);
+ return m_thread_traces.GetTracedThread(tid);
+}
+
+Expected<std::vector<uint8_t>>
+IntelPTManager::GetBinaryData(const TraceGetBinaryDataRequest &request) const {
+ if (request.kind == "threadTraceBuffer") {
+ if (Expected<const IntelPTThreadTrace &> trace =
+ GetTracedThread(*request.tid))
+ return trace->GetIntelPTBuffer(request.offset, request.size);
+ else
+ return trace.takeError();
+ } else if (request.kind == "cpuInfo") {
+ return IntelPTThreadTrace::GetCPUInfo();
+ }
+ return createStringError(inconvertibleErrorCode(),
+ "Unsuported trace binary data kind: %s",
+ request.kind.c_str());
+}
+
+void IntelPTManager::ClearProcessTracing() { m_process_trace = None; }
+
+bool IntelPTManager::IsSupported() {
+ Expected<uint32_t> intel_pt_type = GetOSEventType();
+ if (!intel_pt_type) {
+ llvm::consumeError(intel_pt_type.takeError());
+ return false;
+ }
+ return true;
+}
+
+bool IntelPTManager::IsProcessTracingEnabled() const {
+ return (bool)m_process_trace;
+}
+
+void IntelPTManager::Clear() {
+ ClearProcessTracing();
+ m_thread_traces.Clear();
+}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Linux/IntelPTManager.h b/src/llvm-project/lldb/source/Plugins/Process/Linux/IntelPTManager.h
new file mode 100644
index 0000000..38566a2
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Process/Linux/IntelPTManager.h
@@ -0,0 +1,263 @@
+//===-- IntelPTManager.h -------------------------------------- -*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_IntelPTManager_H_
+#define liblldb_IntelPTManager_H_
+
+#include "lldb/Utility/Status.h"
+#include "lldb/Utility/TraceIntelPTGDBRemotePackets.h"
+#include "lldb/lldb-types.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+
+#include <linux/perf_event.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+namespace lldb_private {
+
+namespace process_linux {
+
+/// This class keeps track of one tracing instance of
+/// Intel(R) Processor Trace on Linux OS at thread level.
+///
+/// The kernel interface for us is the perf_event_open.
+class IntelPTThreadTrace;
+typedef std::unique_ptr<IntelPTThreadTrace> IntelPTThreadTraceUP;
+
+class IntelPTThreadTrace {
+
+ class munmap_delete {
+ size_t m_length;
+
+ public:
+ munmap_delete(size_t length) : m_length(length) {}
+ void operator()(void *ptr) {
+ if (m_length)
+ munmap(ptr, m_length);
+ }
+ };
+
+ class file_close {
+
+ public:
+ file_close() = default;
+ void operator()(int *ptr) {
+ if (ptr == nullptr)
+ return;
+ if (*ptr == -1)
+ return;
+ close(*ptr);
+ std::default_delete<int>()(ptr);
+ }
+ };
+
+ std::unique_ptr<perf_event_mmap_page, munmap_delete> m_mmap_meta;
+ std::unique_ptr<uint8_t, munmap_delete> m_mmap_aux;
+ std::unique_ptr<int, file_close> m_fd;
+ lldb::tid_t m_tid;
+
+ /// Start tracing a thread
+ ///
+ /// \param[in] pid
+ /// The pid of the process whose thread will be traced.
+ ///
+ /// \param[in] buffer_size
+ /// Size of the thread buffer in bytes.
+ ///
+ /// \param[in] enable_tsc
+ /// Whether to use enable TSC timestamps or not.
+ /// More information in TraceIntelPT::GetStartConfigurationHelp().
+ ///
+ /// \param[in] psb_period
+ /// This value defines the period in which PSB packets will be generated.
+ /// More information in TraceIntelPT::GetStartConfigurationHelp().
+ ///
+ /// \return
+ /// \a llvm::Error::success if tracing was successful, or an
+ /// \a llvm::Error otherwise.
+ llvm::Error StartTrace(lldb::pid_t pid, lldb::tid_t tid, uint64_t buffer_size,
+ bool enable_tsc, llvm::Optional<size_t> psb_period);
+
+ llvm::MutableArrayRef<uint8_t> GetAuxBuffer() const;
+ llvm::MutableArrayRef<uint8_t> GetDataBuffer() const;
+
+ IntelPTThreadTrace()
+ : m_mmap_meta(nullptr, munmap_delete(0)),
+ m_mmap_aux(nullptr, munmap_delete(0)), m_fd(nullptr, file_close()) {}
+
+public:
+ /// Get the content of /proc/cpuinfo that can be later used to decode traces.
+ static llvm::Expected<llvm::ArrayRef<uint8_t>> GetCPUInfo();
+
+ /// Start tracing a thread.
+ ///
+ /// See \a StartTrace.
+ ///
+ /// \return
+ /// A \a IntelPTThreadTrace instance if tracing was successful, or
+ /// an \a llvm::Error otherwise.
+ static llvm::Expected<IntelPTThreadTraceUP>
+ Create(lldb::pid_t pid, lldb::tid_t tid, size_t buffer_size, bool enable_tsc,
+ llvm::Optional<size_t> psb_period);
+
+ /// Read the trace buffer of the currently traced thread.
+ ///
+ /// \param[in] offset
+ /// Offset of the data to read.
+ ///
+ /// \param[in] size
+ /// Number of bytes to read.
+ ///
+ /// \return
+ /// A vector with the requested binary data. The vector will have the
+ /// size of the requested \a size. Non-available positions will be
+ /// filled with zeroes.
+ llvm::Expected<std::vector<uint8_t>> GetIntelPTBuffer(size_t offset,
+ size_t size) const;
+
+ Status ReadPerfTraceAux(llvm::MutableArrayRef<uint8_t> &buffer,
+ size_t offset = 0) const;
+
+ Status ReadPerfTraceData(llvm::MutableArrayRef<uint8_t> &buffer,
+ size_t offset = 0) const;
+
+ /// Get the size in bytes of the aux section of the thread or process traced
+ /// by this object.
+ size_t GetTraceBufferSize() const;
+
+ /// Read data from a cyclic buffer
+ ///
+ /// \param[in] [out] buf
+ /// Destination buffer, the buffer will be truncated to written size.
+ ///
+ /// \param[in] src
+ /// Source buffer which must be a cyclic buffer.
+ ///
+ /// \param[in] src_cyc_index
+ /// The index pointer (start of the valid data in the cyclic
+ /// buffer).
+ ///
+ /// \param[in] offset
+ /// The offset to begin reading the data in the cyclic buffer.
+ static void ReadCyclicBuffer(llvm::MutableArrayRef<uint8_t> &dst,
+ llvm::MutableArrayRef<uint8_t> src,
+ size_t src_cyc_index, size_t offset);
+
+ /// Return the thread-specific part of the jLLDBTraceGetState packet.
+ TraceThreadState GetState() const;
+};
+
+/// Manages a list of thread traces.
+class IntelPTThreadTraceCollection {
+public:
+ IntelPTThreadTraceCollection(lldb::pid_t pid) : m_pid(pid) {}
+
+ /// Dispose of all traces
+ void Clear();
+
+ bool TracesThread(lldb::tid_t tid) const;
+
+ size_t GetTotalBufferSize() const;
+
+ std::vector<TraceThreadState> GetThreadStates() const;
+
+ llvm::Expected<const IntelPTThreadTrace &>
+ GetTracedThread(lldb::tid_t tid) const;
+
+ llvm::Error TraceStart(lldb::tid_t tid,
+ const TraceIntelPTStartRequest &request);
+
+ llvm::Error TraceStop(lldb::tid_t tid);
+
+private:
+ lldb::pid_t m_pid;
+ llvm::DenseMap<lldb::tid_t, IntelPTThreadTraceUP> m_thread_traces;
+ /// Total actual thread buffer size in bytes
+ size_t m_total_buffer_size = 0;
+};
+
+/// Manages a "process trace" instance.
+class IntelPTProcessTrace {
+public:
+ IntelPTProcessTrace(lldb::pid_t pid, const TraceIntelPTStartRequest &request)
+ : m_thread_traces(pid), m_tracing_params(request) {}
+
+ bool TracesThread(lldb::tid_t tid) const;
+
+ const IntelPTThreadTraceCollection &GetThreadTraces() const;
+
+ llvm::Error TraceStart(lldb::tid_t tid);
+
+ llvm::Error TraceStop(lldb::tid_t tid);
+
+private:
+ IntelPTThreadTraceCollection m_thread_traces;
+ /// Params used to trace threads when the user started "process tracing".
+ TraceIntelPTStartRequest m_tracing_params;
+};
+
+/// Main class that manages intel-pt process and thread tracing.
+class IntelPTManager {
+public:
+ IntelPTManager(lldb::pid_t pid) : m_pid(pid), m_thread_traces(pid) {}
+
+ static bool IsSupported();
+
+ /// If "process tracing" is enabled, then trace the given thread.
+ llvm::Error OnThreadCreated(lldb::tid_t tid);
+
+ /// Stops tracing a tracing upon a destroy event.
+ llvm::Error OnThreadDestroyed(lldb::tid_t tid);
+
+ /// Implementation of the jLLDBTraceStop packet
+ llvm::Error TraceStop(const TraceStopRequest &request);
+
+ /// Implementation of the jLLDBTraceStart packet
+ ///
+ /// \param[in] process_threads
+ /// A list of all threads owned by the process.
+ llvm::Error TraceStart(const TraceIntelPTStartRequest &request,
+ const std::vector<lldb::tid_t> &process_threads);
+
+ /// Implementation of the jLLDBTraceGetState packet
+ llvm::Expected<llvm::json::Value> GetState() const;
+
+ /// Implementation of the jLLDBTraceGetBinaryData packet
+ llvm::Expected<std::vector<uint8_t>>
+ GetBinaryData(const TraceGetBinaryDataRequest &request) const;
+
+ /// Dispose of all traces
+ void Clear();
+
+private:
+ llvm::Error TraceStop(lldb::tid_t tid);
+
+ /// Start tracing a specific thread.
+ llvm::Error TraceStart(lldb::tid_t tid,
+ const TraceIntelPTStartRequest &request);
+
+ llvm::Expected<const IntelPTThreadTrace &>
+ GetTracedThread(lldb::tid_t tid) const;
+
+ bool IsProcessTracingEnabled() const;
+
+ void ClearProcessTracing();
+
+ lldb::pid_t m_pid;
+ /// Threads traced due to "thread tracing"
+ IntelPTThreadTraceCollection m_thread_traces;
+ /// Threads traced due to "process tracing". Only one active "process tracing"
+ /// instance is assumed for a single process.
+ llvm::Optional<IntelPTProcessTrace> m_process_trace;
+};
+
+} // namespace process_linux
+} // namespace lldb_private
+
+#endif // liblldb_IntelPTManager_H_
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
index e07d763..8c45796 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
@@ -8,9 +8,9 @@
#include "NativeProcessLinux.h"
-#include <errno.h>
-#include <stdint.h>
-#include <string.h>
+#include <cerrno>
+#include <cstdint>
+#include <cstring>
#include <unistd.h>
#include <fstream>
@@ -23,7 +23,6 @@
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
#include "Plugins/Process/Utility/LinuxProcMaps.h"
#include "Procfs.h"
-#include "lldb/Core/EmulateInstruction.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostProcess.h"
@@ -31,6 +30,7 @@
#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Host/common/NativeRegisterContext.h"
+#include "lldb/Host/linux/Host.h"
#include "lldb/Host/linux/Ptrace.h"
#include "lldb/Host/linux/Uio.h"
#include "lldb/Host/posix/ProcessLauncherPosixFork.h"
@@ -38,7 +38,6 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/LLDBAssert.h"
-#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/State.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StringExtractor.h"
@@ -54,11 +53,20 @@
#include <sys/user.h>
#include <sys/wait.h>
+#ifdef __aarch64__
+#include <asm/hwcap.h>
+#include <sys/auxv.h>
+#endif
+
// Support hardware breakpoints in case it has not been defined
#ifndef TRAP_HWBKPT
#define TRAP_HWBKPT 4
#endif
+#ifndef HWCAP2_MTE
+#define HWCAP2_MTE (1 << 18)
+#endif
+
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_linux;
@@ -282,13 +290,29 @@
pid, -1, native_delegate, Info.GetArchitecture(), mainloop, *tids_or));
}
+NativeProcessLinux::Extension
+NativeProcessLinux::Factory::GetSupportedExtensions() const {
+ NativeProcessLinux::Extension supported =
+ Extension::multiprocess | Extension::fork | Extension::vfork |
+ Extension::pass_signals | Extension::auxv | Extension::libraries_svr4;
+
+#ifdef __aarch64__
+ // At this point we do not have a process so read auxv directly.
+ if ((getauxval(AT_HWCAP2) & HWCAP2_MTE))
+ supported |= Extension::memory_tagging;
+#endif
+
+ return supported;
+}
+
// Public Instance Methods
NativeProcessLinux::NativeProcessLinux(::pid_t pid, int terminal_fd,
NativeDelegate &delegate,
const ArchSpec &arch, MainLoop &mainloop,
llvm::ArrayRef<::pid_t> tids)
- : NativeProcessELF(pid, terminal_fd, delegate), m_arch(arch) {
+ : NativeProcessELF(pid, terminal_fd, delegate), m_arch(arch),
+ m_main_loop(mainloop), m_intel_pt_manager(pid) {
if (m_terminal_fd != -1) {
Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK);
assert(status.Success());
@@ -300,8 +324,7 @@
assert(m_sigchld_handle && status.Success());
for (const auto &tid : tids) {
- NativeThreadLinux &thread = AddThread(tid);
- thread.SetStoppedBySignal(SIGSTOP);
+ NativeThreadLinux &thread = AddThread(tid, /*resume*/ false);
ThreadWasCreated(thread);
}
@@ -385,14 +408,22 @@
ptrace_opts |= PTRACE_O_TRACEEXIT;
// Have the tracer trace threads which spawn in the inferior process.
- // TODO: if we want to support tracing the inferiors' child, add the
- // appropriate ptrace flags here (PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK)
ptrace_opts |= PTRACE_O_TRACECLONE;
// Have the tracer notify us before execve returns (needed to disable legacy
// SIGTRAP generation)
ptrace_opts |= PTRACE_O_TRACEEXEC;
+ // Have the tracer trace forked children.
+ ptrace_opts |= PTRACE_O_TRACEFORK;
+
+ // Have the tracer trace vforks.
+ ptrace_opts |= PTRACE_O_TRACEVFORK;
+
+ // Have the tracer trace vfork-done in order to restore breakpoints after
+ // the child finishes sharing memory.
+ ptrace_opts |= PTRACE_O_TRACEVFORKDONE;
+
return PtraceWrapper(PTRACE_SETOPTIONS, pid, nullptr, (void *)ptrace_opts);
}
@@ -446,11 +477,7 @@
LLDB_LOG(log, "tid {0}, si_code: {1}, si_pid: {2}", pid, info.si_code,
info.si_pid);
- NativeThreadLinux &thread = AddThread(pid);
-
- // Resume the newly created thread.
- ResumeThread(thread, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER);
- ThreadWasCreated(thread);
+ MonitorClone(pid, llvm::None);
return;
}
@@ -514,29 +541,24 @@
}
}
-void NativeProcessLinux::WaitForNewThread(::pid_t tid) {
+void NativeProcessLinux::WaitForCloneNotification(::pid_t pid) {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
- if (GetThreadByID(tid)) {
- // We are already tracking the thread - we got the event on the new thread
- // (see MonitorSignal) before this one. We are done.
- return;
- }
-
- // The thread is not tracked yet, let's wait for it to appear.
+ // The PID is not tracked yet, let's wait for it to appear.
int status = -1;
LLDB_LOG(log,
- "received thread creation event for tid {0}. tid not tracked "
- "yet, waiting for thread to appear...",
- tid);
- ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, ::waitpid, tid, &status, __WALL);
- // Since we are waiting on a specific tid, this must be the creation event.
+ "received clone event for pid {0}. pid not tracked yet, "
+ "waiting for it to appear...",
+ pid);
+ ::pid_t wait_pid =
+ llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &status, __WALL);
+ // Since we are waiting on a specific pid, this must be the creation event.
// But let's do some checks just in case.
- if (wait_pid != tid) {
+ if (wait_pid != pid) {
LLDB_LOG(log,
- "waiting for tid {0} failed. Assuming the thread has "
+ "waiting for pid {0} failed. Assuming the pid has "
"disappeared in the meantime",
- tid);
+ pid);
// The only way I know of this could happen is if the whole process was
// SIGKILLed in the mean time. In any case, we can't do anything about that
// now.
@@ -544,18 +566,15 @@
}
if (WIFEXITED(status)) {
LLDB_LOG(log,
- "waiting for tid {0} returned an 'exited' event. Not "
- "tracking the thread.",
- tid);
+ "waiting for pid {0} returned an 'exited' event. Not "
+ "tracking it.",
+ pid);
// Also a very improbable event.
+ m_pending_pid_map.erase(pid);
return;
}
- LLDB_LOG(log, "pid = {0}: tracking new thread tid {1}", GetID(), tid);
- NativeThreadLinux &new_thread = AddThread(tid);
-
- ResumeThread(new_thread, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER);
- ThreadWasCreated(new_thread);
+ MonitorClone(pid, llvm::None);
}
void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info,
@@ -566,26 +585,26 @@
assert(info.si_signo == SIGTRAP && "Unexpected child signal!");
switch (info.si_code) {
- // TODO: these two cases are required if we want to support tracing of the
- // inferiors' children. We'd need this to debug a monitor. case (SIGTRAP |
- // (PTRACE_EVENT_FORK << 8)): case (SIGTRAP | (PTRACE_EVENT_VFORK << 8)):
-
+ case (SIGTRAP | (PTRACE_EVENT_FORK << 8)):
+ case (SIGTRAP | (PTRACE_EVENT_VFORK << 8)):
case (SIGTRAP | (PTRACE_EVENT_CLONE << 8)): {
- // This is the notification on the parent thread which informs us of new
- // thread creation. We don't want to do anything with the parent thread so
- // we just resume it. In case we want to implement "break on thread
- // creation" functionality, we would need to stop here.
+ // This can either mean a new thread or a new process spawned via
+ // clone(2) without SIGCHLD or CLONE_VFORK flag. Note that clone(2)
+ // can also cause PTRACE_EVENT_FORK and PTRACE_EVENT_VFORK if one
+ // of these flags are passed.
unsigned long event_message = 0;
if (GetEventMessage(thread.GetID(), &event_message).Fail()) {
LLDB_LOG(log,
- "pid {0} received thread creation event but "
- "GetEventMessage failed so we don't know the new tid",
+ "pid {0} received clone() event but GetEventMessage failed "
+ "so we don't know the new pid/tid",
thread.GetID());
- } else
- WaitForNewThread(event_message);
+ ResumeThread(thread, thread.GetState(), LLDB_INVALID_SIGNAL_NUMBER);
+ } else {
+ if (!MonitorClone(event_message, {{(info.si_code >> 8), thread.GetID()}}))
+ WaitForCloneNotification(event_message);
+ }
- ResumeThread(thread, thread.GetState(), LLDB_INVALID_SIGNAL_NUMBER);
break;
}
@@ -651,6 +670,16 @@
break;
}
+ case (SIGTRAP | (PTRACE_EVENT_VFORK_DONE << 8)): {
+ if (bool(m_enabled_extensions & Extension::vfork)) {
+ thread.SetStoppedByVForkDone();
+ StopRunningThreads(thread.GetID());
+ }
+ else
+ ResumeThread(thread, thread.GetState(), LLDB_INVALID_SIGNAL_NUMBER);
+ break;
+ }
+
case 0:
case TRAP_TRACE: // We receive this on single stepping.
case TRAP_HWBKPT: // We receive this on watchpoint hit
@@ -860,167 +889,83 @@
StopRunningThreads(thread.GetID());
}
-namespace {
+bool NativeProcessLinux::MonitorClone(
+ lldb::pid_t child_pid,
+ llvm::Optional<NativeProcessLinux::CloneInfo> clone_info) {
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ LLDB_LOG(log, "clone, child_pid={0}, clone info?={1}", child_pid,
+ clone_info.hasValue());
-struct EmulatorBaton {
- NativeProcessLinux &m_process;
- NativeRegisterContext &m_reg_context;
+ auto find_it = m_pending_pid_map.find(child_pid);
+ if (find_it == m_pending_pid_map.end()) {
+ // not in the map, so this is the first signal for the PID
+ m_pending_pid_map.insert({child_pid, clone_info});
+ return false;
+ }
+ m_pending_pid_map.erase(find_it);
- // eRegisterKindDWARF -> RegsiterValue
- std::unordered_map<uint32_t, RegisterValue> m_register_values;
-
- EmulatorBaton(NativeProcessLinux &process, NativeRegisterContext ®_context)
- : m_process(process), m_reg_context(reg_context) {}
-};
-
-} // anonymous namespace
-
-static size_t ReadMemoryCallback(EmulateInstruction *instruction, void *baton,
- const EmulateInstruction::Context &context,
- lldb::addr_t addr, void *dst, size_t length) {
- EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
-
- size_t bytes_read;
- emulator_baton->m_process.ReadMemory(addr, dst, length, bytes_read);
- return bytes_read;
-}
-
-static bool ReadRegisterCallback(EmulateInstruction *instruction, void *baton,
- const RegisterInfo *reg_info,
- RegisterValue ®_value) {
- EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
-
- auto it = emulator_baton->m_register_values.find(
- reg_info->kinds[eRegisterKindDWARF]);
- if (it != emulator_baton->m_register_values.end()) {
- reg_value = it->second;
- return true;
+ // second signal for the pid
+ assert(clone_info.hasValue() != find_it->second.hasValue());
+ if (!clone_info) {
+ // child signal does not indicate the event, so grab the one stored
+ // earlier
+ clone_info = find_it->second;
}
- // The emulator only fill in the dwarf regsiter numbers (and in some case the
- // generic register numbers). Get the full register info from the register
- // context based on the dwarf register numbers.
- const RegisterInfo *full_reg_info =
- emulator_baton->m_reg_context.GetRegisterInfo(
- eRegisterKindDWARF, reg_info->kinds[eRegisterKindDWARF]);
+ LLDB_LOG(log, "second signal for child_pid={0}, parent_tid={1}, event={2}",
+ child_pid, clone_info->parent_tid, clone_info->event);
- Status error =
- emulator_baton->m_reg_context.ReadRegister(full_reg_info, reg_value);
- if (error.Success())
- return true;
+ auto *parent_thread = GetThreadByID(clone_info->parent_tid);
+ assert(parent_thread);
- return false;
-}
+ switch (clone_info->event) {
+ case PTRACE_EVENT_CLONE: {
+ // PTRACE_EVENT_CLONE can either mean a new thread or a new process.
+ // Try to grab the new process' PGID to figure out which one it is.
+ // If PGID is the same as the PID, then it's a new process. Otherwise,
+ // it's a thread.
+ auto tgid_ret = getPIDForTID(child_pid);
+ if (tgid_ret != child_pid) {
+ // A new thread should have PGID matching our process' PID.
+ assert(!tgid_ret || tgid_ret.getValue() == GetID());
-static bool WriteRegisterCallback(EmulateInstruction *instruction, void *baton,
- const EmulateInstruction::Context &context,
- const RegisterInfo *reg_info,
- const RegisterValue ®_value) {
- EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
- emulator_baton->m_register_values[reg_info->kinds[eRegisterKindDWARF]] =
- reg_value;
- return true;
-}
+ NativeThreadLinux &child_thread = AddThread(child_pid, /*resume*/ true);
+ ThreadWasCreated(child_thread);
-static size_t WriteMemoryCallback(EmulateInstruction *instruction, void *baton,
- const EmulateInstruction::Context &context,
- lldb::addr_t addr, const void *dst,
- size_t length) {
- return length;
-}
-
-static lldb::addr_t ReadFlags(NativeRegisterContext ®siter_context) {
- const RegisterInfo *flags_info = regsiter_context.GetRegisterInfo(
- eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
- return regsiter_context.ReadRegisterAsUnsigned(flags_info,
- LLDB_INVALID_ADDRESS);
-}
-
-Status
-NativeProcessLinux::SetupSoftwareSingleStepping(NativeThreadLinux &thread) {
- Status error;
- NativeRegisterContext& register_context = thread.GetRegisterContext();
-
- std::unique_ptr<EmulateInstruction> emulator_up(
- EmulateInstruction::FindPlugin(m_arch, eInstructionTypePCModifying,
- nullptr));
-
- if (emulator_up == nullptr)
- return Status("Instruction emulator not found!");
-
- EmulatorBaton baton(*this, register_context);
- emulator_up->SetBaton(&baton);
- emulator_up->SetReadMemCallback(&ReadMemoryCallback);
- emulator_up->SetReadRegCallback(&ReadRegisterCallback);
- emulator_up->SetWriteMemCallback(&WriteMemoryCallback);
- emulator_up->SetWriteRegCallback(&WriteRegisterCallback);
-
- if (!emulator_up->ReadInstruction())
- return Status("Read instruction failed!");
-
- bool emulation_result =
- emulator_up->EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC);
-
- const RegisterInfo *reg_info_pc = register_context.GetRegisterInfo(
- eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
- const RegisterInfo *reg_info_flags = register_context.GetRegisterInfo(
- eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
-
- auto pc_it =
- baton.m_register_values.find(reg_info_pc->kinds[eRegisterKindDWARF]);
- auto flags_it =
- baton.m_register_values.find(reg_info_flags->kinds[eRegisterKindDWARF]);
-
- lldb::addr_t next_pc;
- lldb::addr_t next_flags;
- if (emulation_result) {
- assert(pc_it != baton.m_register_values.end() &&
- "Emulation was successfull but PC wasn't updated");
- next_pc = pc_it->second.GetAsUInt64();
-
- if (flags_it != baton.m_register_values.end())
- next_flags = flags_it->second.GetAsUInt64();
- else
- next_flags = ReadFlags(register_context);
- } else if (pc_it == baton.m_register_values.end()) {
- // Emulate instruction failed and it haven't changed PC. Advance PC with
- // the size of the current opcode because the emulation of all
- // PC modifying instruction should be successful. The failure most
- // likely caused by a not supported instruction which don't modify PC.
- next_pc = register_context.GetPC() + emulator_up->GetOpcode().GetByteSize();
- next_flags = ReadFlags(register_context);
- } else {
- // The instruction emulation failed after it modified the PC. It is an
- // unknown error where we can't continue because the next instruction is
- // modifying the PC but we don't know how.
- return Status("Instruction emulation failed unexpectedly.");
- }
-
- if (m_arch.GetMachine() == llvm::Triple::arm) {
- if (next_flags & 0x20) {
- // Thumb mode
- error = SetSoftwareBreakpoint(next_pc, 2);
- } else {
- // Arm mode
- error = SetSoftwareBreakpoint(next_pc, 4);
+ // Resume the parent.
+ ResumeThread(*parent_thread, parent_thread->GetState(),
+ LLDB_INVALID_SIGNAL_NUMBER);
+ break;
}
- } else if (m_arch.IsMIPS() || m_arch.GetTriple().isPPC64())
- error = SetSoftwareBreakpoint(next_pc, 4);
- else {
- // No size hint is given for the next breakpoint
- error = SetSoftwareBreakpoint(next_pc, 0);
+ }
+ LLVM_FALLTHROUGH;
+ case PTRACE_EVENT_FORK:
+ case PTRACE_EVENT_VFORK: {
+ bool is_vfork = clone_info->event == PTRACE_EVENT_VFORK;
+ std::unique_ptr<NativeProcessLinux> child_process{new NativeProcessLinux(
+ static_cast<::pid_t>(child_pid), m_terminal_fd, m_delegate, m_arch,
+ m_main_loop, {static_cast<::pid_t>(child_pid)})};
+ if (!is_vfork)
+ child_process->m_software_breakpoints = m_software_breakpoints;
+
+ Extension expected_ext = is_vfork ? Extension::vfork : Extension::fork;
+ if (bool(m_enabled_extensions & expected_ext)) {
+ m_delegate.NewSubprocess(this, std::move(child_process));
+ // NB: non-vfork clone() is reported as fork
+ parent_thread->SetStoppedByFork(is_vfork, child_pid);
+ StopRunningThreads(parent_thread->GetID());
+ } else {
+ child_process->Detach();
+ ResumeThread(*parent_thread, parent_thread->GetState(),
+ LLDB_INVALID_SIGNAL_NUMBER);
+ }
+ break;
+ }
+ default:
+ llvm_unreachable("unknown clone_info.event");
}
- // If setting the breakpoint fails because next_pc is out of the address
- // space, ignore it and let the debugee segfault.
- if (error.GetError() == EIO || error.GetError() == EFAULT) {
- return Status();
- } else if (error.Fail())
- return error;
-
- m_threads_stepping_with_breakpoint.insert({thread.GetID(), next_pc});
-
- return Status();
+ return true;
}
bool NativeProcessLinux::SupportHardwareSingleStepping() const {
@@ -1119,8 +1064,7 @@
e; // Save the error, but still attempt to detach from other threads.
}
- m_processor_trace_monitor.clear();
- m_pt_proces_trace_id = LLDB_INVALID_UID;
+ m_intel_pt_manager.Clear();
return error;
}
@@ -1487,6 +1431,132 @@
return llvm::Error::success();
}
+Status NativeProcessLinux::ReadMemoryTags(int32_t type, lldb::addr_t addr,
+ size_t len,
+ std::vector<uint8_t> &tags) {
+ llvm::Expected<NativeRegisterContextLinux::MemoryTaggingDetails> details =
+ GetCurrentThread()->GetRegisterContext().GetMemoryTaggingDetails(type);
+ if (!details)
+ return Status(details.takeError());
+
+ // Ignore 0 length read
+ if (!len)
+ return Status();
+
+ // lldb will align the range it requests but it is not required to by
+ // the protocol so we'll do it again just in case.
+ // Remove non address bits too. Ptrace calls may work regardless but that
+ // is not a guarantee.
+ MemoryTagManager::TagRange range(details->manager->RemoveNonAddressBits(addr),
+ len);
+ range = details->manager->ExpandToGranule(range);
+
+ // Allocate enough space for all tags to be read
+ size_t num_tags = range.GetByteSize() / details->manager->GetGranuleSize();
+ tags.resize(num_tags * details->manager->GetTagSizeInBytes());
+
+ struct iovec tags_iovec;
+ uint8_t *dest = tags.data();
+ lldb::addr_t read_addr = range.GetRangeBase();
+
+ // This call can return partial data so loop until we error or
+ // get all tags back.
+ while (num_tags) {
+ tags_iovec.iov_base = dest;
+ tags_iovec.iov_len = num_tags;
+
+ Status error = NativeProcessLinux::PtraceWrapper(
+ details->ptrace_read_req, GetID(), reinterpret_cast<void *>(read_addr),
+ static_cast<void *>(&tags_iovec), 0, nullptr);
+
+ if (error.Fail()) {
+ // Discard partial reads
+ tags.resize(0);
+ return error;
+ }
+
+ size_t tags_read = tags_iovec.iov_len;
+ assert(tags_read && (tags_read <= num_tags));
+
+ dest += tags_read * details->manager->GetTagSizeInBytes();
+ read_addr += details->manager->GetGranuleSize() * tags_read;
+ num_tags -= tags_read;
+ }
+
+ return Status();
+}
+
+Status NativeProcessLinux::WriteMemoryTags(int32_t type, lldb::addr_t addr,
+ size_t len,
+ const std::vector<uint8_t> &tags) {
+ llvm::Expected<NativeRegisterContextLinux::MemoryTaggingDetails> details =
+ GetCurrentThread()->GetRegisterContext().GetMemoryTaggingDetails(type);
+ if (!details)
+ return Status(details.takeError());
+
+ // Ignore 0 length write
+ if (!len)
+ return Status();
+
+ // lldb will align the range it requests but it is not required to by
+ // the protocol so we'll do it again just in case.
+ // Remove non address bits too. Ptrace calls may work regardless but that
+ // is not a guarantee.
+ MemoryTagManager::TagRange range(details->manager->RemoveNonAddressBits(addr),
+ len);
+ range = details->manager->ExpandToGranule(range);
+
+ // Not checking number of tags here, we may repeat them below
+ llvm::Expected<std::vector<lldb::addr_t>> unpacked_tags_or_err =
+ details->manager->UnpackTagsData(tags);
+ if (!unpacked_tags_or_err)
+ return Status(unpacked_tags_or_err.takeError());
+
+ llvm::Expected<std::vector<lldb::addr_t>> repeated_tags_or_err =
+ details->manager->RepeatTagsForRange(*unpacked_tags_or_err, range);
+ if (!repeated_tags_or_err)
+ return Status(repeated_tags_or_err.takeError());
+
+ // Repack them for ptrace to use
+ llvm::Expected<std::vector<uint8_t>> final_tag_data =
+ details->manager->PackTags(*repeated_tags_or_err);
+ if (!final_tag_data)
+ return Status(final_tag_data.takeError());
+
+ struct iovec tags_vec;
+ uint8_t *src = final_tag_data->data();
+ lldb::addr_t write_addr = range.GetRangeBase();
+ // unpacked tags size because the number of bytes per tag might not be 1
+ size_t num_tags = repeated_tags_or_err->size();
+
+ // This call can partially write tags, so we loop until we
+ // error or all tags have been written.
+ while (num_tags > 0) {
+ tags_vec.iov_base = src;
+ tags_vec.iov_len = num_tags;
+
+ Status error = NativeProcessLinux::PtraceWrapper(
+ details->ptrace_write_req, GetID(),
+ reinterpret_cast<void *>(write_addr), static_cast<void *>(&tags_vec), 0,
+ nullptr);
+
+ if (error.Fail()) {
+ // Don't attempt to restore the original values in the case of a partial
+ // write
+ return error;
+ }
+
+ size_t tags_written = tags_vec.iov_len;
+ assert(tags_written && (tags_written <= num_tags));
+
+ src += tags_written * details->manager->GetTagSizeInBytes();
+ write_addr += details->manager->GetGranuleSize() * tags_written;
+ num_tags -= tags_written;
+ }
+
+ return Status();
+}
+
size_t NativeProcessLinux::UpdateThreads() {
// The NativeProcessLinux monitoring threads are always up to date with
// respect to thread state and they keep the thread list populated properly.
@@ -1676,12 +1746,33 @@
}
if (found)
- StopTracingForThread(thread_id);
+ NotifyTracersOfThreadDestroyed(thread_id);
+
SignalIfAllThreadsStopped();
return found;
}
-NativeThreadLinux &NativeProcessLinux::AddThread(lldb::tid_t thread_id) {
+Status NativeProcessLinux::NotifyTracersOfNewThread(lldb::tid_t tid) {
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
+ Status error(m_intel_pt_manager.OnThreadCreated(tid));
+ if (error.Fail())
+ LLDB_LOG(log, "Failed to trace a new thread with intel-pt, tid = {0}. {1}",
+ tid, error.AsCString());
+ return error;
+}
+
+Status NativeProcessLinux::NotifyTracersOfThreadDestroyed(lldb::tid_t tid) {
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
+ Status error(m_intel_pt_manager.OnThreadDestroyed(tid));
+ if (error.Fail())
+ LLDB_LOG(log,
+ "Failed to stop a destroyed thread with intel-pt, tid = {0}. {1}",
+ tid, error.AsCString());
+ return error;
+}
+
+NativeThreadLinux &NativeProcessLinux::AddThread(lldb::tid_t thread_id,
+ bool resume) {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id);
@@ -1693,22 +1784,19 @@
SetCurrentThreadID(thread_id);
m_threads.push_back(std::make_unique<NativeThreadLinux>(*this, thread_id));
+ NativeThreadLinux &thread =
+ static_cast<NativeThreadLinux &>(*m_threads.back());
- if (m_pt_proces_trace_id != LLDB_INVALID_UID) {
- auto traceMonitor = ProcessorTraceMonitor::Create(
- GetID(), thread_id, m_pt_process_trace_config, true);
- if (traceMonitor) {
- m_pt_traced_thread_group.insert(thread_id);
- m_processor_trace_monitor.insert(
- std::make_pair(thread_id, std::move(*traceMonitor)));
- } else {
- LLDB_LOG(log, "failed to start trace on thread {0}", thread_id);
- Status error(traceMonitor.takeError());
- LLDB_LOG(log, "error {0}", error);
- }
- }
+ Status tracing_error = NotifyTracersOfNewThread(thread.GetID());
+ if (tracing_error.Fail()) {
+ thread.SetStoppedByProcessorTrace(tracing_error.AsCString());
+ StopRunningThreads(thread.GetID());
+ } else if (resume)
+ ResumeThread(thread, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER);
+ else
+ thread.SetStoppedBySignal(SIGSTOP);
- return static_cast<NativeThreadLinux &>(*m_threads.back());
+ return thread;
}
Status NativeProcessLinux::GetLoadedModuleFileSpec(const char *module_path,
@@ -1926,263 +2014,43 @@
return error;
}
-llvm::Expected<ProcessorTraceMonitor &>
-NativeProcessLinux::LookupProcessorTraceInstance(lldb::user_id_t traceid,
- lldb::tid_t thread) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
- if (thread == LLDB_INVALID_THREAD_ID && traceid == m_pt_proces_trace_id) {
- LLDB_LOG(log, "thread not specified: {0}", traceid);
- return Status("tracing not active thread not specified").ToError();
- }
-
- for (auto& iter : m_processor_trace_monitor) {
- if (traceid == iter.second->GetTraceID() &&
- (thread == iter.first || thread == LLDB_INVALID_THREAD_ID))
- return *(iter.second);
- }
-
- LLDB_LOG(log, "traceid not being traced: {0}", traceid);
- return Status("tracing not active for this thread").ToError();
+llvm::Expected<TraceSupportedResponse> NativeProcessLinux::TraceSupported() {
+ if (IntelPTManager::IsSupported())
+ return TraceSupportedResponse{"intel-pt", "Intel Processor Trace"};
+ return NativeProcessProtocol::TraceSupported();
}
-Status NativeProcessLinux::GetMetaData(lldb::user_id_t traceid,
- lldb::tid_t thread,
- llvm::MutableArrayRef<uint8_t> &buffer,
- size_t offset) {
- TraceOptions trace_options;
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
- Status error;
-
- LLDB_LOG(log, "traceid {0}", traceid);
-
- auto perf_monitor = LookupProcessorTraceInstance(traceid, thread);
- if (!perf_monitor) {
- LLDB_LOG(log, "traceid not being traced: {0}", traceid);
- buffer = buffer.slice(buffer.size());
- error = perf_monitor.takeError();
- return error;
+Error NativeProcessLinux::TraceStart(StringRef json_request, StringRef type) {
+ if (type == "intel-pt") {
+ if (Expected<TraceIntelPTStartRequest> request =
+ json::parse<TraceIntelPTStartRequest>(json_request,
+ "TraceIntelPTStartRequest")) {
+ std::vector<lldb::tid_t> process_threads;
+ for (auto &thread : m_threads)
+ process_threads.push_back(thread->GetID());
+ return m_intel_pt_manager.TraceStart(*request, process_threads);
+ } else
+ return request.takeError();
}
- return (*perf_monitor).ReadPerfTraceData(buffer, offset);
+
+ return NativeProcessProtocol::TraceStart(json_request, type);
}
-Status NativeProcessLinux::GetData(lldb::user_id_t traceid, lldb::tid_t thread,
- llvm::MutableArrayRef<uint8_t> &buffer,
- size_t offset) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
- Status error;
-
- LLDB_LOG(log, "traceid {0}", traceid);
-
- auto perf_monitor = LookupProcessorTraceInstance(traceid, thread);
- if (!perf_monitor) {
- LLDB_LOG(log, "traceid not being traced: {0}", traceid);
- buffer = buffer.slice(buffer.size());
- error = perf_monitor.takeError();
- return error;
- }
- return (*perf_monitor).ReadPerfTraceAux(buffer, offset);
+Error NativeProcessLinux::TraceStop(const TraceStopRequest &request) {
+ if (request.type == "intel-pt")
+ return m_intel_pt_manager.TraceStop(request);
+ return NativeProcessProtocol::TraceStop(request);
}
-Status NativeProcessLinux::GetTraceConfig(lldb::user_id_t traceid,
- TraceOptions &config) {
- Status error;
- if (config.getThreadID() == LLDB_INVALID_THREAD_ID &&
- m_pt_proces_trace_id == traceid) {
- if (m_pt_proces_trace_id == LLDB_INVALID_UID) {
- error.SetErrorString("tracing not active for this process");
- return error;
- }
- config = m_pt_process_trace_config;
- } else {
- auto perf_monitor =
- LookupProcessorTraceInstance(traceid, config.getThreadID());
- if (!perf_monitor) {
- error = perf_monitor.takeError();
- return error;
- }
- error = (*perf_monitor).GetTraceConfig(config);
- }
- return error;
+Expected<json::Value> NativeProcessLinux::TraceGetState(StringRef type) {
+ if (type == "intel-pt")
+ return m_intel_pt_manager.GetState();
+ return NativeProcessProtocol::TraceGetState(type);
}
-llvm::Expected<TraceTypeInfo> NativeProcessLinux::GetSupportedTraceType() {
- if (ProcessorTraceMonitor::IsSupported())
- return TraceTypeInfo{"intel-pt", "Intel Processor Trace"};
- return NativeProcessProtocol::GetSupportedTraceType();
-}
-
-lldb::user_id_t
-NativeProcessLinux::StartTraceGroup(const TraceOptions &config,
- Status &error) {
-
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
- if (config.getType() != TraceType::eTraceTypeProcessorTrace)
- return LLDB_INVALID_UID;
-
- if (m_pt_proces_trace_id != LLDB_INVALID_UID) {
- error.SetErrorString("tracing already active on this process");
- return m_pt_proces_trace_id;
- }
-
- for (const auto &thread_sp : m_threads) {
- if (auto traceInstance = ProcessorTraceMonitor::Create(
- GetID(), thread_sp->GetID(), config, true)) {
- m_pt_traced_thread_group.insert(thread_sp->GetID());
- m_processor_trace_monitor.insert(
- std::make_pair(thread_sp->GetID(), std::move(*traceInstance)));
- }
- }
-
- m_pt_process_trace_config = config;
- error = ProcessorTraceMonitor::GetCPUType(m_pt_process_trace_config);
-
- // Trace on Complete process will have traceid of 0
- m_pt_proces_trace_id = 0;
-
- LLDB_LOG(log, "Process Trace ID {0}", m_pt_proces_trace_id);
- return m_pt_proces_trace_id;
-}
-
-lldb::user_id_t NativeProcessLinux::StartTrace(const TraceOptions &config,
- Status &error) {
- if (config.getType() != TraceType::eTraceTypeProcessorTrace)
- return NativeProcessProtocol::StartTrace(config, error);
-
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
-
- lldb::tid_t threadid = config.getThreadID();
-
- if (threadid == LLDB_INVALID_THREAD_ID)
- return StartTraceGroup(config, error);
-
- auto thread_sp = GetThreadByID(threadid);
- if (!thread_sp) {
- // Thread not tracked by lldb so don't trace.
- error.SetErrorString("invalid thread id");
- return LLDB_INVALID_UID;
- }
-
- const auto &iter = m_processor_trace_monitor.find(threadid);
- if (iter != m_processor_trace_monitor.end()) {
- LLDB_LOG(log, "Thread already being traced");
- error.SetErrorString("tracing already active on this thread");
- return LLDB_INVALID_UID;
- }
-
- auto traceMonitor =
- ProcessorTraceMonitor::Create(GetID(), threadid, config, false);
- if (!traceMonitor) {
- error = traceMonitor.takeError();
- LLDB_LOG(log, "error {0}", error);
- return LLDB_INVALID_UID;
- }
- lldb::user_id_t ret_trace_id = (*traceMonitor)->GetTraceID();
- m_processor_trace_monitor.insert(
- std::make_pair(threadid, std::move(*traceMonitor)));
- return ret_trace_id;
-}
-
-Status NativeProcessLinux::StopTracingForThread(lldb::tid_t thread) {
- Status error;
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
- LLDB_LOG(log, "Thread {0}", thread);
-
- const auto& iter = m_processor_trace_monitor.find(thread);
- if (iter == m_processor_trace_monitor.end()) {
- error.SetErrorString("tracing not active for this thread");
- return error;
- }
-
- if (iter->second->GetTraceID() == m_pt_proces_trace_id) {
- // traceid maps to the whole process so we have to erase it from the thread
- // group.
- LLDB_LOG(log, "traceid maps to process");
- m_pt_traced_thread_group.erase(thread);
- }
- m_processor_trace_monitor.erase(iter);
-
- return error;
-}
-
-Status NativeProcessLinux::StopTrace(lldb::user_id_t traceid,
- lldb::tid_t thread) {
- Status error;
-
- TraceOptions trace_options;
- trace_options.setThreadID(thread);
- error = NativeProcessLinux::GetTraceConfig(traceid, trace_options);
-
- if (error.Fail())
- return error;
-
- switch (trace_options.getType()) {
- case lldb::TraceType::eTraceTypeProcessorTrace:
- if (traceid == m_pt_proces_trace_id &&
- thread == LLDB_INVALID_THREAD_ID)
- StopProcessorTracingOnProcess();
- else
- error = StopProcessorTracingOnThread(traceid, thread);
- break;
- default:
- error.SetErrorString("trace not supported");
- break;
- }
-
- return error;
-}
-
-void NativeProcessLinux::StopProcessorTracingOnProcess() {
- for (auto thread_id_iter : m_pt_traced_thread_group)
- m_processor_trace_monitor.erase(thread_id_iter);
- m_pt_traced_thread_group.clear();
- m_pt_proces_trace_id = LLDB_INVALID_UID;
-}
-
-Status NativeProcessLinux::StopProcessorTracingOnThread(lldb::user_id_t traceid,
- lldb::tid_t thread) {
- Status error;
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
-
- if (thread == LLDB_INVALID_THREAD_ID) {
- for (auto& iter : m_processor_trace_monitor) {
- if (iter.second->GetTraceID() == traceid) {
- // Stopping a trace instance for an individual thread hence there will
- // only be one traceid that can match.
- m_processor_trace_monitor.erase(iter.first);
- return error;
- }
- LLDB_LOG(log, "Trace ID {0}", iter.second->GetTraceID());
- }
-
- LLDB_LOG(log, "Invalid TraceID");
- error.SetErrorString("invalid trace id");
- return error;
- }
-
- // thread is specified so we can use find function on the map.
- const auto& iter = m_processor_trace_monitor.find(thread);
- if (iter == m_processor_trace_monitor.end()) {
- // thread not found in our map.
- LLDB_LOG(log, "thread not being traced");
- error.SetErrorString("tracing not active for this thread");
- return error;
- }
- if (iter->second->GetTraceID() != traceid) {
- // traceid did not match so it has to be invalid.
- LLDB_LOG(log, "Invalid TraceID");
- error.SetErrorString("invalid trace id");
- return error;
- }
-
- LLDB_LOG(log, "UID - {0} , Thread -{1}", traceid, thread);
-
- if (traceid == m_pt_proces_trace_id) {
- // traceid maps to the whole process so we have to erase it from the thread
- // group.
- LLDB_LOG(log, "traceid maps to process");
- m_pt_traced_thread_group.erase(thread);
- }
- m_processor_trace_monitor.erase(iter);
-
- return error;
+Expected<std::vector<uint8_t>> NativeProcessLinux::TraceGetBinaryData(
+ const TraceGetBinaryDataRequest &request) {
+ if (request.type == "intel-pt")
+ return m_intel_pt_manager.GetBinaryData(request);
+ return NativeProcessProtocol::TraceGetBinaryData(request);
}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h b/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h
index b7d70a6..902afb6 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h
@@ -20,9 +20,10 @@
#include "lldb/Utility/FileSpec.h"
#include "lldb/lldb-types.h"
+#include "IntelPTManager.h"
#include "NativeThreadLinux.h"
#include "Plugins/Process/POSIX/NativeProcessELF.h"
-#include "ProcessorTrace.h"
+#include "Plugins/Process/Utility/NativeProcessSoftwareSingleStep.h"
namespace lldb_private {
class Status;
@@ -36,7 +37,8 @@
/// for debugging.
///
/// Changes in the inferior process state are broadcasted.
-class NativeProcessLinux : public NativeProcessELF {
+class NativeProcessLinux : public NativeProcessELF,
+ private NativeProcessSoftwareSingleStep {
public:
class Factory : public NativeProcessProtocol::Factory {
public:
@@ -47,6 +49,8 @@
llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Attach(lldb::pid_t pid, NativeDelegate &native_delegate,
MainLoop &mainloop) const override;
+
+ Extension GetSupportedExtensions() const override;
};
// NativeProcessProtocol Interface
@@ -76,6 +80,12 @@
llvm::Error DeallocateMemory(lldb::addr_t addr) override;
+ Status ReadMemoryTags(int32_t type, lldb::addr_t addr, size_t len,
+ std::vector<uint8_t> &tags) override;
+
+ Status WriteMemoryTags(int32_t type, lldb::addr_t addr, size_t len,
+ const std::vector<uint8_t> &tags) override;
+
size_t UpdateThreads() override;
const ArchSpec &GetArchitecture() const override { return m_arch; }
@@ -101,23 +111,22 @@
return getProcFile(GetID(), "auxv");
}
- lldb::user_id_t StartTrace(const TraceOptions &config,
- Status &error) override;
+ /// Tracing
+ /// These methods implement the jLLDBTrace packets
+ /// \{
+ llvm::Error TraceStart(llvm::StringRef json_request,
+ llvm::StringRef type) override;
- Status StopTrace(lldb::user_id_t traceid,
- lldb::tid_t thread) override;
+ llvm::Error TraceStop(const TraceStopRequest &request) override;
- Status GetData(lldb::user_id_t traceid, lldb::tid_t thread,
- llvm::MutableArrayRef<uint8_t> &buffer,
- size_t offset = 0) override;
+ llvm::Expected<llvm::json::Value>
+ TraceGetState(llvm::StringRef type) override;
- Status GetMetaData(lldb::user_id_t traceid, lldb::tid_t thread,
- llvm::MutableArrayRef<uint8_t> &buffer,
- size_t offset = 0) override;
+ llvm::Expected<std::vector<uint8_t>>
+ TraceGetBinaryData(const TraceGetBinaryDataRequest &request) override;
- Status GetTraceConfig(lldb::user_id_t traceid, TraceOptions &config) override;
-
- virtual llvm::Expected<TraceTypeInfo> GetSupportedTraceType() override;
+ llvm::Expected<TraceSupportedResponse> TraceSupported() override;
+ /// }
// Interface used by NativeRegisterContext-derived classes.
static Status PtraceWrapper(int req, lldb::pid_t pid, void *addr = nullptr,
@@ -135,16 +144,13 @@
private:
MainLoop::SignalHandleUP m_sigchld_handle;
ArchSpec m_arch;
+ MainLoop& m_main_loop;
LazyBool m_supports_mem_region = eLazyBoolCalculate;
std::vector<std::pair<MemoryRegionInfo, FileSpec>> m_mem_region_cache;
lldb::tid_t m_pending_notification_tid = LLDB_INVALID_THREAD_ID;
- // List of thread ids stepping with a breakpoint with the address of
- // the relevan breakpoint
- std::map<lldb::tid_t, lldb::addr_t> m_threads_stepping_with_breakpoint;
-
/// Inferior memory (allocated by us) and its size.
llvm::DenseMap<lldb::addr_t, lldb::addr_t> m_allocated_memory;
@@ -160,7 +166,7 @@
void MonitorCallback(lldb::pid_t pid, bool exited, WaitStatus status);
- void WaitForNewThread(::pid_t tid);
+ void WaitForCloneNotification(::pid_t pid);
void MonitorSIGTRAP(const siginfo_t &info, NativeThreadLinux &thread);
@@ -173,13 +179,32 @@
void MonitorSignal(const siginfo_t &info, NativeThreadLinux &thread,
bool exited);
- Status SetupSoftwareSingleStepping(NativeThreadLinux &thread);
-
bool HasThreadNoLock(lldb::tid_t thread_id);
bool StopTrackingThread(lldb::tid_t thread_id);
- NativeThreadLinux &AddThread(lldb::tid_t thread_id);
+ /// Create a new thread.
+ ///
+ /// If process tracing is enabled and the thread can't be traced, then the
+ /// thread is left stopped with a \a eStopReasonProcessorTrace status, and
+ /// then the process is stopped.
+ ///
+ /// \param[in] resume
+ /// If a tracing error didn't happen, then resume the thread after
+ /// creation if \b true, or leave it stopped with SIGSTOP if \b false.
+ NativeThreadLinux &AddThread(lldb::tid_t thread_id, bool resume);
+
+ /// Start tracing a new thread if process tracing is enabled.
+ ///
+ /// Trace mechanisms should modify this method to provide automatic tracing
+ /// for new threads.
+ Status NotifyTracersOfNewThread(lldb::tid_t tid);
+
+ /// Stop tracing threads upon a destroy event.
+ ///
+ /// Trace mechanisms should modify this method to provide automatic trace
+ /// stopping for threads being destroyed.
+ Status NotifyTracersOfThreadDestroyed(lldb::tid_t tid);
/// Writes a siginfo_t structure corresponding to the given thread ID to the
/// memory region pointed to by \p siginfo.
@@ -216,42 +241,23 @@
Status PopulateMemoryRegionCache();
- lldb::user_id_t StartTraceGroup(const TraceOptions &config,
- Status &error);
+ /// Manages Intel PT process and thread traces.
+ IntelPTManager m_intel_pt_manager;
- // This function is intended to be used to stop tracing
- // on a thread that exited.
- Status StopTracingForThread(lldb::tid_t thread);
+ struct CloneInfo {
+ int event;
+ lldb::tid_t parent_tid;
+ };
- // The below function as the name suggests, looks up a ProcessorTrace
- // instance from the m_processor_trace_monitor map. In the case of
- // process tracing where the traceid passed would map to the complete
- // process, it is mandatory to provide a threadid to obtain a trace
- // instance (since ProcessorTrace is tied to a thread). In the other
- // scenario that an individual thread is being traced, just the traceid
- // is sufficient to obtain the actual ProcessorTrace instance.
- llvm::Expected<ProcessorTraceMonitor &>
- LookupProcessorTraceInstance(lldb::user_id_t traceid, lldb::tid_t thread);
+ // Map of child processes that have been signaled once, and we are
+ // waiting for the second signal.
+ llvm::DenseMap<lldb::pid_t, llvm::Optional<CloneInfo>> m_pending_pid_map;
- // Stops tracing on individual threads being traced. Not intended
- // to be used to stop tracing on complete process.
- Status StopProcessorTracingOnThread(lldb::user_id_t traceid,
- lldb::tid_t thread);
-
- // Intended to stop tracing on complete process.
- // Should not be used for stopping trace on
- // individual threads.
- void StopProcessorTracingOnProcess();
-
- llvm::DenseMap<lldb::tid_t, ProcessorTraceMonitorUP>
- m_processor_trace_monitor;
-
- // Set for tracking threads being traced under
- // same process user id.
- llvm::DenseSet<lldb::tid_t> m_pt_traced_thread_group;
-
- lldb::user_id_t m_pt_proces_trace_id = LLDB_INVALID_UID;
- TraceOptions m_pt_process_trace_config;
+ // Handle a clone()-like event. If received by parent, clone_info contains
+ // additional info. Returns true if the event is handled, or false if it
+ // is pending second notification.
+ bool MonitorClone(lldb::pid_t child_pid,
+ llvm::Optional<CloneInfo> clone_info);
};
} // namespace process_linux
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.h b/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.h
index fa067b7..b66f690 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.h
@@ -11,10 +11,14 @@
#include "Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h"
#include "lldb/Host/common/NativeThreadProtocol.h"
+#include "lldb/Target/MemoryTagManager.h"
+#include "llvm/Support/Error.h"
namespace lldb_private {
namespace process_linux {
+class NativeThreadLinux;
+
class NativeRegisterContextLinux
: public virtual NativeRegisterContextRegisterInfo {
public:
@@ -24,7 +28,7 @@
// variant should be compiled into the final executable.
static std::unique_ptr<NativeRegisterContextLinux>
CreateHostNativeRegisterContextLinux(const ArchSpec &target_arch,
- NativeThreadProtocol &native_thread);
+ NativeThreadLinux &native_thread);
// Invalidates cached values in register context data structures
virtual void InvalidateAllRegisters(){}
@@ -55,7 +59,29 @@
/// they are supported.
virtual llvm::Optional<MmapData> GetMmapData() { return llvm::None; }
+ struct MemoryTaggingDetails {
+ /// Object with tag handling utilities. If the function below returns
+ /// a valid structure, you can assume that this pointer is valid.
+ std::unique_ptr<MemoryTagManager> manager;
+ int ptrace_read_req; /// ptrace operation number for memory tag read
+ int ptrace_write_req; /// ptrace operation number for memory tag write
+ };
+ /// Return architecture specific data needed to use memory tags,
+ /// if they are supported.
+ virtual llvm::Expected<MemoryTaggingDetails>
+ GetMemoryTaggingDetails(int32_t type) {
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "Architecture does not support memory tagging");
+ }
+
protected:
+ // NB: This constructor is here only because gcc<=6.5 requires a virtual base
+ // class initializer on abstract class (even though it is never used). It can
+ // be deleted once we move to gcc>=7.0.
+ NativeRegisterContextLinux(NativeThreadProtocol &thread)
+ : NativeRegisterContextRegisterInfo(thread, nullptr) {}
+
lldb::ByteOrder GetByteOrder() const;
virtual Status ReadRegisterRaw(uint32_t reg_index, RegisterValue ®_value);
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp b/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
index e15e0f8..91f8828 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
@@ -47,7 +47,7 @@
std::unique_ptr<NativeRegisterContextLinux>
NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
- const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
+ const ArchSpec &target_arch, NativeThreadLinux &native_thread) {
return std::make_unique<NativeRegisterContextLinux_arm>(target_arch,
native_thread);
}
@@ -56,8 +56,9 @@
NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm(
const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
- : NativeRegisterContextRegisterInfo(
- native_thread, new RegisterInfoPOSIX_arm(target_arch)) {
+ : NativeRegisterContextRegisterInfo(native_thread,
+ new RegisterInfoPOSIX_arm(target_arch)),
+ NativeRegisterContextLinux(native_thread) {
assert(target_arch.GetMachine() == llvm::Triple::arm);
::memset(&m_fpr, 0, sizeof(m_fpr));
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
index c34afe6..34a520e 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
@@ -13,6 +13,7 @@
#include "lldb/Host/common/NativeProcessProtocol.h"
+#include "lldb/Host/linux/Ptrace.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegisterValue.h"
@@ -21,6 +22,7 @@
#include "Plugins/Process/Linux/NativeProcessLinux.h"
#include "Plugins/Process/Linux/Procfs.h"
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
+#include "Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h"
#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
// System includes - They have to be included after framework includes because
@@ -33,6 +35,17 @@
#define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension */
#endif
+#ifndef NT_ARM_PAC_MASK
+#define NT_ARM_PAC_MASK 0x406 /* Pointer authentication code masks */
+#endif
+
+#ifndef NT_ARM_TAGGED_ADDR_CTRL
+#define NT_ARM_TAGGED_ADDR_CTRL 0x409 /* Tagged address control register */
+#endif
+
+#define HWCAP_PACA (1 << 30)
+#define HWCAP2_MTE (1 << 18)
+
#define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize())
using namespace lldb;
@@ -41,28 +54,63 @@
std::unique_ptr<NativeRegisterContextLinux>
NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
- const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
+ const ArchSpec &target_arch, NativeThreadLinux &native_thread) {
switch (target_arch.GetMachine()) {
case llvm::Triple::arm:
return std::make_unique<NativeRegisterContextLinux_arm>(target_arch,
- native_thread);
- case llvm::Triple::aarch64:
- return std::make_unique<NativeRegisterContextLinux_arm64>(target_arch,
- native_thread);
+ native_thread);
+ case llvm::Triple::aarch64: {
+ // Configure register sets supported by this AArch64 target.
+ // Read SVE header to check for SVE support.
+ struct user_sve_header sve_header;
+ struct iovec ioVec;
+ ioVec.iov_base = &sve_header;
+ ioVec.iov_len = sizeof(sve_header);
+ unsigned int regset = NT_ARM_SVE;
+
+ Flags opt_regsets;
+ if (NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET,
+ native_thread.GetID(), ®set,
+ &ioVec, sizeof(sve_header))
+ .Success())
+ opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskSVE);
+
+ NativeProcessLinux &process = native_thread.GetProcess();
+
+ llvm::Optional<uint64_t> auxv_at_hwcap =
+ process.GetAuxValue(AuxVector::AUXV_AT_HWCAP);
+ if (auxv_at_hwcap && (*auxv_at_hwcap & HWCAP_PACA))
+ opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskPAuth);
+
+ llvm::Optional<uint64_t> auxv_at_hwcap2 =
+ process.GetAuxValue(AuxVector::AUXV_AT_HWCAP2);
+ if (auxv_at_hwcap2 && (*auxv_at_hwcap2 & HWCAP2_MTE))
+ opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskMTE);
+
+ auto register_info_up =
+ std::make_unique<RegisterInfoPOSIX_arm64>(target_arch, opt_regsets);
+ return std::make_unique<NativeRegisterContextLinux_arm64>(
+ target_arch, native_thread, std::move(register_info_up));
+ }
default:
llvm_unreachable("have no register context for architecture");
}
}
NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(
- const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
- : NativeRegisterContextRegisterInfo(
- native_thread, new RegisterInfoPOSIX_arm64(target_arch)) {
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread,
+ std::unique_ptr<RegisterInfoPOSIX_arm64> register_info_up)
+ : NativeRegisterContextRegisterInfo(native_thread,
+ register_info_up.release()),
+ NativeRegisterContextLinux(native_thread) {
::memset(&m_fpr, 0, sizeof(m_fpr));
::memset(&m_gpr_arm64, 0, sizeof(m_gpr_arm64));
::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs));
- ::memset(&m_hbr_regs, 0, sizeof(m_hbr_regs));
+ ::memset(&m_hbp_regs, 0, sizeof(m_hbp_regs));
::memset(&m_sve_header, 0, sizeof(m_sve_header));
+ ::memset(&m_pac_mask, 0, sizeof(m_pac_mask));
+
+ m_mte_ctrl_reg = 0;
// 16 is just a maximum value, query hardware for actual watchpoint count
m_max_hwp_supported = 16;
@@ -74,9 +122,13 @@
m_fpu_is_valid = false;
m_sve_buffer_is_valid = false;
m_sve_header_is_valid = false;
+ m_pac_mask_is_valid = false;
+ m_mte_ctrl_is_valid = false;
- // SVE is not enabled until we query user_sve_header
- m_sve_state = SVEState::Unknown;
+ if (GetRegisterInfo().IsSVEEnabled())
+ m_sve_state = SVEState::Unknown;
+ else
+ m_sve_state = SVEState::Disabled;
}
RegisterInfoPOSIX_arm64 &
@@ -155,15 +207,15 @@
if (reg == GetRegisterInfo().GetRegNumFPSR()) {
sve_reg_num = reg;
if (m_sve_state == SVEState::Full)
- offset = SVE_PT_SVE_FPSR_OFFSET(sve_vq_from_vl(m_sve_header.vl));
+ offset = sve::PTraceFPSROffset(sve::vq_from_vl(m_sve_header.vl));
else if (m_sve_state == SVEState::FPSIMD)
- offset = SVE_PT_FPSIMD_OFFSET + (32 * 16);
+ offset = sve::ptrace_fpsimd_offset + (32 * 16);
} else if (reg == GetRegisterInfo().GetRegNumFPCR()) {
sve_reg_num = reg;
if (m_sve_state == SVEState::Full)
- offset = SVE_PT_SVE_FPCR_OFFSET(sve_vq_from_vl(m_sve_header.vl));
+ offset = sve::PTraceFPCROffset(sve::vq_from_vl(m_sve_header.vl));
else if (m_sve_state == SVEState::FPSIMD)
- offset = SVE_PT_FPSIMD_OFFSET + (32 * 16) + 4;
+ offset = sve::ptrace_fpsimd_offset + (32 * 16) + 4;
} else {
// Extract SVE Z register value register number for this reg_info
if (reg_info->value_regs &&
@@ -208,6 +260,22 @@
src = (uint8_t *)GetSVEBuffer() + offset;
}
}
+ } else if (IsPAuth(reg)) {
+ error = ReadPAuthMask();
+ if (error.Fail())
+ return error;
+
+ offset = reg_info->byte_offset - GetRegisterInfo().GetPAuthOffset();
+ assert(offset < GetPACMaskSize());
+ src = (uint8_t *)GetPACMask() + offset;
+ } else if (IsMTE(reg)) {
+ error = ReadMTEControl();
+ if (error.Fail())
+ return error;
+
+ offset = reg_info->byte_offset - GetRegisterInfo().GetMTEOffset();
+ assert(offset < GetMTEControlSize());
+ src = (uint8_t *)GetMTEControl() + offset;
} else
return Status("failed - register wasn't recognized to be a GPR or an FPR, "
"write strategy unknown");
@@ -273,15 +341,15 @@
if (reg == GetRegisterInfo().GetRegNumFPSR()) {
sve_reg_num = reg;
if (m_sve_state == SVEState::Full)
- offset = SVE_PT_SVE_FPSR_OFFSET(sve_vq_from_vl(m_sve_header.vl));
+ offset = sve::PTraceFPSROffset(sve::vq_from_vl(m_sve_header.vl));
else if (m_sve_state == SVEState::FPSIMD)
- offset = SVE_PT_FPSIMD_OFFSET + (32 * 16);
+ offset = sve::ptrace_fpsimd_offset + (32 * 16);
} else if (reg == GetRegisterInfo().GetRegNumFPCR()) {
sve_reg_num = reg;
if (m_sve_state == SVEState::Full)
- offset = SVE_PT_SVE_FPCR_OFFSET(sve_vq_from_vl(m_sve_header.vl));
+ offset = sve::PTraceFPCROffset(sve::vq_from_vl(m_sve_header.vl));
else if (m_sve_state == SVEState::FPSIMD)
- offset = SVE_PT_FPSIMD_OFFSET + (32 * 16) + 4;
+ offset = sve::ptrace_fpsimd_offset + (32 * 16) + 4;
} else {
// Extract SVE Z register value register number for this reg_info
if (reg_info->value_regs &&
@@ -366,6 +434,17 @@
return WriteAllSVE();
}
}
+ } else if (IsMTE(reg)) {
+ error = ReadMTEControl();
+ if (error.Fail())
+ return error;
+
+ offset = reg_info->byte_offset - GetRegisterInfo().GetMTEOffset();
+ assert(offset < GetMTEControlSize());
+ dst = (uint8_t *)GetMTEControl() + offset;
+ ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
+
+ return WriteMTEControl();
}
return Status("Failed to write register value");
@@ -451,436 +530,20 @@
}
bool NativeRegisterContextLinux_arm64::IsSVE(unsigned reg) const {
- if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
- RegisterInfoPOSIX_arm64::SVERegSet)
- return true;
- return false;
+ return GetRegisterInfo().IsSVEReg(reg);
}
-uint32_t NativeRegisterContextLinux_arm64::NumSupportedHardwareBreakpoints() {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS));
-
- LLDB_LOGF(log, "NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
-
- Status error;
-
- // Read hardware breakpoint and watchpoint information.
- error = ReadHardwareDebugInfo();
-
- if (error.Fail())
- return 0;
-
- return m_max_hbp_supported;
+bool NativeRegisterContextLinux_arm64::IsPAuth(unsigned reg) const {
+ return GetRegisterInfo().IsPAuthReg(reg);
}
-uint32_t
-NativeRegisterContextLinux_arm64::SetHardwareBreakpoint(lldb::addr_t addr,
- size_t size) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS));
- LLDB_LOG(log, "addr: {0:x}, size: {1:x}", addr, size);
-
- // Read hardware breakpoint and watchpoint information.
- Status error = ReadHardwareDebugInfo();
-
- if (error.Fail())
- return LLDB_INVALID_INDEX32;
-
- uint32_t control_value = 0, bp_index = 0;
-
- // Check if size has a valid hardware breakpoint length.
- if (size != 4)
- return LLDB_INVALID_INDEX32; // Invalid size for a AArch64 hardware
- // breakpoint
-
- // Check 4-byte alignment for hardware breakpoint target address.
- if (addr & 0x03)
- return LLDB_INVALID_INDEX32; // Invalid address, should be 4-byte aligned.
-
- // Setup control value
- control_value = 0;
- control_value |= ((1 << size) - 1) << 5;
- control_value |= (2 << 1) | 1;
-
- // Iterate over stored breakpoints and find a free bp_index
- bp_index = LLDB_INVALID_INDEX32;
- for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
- if ((m_hbr_regs[i].control & 1) == 0) {
- bp_index = i; // Mark last free slot
- } else if (m_hbr_regs[i].address == addr) {
- return LLDB_INVALID_INDEX32; // We do not support duplicate breakpoints.
- }
- }
-
- if (bp_index == LLDB_INVALID_INDEX32)
- return LLDB_INVALID_INDEX32;
-
- // Update breakpoint in local cache
- m_hbr_regs[bp_index].real_addr = addr;
- m_hbr_regs[bp_index].address = addr;
- m_hbr_regs[bp_index].control = control_value;
-
- // PTRACE call to set corresponding hardware breakpoint register.
- error = WriteHardwareDebugRegs(eDREGTypeBREAK);
-
- if (error.Fail()) {
- m_hbr_regs[bp_index].address = 0;
- m_hbr_regs[bp_index].control &= ~1;
-
- return LLDB_INVALID_INDEX32;
- }
-
- return bp_index;
+bool NativeRegisterContextLinux_arm64::IsMTE(unsigned reg) const {
+ return GetRegisterInfo().IsMTEReg(reg);
}
-bool NativeRegisterContextLinux_arm64::ClearHardwareBreakpoint(
- uint32_t hw_idx) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS));
- LLDB_LOG(log, "hw_idx: {0}", hw_idx);
-
- // Read hardware breakpoint and watchpoint information.
- Status error = ReadHardwareDebugInfo();
-
- if (error.Fail())
- return false;
-
- if (hw_idx >= m_max_hbp_supported)
- return false;
-
- // Create a backup we can revert to in case of failure.
- lldb::addr_t tempAddr = m_hbr_regs[hw_idx].address;
- uint32_t tempControl = m_hbr_regs[hw_idx].control;
-
- m_hbr_regs[hw_idx].control &= ~1;
- m_hbr_regs[hw_idx].address = 0;
-
- // PTRACE call to clear corresponding hardware breakpoint register.
- error = WriteHardwareDebugRegs(eDREGTypeBREAK);
-
- if (error.Fail()) {
- m_hbr_regs[hw_idx].control = tempControl;
- m_hbr_regs[hw_idx].address = tempAddr;
-
- return false;
- }
-
- return true;
-}
-
-Status NativeRegisterContextLinux_arm64::GetHardwareBreakHitIndex(
- uint32_t &bp_index, lldb::addr_t trap_addr) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS));
-
- LLDB_LOGF(log, "NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
-
- lldb::addr_t break_addr;
-
- for (bp_index = 0; bp_index < m_max_hbp_supported; ++bp_index) {
- break_addr = m_hbr_regs[bp_index].address;
-
- if ((m_hbr_regs[bp_index].control & 0x1) && (trap_addr == break_addr)) {
- m_hbr_regs[bp_index].hit_addr = trap_addr;
- return Status();
- }
- }
-
- bp_index = LLDB_INVALID_INDEX32;
- return Status();
-}
-
-Status NativeRegisterContextLinux_arm64::ClearAllHardwareBreakpoints() {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS));
-
- LLDB_LOGF(log, "NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
-
- Status error;
-
- // Read hardware breakpoint and watchpoint information.
- error = ReadHardwareDebugInfo();
-
- if (error.Fail())
- return error;
-
- lldb::addr_t tempAddr = 0;
- uint32_t tempControl = 0;
-
- for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
- if (m_hbr_regs[i].control & 0x01) {
- // Create a backup we can revert to in case of failure.
- tempAddr = m_hbr_regs[i].address;
- tempControl = m_hbr_regs[i].control;
-
- // Clear watchpoints in local cache
- m_hbr_regs[i].control &= ~1;
- m_hbr_regs[i].address = 0;
-
- // Ptrace call to update hardware debug registers
- error = WriteHardwareDebugRegs(eDREGTypeBREAK);
-
- if (error.Fail()) {
- m_hbr_regs[i].control = tempControl;
- m_hbr_regs[i].address = tempAddr;
-
- return error;
- }
- }
- }
-
- return Status();
-}
-
-uint32_t NativeRegisterContextLinux_arm64::NumSupportedHardwareWatchpoints() {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
-
- // Read hardware breakpoint and watchpoint information.
- Status error = ReadHardwareDebugInfo();
-
- if (error.Fail())
- return 0;
-
- LLDB_LOG(log, "{0}", m_max_hwp_supported);
- return m_max_hwp_supported;
-}
-
-uint32_t NativeRegisterContextLinux_arm64::SetHardwareWatchpoint(
- lldb::addr_t addr, size_t size, uint32_t watch_flags) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
- LLDB_LOG(log, "addr: {0:x}, size: {1:x} watch_flags: {2:x}", addr, size,
- watch_flags);
-
- // Read hardware breakpoint and watchpoint information.
- Status error = ReadHardwareDebugInfo();
-
- if (error.Fail())
- return LLDB_INVALID_INDEX32;
-
- uint32_t control_value = 0, wp_index = 0;
- lldb::addr_t real_addr = addr;
-
- // Check if we are setting watchpoint other than read/write/access Also
- // update watchpoint flag to match AArch64 write-read bit configuration.
- switch (watch_flags) {
- case 1:
- watch_flags = 2;
- break;
- case 2:
- watch_flags = 1;
- break;
- case 3:
- break;
- default:
- return LLDB_INVALID_INDEX32;
- }
-
- // Check if size has a valid hardware watchpoint length.
- if (size != 1 && size != 2 && size != 4 && size != 8)
- return LLDB_INVALID_INDEX32;
-
- // Check 8-byte alignment for hardware watchpoint target address. Below is a
- // hack to recalculate address and size in order to make sure we can watch
- // non 8-byte aligned addresses as well.
- if (addr & 0x07) {
- uint8_t watch_mask = (addr & 0x07) + size;
-
- if (watch_mask > 0x08)
- return LLDB_INVALID_INDEX32;
- else if (watch_mask <= 0x02)
- size = 2;
- else if (watch_mask <= 0x04)
- size = 4;
- else
- size = 8;
-
- addr = addr & (~0x07);
- }
-
- // Setup control value
- control_value = watch_flags << 3;
- control_value |= ((1 << size) - 1) << 5;
- control_value |= (2 << 1) | 1;
-
- // Iterate over stored watchpoints and find a free wp_index
- wp_index = LLDB_INVALID_INDEX32;
- for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
- if ((m_hwp_regs[i].control & 1) == 0) {
- wp_index = i; // Mark last free slot
- } else if (m_hwp_regs[i].address == addr) {
- return LLDB_INVALID_INDEX32; // We do not support duplicate watchpoints.
- }
- }
-
- if (wp_index == LLDB_INVALID_INDEX32)
- return LLDB_INVALID_INDEX32;
-
- // Update watchpoint in local cache
- m_hwp_regs[wp_index].real_addr = real_addr;
- m_hwp_regs[wp_index].address = addr;
- m_hwp_regs[wp_index].control = control_value;
-
- // PTRACE call to set corresponding watchpoint register.
- error = WriteHardwareDebugRegs(eDREGTypeWATCH);
-
- if (error.Fail()) {
- m_hwp_regs[wp_index].address = 0;
- m_hwp_regs[wp_index].control &= ~1;
-
- return LLDB_INVALID_INDEX32;
- }
-
- return wp_index;
-}
-
-bool NativeRegisterContextLinux_arm64::ClearHardwareWatchpoint(
- uint32_t wp_index) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
- LLDB_LOG(log, "wp_index: {0}", wp_index);
-
- // Read hardware breakpoint and watchpoint information.
- Status error = ReadHardwareDebugInfo();
-
- if (error.Fail())
- return false;
-
- if (wp_index >= m_max_hwp_supported)
- return false;
-
- // Create a backup we can revert to in case of failure.
- lldb::addr_t tempAddr = m_hwp_regs[wp_index].address;
- uint32_t tempControl = m_hwp_regs[wp_index].control;
-
- // Update watchpoint in local cache
- m_hwp_regs[wp_index].control &= ~1;
- m_hwp_regs[wp_index].address = 0;
-
- // Ptrace call to update hardware debug registers
- error = WriteHardwareDebugRegs(eDREGTypeWATCH);
-
- if (error.Fail()) {
- m_hwp_regs[wp_index].control = tempControl;
- m_hwp_regs[wp_index].address = tempAddr;
-
- return false;
- }
-
- return true;
-}
-
-Status NativeRegisterContextLinux_arm64::ClearAllHardwareWatchpoints() {
- // Read hardware breakpoint and watchpoint information.
- Status error = ReadHardwareDebugInfo();
-
- if (error.Fail())
- return error;
-
- lldb::addr_t tempAddr = 0;
- uint32_t tempControl = 0;
-
- for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
- if (m_hwp_regs[i].control & 0x01) {
- // Create a backup we can revert to in case of failure.
- tempAddr = m_hwp_regs[i].address;
- tempControl = m_hwp_regs[i].control;
-
- // Clear watchpoints in local cache
- m_hwp_regs[i].control &= ~1;
- m_hwp_regs[i].address = 0;
-
- // Ptrace call to update hardware debug registers
- error = WriteHardwareDebugRegs(eDREGTypeWATCH);
-
- if (error.Fail()) {
- m_hwp_regs[i].control = tempControl;
- m_hwp_regs[i].address = tempAddr;
-
- return error;
- }
- }
- }
-
- return Status();
-}
-
-uint32_t
-NativeRegisterContextLinux_arm64::GetWatchpointSize(uint32_t wp_index) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
- LLDB_LOG(log, "wp_index: {0}", wp_index);
-
- switch ((m_hwp_regs[wp_index].control >> 5) & 0xff) {
- case 0x01:
- return 1;
- case 0x03:
- return 2;
- case 0x0f:
- return 4;
- case 0xff:
- return 8;
- default:
- return 0;
- }
-}
-bool NativeRegisterContextLinux_arm64::WatchpointIsEnabled(uint32_t wp_index) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
- LLDB_LOG(log, "wp_index: {0}", wp_index);
-
- if ((m_hwp_regs[wp_index].control & 0x1) == 0x1)
- return true;
- else
- return false;
-}
-
-Status NativeRegisterContextLinux_arm64::GetWatchpointHitIndex(
- uint32_t &wp_index, lldb::addr_t trap_addr) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
- LLDB_LOG(log, "wp_index: {0}, trap_addr: {1:x}", wp_index, trap_addr);
-
- uint32_t watch_size;
- lldb::addr_t watch_addr;
-
- for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) {
- watch_size = GetWatchpointSize(wp_index);
- watch_addr = m_hwp_regs[wp_index].address;
-
- if (WatchpointIsEnabled(wp_index) && trap_addr >= watch_addr &&
- trap_addr < watch_addr + watch_size) {
- m_hwp_regs[wp_index].hit_addr = trap_addr;
- return Status();
- }
- }
-
- wp_index = LLDB_INVALID_INDEX32;
- return Status();
-}
-
-lldb::addr_t
-NativeRegisterContextLinux_arm64::GetWatchpointAddress(uint32_t wp_index) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
- LLDB_LOG(log, "wp_index: {0}", wp_index);
-
- if (wp_index >= m_max_hwp_supported)
- return LLDB_INVALID_ADDRESS;
-
- if (WatchpointIsEnabled(wp_index))
- return m_hwp_regs[wp_index].real_addr;
- else
- return LLDB_INVALID_ADDRESS;
-}
-
-lldb::addr_t
-NativeRegisterContextLinux_arm64::GetWatchpointHitAddress(uint32_t wp_index) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
- LLDB_LOG(log, "wp_index: {0}", wp_index);
-
- if (wp_index >= m_max_hwp_supported)
- return LLDB_INVALID_ADDRESS;
-
- if (WatchpointIsEnabled(wp_index))
- return m_hwp_regs[wp_index].hit_addr;
- else
- return LLDB_INVALID_ADDRESS;
-}
-
-Status NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() {
+llvm::Error NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() {
if (!m_refresh_hwdebug_info) {
- return Status();
+ return llvm::Error::success();
}
::pid_t tid = m_thread.GetID();
@@ -896,7 +559,7 @@
&ioVec, ioVec.iov_len);
if (error.Fail())
- return error;
+ return error.ToError();
m_max_hwp_supported = dreg_state.dbg_info & 0xff;
@@ -905,24 +568,26 @@
&ioVec, ioVec.iov_len);
if (error.Fail())
- return error;
+ return error.ToError();
m_max_hbp_supported = dreg_state.dbg_info & 0xff;
m_refresh_hwdebug_info = false;
- return error;
+ return llvm::Error::success();
}
-Status NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(int hwbType) {
+llvm::Error
+NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(DREGType hwbType) {
struct iovec ioVec;
struct user_hwdebug_state dreg_state;
- Status error;
+ int regset;
memset(&dreg_state, 0, sizeof(dreg_state));
ioVec.iov_base = &dreg_state;
- if (hwbType == eDREGTypeWATCH) {
- hwbType = NT_ARM_HW_WATCH;
+ switch (hwbType) {
+ case eDREGTypeWATCH:
+ regset = NT_ARM_HW_WATCH;
ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) +
(sizeof(dreg_state.dbg_regs[0]) * m_max_hwp_supported);
@@ -930,19 +595,22 @@
dreg_state.dbg_regs[i].addr = m_hwp_regs[i].address;
dreg_state.dbg_regs[i].ctrl = m_hwp_regs[i].control;
}
- } else {
- hwbType = NT_ARM_HW_BREAK;
+ break;
+ case eDREGTypeBREAK:
+ regset = NT_ARM_HW_BREAK;
ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) +
(sizeof(dreg_state.dbg_regs[0]) * m_max_hbp_supported);
for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
- dreg_state.dbg_regs[i].addr = m_hbr_regs[i].address;
- dreg_state.dbg_regs[i].ctrl = m_hbr_regs[i].control;
+ dreg_state.dbg_regs[i].addr = m_hbp_regs[i].address;
+ dreg_state.dbg_regs[i].ctrl = m_hbp_regs[i].control;
}
+ break;
}
return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(),
- &hwbType, &ioVec, ioVec.iov_len);
+ ®set, &ioVec, ioVec.iov_len)
+ .ToError();
}
Status NativeRegisterContextLinux_arm64::ReadGPR() {
@@ -1014,6 +682,8 @@
m_fpu_is_valid = false;
m_sve_buffer_is_valid = false;
m_sve_header_is_valid = false;
+ m_pac_mask_is_valid = false;
+ m_mte_ctrl_is_valid = false;
// Update SVE registers in case there is change in configuration.
ConfigureRegisterContext();
@@ -1031,7 +701,26 @@
error = ReadRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE);
- m_sve_header_is_valid = true;
+ if (error.Success())
+ m_sve_header_is_valid = true;
+
+ return error;
+}
+
+Status NativeRegisterContextLinux_arm64::ReadPAuthMask() {
+ Status error;
+
+ if (m_pac_mask_is_valid)
+ return error;
+
+ struct iovec ioVec;
+ ioVec.iov_base = GetPACMask();
+ ioVec.iov_len = GetPACMaskSize();
+
+ error = ReadRegisterSet(&ioVec, GetPACMaskSize(), NT_ARM_PAC_MASK);
+
+ if (error.Success())
+ m_pac_mask_is_valid = true;
return error;
}
@@ -1091,25 +780,65 @@
return WriteRegisterSet(&ioVec, GetSVEBufferSize(), NT_ARM_SVE);
}
+Status NativeRegisterContextLinux_arm64::ReadMTEControl() {
+ Status error;
+
+ if (m_mte_ctrl_is_valid)
+ return error;
+
+ struct iovec ioVec;
+ ioVec.iov_base = GetMTEControl();
+ ioVec.iov_len = GetMTEControlSize();
+
+ error = ReadRegisterSet(&ioVec, GetMTEControlSize(), NT_ARM_TAGGED_ADDR_CTRL);
+
+ if (error.Success())
+ m_mte_ctrl_is_valid = true;
+
+ return error;
+}
+
+Status NativeRegisterContextLinux_arm64::WriteMTEControl() {
+ Status error;
+
+ error = ReadMTEControl();
+ if (error.Fail())
+ return error;
+
+ struct iovec ioVec;
+ ioVec.iov_base = GetMTEControl();
+ ioVec.iov_len = GetMTEControlSize();
+
+ m_mte_ctrl_is_valid = false;
+
+ return WriteRegisterSet(&ioVec, GetMTEControlSize(), NT_ARM_TAGGED_ADDR_CTRL);
+}
+
void NativeRegisterContextLinux_arm64::ConfigureRegisterContext() {
- // Read SVE configuration data and configure register infos.
+ // ConfigureRegisterContext gets called from InvalidateAllRegisters
+ // on every stop and configures SVE vector length.
+ // If m_sve_state is set to SVEState::Disabled on first stop, code below will
+ // be deemed non operational for the lifetime of current process.
if (!m_sve_header_is_valid && m_sve_state != SVEState::Disabled) {
Status error = ReadSVEHeader();
- if (!error.Success() && m_sve_state == SVEState::Unknown) {
- m_sve_state = SVEState::Disabled;
- GetRegisterInfo().ConfigureVectorRegisterInfos(
- RegisterInfoPOSIX_arm64::eVectorQuadwordAArch64);
- } else {
- if ((m_sve_header.flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_FPSIMD)
+ if (error.Success()) {
+ // If SVE is enabled thread can switch between SVEState::FPSIMD and
+ // SVEState::Full on every stop.
+ if ((m_sve_header.flags & sve::ptrace_regs_mask) ==
+ sve::ptrace_regs_fpsimd)
m_sve_state = SVEState::FPSIMD;
- else if ((m_sve_header.flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_SVE)
+ else if ((m_sve_header.flags & sve::ptrace_regs_mask) ==
+ sve::ptrace_regs_sve)
m_sve_state = SVEState::Full;
+ // On every stop we configure SVE vector length by calling
+ // ConfigureVectorLength regardless of current SVEState of this thread.
uint32_t vq = RegisterInfoPOSIX_arm64::eVectorQuadwordAArch64SVE;
if (sve_vl_valid(m_sve_header.vl))
- vq = sve_vq_from_vl(m_sve_header.vl);
- GetRegisterInfo().ConfigureVectorRegisterInfos(vq);
- m_sve_ptrace_payload.resize(SVE_PT_SIZE(vq, SVE_PT_REGS_SVE));
+ vq = sve::vq_from_vl(m_sve_header.vl);
+
+ GetRegisterInfo().ConfigureVectorLength(vq);
+ m_sve_ptrace_payload.resize(sve::PTraceSize(vq, sve::ptrace_regs_sve));
}
}
}
@@ -1125,19 +854,19 @@
uint32_t sve_reg_offset = LLDB_INVALID_INDEX32;
if (m_sve_state == SVEState::FPSIMD) {
const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
- sve_reg_offset =
- SVE_PT_FPSIMD_OFFSET + (reg - GetRegisterInfo().GetRegNumSVEZ0()) * 16;
+ sve_reg_offset = sve::ptrace_fpsimd_offset +
+ (reg - GetRegisterInfo().GetRegNumSVEZ0()) * 16;
} else if (m_sve_state == SVEState::Full) {
uint32_t sve_z0_offset = GetGPRSize() + 16;
sve_reg_offset =
- SVE_SIG_REGS_OFFSET + reg_info->byte_offset - sve_z0_offset;
+ sve::SigRegsOffset() + reg_info->byte_offset - sve_z0_offset;
}
return sve_reg_offset;
}
void *NativeRegisterContextLinux_arm64::GetSVEBuffer() {
if (m_sve_state == SVEState::FPSIMD)
- return m_sve_ptrace_payload.data() + SVE_PT_FPSIMD_OFFSET;
+ return m_sve_ptrace_payload.data() + sve::ptrace_fpsimd_offset;
return m_sve_ptrace_payload.data();
}
@@ -1152,4 +881,30 @@
return expedited_reg_nums;
}
+llvm::Expected<NativeRegisterContextLinux::MemoryTaggingDetails>
+NativeRegisterContextLinux_arm64::GetMemoryTaggingDetails(int32_t type) {
+ if (type == MemoryTagManagerAArch64MTE::eMTE_allocation) {
+ return MemoryTaggingDetails{std::make_unique<MemoryTagManagerAArch64MTE>(),
+ PTRACE_PEEKMTETAGS, PTRACE_POKEMTETAGS};
+ }
+
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Unknown AArch64 memory tag type %d", type);
+}
+
+lldb::addr_t NativeRegisterContextLinux_arm64::FixWatchpointHitAddress(
+ lldb::addr_t hit_addr) {
+ // Linux configures user-space virtual addresses with top byte ignored.
+ // We set default value of mask such that top byte is masked out.
+ lldb::addr_t mask = ~((1ULL << 56) - 1);
+
+ // Try to read pointer authentication data_mask register and calculate a
+ // consolidated data address mask after ignoring the top byte.
+ if (ReadPAuthMask().Success())
+ mask |= m_pac_mask.data_mask;
+
+ return hit_addr & ~mask;
+ ;
+}
+
#endif // defined (__arm64__) || defined (__aarch64__)
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h b/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
index 344eae24..4dfc78b 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
@@ -12,6 +12,8 @@
#define lldb_NativeRegisterContextLinux_arm64_h
#include "Plugins/Process/Linux/NativeRegisterContextLinux.h"
+#include "Plugins/Process/Utility/LinuxPTraceDefines_arm64sve.h"
+#include "Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.h"
#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
#include <asm/ptrace.h>
@@ -21,10 +23,13 @@
class NativeProcessLinux;
-class NativeRegisterContextLinux_arm64 : public NativeRegisterContextLinux {
+class NativeRegisterContextLinux_arm64
+ : public NativeRegisterContextLinux,
+ public NativeRegisterContextDBReg_arm64 {
public:
- NativeRegisterContextLinux_arm64(const ArchSpec &target_arch,
- NativeThreadProtocol &native_thread);
+ NativeRegisterContextLinux_arm64(
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread,
+ std::unique_ptr<RegisterInfoPOSIX_arm64> register_info_up);
uint32_t GetRegisterSetCount() const override;
@@ -49,44 +54,10 @@
bool RegisterOffsetIsDynamic() const override { return true; }
- // Hardware breakpoints/watchpoint management functions
-
- uint32_t NumSupportedHardwareBreakpoints() override;
-
- uint32_t SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override;
-
- bool ClearHardwareBreakpoint(uint32_t hw_idx) override;
-
- Status ClearAllHardwareBreakpoints() override;
-
- Status GetHardwareBreakHitIndex(uint32_t &bp_index,
- lldb::addr_t trap_addr) override;
-
- uint32_t NumSupportedHardwareWatchpoints() override;
-
- uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size,
- uint32_t watch_flags) override;
-
- bool ClearHardwareWatchpoint(uint32_t hw_index) override;
-
- Status ClearAllHardwareWatchpoints() override;
-
- Status GetWatchpointHitIndex(uint32_t &wp_index,
- lldb::addr_t trap_addr) override;
-
- lldb::addr_t GetWatchpointHitAddress(uint32_t wp_index) override;
-
- lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override;
-
- uint32_t GetWatchpointSize(uint32_t wp_index);
-
- bool WatchpointIsEnabled(uint32_t wp_index);
-
- // Debug register type select
- enum DREGType { eDREGTypeWATCH = 0, eDREGTypeBREAK };
+ llvm::Expected<MemoryTaggingDetails>
+ GetMemoryTaggingDetails(int32_t type) override;
protected:
-
Status ReadGPR() override;
Status WriteGPR() override;
@@ -105,12 +76,16 @@
size_t GetFPRSize() override { return sizeof(m_fpr); }
+ lldb::addr_t FixWatchpointHitAddress(lldb::addr_t hit_addr) override;
+
private:
bool m_gpr_is_valid;
bool m_fpu_is_valid;
bool m_sve_buffer_is_valid;
+ bool m_mte_ctrl_is_valid;
bool m_sve_header_is_valid;
+ bool m_pac_mask_is_valid;
struct user_pt_regs m_gpr_arm64; // 64-bit general purpose registers.
@@ -118,25 +93,19 @@
m_fpr; // floating-point registers including extended register sets.
SVEState m_sve_state;
- struct user_sve_header m_sve_header;
+ struct sve::user_sve_header m_sve_header;
std::vector<uint8_t> m_sve_ptrace_payload;
- // Debug register info for hardware breakpoints and watchpoints management.
- struct DREG {
- lldb::addr_t address; // Breakpoint/watchpoint address value.
- lldb::addr_t hit_addr; // Address at which last watchpoint trigger exception
- // occurred.
- lldb::addr_t real_addr; // Address value that should cause target to stop.
- uint32_t control; // Breakpoint/watchpoint control value.
- uint32_t refcount; // Serves as enable/disable and reference counter.
+ bool m_refresh_hwdebug_info;
+
+ struct user_pac_mask {
+ uint64_t data_mask;
+ uint64_t insn_mask;
};
- struct DREG m_hbr_regs[16]; // Arm native linux hardware breakpoints
- struct DREG m_hwp_regs[16]; // Arm native linux hardware watchpoints
+ struct user_pac_mask m_pac_mask;
- uint32_t m_max_hwp_supported;
- uint32_t m_max_hbp_supported;
- bool m_refresh_hwdebug_info;
+ uint64_t m_mte_ctrl_reg;
bool IsGPR(unsigned reg) const;
@@ -150,7 +119,15 @@
Status WriteSVEHeader();
+ Status ReadPAuthMask();
+
+ Status ReadMTEControl();
+
+ Status WriteMTEControl();
+
bool IsSVE(unsigned reg) const;
+ bool IsPAuth(unsigned reg) const;
+ bool IsMTE(unsigned reg) const;
uint64_t GetSVERegVG() { return m_sve_header.vl / 8; }
@@ -158,15 +135,23 @@
void *GetSVEHeader() { return &m_sve_header; }
+ void *GetPACMask() { return &m_pac_mask; }
+
+ void *GetMTEControl() { return &m_mte_ctrl_reg; }
+
void *GetSVEBuffer();
size_t GetSVEHeaderSize() { return sizeof(m_sve_header); }
+ size_t GetPACMaskSize() { return sizeof(m_pac_mask); }
+
size_t GetSVEBufferSize() { return m_sve_ptrace_payload.size(); }
- Status ReadHardwareDebugInfo();
+ size_t GetMTEControlSize() { return sizeof(m_mte_ctrl_reg); }
- Status WriteHardwareDebugRegs(int hwbType);
+ llvm::Error ReadHardwareDebugInfo() override;
+
+ llvm::Error WriteHardwareDebugRegs(DREGType hwbType) override;
uint32_t CalculateFprOffset(const RegisterInfo *reg_info) const;
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp b/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
deleted file mode 100644
index 5abbab1..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
+++ /dev/null
@@ -1,1036 +0,0 @@
-//===-- NativeRegisterContextLinux_mips64.cpp -----------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-#if defined(__mips__)
-
-#include "NativeRegisterContextLinux_mips64.h"
-
-
-#include "Plugins/Process/Linux/NativeProcessLinux.h"
-#include "Plugins/Process/Linux/Procfs.h"
-#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
-#include "Plugins/Process/Utility/RegisterContextLinux_mips.h"
-#include "Plugins/Process/Utility/RegisterContextLinux_mips64.h"
-#include "lldb/Core/EmulateInstruction.h"
-#include "lldb/Host/Host.h"
-#include "lldb/Host/HostInfo.h"
-#include "lldb/Utility/DataBufferHeap.h"
-#include "lldb/Utility/LLDBAssert.h"
-#include "lldb/Utility/Log.h"
-#include "lldb/Utility/RegisterValue.h"
-#include "lldb/Utility/Status.h"
-#include "lldb/lldb-enumerations.h"
-#include "lldb/lldb-private-enumerations.h"
-#define NT_MIPS_MSA 0x600
-#define CONFIG5_FRE (1 << 8)
-#define SR_FR (1 << 26)
-#define NUM_REGISTERS 32
-
-#include <asm/ptrace.h>
-#include <sys/ptrace.h>
-
-#ifndef PTRACE_GET_WATCH_REGS
-enum pt_watch_style { pt_watch_style_mips32, pt_watch_style_mips64 };
-struct mips32_watch_regs {
- uint32_t watchlo[8];
- uint16_t watchhi[8];
- uint16_t watch_masks[8];
- uint32_t num_valid;
-} __attribute__((aligned(8)));
-
-struct mips64_watch_regs {
- uint64_t watchlo[8];
- uint16_t watchhi[8];
- uint16_t watch_masks[8];
- uint32_t num_valid;
-} __attribute__((aligned(8)));
-
-struct pt_watch_regs {
- enum pt_watch_style style;
- union {
- struct mips32_watch_regs mips32;
- struct mips64_watch_regs mips64;
- };
-};
-
-#define PTRACE_GET_WATCH_REGS 0xd0
-#define PTRACE_SET_WATCH_REGS 0xd1
-#endif
-
-#define W (1 << 0)
-#define R (1 << 1)
-#define I (1 << 2)
-
-#define IRW (I | R | W)
-
-#ifndef PTRACE_GETREGSET
-#define PTRACE_GETREGSET 0x4204
-#endif
-struct pt_watch_regs default_watch_regs;
-
-using namespace lldb_private;
-using namespace lldb_private::process_linux;
-
-std::unique_ptr<NativeRegisterContextLinux>
-NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
- const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
- return std::make_unique<NativeRegisterContextLinux_mips64>(target_arch,
- native_thread);
-}
-
-#define REG_CONTEXT_SIZE \
- (GetRegisterInfoInterface().GetGPRSize() + sizeof(FPR_linux_mips) + \
- sizeof(MSA_linux_mips))
-
-// NativeRegisterContextLinux_mips64 members.
-
-static RegisterInfoInterface *
-CreateRegisterInfoInterface(const ArchSpec &target_arch) {
- if ((target_arch.GetMachine() == llvm::Triple::mips) ||
- (target_arch.GetMachine() == llvm::Triple::mipsel)) {
- // 32-bit hosts run with a RegisterContextLinux_mips context.
- return new RegisterContextLinux_mips(
- target_arch, NativeRegisterContextLinux_mips64::IsMSAAvailable());
- } else {
- return new RegisterContextLinux_mips64(
- target_arch, NativeRegisterContextLinux_mips64::IsMSAAvailable());
- }
-}
-
-NativeRegisterContextLinux_mips64::NativeRegisterContextLinux_mips64(
- const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
- : NativeRegisterContextRegisterInfo(
- native_thread, CreateRegisterInfoInterface(target_arch)) {
- switch (target_arch.GetMachine()) {
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- m_reg_info.num_registers = k_num_registers_mips;
- m_reg_info.num_gpr_registers = k_num_gpr_registers_mips;
- m_reg_info.num_fpr_registers = k_num_fpr_registers_mips;
- m_reg_info.last_gpr = k_last_gpr_mips;
- m_reg_info.first_fpr = k_first_fpr_mips;
- m_reg_info.last_fpr = k_last_fpr_mips;
- m_reg_info.first_msa = k_first_msa_mips;
- m_reg_info.last_msa = k_last_msa_mips;
- break;
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- m_reg_info.num_registers = k_num_registers_mips64;
- m_reg_info.num_gpr_registers = k_num_gpr_registers_mips64;
- m_reg_info.num_fpr_registers = k_num_fpr_registers_mips64;
- m_reg_info.last_gpr = k_last_gpr_mips64;
- m_reg_info.first_fpr = k_first_fpr_mips64;
- m_reg_info.last_fpr = k_last_fpr_mips64;
- m_reg_info.first_msa = k_first_msa_mips64;
- m_reg_info.last_msa = k_last_msa_mips64;
- break;
- default:
- assert(false && "Unhandled target architecture.");
- break;
- }
-
- // Initialize m_iovec to point to the buffer and buffer size using the
- // conventions of Berkeley style UIO structures, as required by PTRACE
- // extensions.
- m_iovec.iov_base = &m_msa;
- m_iovec.iov_len = sizeof(MSA_linux_mips);
-
- // init h/w watchpoint addr map
- for (int index = 0; index <= MAX_NUM_WP; index++)
- hw_addr_map[index] = LLDB_INVALID_ADDRESS;
-
- ::memset(&m_gpr, 0, sizeof(GPR_linux_mips));
- ::memset(&m_fpr, 0, sizeof(FPR_linux_mips));
- ::memset(&m_msa, 0, sizeof(MSA_linux_mips));
-}
-
-uint32_t NativeRegisterContextLinux_mips64::GetRegisterSetCount() const {
- switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el: {
- const auto context = static_cast<const RegisterContextLinux_mips64 &>
- (GetRegisterInfoInterface());
- return context.GetRegisterSetCount();
- }
- case llvm::Triple::mips:
- case llvm::Triple::mipsel: {
- const auto context = static_cast<const RegisterContextLinux_mips &>
- (GetRegisterInfoInterface());
- return context.GetRegisterSetCount();
- }
- default:
- llvm_unreachable("Unhandled target architecture.");
- }
-}
-
-lldb::addr_t NativeRegisterContextLinux_mips64::GetPCfromBreakpointLocation(
- lldb::addr_t fail_value) {
- Status error;
- RegisterValue pc_value;
- lldb::addr_t pc = fail_value;
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS));
- LLDB_LOG(log, "Reading PC from breakpoint location");
-
- // PC register is at index 34 of the register array
- const RegisterInfo *const pc_info_p = GetRegisterInfoAtIndex(gpr_pc_mips64);
-
- error = ReadRegister(pc_info_p, pc_value);
- if (error.Success()) {
- pc = pc_value.GetAsUInt64();
-
- // CAUSE register is at index 37 of the register array
- const RegisterInfo *const cause_info_p =
- GetRegisterInfoAtIndex(gpr_cause_mips64);
- RegisterValue cause_value;
-
- ReadRegister(cause_info_p, cause_value);
-
- uint64_t cause = cause_value.GetAsUInt64();
- LLDB_LOG(log, "PC {0:x} cause {1:x}", pc, cause);
-
- /*
- * The breakpoint might be in a delay slot. In this case PC points
- * to the delayed branch instruction rather then the instruction
- * in the delay slot. If the CAUSE.BD flag is set then adjust the
- * PC based on the size of the branch instruction.
- */
- if ((cause & (1 << 31)) != 0) {
- lldb::addr_t branch_delay = 0;
- branch_delay =
- 4; // FIXME - Adjust according to size of branch instruction at PC
- pc = pc + branch_delay;
- pc_value.SetUInt64(pc);
- WriteRegister(pc_info_p, pc_value);
- LLDB_LOG(log, "New PC {0:x}", pc);
- }
- }
-
- return pc;
-}
-
-const RegisterSet *
-NativeRegisterContextLinux_mips64::GetRegisterSet(uint32_t set_index) const {
- if (set_index >= GetRegisterSetCount())
- return nullptr;
-
- switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el: {
- const auto context = static_cast<const RegisterContextLinux_mips64 &>
- (GetRegisterInfoInterface());
- return context.GetRegisterSet(set_index);
- }
- case llvm::Triple::mips:
- case llvm::Triple::mipsel: {
- const auto context = static_cast<const RegisterContextLinux_mips &>
- (GetRegisterInfoInterface());
- return context.GetRegisterSet(set_index);
- }
- default:
- llvm_unreachable("Unhandled target architecture.");
- }
-}
-
-lldb_private::Status
-NativeRegisterContextLinux_mips64::ReadRegister(const RegisterInfo *reg_info,
- RegisterValue ®_value) {
- Status error;
-
- if (!reg_info) {
- error.SetErrorString("reg_info NULL");
- return error;
- }
-
- const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
- uint8_t byte_size = reg_info->byte_size;
- if (reg == LLDB_INVALID_REGNUM) {
- // This is likely an internal register for lldb use only and should not be
- // directly queried.
- error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
- "register, cannot read directly",
- reg_info->name);
- return error;
- }
-
- if (IsMSA(reg) && !IsMSAAvailable()) {
- error.SetErrorString("MSA not available on this processor");
- return error;
- }
-
- if (IsMSA(reg) || IsFPR(reg)) {
- uint8_t *src = nullptr;
- lldbassert(reg_info->byte_offset < sizeof(UserArea));
-
- error = ReadCP1();
-
- if (!error.Success()) {
- error.SetErrorString("failed to read co-processor 1 register");
- return error;
- }
-
- if (IsFPR(reg)) {
- if (IsFR0() && (byte_size != 4)) {
- byte_size = 4;
- uint8_t ptrace_index;
- ptrace_index = reg_info->kinds[lldb::eRegisterKindProcessPlugin];
- src = ReturnFPOffset(ptrace_index, reg_info->byte_offset);
- } else
- src = (uint8_t *)&m_fpr + reg_info->byte_offset - sizeof(m_gpr);
- } else
- src = (uint8_t *)&m_msa + reg_info->byte_offset -
- (sizeof(m_gpr) + sizeof(m_fpr));
- switch (byte_size) {
- case 4:
- reg_value.SetUInt32(*(uint32_t *)src);
- break;
- case 8:
- reg_value.SetUInt64(*(uint64_t *)src);
- break;
- case 16:
- reg_value.SetBytes((const void *)src, 16, GetByteOrder());
- break;
- default:
- assert(false && "Unhandled data size.");
- error.SetErrorStringWithFormat("unhandled byte size: %" PRIu32,
- reg_info->byte_size);
- break;
- }
- } else {
- error = ReadRegisterRaw(reg, reg_value);
- }
-
- return error;
-}
-
-lldb_private::Status NativeRegisterContextLinux_mips64::WriteRegister(
- const RegisterInfo *reg_info, const RegisterValue ®_value) {
- Status error;
-
- assert(reg_info && "reg_info is null");
-
- const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB];
-
- if (reg_index == LLDB_INVALID_REGNUM)
- return Status("no lldb regnum for %s", reg_info && reg_info->name
- ? reg_info->name
- : "<unknown register>");
-
- if (IsMSA(reg_index) && !IsMSAAvailable()) {
- error.SetErrorString("MSA not available on this processor");
- return error;
- }
-
- if (IsFPR(reg_index) || IsMSA(reg_index)) {
- uint8_t *dst = nullptr;
- uint64_t *src = nullptr;
- uint8_t byte_size = reg_info->byte_size;
- lldbassert(reg_info->byte_offset < sizeof(UserArea));
-
- // Initialise the FP and MSA buffers by reading all co-processor 1
- // registers
- ReadCP1();
-
- if (IsFPR(reg_index)) {
- if (IsFR0() && (byte_size != 4)) {
- byte_size = 4;
- uint8_t ptrace_index;
- ptrace_index = reg_info->kinds[lldb::eRegisterKindProcessPlugin];
- dst = ReturnFPOffset(ptrace_index, reg_info->byte_offset);
- } else
- dst = (uint8_t *)&m_fpr + reg_info->byte_offset - sizeof(m_gpr);
- } else
- dst = (uint8_t *)&m_msa + reg_info->byte_offset -
- (sizeof(m_gpr) + sizeof(m_fpr));
- switch (byte_size) {
- case 4:
- *(uint32_t *)dst = reg_value.GetAsUInt32();
- break;
- case 8:
- *(uint64_t *)dst = reg_value.GetAsUInt64();
- break;
- case 16:
- src = (uint64_t *)reg_value.GetBytes();
- *(uint64_t *)dst = *src;
- *(uint64_t *)(dst + 8) = *(src + 1);
- break;
- default:
- assert(false && "Unhandled data size.");
- error.SetErrorStringWithFormat("unhandled byte size: %" PRIu32,
- reg_info->byte_size);
- break;
- }
- error = WriteCP1();
- if (!error.Success()) {
- error.SetErrorString("failed to write co-processor 1 register");
- return error;
- }
- } else {
- error = WriteRegisterRaw(reg_index, reg_value);
- }
-
- return error;
-}
-
-Status NativeRegisterContextLinux_mips64::ReadAllRegisterValues(
- lldb::DataBufferSP &data_sp) {
- Status error;
-
- data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
- error = ReadGPR();
- if (!error.Success()) {
- error.SetErrorString("ReadGPR() failed");
- return error;
- }
-
- error = ReadCP1();
- if (!error.Success()) {
- error.SetErrorString("ReadCP1() failed");
- return error;
- }
-
- uint8_t *dst = data_sp->GetBytes();
- ::memcpy(dst, &m_gpr, GetRegisterInfoInterface().GetGPRSize());
- dst += GetRegisterInfoInterface().GetGPRSize();
-
- ::memcpy(dst, &m_fpr, GetFPRSize());
- dst += GetFPRSize();
-
- ::memcpy(dst, &m_msa, sizeof(MSA_linux_mips));
-
- return error;
-}
-
-Status NativeRegisterContextLinux_mips64::WriteAllRegisterValues(
- const lldb::DataBufferSP &data_sp) {
- Status error;
-
- if (!data_sp) {
- error.SetErrorStringWithFormat(
- "NativeRegisterContextLinux_mips64::%s invalid data_sp provided",
- __FUNCTION__);
- return error;
- }
-
- if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) {
- error.SetErrorStringWithFormat(
- "NativeRegisterContextLinux_mips64::%s data_sp contained mismatched "
- "data size, expected %" PRIu64 ", actual %" PRIu64,
- __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize());
- return error;
- }
-
- uint8_t *src = data_sp->GetBytes();
- if (src == nullptr) {
- error.SetErrorStringWithFormat("NativeRegisterContextLinux_mips64::%s "
- "DataBuffer::GetBytes() returned a null "
- "pointer",
- __FUNCTION__);
- return error;
- }
-
- ::memcpy(&m_gpr, src, GetRegisterInfoInterface().GetGPRSize());
- src += GetRegisterInfoInterface().GetGPRSize();
-
- ::memcpy(&m_fpr, src, GetFPRSize());
- src += GetFPRSize();
-
- ::memcpy(&m_msa, src, sizeof(MSA_linux_mips));
-
- error = WriteGPR();
- if (!error.Success()) {
- error.SetErrorStringWithFormat(
- "NativeRegisterContextLinux_mips64::%s WriteGPR() failed",
- __FUNCTION__);
- return error;
- }
-
- error = WriteCP1();
- if (!error.Success()) {
- error.SetErrorStringWithFormat(
- "NativeRegisterContextLinux_mips64::%s WriteCP1() failed",
- __FUNCTION__);
- return error;
- }
-
- return error;
-}
-
-Status NativeRegisterContextLinux_mips64::ReadCP1() {
- Status error;
-
- uint8_t *src = nullptr;
- uint8_t *dst = nullptr;
-
- lldb::ByteOrder byte_order = GetByteOrder();
-
- bool IsBigEndian = (byte_order == lldb::eByteOrderBig);
-
- if (IsMSAAvailable()) {
- error = NativeRegisterContextLinux::ReadRegisterSet(
- &m_iovec, sizeof(MSA_linux_mips), NT_MIPS_MSA);
- src = (uint8_t *)&m_msa + (IsBigEndian * 8);
- dst = (uint8_t *)&m_fpr;
- for (int i = 0; i < NUM_REGISTERS; i++) {
- // Copy fp values from msa buffer fetched via ptrace
- *(uint64_t *)dst = *(uint64_t *)src;
- src = src + 16;
- dst = dst + 8;
- }
- m_fpr.fir = m_msa.fir;
- m_fpr.fcsr = m_msa.fcsr;
- m_fpr.config5 = m_msa.config5;
- } else {
- error = NativeRegisterContextLinux::ReadFPR();
- }
- return error;
-}
-
-uint8_t *
-NativeRegisterContextLinux_mips64::ReturnFPOffset(uint8_t reg_index,
- uint32_t byte_offset) {
-
- uint8_t *fp_buffer_ptr = nullptr;
- lldb::ByteOrder byte_order = GetByteOrder();
- bool IsBigEndian = (byte_order == lldb::eByteOrderBig);
- if (reg_index % 2) {
- uint8_t offset_diff = (IsBigEndian) ? 8 : 4;
- fp_buffer_ptr =
- (uint8_t *)&m_fpr + byte_offset - offset_diff - sizeof(m_gpr);
- } else {
- fp_buffer_ptr =
- (uint8_t *)&m_fpr + byte_offset + 4 * (IsBigEndian) - sizeof(m_gpr);
- }
- return fp_buffer_ptr;
-}
-
-Status NativeRegisterContextLinux_mips64::WriteCP1() {
- Status error;
-
- uint8_t *src = nullptr;
- uint8_t *dst = nullptr;
-
- lldb::ByteOrder byte_order = GetByteOrder();
-
- bool IsBigEndian = (byte_order == lldb::eByteOrderBig);
-
- if (IsMSAAvailable()) {
- dst = (uint8_t *)&m_msa + (IsBigEndian * 8);
- src = (uint8_t *)&m_fpr;
- for (int i = 0; i < NUM_REGISTERS; i++) {
- // Copy fp values to msa buffer for ptrace
- *(uint64_t *)dst = *(uint64_t *)src;
- dst = dst + 16;
- src = src + 8;
- }
- m_msa.fir = m_fpr.fir;
- m_msa.fcsr = m_fpr.fcsr;
- m_msa.config5 = m_fpr.config5;
- error = NativeRegisterContextLinux::WriteRegisterSet(
- &m_iovec, sizeof(MSA_linux_mips), NT_MIPS_MSA);
- } else {
- error = NativeRegisterContextLinux::WriteFPR();
- }
-
- return error;
-}
-
-bool NativeRegisterContextLinux_mips64::IsFR0() {
- const RegisterInfo *const reg_info_p = GetRegisterInfoAtIndex(gpr_sr_mips64);
-
- RegisterValue reg_value;
- ReadRegister(reg_info_p, reg_value);
-
- uint64_t value = reg_value.GetAsUInt64();
-
- return (!(value & SR_FR));
-}
-
-bool NativeRegisterContextLinux_mips64::IsFRE() {
- const RegisterInfo *const reg_info_p =
- GetRegisterInfoAtIndex(gpr_config5_mips64);
-
- RegisterValue reg_value;
- ReadRegister(reg_info_p, reg_value);
-
- uint64_t config5 = reg_value.GetAsUInt64();
-
- return (config5 & CONFIG5_FRE);
-}
-
-bool NativeRegisterContextLinux_mips64::IsFPR(uint32_t reg_index) const {
- return (m_reg_info.first_fpr <= reg_index &&
- reg_index <= m_reg_info.last_fpr);
-}
-
-static uint32_t GetWatchHi(struct pt_watch_regs *regs, uint32_t index) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
- if (regs->style == pt_watch_style_mips32)
- return regs->mips32.watchhi[index];
- else if (regs->style == pt_watch_style_mips64)
- return regs->mips64.watchhi[index];
- LLDB_LOG(log, "Invalid watch register style");
- return 0;
-}
-
-static void SetWatchHi(struct pt_watch_regs *regs, uint32_t index,
- uint16_t value) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
- if (regs->style == pt_watch_style_mips32)
- regs->mips32.watchhi[index] = value;
- else if (regs->style == pt_watch_style_mips64)
- regs->mips64.watchhi[index] = value;
- LLDB_LOG(log, "Invalid watch register style");
- return;
-}
-
-static lldb::addr_t GetWatchLo(struct pt_watch_regs *regs, uint32_t index) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
- if (regs->style == pt_watch_style_mips32)
- return regs->mips32.watchlo[index];
- else if (regs->style == pt_watch_style_mips64)
- return regs->mips64.watchlo[index];
- LLDB_LOG(log, "Invalid watch register style");
- return LLDB_INVALID_ADDRESS;
-}
-
-static void SetWatchLo(struct pt_watch_regs *regs, uint32_t index,
- uint64_t value) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
- if (regs->style == pt_watch_style_mips32)
- regs->mips32.watchlo[index] = (uint32_t)value;
- else if (regs->style == pt_watch_style_mips64)
- regs->mips64.watchlo[index] = value;
- else
- LLDB_LOG(log, "Invalid watch register style");
-}
-
-static uint32_t GetIRWMask(struct pt_watch_regs *regs, uint32_t index) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
- if (regs->style == pt_watch_style_mips32)
- return regs->mips32.watch_masks[index] & IRW;
- else if (regs->style == pt_watch_style_mips64)
- return regs->mips64.watch_masks[index] & IRW;
- LLDB_LOG(log, "Invalid watch register style");
- return 0;
-}
-
-static uint32_t GetRegMask(struct pt_watch_regs *regs, uint32_t index) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
- if (regs->style == pt_watch_style_mips32)
- return regs->mips32.watch_masks[index] & ~IRW;
- else if (regs->style == pt_watch_style_mips64)
- return regs->mips64.watch_masks[index] & ~IRW;
- LLDB_LOG(log, "Invalid watch register style");
- return 0;
-}
-
-static lldb::addr_t GetRangeMask(lldb::addr_t mask) {
- lldb::addr_t mask_bit = 1;
- while (mask_bit < mask) {
- mask = mask | mask_bit;
- mask_bit <<= 1;
- }
- return mask;
-}
-
-static int GetVacantWatchIndex(struct pt_watch_regs *regs, lldb::addr_t addr,
- uint32_t size, uint32_t irw,
- uint32_t num_valid) {
- lldb::addr_t last_byte = addr + size - 1;
- lldb::addr_t mask = GetRangeMask(addr ^ last_byte) | IRW;
- lldb::addr_t base_addr = addr & ~mask;
-
- // Check if this address is already watched by previous watch points.
- lldb::addr_t lo;
- uint16_t hi;
- uint32_t vacant_watches = 0;
- for (uint32_t index = 0; index < num_valid; index++) {
- lo = GetWatchLo(regs, index);
- if (lo != 0 && irw == ((uint32_t)lo & irw)) {
- hi = GetWatchHi(regs, index) | IRW;
- lo &= ~(lldb::addr_t)hi;
- if (addr >= lo && last_byte <= (lo + hi))
- return index;
- } else
- vacant_watches++;
- }
-
- // Now try to find a vacant index
- if (vacant_watches > 0) {
- vacant_watches = 0;
- for (uint32_t index = 0; index < num_valid; index++) {
- lo = GetWatchLo(regs, index);
- if (lo == 0 && irw == (GetIRWMask(regs, index) & irw)) {
- if (mask <= (GetRegMask(regs, index) | IRW)) {
- // It fits, we can use it.
- SetWatchLo(regs, index, base_addr | irw);
- SetWatchHi(regs, index, mask & ~IRW);
- return index;
- } else {
- // It doesn't fit, but has the proper IRW capabilities
- vacant_watches++;
- }
- }
- }
-
- if (vacant_watches > 1) {
- // Split this watchpoint across several registers
- struct pt_watch_regs regs_copy;
- regs_copy = *regs;
- lldb::addr_t break_addr;
- uint32_t segment_size;
- for (uint32_t index = 0; index < num_valid; index++) {
- lo = GetWatchLo(®s_copy, index);
- hi = GetRegMask(®s_copy, index) | IRW;
- if (lo == 0 && irw == (hi & irw)) {
- lo = addr & ~(lldb::addr_t)hi;
- break_addr = lo + hi + 1;
- if (break_addr >= addr + size)
- segment_size = size;
- else
- segment_size = break_addr - addr;
- mask = GetRangeMask(addr ^ (addr + segment_size - 1));
- SetWatchLo(®s_copy, index, (addr & ~mask) | irw);
- SetWatchHi(®s_copy, index, mask & ~IRW);
- if (break_addr >= addr + size) {
- *regs = regs_copy;
- return index;
- }
- size = addr + size - break_addr;
- addr = break_addr;
- }
- }
- }
- }
- return LLDB_INVALID_INDEX32;
-}
-
-bool NativeRegisterContextLinux_mips64::IsMSA(uint32_t reg_index) const {
- return (m_reg_info.first_msa <= reg_index &&
- reg_index <= m_reg_info.last_msa);
-}
-
-bool NativeRegisterContextLinux_mips64::IsMSAAvailable() {
- MSA_linux_mips msa_buf;
- unsigned int regset = NT_MIPS_MSA;
-
- Status error = NativeProcessLinux::PtraceWrapper(
- PTRACE_GETREGSET, Host::GetCurrentProcessID(),
- static_cast<void *>(®set), &msa_buf, sizeof(MSA_linux_mips));
-
- if (error.Success() && msa_buf.mir) {
- return true;
- }
-
- return false;
-}
-
-Status NativeRegisterContextLinux_mips64::IsWatchpointHit(uint32_t wp_index,
- bool &is_hit) {
- if (wp_index >= NumSupportedHardwareWatchpoints())
- return Status("Watchpoint index out of range");
-
- // reading the current state of watch regs
- struct pt_watch_regs watch_readback;
- Status error = DoReadWatchPointRegisterValue(
- m_thread.GetID(), static_cast<void *>(&watch_readback));
-
- if (GetWatchHi(&watch_readback, wp_index) & (IRW)) {
- // clear hit flag in watchhi
- SetWatchHi(&watch_readback, wp_index,
- (GetWatchHi(&watch_readback, wp_index) & ~(IRW)));
- DoWriteWatchPointRegisterValue(m_thread.GetID(),
- static_cast<void *>(&watch_readback));
-
- is_hit = true;
- return error;
- }
- is_hit = false;
- return error;
-}
-
-Status NativeRegisterContextLinux_mips64::GetWatchpointHitIndex(
- uint32_t &wp_index, lldb::addr_t trap_addr) {
- uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
- for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) {
- bool is_hit;
- Status error = IsWatchpointHit(wp_index, is_hit);
- if (error.Fail()) {
- wp_index = LLDB_INVALID_INDEX32;
- } else if (is_hit) {
- return error;
- }
- }
- wp_index = LLDB_INVALID_INDEX32;
- return Status();
-}
-
-Status NativeRegisterContextLinux_mips64::IsWatchpointVacant(uint32_t wp_index,
- bool &is_vacant) {
- is_vacant = false;
- return Status("MIPS TODO: "
- "NativeRegisterContextLinux_mips64::IsWatchpointVacant not "
- "implemented");
-}
-
-bool NativeRegisterContextLinux_mips64::ClearHardwareWatchpoint(
- uint32_t wp_index) {
- if (wp_index >= NumSupportedHardwareWatchpoints())
- return false;
-
- struct pt_watch_regs regs;
- // First reading the current state of watch regs
- DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(®s));
-
- if (regs.style == pt_watch_style_mips32) {
- regs.mips32.watchlo[wp_index] = default_watch_regs.mips32.watchlo[wp_index];
- regs.mips32.watchhi[wp_index] = default_watch_regs.mips32.watchhi[wp_index];
- regs.mips32.watch_masks[wp_index] =
- default_watch_regs.mips32.watch_masks[wp_index];
- } else // pt_watch_style_mips64
- {
- regs.mips64.watchlo[wp_index] = default_watch_regs.mips64.watchlo[wp_index];
- regs.mips64.watchhi[wp_index] = default_watch_regs.mips64.watchhi[wp_index];
- regs.mips64.watch_masks[wp_index] =
- default_watch_regs.mips64.watch_masks[wp_index];
- }
-
- Status error = DoWriteWatchPointRegisterValue(m_thread.GetID(),
- static_cast<void *>(®s));
- if (!error.Fail()) {
- hw_addr_map[wp_index] = LLDB_INVALID_ADDRESS;
- return true;
- }
- return false;
-}
-
-Status NativeRegisterContextLinux_mips64::ClearAllHardwareWatchpoints() {
- return DoWriteWatchPointRegisterValue(
- m_thread.GetID(), static_cast<void *>(&default_watch_regs));
-}
-
-Status NativeRegisterContextLinux_mips64::SetHardwareWatchpointWithIndex(
- lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) {
- Status error;
- error.SetErrorString("MIPS TODO: "
- "NativeRegisterContextLinux_mips64::"
- "SetHardwareWatchpointWithIndex not implemented");
- return error;
-}
-
-uint32_t NativeRegisterContextLinux_mips64::SetHardwareWatchpoint(
- lldb::addr_t addr, size_t size, uint32_t watch_flags) {
- struct pt_watch_regs regs;
-
- // First reading the current state of watch regs
- DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(®s));
-
- // Try if a new watch point fits in this state
- int index = GetVacantWatchIndex(®s, addr, size, watch_flags,
- NumSupportedHardwareWatchpoints());
-
- // New watchpoint doesn't fit
- if (index == LLDB_INVALID_INDEX32)
- return LLDB_INVALID_INDEX32;
-
- // It fits, so we go ahead with updating the state of watch regs
- DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(®s));
-
- // Storing exact address
- hw_addr_map[index] = addr;
- return index;
-}
-
-lldb::addr_t
-NativeRegisterContextLinux_mips64::GetWatchpointAddress(uint32_t wp_index) {
- if (wp_index >= NumSupportedHardwareWatchpoints())
- return LLDB_INVALID_ADDRESS;
-
- return hw_addr_map[wp_index];
-}
-
-struct EmulatorBaton {
- lldb::addr_t m_watch_hit_addr;
- NativeProcessLinux *m_process;
- NativeRegisterContext *m_reg_context;
-
- EmulatorBaton(NativeProcessLinux *process, NativeRegisterContext *reg_context)
- : m_watch_hit_addr(LLDB_INVALID_ADDRESS), m_process(process),
- m_reg_context(reg_context) {}
-};
-
-static size_t ReadMemoryCallback(EmulateInstruction *instruction, void *baton,
- const EmulateInstruction::Context &context,
- lldb::addr_t addr, void *dst, size_t length) {
- size_t bytes_read;
- EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
- emulator_baton->m_process->ReadMemory(addr, dst, length, bytes_read);
- return bytes_read;
-}
-
-static size_t WriteMemoryCallback(EmulateInstruction *instruction, void *baton,
- const EmulateInstruction::Context &context,
- lldb::addr_t addr, const void *dst,
- size_t length) {
- return length;
-}
-
-static bool ReadRegisterCallback(EmulateInstruction *instruction, void *baton,
- const RegisterInfo *reg_info,
- RegisterValue ®_value) {
- EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
-
- const RegisterInfo *full_reg_info =
- emulator_baton->m_reg_context->GetRegisterInfo(
- lldb::eRegisterKindDWARF, reg_info->kinds[lldb::eRegisterKindDWARF]);
-
- Status error =
- emulator_baton->m_reg_context->ReadRegister(full_reg_info, reg_value);
- if (error.Success())
- return true;
-
- return false;
-}
-
-static bool WriteRegisterCallback(EmulateInstruction *instruction, void *baton,
- const EmulateInstruction::Context &context,
- const RegisterInfo *reg_info,
- const RegisterValue ®_value) {
- if (reg_info->kinds[lldb::eRegisterKindDWARF] == dwarf_bad_mips64) {
- EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
- emulator_baton->m_watch_hit_addr = reg_value.GetAsUInt64();
- }
-
- return true;
-}
-
-/*
- * MIPS Linux kernel returns a masked address (last 3bits are masked)
- * when a HW watchpoint is hit. However user may not have set a watchpoint
- * on this address. Emulate instruction at PC and find the base address of
- * the load/store instruction. This will give the exact address used to
- * read/write the variable. Send this exact address to client so that
- * it can decide to stop or continue the thread.
-*/
-lldb::addr_t
-NativeRegisterContextLinux_mips64::GetWatchpointHitAddress(uint32_t wp_index) {
- if (wp_index >= NumSupportedHardwareWatchpoints())
- return LLDB_INVALID_ADDRESS;
-
- lldb_private::ArchSpec arch;
- arch = GetRegisterInfoInterface().GetTargetArchitecture();
- std::unique_ptr<EmulateInstruction> emulator_up(
- EmulateInstruction::FindPlugin(arch, lldb_private::eInstructionTypeAny,
- nullptr));
-
- if (emulator_up == nullptr)
- return LLDB_INVALID_ADDRESS;
-
- EmulatorBaton baton(
- static_cast<NativeProcessLinux *>(&m_thread.GetProcess()), this);
- emulator_up->SetBaton(&baton);
- emulator_up->SetReadMemCallback(&ReadMemoryCallback);
- emulator_up->SetReadRegCallback(&ReadRegisterCallback);
- emulator_up->SetWriteMemCallback(&WriteMemoryCallback);
- emulator_up->SetWriteRegCallback(&WriteRegisterCallback);
-
- if (!emulator_up->ReadInstruction())
- return LLDB_INVALID_ADDRESS;
-
- if (emulator_up->EvaluateInstruction(lldb::eEmulateInstructionOptionNone))
- return baton.m_watch_hit_addr;
-
- return LLDB_INVALID_ADDRESS;
-}
-
-uint32_t NativeRegisterContextLinux_mips64::NumSupportedHardwareWatchpoints() {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
- struct pt_watch_regs regs;
- static int num_valid = 0;
- if (!num_valid) {
- DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(®s));
- default_watch_regs =
- regs; // Keeping default watch regs values for future use
- switch (regs.style) {
- case pt_watch_style_mips32:
- num_valid = regs.mips32.num_valid; // Using num_valid as cache
- return num_valid;
- case pt_watch_style_mips64:
- num_valid = regs.mips64.num_valid;
- return num_valid;
- }
- LLDB_LOG(log, "Invalid watch register style");
- return 0;
- }
- return num_valid;
-}
-
-Status
-NativeRegisterContextLinux_mips64::ReadRegisterRaw(uint32_t reg_index,
- RegisterValue &value) {
- const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg_index);
-
- if (!reg_info)
- return Status("register %" PRIu32 " not found", reg_index);
-
- uint32_t offset = reg_info->kinds[lldb::eRegisterKindProcessPlugin];
-
- if ((offset == ptrace_sr_mips) || (offset == ptrace_config5_mips))
- return Read_SR_Config(reg_info->byte_offset, reg_info->name,
- reg_info->byte_size, value);
-
- return DoReadRegisterValue(offset, reg_info->name, reg_info->byte_size,
- value);
-}
-
-Status NativeRegisterContextLinux_mips64::WriteRegisterRaw(
- uint32_t reg_index, const RegisterValue &value) {
- const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg_index);
-
- if (!reg_info)
- return Status("register %" PRIu32 " not found", reg_index);
-
- if (reg_info->invalidate_regs)
- lldbassert(false && "reg_info->invalidate_regs is unhandled");
-
- uint32_t offset = reg_info->kinds[lldb::eRegisterKindProcessPlugin];
- return DoWriteRegisterValue(offset, reg_info->name, value);
-}
-
-Status NativeRegisterContextLinux_mips64::Read_SR_Config(uint32_t offset,
- const char *reg_name,
- uint32_t size,
- RegisterValue &value) {
- GPR_linux_mips regs;
- ::memset(®s, 0, sizeof(GPR_linux_mips));
-
- Status error = NativeProcessLinux::PtraceWrapper(
- PTRACE_GETREGS, m_thread.GetID(), NULL, ®s, sizeof regs);
- if (error.Success()) {
- const lldb_private::ArchSpec &arch =
- m_thread.GetProcess().GetArchitecture();
- void *target_address = ((uint8_t *)®s) + offset +
- 4 * (arch.GetMachine() == llvm::Triple::mips);
- value.SetUInt(*(uint32_t *)target_address, size);
- }
- return error;
-}
-
-Status NativeRegisterContextLinux_mips64::DoReadWatchPointRegisterValue(
- lldb::tid_t tid, void *watch_readback) {
- return NativeProcessLinux::PtraceWrapper(PTRACE_GET_WATCH_REGS,
- m_thread.GetID(), watch_readback);
-}
-
-Status NativeRegisterContextLinux_mips64::DoWriteWatchPointRegisterValue(
- lldb::tid_t tid, void *watch_reg_value) {
- return NativeProcessLinux::PtraceWrapper(PTRACE_SET_WATCH_REGS,
- m_thread.GetID(), watch_reg_value);
-}
-
-#endif // defined (__mips__)
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h b/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h
deleted file mode 100644
index 5465b84..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h
+++ /dev/null
@@ -1,139 +0,0 @@
-//===-- NativeRegisterContextLinux_mips64.h ---------------------*- 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
-//
-//===----------------------------------------------------------------------===//
-
-#if defined(__mips__)
-
-#ifndef lldb_NativeRegisterContextLinux_mips64_h
-#define lldb_NativeRegisterContextLinux_mips64_h
-
-#include "Plugins/Process/Linux/NativeRegisterContextLinux.h"
-#include "Plugins/Process/Utility/RegisterContext_mips.h"
-#include "Plugins/Process/Utility/lldb-mips-linux-register-enums.h"
-#include <sys/uio.h>
-
-#define MAX_NUM_WP 8
-
-namespace lldb_private {
-namespace process_linux {
-
-class NativeProcessLinux;
-
-class NativeRegisterContextLinux_mips64 : public NativeRegisterContextLinux {
-public:
- NativeRegisterContextLinux_mips64(const ArchSpec &target_arch,
- NativeThreadProtocol &native_thread);
-
- uint32_t GetRegisterSetCount() const override;
-
- lldb::addr_t GetPCfromBreakpointLocation(
- lldb::addr_t fail_value = LLDB_INVALID_ADDRESS) override;
-
- lldb::addr_t GetWatchpointHitAddress(uint32_t wp_index) override;
-
- const RegisterSet *GetRegisterSet(uint32_t set_index) const override;
-
- Status ReadRegister(const RegisterInfo *reg_info,
- RegisterValue ®_value) override;
-
- Status WriteRegister(const RegisterInfo *reg_info,
- const RegisterValue ®_value) override;
-
- Status ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
-
- Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
-
- Status ReadCP1();
-
- Status WriteCP1();
-
- uint8_t *ReturnFPOffset(uint8_t reg_index, uint32_t byte_offset);
-
- Status IsWatchpointHit(uint32_t wp_index, bool &is_hit) override;
-
- Status GetWatchpointHitIndex(uint32_t &wp_index,
- lldb::addr_t trap_addr) override;
-
- Status IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override;
-
- bool ClearHardwareWatchpoint(uint32_t wp_index) override;
-
- Status ClearAllHardwareWatchpoints() override;
-
- Status SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size,
- uint32_t watch_flags,
- uint32_t wp_index);
-
- uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size,
- uint32_t watch_flags) override;
-
- lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override;
-
- uint32_t NumSupportedHardwareWatchpoints() override;
-
- static bool IsMSAAvailable();
-
-protected:
- Status Read_SR_Config(uint32_t offset, const char *reg_name, uint32_t size,
- RegisterValue &value);
-
- Status ReadRegisterRaw(uint32_t reg_index, RegisterValue &value) override;
-
- Status WriteRegisterRaw(uint32_t reg_index,
- const RegisterValue &value) override;
-
- Status DoReadWatchPointRegisterValue(lldb::tid_t tid, void *watch_readback);
-
- Status DoWriteWatchPointRegisterValue(lldb::tid_t tid, void *watch_readback);
-
- bool IsFR0();
-
- bool IsFRE();
-
- bool IsFPR(uint32_t reg_index) const;
-
- bool IsMSA(uint32_t reg_index) const;
-
- void *GetGPRBuffer() override { return &m_gpr; }
-
- void *GetFPRBuffer() override { return &m_fpr; }
-
- size_t GetFPRSize() override { return sizeof(FPR_linux_mips); }
-
-private:
- // Info about register ranges.
- struct RegInfo {
- uint32_t num_registers;
- uint32_t num_gpr_registers;
- uint32_t num_fpr_registers;
-
- uint32_t last_gpr;
- uint32_t first_fpr;
- uint32_t last_fpr;
- uint32_t first_msa;
- uint32_t last_msa;
- };
-
- RegInfo m_reg_info;
-
- GPR_linux_mips m_gpr;
-
- FPR_linux_mips m_fpr;
-
- MSA_linux_mips m_msa;
-
- lldb::addr_t hw_addr_map[MAX_NUM_WP];
-
- struct iovec m_iovec;
-};
-
-} // namespace process_linux
-} // namespace lldb_private
-
-#endif // #ifndef lldb_NativeRegisterContextLinux_mips64_h
-
-#endif // defined (__mips__)
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.cpp b/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.cpp
index 22acbda..60582e4 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.cpp
@@ -115,7 +115,7 @@
std::unique_ptr<NativeRegisterContextLinux>
NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
- const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
+ const ArchSpec &target_arch, NativeThreadLinux &native_thread) {
switch (target_arch.GetMachine()) {
case llvm::Triple::ppc64le:
return std::make_unique<NativeRegisterContextLinux_ppc64le>(target_arch,
@@ -128,7 +128,8 @@
NativeRegisterContextLinux_ppc64le::NativeRegisterContextLinux_ppc64le(
const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
: NativeRegisterContextRegisterInfo(
- native_thread, new RegisterInfoPOSIX_ppc64le(target_arch)) {
+ native_thread, new RegisterInfoPOSIX_ppc64le(target_arch)),
+ NativeRegisterContextLinux(native_thread) {
if (target_arch.GetMachine() != llvm::Triple::ppc64le) {
llvm_unreachable("Unhandled target architecture.");
}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp b/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp
index 098aa34..3c09164 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp
@@ -93,7 +93,7 @@
std::unique_ptr<NativeRegisterContextLinux>
NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
- const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
+ const ArchSpec &target_arch, NativeThreadLinux &native_thread) {
return std::make_unique<NativeRegisterContextLinux_s390x>(target_arch,
native_thread);
}
@@ -110,7 +110,8 @@
NativeRegisterContextLinux_s390x::NativeRegisterContextLinux_s390x(
const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
: NativeRegisterContextRegisterInfo(
- native_thread, CreateRegisterInfoInterface(target_arch)) {
+ native_thread, CreateRegisterInfoInterface(target_arch)),
+ NativeRegisterContextLinux(native_thread) {
// Set up data about ranges of valid registers.
switch (target_arch.GetMachine()) {
case llvm::Triple::systemz:
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp b/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
index c6aa320..bd4b168 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
@@ -10,14 +10,14 @@
#include "NativeRegisterContextLinux_x86_64.h"
+#include "Plugins/Process/Linux/NativeThreadLinux.h"
+#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
+#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
-
-#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
-#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
#include <cpuid.h>
#include <linux/elf.h>
@@ -250,7 +250,7 @@
std::unique_ptr<NativeRegisterContextLinux>
NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
- const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
+ const ArchSpec &target_arch, NativeThreadLinux &native_thread) {
return std::unique_ptr<NativeRegisterContextLinux>(
new NativeRegisterContextLinux_x86_64(target_arch, native_thread));
}
@@ -292,6 +292,8 @@
const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
: NativeRegisterContextRegisterInfo(
native_thread, CreateRegisterInfoInterface(target_arch)),
+ NativeRegisterContextLinux(native_thread),
+ NativeRegisterContextDBReg_x86(native_thread),
m_xstate_type(XStateType::Invalid), m_ymm_set(), m_mpx_set(),
m_reg_info(), m_gpr_x86_64() {
// Set up data about ranges of valid registers.
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h b/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h
index 82270dd..8287e49 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h
@@ -12,7 +12,7 @@
#define lldb_NativeRegisterContextLinux_x86_64_h
#include "Plugins/Process/Linux/NativeRegisterContextLinux.h"
-#include "Plugins/Process/Utility/NativeRegisterContextWatchpoint_x86.h"
+#include "Plugins/Process/Utility/NativeRegisterContextDBReg_x86.h"
#include "Plugins/Process/Utility/RegisterContext_x86.h"
#include "Plugins/Process/Utility/lldb-x86-register-enums.h"
#include <sys/uio.h>
@@ -24,7 +24,7 @@
class NativeRegisterContextLinux_x86_64
: public NativeRegisterContextLinux,
- public NativeRegisterContextWatchpoint_x86 {
+ public NativeRegisterContextDBReg_x86 {
public:
NativeRegisterContextLinux_x86_64(const ArchSpec &target_arch,
NativeThreadProtocol &native_thread);
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp b/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp
index 5aec98b..a7e4e9b 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp
@@ -8,7 +8,7 @@
#include "NativeThreadLinux.h"
-#include <signal.h>
+#include <csignal>
#include <sstream>
#include "NativeProcessLinux.h"
@@ -26,6 +26,7 @@
#include "llvm/ADT/SmallString.h"
#include "Plugins/Process/POSIX/CrashReason.h"
+#include "Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h"
#include <sys/syscall.h>
// Try to define a macro to encapsulate the tgkill syscall
@@ -77,6 +78,9 @@
case eStopReasonInstrumentation:
log.Printf("%s: %s instrumentation", __FUNCTION__, header);
return;
+ case eStopReasonProcessorTrace:
+ log.Printf("%s: %s processor trace", __FUNCTION__, header);
+ return;
default:
log.Printf("%s: %s invalid stop reason %" PRIu32, __FUNCTION__, header,
static_cast<uint32_t>(stop_info.reason));
@@ -296,11 +300,69 @@
? CrashReason::eInvalidAddress
: GetCrashReason(*info);
m_stop_description = GetCrashReasonString(reason, *info);
+
+ if (reason == CrashReason::eSyncTagCheckFault) {
+ AnnotateSyncTagCheckFault(info);
+ }
+
break;
}
}
}
+void NativeThreadLinux::AnnotateSyncTagCheckFault(const siginfo_t *info) {
+ int32_t allocation_tag_type = 0;
+ switch (GetProcess().GetArchitecture().GetMachine()) {
+ // aarch64_32 deliberately not here because there's no 32 bit MTE
+ case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_be:
+ allocation_tag_type = MemoryTagManagerAArch64MTE::eMTE_allocation;
+ break;
+ default:
+ return;
+ }
+
+ auto details =
+ GetRegisterContext().GetMemoryTaggingDetails(allocation_tag_type);
+ if (!details) {
+ llvm::consumeError(details.takeError());
+ return;
+ }
+
+ // We assume that the stop description is currently:
+ // signal SIGSEGV: sync tag check fault (fault address: <addr>)
+ // Remove the closing )
+ m_stop_description.pop_back();
+
+ std::stringstream ss;
+ lldb::addr_t fault_addr = reinterpret_cast<uintptr_t>(info->si_addr);
+ std::unique_ptr<MemoryTagManager> manager(std::move(details->manager));
+
+ ss << " logical tag: 0x" << std::hex << manager->GetLogicalTag(fault_addr);
+
+ std::vector<uint8_t> allocation_tag_data;
+ // The fault address may not be granule aligned. ReadMemoryTags will granule
+ // align any range you give it, potentially making it larger.
+ // To prevent this set len to 1. This always results in a range that is at
+ // most 1 granule in size and includes fault_addr.
+ Status status = GetProcess().ReadMemoryTags(allocation_tag_type, fault_addr,
+ 1, allocation_tag_data);
+
+ if (status.Success()) {
+ llvm::Expected<std::vector<lldb::addr_t>> allocation_tag =
+ manager->UnpackTagsData(allocation_tag_data, 1);
+ if (allocation_tag) {
+ ss << " allocation tag: 0x" << std::hex << allocation_tag->front() << ")";
+ } else {
+ llvm::consumeError(allocation_tag.takeError());
+ ss << ")";
+ }
+ } else
+ ss << ")";
+
+ m_stop_description += ss.str();
+}
+
bool NativeThreadLinux::IsStopped(int *signo) {
if (!StateIsStoppedState(m_state, false))
return false;
@@ -391,6 +453,21 @@
m_stop_info.details.signal.signo = SIGTRAP;
}
+void NativeThreadLinux::SetStoppedByFork(bool is_vfork, lldb::pid_t child_pid) {
+ SetStopped();
+
+ m_stop_info.reason =
+ is_vfork ? StopReason::eStopReasonVFork : StopReason::eStopReasonFork;
+ m_stop_info.details.fork.child_pid = child_pid;
+ m_stop_info.details.fork.child_tid = child_pid;
+}
+
+void NativeThreadLinux::SetStoppedByVForkDone() {
+ SetStopped();
+
+ m_stop_info.reason = StopReason::eStopReasonVForkDone;
+}
+
void NativeThreadLinux::SetStoppedWithNoReason() {
SetStopped();
@@ -398,6 +475,15 @@
m_stop_info.details.signal.signo = 0;
}
+void NativeThreadLinux::SetStoppedByProcessorTrace(
+ llvm::StringRef description) {
+ SetStopped();
+
+ m_stop_info.reason = StopReason::eStopReasonProcessorTrace;
+ m_stop_info.details.signal.signo = 0;
+ m_stop_description = description.str();
+}
+
void NativeThreadLinux::SetExited() {
const StateType new_state = StateType::eStateExited;
MaybeLogStateChange(new_state);
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h b/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h
index fd43c89..c18665b 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h
@@ -14,6 +14,8 @@
#include "lldb/Host/common/NativeThreadProtocol.h"
#include "lldb/lldb-private-forward.h"
+#include "llvm/ADT/StringRef.h"
+
#include <csignal>
#include <map>
#include <memory>
@@ -51,6 +53,8 @@
Status RemoveHardwareBreakpoint(lldb::addr_t addr) override;
+ NativeProcessLinux &GetProcess();
+
private:
// Interface for friend classes
@@ -81,8 +85,14 @@
void SetStoppedByTrace();
+ void SetStoppedByFork(bool is_vfork, lldb::pid_t child_pid);
+
+ void SetStoppedByVForkDone();
+
void SetStoppedWithNoReason();
+ void SetStoppedByProcessorTrace(llvm::StringRef description);
+
void SetExited();
Status RequestStop();
@@ -90,10 +100,13 @@
// Private interface
void MaybeLogStateChange(lldb::StateType new_state);
- NativeProcessLinux &GetProcess();
-
void SetStopped();
+ /// Extend m_stop_description with logical and allocation tag values.
+ /// If there is an error along the way just add the information we were able
+ /// to get.
+ void AnnotateSyncTagCheckFault(const siginfo_t *info);
+
// Member Variables
lldb::StateType m_state;
ThreadStopInfo m_stop_info;
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Linux/ProcessorTrace.cpp b/src/llvm-project/lldb/source/Plugins/Process/Linux/ProcessorTrace.cpp
deleted file mode 100644
index 1a8aa36..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/Linux/ProcessorTrace.cpp
+++ /dev/null
@@ -1,428 +0,0 @@
-//===-- ProcessorTrace.cpp ------------------------------------------------===//
-//
-// 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 <algorithm>
-#include <fstream>
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/MathExtras.h"
-
-#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
-#include "ProcessorTrace.h"
-#include "lldb/Host/linux/Support.h"
-
-#include <sys/ioctl.h>
-#include <sys/syscall.h>
-
-using namespace lldb;
-using namespace lldb_private;
-using namespace process_linux;
-using namespace llvm;
-
-lldb::user_id_t ProcessorTraceMonitor::m_trace_num = 1;
-const char *kOSEventIntelPTTypeFile =
- "/sys/bus/event_source/devices/intel_pt/type";
-
-Status ProcessorTraceMonitor::GetTraceConfig(TraceOptions &config) const {
-#ifndef PERF_ATTR_SIZE_VER5
- llvm_unreachable("perf event not supported");
-#else
- Status error;
-
- config.setType(lldb::TraceType::eTraceTypeProcessorTrace);
- config.setMetaDataBufferSize(m_mmap_meta->data_size);
-
- config.setTraceBufferSize(m_mmap_meta->aux_size);
-
- error = GetCPUType(config);
-
- return error;
-#endif
-}
-
-Expected<uint32_t> ProcessorTraceMonitor::GetOSEventType() {
- auto intel_pt_type_text =
- llvm::MemoryBuffer::getFileAsStream(kOSEventIntelPTTypeFile);
-
- if (!intel_pt_type_text)
- return createStringError(inconvertibleErrorCode(),
- "Can't open the file '%s'",
- kOSEventIntelPTTypeFile);
-
- uint32_t intel_pt_type = 0;
- StringRef buffer = intel_pt_type_text.get()->getBuffer();
- if (buffer.trim().getAsInteger(10, intel_pt_type))
- return createStringError(
- inconvertibleErrorCode(),
- "The file '%s' has a invalid value. It should be an unsigned int.",
- kOSEventIntelPTTypeFile);
- return intel_pt_type;
-}
-
-bool ProcessorTraceMonitor::IsSupported() { return (bool)GetOSEventType(); }
-
-Status ProcessorTraceMonitor::StartTrace(lldb::pid_t pid, lldb::tid_t tid,
- const TraceOptions &config) {
-#ifndef PERF_ATTR_SIZE_VER5
- llvm_unreachable("perf event not supported");
-#else
- Status error;
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
-
- LLDB_LOG(log, "called thread id {0}", tid);
- uint64_t page_size = getpagesize();
- uint64_t bufsize = config.getTraceBufferSize();
- uint64_t metabufsize = config.getMetaDataBufferSize();
-
- uint64_t numpages = static_cast<uint64_t>(
- llvm::PowerOf2Floor((bufsize + page_size - 1) / page_size));
- numpages = std::max<uint64_t>(1, numpages);
- bufsize = page_size * numpages;
-
- numpages = static_cast<uint64_t>(
- llvm::PowerOf2Floor((metabufsize + page_size - 1) / page_size));
- metabufsize = page_size * numpages;
-
- perf_event_attr attr;
- memset(&attr, 0, sizeof(attr));
- attr.size = sizeof(attr);
- attr.exclude_kernel = 1;
- attr.sample_type = PERF_SAMPLE_TIME;
- attr.sample_id_all = 1;
- attr.exclude_hv = 1;
- attr.exclude_idle = 1;
- attr.mmap = 1;
-
- Expected<uint32_t> intel_pt_type = GetOSEventType();
-
- if (!intel_pt_type) {
- error = intel_pt_type.takeError();
- return error;
- }
-
- LLDB_LOG(log, "intel pt type {0}", *intel_pt_type);
- attr.type = *intel_pt_type;
-
- LLDB_LOG(log, "meta buffer size {0}", metabufsize);
- LLDB_LOG(log, "buffer size {0} ", bufsize);
-
- if (error.Fail()) {
- LLDB_LOG(log, "Status in custom config");
-
- return error;
- }
-
- errno = 0;
- auto fd =
- syscall(SYS_perf_event_open, &attr, static_cast<::tid_t>(tid), -1, -1, 0);
- if (fd == -1) {
- LLDB_LOG(log, "syscall error {0}", errno);
- error.SetErrorString("perf event syscall Failed");
- return error;
- }
-
- m_fd = std::unique_ptr<int, file_close>(new int(fd), file_close());
-
- errno = 0;
- auto base =
- mmap(nullptr, (metabufsize + page_size), PROT_WRITE, MAP_SHARED, fd, 0);
-
- if (base == MAP_FAILED) {
- LLDB_LOG(log, "mmap base error {0}", errno);
- error.SetErrorString("Meta buffer allocation failed");
- return error;
- }
-
- m_mmap_meta = std::unique_ptr<perf_event_mmap_page, munmap_delete>(
- reinterpret_cast<perf_event_mmap_page *>(base),
- munmap_delete(metabufsize + page_size));
-
- m_mmap_meta->aux_offset = m_mmap_meta->data_offset + m_mmap_meta->data_size;
- m_mmap_meta->aux_size = bufsize;
-
- errno = 0;
- auto mmap_aux = mmap(nullptr, bufsize, PROT_READ, MAP_SHARED, fd,
- static_cast<long int>(m_mmap_meta->aux_offset));
-
- if (mmap_aux == MAP_FAILED) {
- LLDB_LOG(log, "second mmap done {0}", errno);
- error.SetErrorString("Trace buffer allocation failed");
- return error;
- }
- m_mmap_aux = std::unique_ptr<uint8_t, munmap_delete>(
- reinterpret_cast<uint8_t *>(mmap_aux), munmap_delete(bufsize));
- return error;
-#endif
-}
-
-llvm::MutableArrayRef<uint8_t> ProcessorTraceMonitor::GetDataBuffer() {
-#ifndef PERF_ATTR_SIZE_VER5
- llvm_unreachable("perf event not supported");
-#else
- return MutableArrayRef<uint8_t>(
- (reinterpret_cast<uint8_t *>(m_mmap_meta.get()) +
- m_mmap_meta->data_offset),
- m_mmap_meta->data_size);
-#endif
-}
-
-llvm::MutableArrayRef<uint8_t> ProcessorTraceMonitor::GetAuxBuffer() {
-#ifndef PERF_ATTR_SIZE_VER5
- llvm_unreachable("perf event not supported");
-#else
- return MutableArrayRef<uint8_t>(m_mmap_aux.get(), m_mmap_meta->aux_size);
-#endif
-}
-
-Status ProcessorTraceMonitor::GetCPUType(TraceOptions &config) {
-
- Status error;
- uint64_t cpu_family = -1;
- uint64_t model = -1;
- uint64_t stepping = -1;
- std::string vendor_id;
-
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
-
- auto BufferOrError = getProcFile("cpuinfo");
- if (!BufferOrError)
- return BufferOrError.getError();
-
- LLDB_LOG(log, "GetCPUType Function");
-
- StringRef Rest = BufferOrError.get()->getBuffer();
- while (!Rest.empty()) {
- StringRef Line;
- std::tie(Line, Rest) = Rest.split('\n');
-
- SmallVector<StringRef, 2> columns;
- Line.split(columns, StringRef(":"), -1, false);
-
- if (columns.size() < 2)
- continue; // continue searching
-
- columns[1] = columns[1].trim(" ");
- if (columns[0].contains("cpu family") &&
- columns[1].getAsInteger(10, cpu_family))
- continue;
-
- else if (columns[0].contains("model") && columns[1].getAsInteger(10, model))
- continue;
-
- else if (columns[0].contains("stepping") &&
- columns[1].getAsInteger(10, stepping))
- continue;
-
- else if (columns[0].contains("vendor_id")) {
- vendor_id = columns[1].str();
- if (!vendor_id.empty())
- continue;
- }
- LLDB_LOG(log, "{0}:{1}:{2}:{3}", cpu_family, model, stepping, vendor_id);
-
- if ((cpu_family != static_cast<uint64_t>(-1)) &&
- (model != static_cast<uint64_t>(-1)) &&
- (stepping != static_cast<uint64_t>(-1)) && (!vendor_id.empty())) {
- auto params_dict = std::make_shared<StructuredData::Dictionary>();
- params_dict->AddIntegerItem("cpu_family", cpu_family);
- params_dict->AddIntegerItem("cpu_model", model);
- params_dict->AddIntegerItem("cpu_stepping", stepping);
- params_dict->AddStringItem("cpu_vendor", vendor_id);
-
- llvm::StringRef intel_custom_params_key("intel-pt");
-
- auto intel_custom_params = std::make_shared<StructuredData::Dictionary>();
- intel_custom_params->AddItem(
- intel_custom_params_key,
- StructuredData::ObjectSP(std::move(params_dict)));
-
- config.setTraceParams(intel_custom_params);
- return error; // we are done
- }
- }
-
- error.SetErrorString("cpu info not found");
- return error;
-}
-
-llvm::Expected<ProcessorTraceMonitorUP>
-ProcessorTraceMonitor::Create(lldb::pid_t pid, lldb::tid_t tid,
- const TraceOptions &config,
- bool useProcessSettings) {
-
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
-
- Status error;
- if (tid == LLDB_INVALID_THREAD_ID) {
- error.SetErrorString("thread not specified");
- return error.ToError();
- }
-
- ProcessorTraceMonitorUP pt_monitor_up(new ProcessorTraceMonitor);
-
- error = pt_monitor_up->StartTrace(pid, tid, config);
- if (error.Fail())
- return error.ToError();
-
- pt_monitor_up->SetThreadID(tid);
-
- if (useProcessSettings) {
- pt_monitor_up->SetTraceID(0);
- } else {
- pt_monitor_up->SetTraceID(m_trace_num++);
- LLDB_LOG(log, "Trace ID {0}", m_trace_num);
- }
- return std::move(pt_monitor_up);
-}
-
-Status
-ProcessorTraceMonitor::ReadPerfTraceAux(llvm::MutableArrayRef<uint8_t> &buffer,
- size_t offset) {
-#ifndef PERF_ATTR_SIZE_VER5
- llvm_unreachable("perf event not supported");
-#else
- // Disable the perf event to force a flush out of the CPU's internal buffer.
- // Besides, we can guarantee that the CPU won't override any data as we are
- // reading the buffer.
- //
- // The Intel documentation says:
- //
- // Packets are first buffered internally and then written out asynchronously.
- // To collect packet output for postprocessing, a collector needs first to
- // ensure that all packet data has been flushed from internal buffers.
- // Software can ensure this by stopping packet generation by clearing
- // IA32_RTIT_CTL.TraceEn (see “Disabling Packet Generation” in
- // Section 35.2.7.2).
- //
- // This is achieved by the PERF_EVENT_IOC_DISABLE ioctl request, as mentioned
- // in the man page of perf_event_open.
- ioctl(*m_fd, PERF_EVENT_IOC_DISABLE);
-
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
- Status error;
- uint64_t head = m_mmap_meta->aux_head;
-
- LLDB_LOG(log, "Aux size -{0} , Head - {1}", m_mmap_meta->aux_size, head);
-
- /**
- * When configured as ring buffer, the aux buffer keeps wrapping around
- * the buffer and its not possible to detect how many times the buffer
- * wrapped. Initially the buffer is filled with zeros,as shown below
- * so in order to get complete buffer we first copy firstpartsize, followed
- * by any left over part from beginning to aux_head
- *
- * aux_offset [d,d,d,d,d,d,d,d,0,0,0,0,0,0,0,0,0,0,0] aux_size
- * aux_head->||<- firstpartsize ->|
- *
- * */
-
- ReadCyclicBuffer(buffer, GetAuxBuffer(), static_cast<size_t>(head), offset);
- LLDB_LOG(log, "ReadCyclic BUffer Done");
-
- // Reenable tracing now we have read the buffer
- ioctl(*m_fd, PERF_EVENT_IOC_ENABLE);
- return error;
-#endif
-}
-
-Status
-ProcessorTraceMonitor::ReadPerfTraceData(llvm::MutableArrayRef<uint8_t> &buffer,
- size_t offset) {
-#ifndef PERF_ATTR_SIZE_VER5
- llvm_unreachable("perf event not supported");
-#else
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
- uint64_t bytes_remaining = buffer.size();
- Status error;
-
- uint64_t head = m_mmap_meta->data_head;
-
- /*
- * The data buffer and aux buffer have different implementations
- * with respect to their definition of head pointer. In the case
- * of Aux data buffer the head always wraps around the aux buffer
- * and we don't need to care about it, whereas the data_head keeps
- * increasing and needs to be wrapped by modulus operator
- */
-
- LLDB_LOG(log, "bytes_remaining - {0}", bytes_remaining);
-
- auto data_buffer = GetDataBuffer();
-
- if (head > data_buffer.size()) {
- head = head % data_buffer.size();
- LLDB_LOG(log, "Data size -{0} Head - {1}", m_mmap_meta->data_size, head);
-
- ReadCyclicBuffer(buffer, data_buffer, static_cast<size_t>(head), offset);
- bytes_remaining -= buffer.size();
- } else {
- LLDB_LOG(log, "Head - {0}", head);
- if (offset >= head) {
- LLDB_LOG(log, "Invalid Offset ");
- error.SetErrorString("invalid offset");
- buffer = buffer.slice(buffer.size());
- return error;
- }
-
- auto data = data_buffer.slice(offset, (head - offset));
- auto remaining = std::copy(data.begin(), data.end(), buffer.begin());
- bytes_remaining -= (remaining - buffer.begin());
- }
- buffer = buffer.drop_back(bytes_remaining);
- return error;
-#endif
-}
-
-void ProcessorTraceMonitor::ReadCyclicBuffer(
- llvm::MutableArrayRef<uint8_t> &dst, llvm::MutableArrayRef<uint8_t> src,
- size_t src_cyc_index, size_t offset) {
-
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
-
- if (dst.empty() || src.empty()) {
- dst = dst.drop_back(dst.size());
- return;
- }
-
- if (dst.data() == nullptr || src.data() == nullptr) {
- dst = dst.drop_back(dst.size());
- return;
- }
-
- if (src_cyc_index > src.size()) {
- dst = dst.drop_back(dst.size());
- return;
- }
-
- if (offset >= src.size()) {
- LLDB_LOG(log, "Too Big offset ");
- dst = dst.drop_back(dst.size());
- return;
- }
-
- llvm::SmallVector<MutableArrayRef<uint8_t>, 2> parts = {
- src.slice(src_cyc_index), src.take_front(src_cyc_index)};
-
- if (offset > parts[0].size()) {
- parts[1] = parts[1].slice(offset - parts[0].size());
- parts[0] = parts[0].drop_back(parts[0].size());
- } else if (offset == parts[0].size()) {
- parts[0] = parts[0].drop_back(parts[0].size());
- } else {
- parts[0] = parts[0].slice(offset);
- }
- auto next = dst.begin();
- auto bytes_left = dst.size();
- for (auto part : parts) {
- size_t chunk_size = std::min(part.size(), bytes_left);
- next = std::copy_n(part.begin(), chunk_size, next);
- bytes_left -= chunk_size;
- }
- dst = dst.drop_back(bytes_left);
-}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Linux/ProcessorTrace.h b/src/llvm-project/lldb/source/Plugins/Process/Linux/ProcessorTrace.h
deleted file mode 100644
index 29f98cc..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/Linux/ProcessorTrace.h
+++ /dev/null
@@ -1,140 +0,0 @@
-//===-- ProcessorTrace.h -------------------------------------- -*- 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_ProcessorTrace_H_
-#define liblldb_ProcessorTrace_H_
-
-#include "lldb/Utility/Status.h"
-#include "lldb/Utility/TraceOptions.h"
-#include "lldb/lldb-types.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/DenseSet.h"
-
-#include <linux/perf_event.h>
-#include <sys/mman.h>
-#include <unistd.h>
-
-namespace lldb_private {
-
-namespace process_linux {
-
-// This class keeps track of one tracing instance of
-// Intel(R) Processor Trace on Linux OS. There is a map keeping track
-// of different tracing instances on each thread, which enables trace
-// gathering on a per thread level.
-//
-// The tracing instance is linked with a trace id. The trace id acts like
-// a key to the tracing instance and trace manipulations could be
-// performed using the trace id.
-//
-// The trace id could map to trace instances for a group of threads
-// (spanning to all the threads in the process) or a single thread.
-// The kernel interface for us is the perf_event_open.
-
-class ProcessorTraceMonitor;
-typedef std::unique_ptr<ProcessorTraceMonitor> ProcessorTraceMonitorUP;
-
-class ProcessorTraceMonitor {
-
- class munmap_delete {
- size_t m_length;
-
- public:
- munmap_delete(size_t length) : m_length(length) {}
- void operator()(void *ptr) {
- if (m_length)
- munmap(ptr, m_length);
- }
- };
-
- class file_close {
-
- public:
- file_close() = default;
- void operator()(int *ptr) {
- if (ptr == nullptr)
- return;
- if (*ptr == -1)
- return;
- close(*ptr);
- std::default_delete<int>()(ptr);
- }
- };
-
- std::unique_ptr<perf_event_mmap_page, munmap_delete> m_mmap_meta;
- std::unique_ptr<uint8_t, munmap_delete> m_mmap_aux;
- std::unique_ptr<int, file_close> m_fd;
-
- // perf_event_mmap_page *m_mmap_base;
- lldb::user_id_t m_traceid;
- lldb::tid_t m_thread_id;
-
- // Counter to track trace instances.
- static lldb::user_id_t m_trace_num;
-
- void SetTraceID(lldb::user_id_t traceid) { m_traceid = traceid; }
-
- Status StartTrace(lldb::pid_t pid, lldb::tid_t tid,
- const TraceOptions &config);
-
- llvm::MutableArrayRef<uint8_t> GetAuxBuffer();
- llvm::MutableArrayRef<uint8_t> GetDataBuffer();
-
- ProcessorTraceMonitor()
- : m_mmap_meta(nullptr, munmap_delete(0)),
- m_mmap_aux(nullptr, munmap_delete(0)), m_fd(nullptr, file_close()),
- m_traceid(LLDB_INVALID_UID), m_thread_id(LLDB_INVALID_THREAD_ID){};
-
- void SetThreadID(lldb::tid_t tid) { m_thread_id = tid; }
-
-public:
- static llvm::Expected<uint32_t> GetOSEventType();
-
- static bool IsSupported();
-
- static Status GetCPUType(TraceOptions &config);
-
- static llvm::Expected<ProcessorTraceMonitorUP>
- Create(lldb::pid_t pid, lldb::tid_t tid, const TraceOptions &config,
- bool useProcessSettings);
-
- Status ReadPerfTraceAux(llvm::MutableArrayRef<uint8_t> &buffer,
- size_t offset = 0);
-
- Status ReadPerfTraceData(llvm::MutableArrayRef<uint8_t> &buffer,
- size_t offset = 0);
-
- ~ProcessorTraceMonitor() = default;
-
- lldb::tid_t GetThreadID() const { return m_thread_id; }
-
- lldb::user_id_t GetTraceID() const { return m_traceid; }
-
- Status GetTraceConfig(TraceOptions &config) const;
-
- /// Read data from a cyclic buffer
- ///
- /// \param[in] [out] buf
- /// Destination buffer, the buffer will be truncated to written size.
- ///
- /// \param[in] src
- /// Source buffer which must be a cyclic buffer.
- ///
- /// \param[in] src_cyc_index
- /// The index pointer (start of the valid data in the cyclic
- /// buffer).
- ///
- /// \param[in] offset
- /// The offset to begin reading the data in the cyclic buffer.
- static void ReadCyclicBuffer(llvm::MutableArrayRef<uint8_t> &dst,
- llvm::MutableArrayRef<uint8_t> src,
- size_t src_cyc_index, size_t offset);
-};
-} // namespace process_linux
-} // namespace lldb_private
-#endif
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Linux/SingleStepCheck.cpp b/src/llvm-project/lldb/source/Plugins/Process/Linux/SingleStepCheck.cpp
index f0c6bdc..5b337f1 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Linux/SingleStepCheck.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Linux/SingleStepCheck.cpp
@@ -8,8 +8,8 @@
#include "SingleStepCheck.h"
+#include <csignal>
#include <sched.h>
-#include <signal.h>
#include <sys/wait.h>
#include <unistd.h>
diff --git a/src/llvm-project/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp b/src/llvm-project/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp
index fc0539a..d397d16 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp
@@ -8,10 +8,9 @@
#include "CommunicationKDP.h"
-#include <errno.h>
-#include <limits.h>
-#include <string.h>
-
+#include <cerrno>
+#include <climits>
+#include <cstring>
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Host/Host.h"
diff --git a/src/llvm-project/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/src/llvm-project/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
index 913c889..47b2f8d 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#include <errno.h>
-#include <stdlib.h>
+#include <cerrno>
+#include <cstdlib>
#include <memory>
#include <mutex>
@@ -73,7 +73,7 @@
m_collection_sp->Initialize(g_processkdp_properties);
}
- virtual ~PluginProperties() {}
+ virtual ~PluginProperties() = default;
uint64_t GetPacketTimeout() {
const uint32_t idx = ePropertyKDPPacketTimeout;
@@ -902,7 +902,7 @@
m_option_group.Finalize();
}
- ~CommandObjectProcessKDPPacketSend() {}
+ ~CommandObjectProcessKDPPacketSend() = default;
bool DoExecute(Args &command, CommandReturnObject &result) override {
const size_t argc = command.GetArgumentCount();
@@ -910,7 +910,6 @@
if (!m_command_byte.GetOptionValue().OptionWasSet()) {
result.AppendError(
"the --command option must be set to a valid command byte");
- result.SetStatus(eReturnStatusFailed);
} else {
const uint64_t command_byte =
m_command_byte.GetOptionValue().GetUInt64Value(0);
@@ -933,7 +932,6 @@
"even number of ASCII hex "
"characters: '%s'",
ascii_hex_bytes_cstr);
- result.SetStatus(eReturnStatusFailed);
return false;
}
payload_bytes.resize(ascii_hex_bytes_cstr_len / 2);
@@ -943,7 +941,6 @@
"ASCII hex characters (no "
"spaces or hex prefixes): '%s'",
ascii_hex_bytes_cstr);
- result.SetStatus(eReturnStatusFailed);
return false;
}
}
@@ -970,30 +967,25 @@
else
result.AppendErrorWithFormat("unknown error 0x%8.8x",
error.GetError());
- result.SetStatus(eReturnStatusFailed);
return false;
}
} else {
result.AppendErrorWithFormat("process must be stopped in order "
"to send KDP packets, state is %s",
StateAsCString(state));
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendError("invalid process");
- result.SetStatus(eReturnStatusFailed);
}
} else {
result.AppendErrorWithFormat("invalid command byte 0x%" PRIx64
", valid values are 1 - 255",
command_byte);
- result.SetStatus(eReturnStatusFailed);
}
}
} else {
result.AppendErrorWithFormat("'%s' takes no arguments, only options.",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
}
return false;
}
@@ -1011,7 +1003,7 @@
CommandObjectSP(new CommandObjectProcessKDPPacketSend(interpreter)));
}
- ~CommandObjectProcessKDPPacket() {}
+ ~CommandObjectProcessKDPPacket() = default;
};
class CommandObjectMultiwordProcessKDP : public CommandObjectMultiword {
@@ -1025,7 +1017,7 @@
interpreter)));
}
- ~CommandObjectMultiwordProcessKDP() {}
+ ~CommandObjectMultiwordProcessKDP() = default;
};
CommandObject *ProcessKDP::GetPluginCommandObject() {
diff --git a/src/llvm-project/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp b/src/llvm-project/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp
index 81b602a..64f0caa 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp
@@ -19,7 +19,7 @@
: RegisterContextDarwin_arm(thread, concrete_frame_idx),
m_kdp_thread(thread) {}
-RegisterContextKDP_arm::~RegisterContextKDP_arm() {}
+RegisterContextKDP_arm::~RegisterContextKDP_arm() = default;
int RegisterContextKDP_arm::DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) {
ProcessSP process_sp(CalculateProcess());
diff --git a/src/llvm-project/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm64.cpp b/src/llvm-project/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm64.cpp
index c5e7109..c56356d 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm64.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm64.cpp
@@ -19,7 +19,7 @@
: RegisterContextDarwin_arm64(thread, concrete_frame_idx),
m_kdp_thread(thread) {}
-RegisterContextKDP_arm64::~RegisterContextKDP_arm64() {}
+RegisterContextKDP_arm64::~RegisterContextKDP_arm64() = default;
int RegisterContextKDP_arm64::DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) {
ProcessSP process_sp(CalculateProcess());
diff --git a/src/llvm-project/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp b/src/llvm-project/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp
index aa46e46..61dfeae 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp
@@ -18,7 +18,7 @@
: RegisterContextDarwin_i386(thread, concrete_frame_idx),
m_kdp_thread(thread) {}
-RegisterContextKDP_i386::~RegisterContextKDP_i386() {}
+RegisterContextKDP_i386::~RegisterContextKDP_i386() = default;
int RegisterContextKDP_i386::DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) {
ProcessSP process_sp(CalculateProcess());
diff --git a/src/llvm-project/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp b/src/llvm-project/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp
index 565dd1c..9c47c22 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp
@@ -18,7 +18,7 @@
: RegisterContextDarwin_x86_64(thread, concrete_frame_idx),
m_kdp_thread(thread) {}
-RegisterContextKDP_x86_64::~RegisterContextKDP_x86_64() {}
+RegisterContextKDP_x86_64::~RegisterContextKDP_x86_64() = default;
int RegisterContextKDP_x86_64::DoReadGPR(lldb::tid_t tid, int flavor,
GPR &gpr) {
diff --git a/src/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/src/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
index 57f0eb3..9ea1a16 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
@@ -133,13 +133,20 @@
return std::move(process_up);
}
+NativeProcessNetBSD::Extension
+NativeProcessNetBSD::Factory::GetSupportedExtensions() const {
+ return Extension::multiprocess | Extension::fork | Extension::vfork |
+ Extension::pass_signals | Extension::auxv | Extension::libraries_svr4;
+}
+
// Public Instance Methods
NativeProcessNetBSD::NativeProcessNetBSD(::pid_t pid, int terminal_fd,
NativeDelegate &delegate,
const ArchSpec &arch,
MainLoop &mainloop)
- : NativeProcessELF(pid, terminal_fd, delegate), m_arch(arch) {
+ : NativeProcessELF(pid, terminal_fd, delegate), m_arch(arch),
+ m_main_loop(mainloop) {
if (m_terminal_fd != -1) {
Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK);
assert(status.Success());
@@ -256,6 +263,33 @@
SetState(StateType::eStateStopped, true);
return;
}
+ case TRAP_CHLD: {
+ ptrace_state_t pst;
+ Status error = PtraceWrapper(PT_GET_PROCESS_STATE, pid, &pst, sizeof(pst));
+ if (error.Fail()) {
+ SetState(StateType::eStateInvalid);
+ return;
+ }
+
+ assert(thread);
+ if (pst.pe_report_event == PTRACE_VFORK_DONE) {
+ if ((m_enabled_extensions & Extension::vfork) == Extension::vfork) {
+ thread->SetStoppedByVForkDone();
+ SetState(StateType::eStateStopped, true);
+ } else {
+ Status error =
+ PtraceWrapper(PT_CONTINUE, pid, reinterpret_cast<void *>(1), 0);
+ if (error.Fail())
+ SetState(StateType::eStateInvalid);
+ }
+ } else {
+ assert(pst.pe_report_event == PTRACE_FORK ||
+ pst.pe_report_event == PTRACE_VFORK);
+ MonitorClone(pst.pe_other_pid, pst.pe_report_event == PTRACE_VFORK,
+ *thread);
+ }
+ return;
+ }
case TRAP_LWP: {
ptrace_state_t pst;
Status error = PtraceWrapper(PT_GET_PROCESS_STATE, pid, &pst, sizeof(pst));
@@ -510,7 +544,7 @@
if (GetID() == LLDB_INVALID_PROCESS_ID)
return error;
- return PtraceWrapper(PT_DETACH, GetID());
+ return PtraceWrapper(PT_DETACH, GetID(), reinterpret_cast<void *>(1));
}
Status NativeProcessNetBSD::Signal(int signo) {
@@ -738,17 +772,17 @@
void NativeProcessNetBSD::SigchldHandler() {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
- // Process all pending waitpid notifications.
int status;
::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status,
WALLSIG | WNOHANG);
if (wait_pid == 0)
- return; // We are done.
+ return;
if (wait_pid == -1) {
Status error(errno, eErrorTypePOSIX);
LLDB_LOG(log, "waitpid ({0}, &status, _) failed: {1}", GetID(), error);
+ return;
}
WaitStatus wait_status = WaitStatus::Decode(status);
@@ -936,8 +970,9 @@
PtraceWrapper(PT_GET_EVENT_MASK, GetID(), &events, sizeof(events));
if (status.Fail())
return status;
- // TODO: PTRACE_FORK | PTRACE_VFORK | PTRACE_POSIX_SPAWN?
- events.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT;
+ // TODO: PTRACE_POSIX_SPAWN?
+ events.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT | PTRACE_FORK |
+ PTRACE_VFORK | PTRACE_VFORK_DONE;
status = PtraceWrapper(PT_SET_EVENT_MASK, GetID(), &events, sizeof(events));
if (status.Fail())
return status;
@@ -974,3 +1009,67 @@
return error;
}
+
+void NativeProcessNetBSD::MonitorClone(::pid_t child_pid, bool is_vfork,
+ NativeThreadNetBSD &parent_thread) {
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+ LLDB_LOG(log, "clone, child_pid={0}", child_pid);
+
+ int status;
+ ::pid_t wait_pid =
+ llvm::sys::RetryAfterSignal(-1, ::waitpid, child_pid, &status, 0);
+ if (wait_pid != child_pid) {
+ LLDB_LOG(log,
+ "waiting for pid {0} failed. Assuming the pid has "
+ "disappeared in the meantime",
+ child_pid);
+ return;
+ }
+ if (WIFEXITED(status)) {
+ LLDB_LOG(log,
+ "waiting for pid {0} returned an 'exited' event. Not "
+ "tracking it.",
+ child_pid);
+ return;
+ }
+
+ ptrace_siginfo_t info;
+ const auto siginfo_err =
+ PtraceWrapper(PT_GET_SIGINFO, child_pid, &info, sizeof(info));
+ if (siginfo_err.Fail()) {
+ LLDB_LOG(log, "PT_GET_SIGINFO failed {0}", siginfo_err);
+ return;
+ }
+ assert(info.psi_lwpid >= 0);
+ lldb::tid_t child_tid = info.psi_lwpid;
+
+ std::unique_ptr<NativeProcessNetBSD> child_process{
+ new NativeProcessNetBSD(static_cast<::pid_t>(child_pid), m_terminal_fd,
+ m_delegate, m_arch, m_main_loop)};
+ if (!is_vfork)
+ child_process->m_software_breakpoints = m_software_breakpoints;
+
+ Extension expected_ext = is_vfork ? Extension::vfork : Extension::fork;
+ if ((m_enabled_extensions & expected_ext) == expected_ext) {
+ child_process->SetupTrace();
+ for (const auto &thread : child_process->m_threads)
+ static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(SIGSTOP);
+ child_process->SetState(StateType::eStateStopped, false);
+
+ m_delegate.NewSubprocess(this, std::move(child_process));
+ if (is_vfork)
+ parent_thread.SetStoppedByVFork(child_pid, child_tid);
+ else
+ parent_thread.SetStoppedByFork(child_pid, child_tid);
+ SetState(StateType::eStateStopped, true);
+ } else {
+ child_process->Detach();
+ Status pt_error =
+ PtraceWrapper(PT_CONTINUE, GetID(), reinterpret_cast<void *>(1), 0);
+ if (pt_error.Fail()) {
+ LLDB_LOG_ERROR(log, std::move(pt_error.ToError()),
+ "unable to resume parent process {1}: {0}", GetID());
+ SetState(StateType::eStateInvalid);
+ }
+ }
+}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h b/src/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
index 3d59a4f..90d32aa 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
@@ -36,6 +36,8 @@
llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Attach(lldb::pid_t pid, NativeDelegate &native_delegate,
MainLoop &mainloop) const override;
+
+ Extension GetSupportedExtensions() const override;
};
// NativeProcessProtocol Interface
@@ -89,6 +91,7 @@
private:
MainLoop::SignalHandleUP m_sigchld_handle;
ArchSpec m_arch;
+ MainLoop& m_main_loop;
LazyBool m_supports_mem_region = eLazyBoolCalculate;
std::vector<std::pair<MemoryRegionInfo, FileSpec>> m_mem_region_cache;
@@ -106,6 +109,8 @@
void MonitorSIGSTOP(lldb::pid_t pid);
void MonitorSIGTRAP(lldb::pid_t pid);
void MonitorSignal(lldb::pid_t pid, int signal);
+ void MonitorClone(::pid_t child_pid, bool is_vfork,
+ NativeThreadNetBSD &parent_thread);
Status PopulateMemoryRegionCache();
void SigchldHandler();
diff --git a/src/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp b/src/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
index ed1884c..3d164ea 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
@@ -29,8 +29,8 @@
#include <x86/specialreg.h>
#include <elf.h>
#include <err.h>
-#include <stdint.h>
-#include <stdlib.h>
+#include <cstdint>
+#include <cstdlib>
// clang-format on
using namespace lldb_private;
@@ -267,7 +267,7 @@
const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
: NativeRegisterContextRegisterInfo(
native_thread, CreateRegisterInfoInterface(target_arch)),
- m_regset_offsets({0}) {
+ NativeRegisterContextDBReg_x86(native_thread), m_regset_offsets({0}) {
assert(m_gpr.size() == GetRegisterInfoInterface().GetGPRSize());
std::array<uint32_t, MaxRegularRegSet + 1> first_regnos;
diff --git a/src/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h b/src/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h
index d20fd67..3100595 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h
@@ -22,7 +22,7 @@
#include "Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h"
#include "Plugins/Process/Utility/RegisterContext_x86.h"
-#include "Plugins/Process/Utility/NativeRegisterContextWatchpoint_x86.h"
+#include "Plugins/Process/Utility/NativeRegisterContextDBReg_x86.h"
#include "Plugins/Process/Utility/lldb-x86-register-enums.h"
namespace lldb_private {
@@ -32,7 +32,7 @@
class NativeRegisterContextNetBSD_x86_64
: public NativeRegisterContextNetBSD,
- public NativeRegisterContextWatchpoint_x86 {
+ public NativeRegisterContextDBReg_x86 {
public:
NativeRegisterContextNetBSD_x86_64(const ArchSpec &target_arch,
NativeThreadProtocol &native_thread);
diff --git a/src/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp b/src/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
index 1a3fd4d..400b89a 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
@@ -130,6 +130,30 @@
m_stop_info.details.signal.signo = SIGTRAP;
}
+void NativeThreadNetBSD::SetStoppedByFork(lldb::pid_t child_pid,
+ lldb::tid_t child_tid) {
+ SetStopped();
+
+ m_stop_info.reason = StopReason::eStopReasonFork;
+ m_stop_info.details.fork.child_pid = child_pid;
+ m_stop_info.details.fork.child_tid = child_tid;
+}
+
+void NativeThreadNetBSD::SetStoppedByVFork(lldb::pid_t child_pid,
+ lldb::tid_t child_tid) {
+ SetStopped();
+
+ m_stop_info.reason = StopReason::eStopReasonVFork;
+ m_stop_info.details.fork.child_pid = child_pid;
+ m_stop_info.details.fork.child_tid = child_tid;
+}
+
+void NativeThreadNetBSD::SetStoppedByVForkDone() {
+ SetStopped();
+
+ m_stop_info.reason = StopReason::eStopReasonVForkDone;
+}
+
void NativeThreadNetBSD::SetStoppedWithNoReason() {
SetStopped();
diff --git a/src/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h b/src/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
index d4e21bd..ee93053 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
@@ -59,6 +59,9 @@
void SetStoppedByTrace();
void SetStoppedByExec();
void SetStoppedByWatchpoint(uint32_t wp_index);
+ void SetStoppedByFork(lldb::pid_t child_pid, lldb::tid_t child_tid);
+ void SetStoppedByVFork(lldb::pid_t child_pid, lldb::tid_t child_tid);
+ void SetStoppedByVForkDone();
void SetStoppedWithNoReason();
void SetStopped();
void SetRunning();
diff --git a/src/llvm-project/lldb/source/Plugins/Process/POSIX/CrashReason.h b/src/llvm-project/lldb/source/Plugins/Process/POSIX/CrashReason.h
index f521389..24acdc0 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/POSIX/CrashReason.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/POSIX/CrashReason.h
@@ -11,7 +11,7 @@
#include "lldb/lldb-types.h"
-#include <signal.h>
+#include <csignal>
#include <string>
diff --git a/src/llvm-project/lldb/source/Plugins/Process/POSIX/NativeProcessELF.h b/src/llvm-project/lldb/source/Plugins/Process/POSIX/NativeProcessELF.h
index dcfa929..c014099 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/POSIX/NativeProcessELF.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/POSIX/NativeProcessELF.h
@@ -21,6 +21,9 @@
class NativeProcessELF : public NativeProcessProtocol {
using NativeProcessProtocol::NativeProcessProtocol;
+public:
+ llvm::Optional<uint64_t> GetAuxValue(enum AuxVector::EntryType type);
+
protected:
template <typename T> struct ELFLinkMap {
T l_addr;
@@ -30,8 +33,6 @@
T l_prev;
};
- llvm::Optional<uint64_t> GetAuxValue(enum AuxVector::EntryType type);
-
lldb::addr_t GetSharedLibraryInfoAddress() override;
template <typename ELF_EHDR, typename ELF_PHDR, typename ELF_DYN>
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/CMakeLists.txt b/src/llvm-project/lldb/source/Plugins/Process/Utility/CMakeLists.txt
index 9965d89..1431876 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/CMakeLists.txt
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/CMakeLists.txt
@@ -8,9 +8,12 @@
InferiorCallPOSIX.cpp
LinuxProcMaps.cpp
LinuxSignals.cpp
+ MemoryTagManagerAArch64MTE.cpp
MipsLinuxSignals.cpp
+ NativeProcessSoftwareSingleStep.cpp
+ NativeRegisterContextDBReg_arm64.cpp
+ NativeRegisterContextDBReg_x86.cpp
NativeRegisterContextRegisterInfo.cpp
- NativeRegisterContextWatchpoint_x86.cpp
NetBSDSignals.cpp
RegisterContext_x86.cpp
RegisterContextDarwin_arm.cpp
@@ -25,8 +28,6 @@
RegisterContextHistory.cpp
RegisterContextLinux_i386.cpp
RegisterContextLinux_x86_64.cpp
- RegisterContextLinux_mips64.cpp
- RegisterContextLinux_mips.cpp
RegisterContextLinux_s390x.cpp
RegisterContextMach_arm.cpp
RegisterContextMach_i386.cpp
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
index 5463a07..a85d7bd 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
@@ -697,6 +697,14 @@
return nullptr;
}
+const RegisterInfo *DynamicRegisterInfo::GetRegisterInfo(uint32_t kind,
+ uint32_t num) const {
+ uint32_t reg_index = ConvertRegisterKindToRegisterNumber(kind, num);
+ if (reg_index != LLDB_INVALID_REGNUM)
+ return &m_regs[reg_index];
+ return nullptr;
+}
+
const RegisterSet *DynamicRegisterInfo::GetRegisterSet(uint32_t i) const {
if (i < m_sets.size())
return &m_sets[i];
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h b/src/llvm-project/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h
index fbf9db6..7e90454 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h
@@ -60,6 +60,9 @@
uint32_t ConvertRegisterKindToRegisterNumber(uint32_t kind,
uint32_t num) const;
+ const lldb_private::RegisterInfo *GetRegisterInfo(uint32_t kind,
+ uint32_t num) const;
+
void Dump() const;
void Clear();
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp
index 9b95229..7749dc6 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp
@@ -30,7 +30,7 @@
// Destructor
-HistoryUnwind::~HistoryUnwind() {}
+HistoryUnwind::~HistoryUnwind() = default;
void HistoryUnwind::DoClear() {
std::lock_guard<std::recursive_mutex> guard(m_unwind_mutex);
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/LinuxPTraceDefines_arm64sve.h b/src/llvm-project/lldb/source/Plugins/Process/Utility/LinuxPTraceDefines_arm64sve.h
index 7f6f7cf..817dca3 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/LinuxPTraceDefines_arm64sve.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/LinuxPTraceDefines_arm64sve.h
@@ -9,7 +9,7 @@
#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LINUXPTRACEDEFINES_ARM64SVE_H
#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LINUXPTRACEDEFINES_ARM64SVE_H
-#include <stdint.h>
+#include <cstdint>
namespace lldb_private {
namespace sve {
@@ -65,7 +65,7 @@
* The same convention applies when returning from a signal: a caller
* will need to remove or resize the sve_context block if it wants to
* make the SVE registers live when they were previously non-live or
- * vice-versa. This may require the the caller to allocate fresh
+ * vice-versa. This may require the caller to allocate fresh
* memory and/or move other context blocks in the signal frame.
*
* Changing the vector length during signal return is not permitted:
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.cpp
new file mode 100644
index 0000000..d74b66b
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.cpp
@@ -0,0 +1,200 @@
+//===-- MemoryTagManagerAArch64MTE.cpp --------------------------*- 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 "MemoryTagManagerAArch64MTE.h"
+
+using namespace lldb_private;
+
+static const unsigned MTE_START_BIT = 56;
+static const unsigned MTE_TAG_MAX = 0xf;
+static const unsigned MTE_GRANULE_SIZE = 16;
+
+lldb::addr_t
+MemoryTagManagerAArch64MTE::GetLogicalTag(lldb::addr_t addr) const {
+ return (addr >> MTE_START_BIT) & MTE_TAG_MAX;
+}
+
+lldb::addr_t
+MemoryTagManagerAArch64MTE::RemoveNonAddressBits(lldb::addr_t addr) const {
+ // Here we're ignoring the whole top byte. If you've got MTE
+ // you must also have TBI (top byte ignore).
+ // The other 4 bits could contain other extension bits or
+ // user metadata.
+ return addr & ~((lldb::addr_t)0xFF << MTE_START_BIT);
+}
+
+ptrdiff_t MemoryTagManagerAArch64MTE::AddressDiff(lldb::addr_t addr1,
+ lldb::addr_t addr2) const {
+ return RemoveNonAddressBits(addr1) - RemoveNonAddressBits(addr2);
+}
+
+lldb::addr_t MemoryTagManagerAArch64MTE::GetGranuleSize() const {
+ return MTE_GRANULE_SIZE;
+}
+
+int32_t MemoryTagManagerAArch64MTE::GetAllocationTagType() const {
+ return eMTE_allocation;
+}
+
+size_t MemoryTagManagerAArch64MTE::GetTagSizeInBytes() const { return 1; }
+
+MemoryTagManagerAArch64MTE::TagRange
+MemoryTagManagerAArch64MTE::ExpandToGranule(TagRange range) const {
+ // Ignore reading a length of 0
+ if (!range.IsValid())
+ return range;
+
+ const size_t granule = GetGranuleSize();
+
+ // Align start down to granule start
+ lldb::addr_t new_start = range.GetRangeBase();
+ lldb::addr_t align_down_amount = new_start % granule;
+ new_start -= align_down_amount;
+
+ // Account for the distance we moved the start above
+ size_t new_len = range.GetByteSize() + align_down_amount;
+ // Then align up to the end of the granule
+ size_t align_up_amount = granule - (new_len % granule);
+ if (align_up_amount != granule)
+ new_len += align_up_amount;
+
+ return TagRange(new_start, new_len);
+}
+
+llvm::Expected<MemoryTagManager::TagRange>
+MemoryTagManagerAArch64MTE::MakeTaggedRange(
+ lldb::addr_t addr, lldb::addr_t end_addr,
+ const lldb_private::MemoryRegionInfos &memory_regions) const {
+ // First check that the range is not inverted.
+ // We must remove tags here otherwise an address with a higher
+ // tag value will always be > the other.
+ ptrdiff_t len = AddressDiff(end_addr, addr);
+ if (len <= 0) {
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "End address (0x%" PRIx64
+ ") must be greater than the start address (0x%" PRIx64 ")",
+ end_addr, addr);
+ }
+
+ // Region addresses will not have memory tags. So when searching
+ // we must use an untagged address.
+ MemoryRegionInfo::RangeType tag_range(RemoveNonAddressBits(addr), len);
+ tag_range = ExpandToGranule(tag_range);
+
+ // Make a copy so we can use the original for errors and the final return.
+ MemoryRegionInfo::RangeType remaining_range(tag_range);
+
+ // While there are parts of the range that don't have a matching tagged memory
+ // region
+ while (remaining_range.IsValid()) {
+ // Search for a region that contains the start of the range
+ MemoryRegionInfos::const_iterator region = std::find_if(
+ memory_regions.cbegin(), memory_regions.cend(),
+ [&remaining_range](const MemoryRegionInfo ®ion) {
+ return region.GetRange().Contains(remaining_range.GetRangeBase());
+ });
+
+ if (region == memory_regions.cend() ||
+ region->GetMemoryTagged() != MemoryRegionInfo::eYes) {
+ // Some part of this range is untagged (or unmapped) so error
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Address range 0x%" PRIx64 ":0x%" PRIx64
+ " is not in a memory tagged region",
+ tag_range.GetRangeBase(),
+ tag_range.GetRangeEnd());
+ }
+
+ // We've found some part of the range so remove that part and continue
+ // searching for the rest. Moving the base "slides" the range so we need to
+ // save/restore the original end. If old_end is less than the new base, the
+ // range will be set to have 0 size and we'll exit the while.
+ lldb::addr_t old_end = remaining_range.GetRangeEnd();
+ remaining_range.SetRangeBase(region->GetRange().GetRangeEnd());
+ remaining_range.SetRangeEnd(old_end);
+ }
+
+ // Every part of the range is contained within a tagged memory region.
+ return tag_range;
+}
+
+llvm::Expected<std::vector<lldb::addr_t>>
+MemoryTagManagerAArch64MTE::UnpackTagsData(const std::vector<uint8_t> &tags,
+ size_t granules /*=0*/) const {
+ // 0 means don't check the number of tags before unpacking
+ if (granules) {
+ size_t num_tags = tags.size() / GetTagSizeInBytes();
+ if (num_tags != granules) {
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "Packed tag data size does not match expected number of tags. "
+ "Expected %zu tag(s) for %zu granule(s), got %zu tag(s).",
+ granules, granules, num_tags);
+ }
+ }
+
+ // (if bytes per tag was not 1, we would reconstruct them here)
+
+ std::vector<lldb::addr_t> unpacked;
+ unpacked.reserve(tags.size());
+ for (auto it = tags.begin(); it != tags.end(); ++it) {
+ // Check all tags are in range
+ if (*it > MTE_TAG_MAX) {
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "Found tag 0x%x which is > max MTE tag value of 0x%x.", *it,
+ MTE_TAG_MAX);
+ }
+ unpacked.push_back(*it);
+ }
+
+ return unpacked;
+}
+
+llvm::Expected<std::vector<uint8_t>> MemoryTagManagerAArch64MTE::PackTags(
+ const std::vector<lldb::addr_t> &tags) const {
+ std::vector<uint8_t> packed;
+ packed.reserve(tags.size() * GetTagSizeInBytes());
+
+ for (auto tag : tags) {
+ if (tag > MTE_TAG_MAX) {
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Found tag 0x%" PRIx64
+ " which is > max MTE tag value of 0x%x.",
+ tag, MTE_TAG_MAX);
+ }
+ packed.push_back(static_cast<uint8_t>(tag));
+ }
+
+ return packed;
+}
+
+llvm::Expected<std::vector<lldb::addr_t>>
+MemoryTagManagerAArch64MTE::RepeatTagsForRange(
+ const std::vector<lldb::addr_t> &tags, TagRange range) const {
+ std::vector<lldb::addr_t> new_tags;
+
+ // If the range is not empty
+ if (range.IsValid()) {
+ if (tags.empty()) {
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "Expected some tags to cover given range, got zero.");
+ }
+
+ // We assume that this range has already been expanded/aligned to granules
+ size_t granules = range.GetByteSize() / GetGranuleSize();
+ new_tags.reserve(granules);
+ for (size_t to_copy = 0; granules > 0; granules -= to_copy) {
+ to_copy = granules > tags.size() ? tags.size() : granules;
+ new_tags.insert(new_tags.end(), tags.begin(), tags.begin() + to_copy);
+ }
+ }
+
+ return new_tags;
+}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h b/src/llvm-project/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h
new file mode 100644
index 0000000..d4e8249
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h
@@ -0,0 +1,53 @@
+//===-- MemoryTagManagerAArch64MTE.h ----------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_MEMORYTAGMANAGERAARCH64MTE_H
+#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_MEMORYTAGMANAGERAARCH64MTE_H
+
+#include "lldb/Target/MemoryTagManager.h"
+
+namespace lldb_private {
+
+class MemoryTagManagerAArch64MTE : public MemoryTagManager {
+public:
+ // This enum is supposed to be shared for all of AArch64 but until
+ // there are more tag types than MTE, it will live here.
+ enum MTETagTypes {
+ eMTE_logical = 0,
+ eMTE_allocation = 1,
+ };
+
+ lldb::addr_t GetGranuleSize() const override;
+ int32_t GetAllocationTagType() const override;
+ size_t GetTagSizeInBytes() const override;
+
+ lldb::addr_t GetLogicalTag(lldb::addr_t addr) const override;
+ lldb::addr_t RemoveNonAddressBits(lldb::addr_t addr) const override;
+ ptrdiff_t AddressDiff(lldb::addr_t addr1, lldb::addr_t addr2) const override;
+
+ TagRange ExpandToGranule(TagRange range) const override;
+
+ llvm::Expected<TagRange> MakeTaggedRange(
+ lldb::addr_t addr, lldb::addr_t end_addr,
+ const lldb_private::MemoryRegionInfos &memory_regions) const override;
+
+ llvm::Expected<std::vector<lldb::addr_t>>
+ UnpackTagsData(const std::vector<uint8_t> &tags,
+ size_t granules = 0) const override;
+
+ llvm::Expected<std::vector<uint8_t>>
+ PackTags(const std::vector<lldb::addr_t> &tags) const override;
+
+ llvm::Expected<std::vector<lldb::addr_t>>
+ RepeatTagsForRange(const std::vector<lldb::addr_t> &tags,
+ TagRange range) const override;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_MEMORYTAGMANAGERAARCH64MTE_H
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/NativeProcessSoftwareSingleStep.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/NativeProcessSoftwareSingleStep.cpp
new file mode 100644
index 0000000..ee5295b
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/NativeProcessSoftwareSingleStep.cpp
@@ -0,0 +1,182 @@
+//===-- NativeProcessSoftwareSingleStep.cpp -------------------------------===//
+//
+// 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 "NativeProcessSoftwareSingleStep.h"
+
+#include "lldb/Core/EmulateInstruction.h"
+#include "lldb/Host/common/NativeRegisterContext.h"
+#include "lldb/Utility/RegisterValue.h"
+
+#include <unordered_map>
+
+using namespace lldb;
+using namespace lldb_private;
+
+namespace {
+
+struct EmulatorBaton {
+ NativeProcessProtocol &m_process;
+ NativeRegisterContext &m_reg_context;
+
+ // eRegisterKindDWARF -> RegsiterValue
+ std::unordered_map<uint32_t, RegisterValue> m_register_values;
+
+ EmulatorBaton(NativeProcessProtocol &process,
+ NativeRegisterContext ®_context)
+ : m_process(process), m_reg_context(reg_context) {}
+};
+
+} // anonymous namespace
+
+static size_t ReadMemoryCallback(EmulateInstruction *instruction, void *baton,
+ const EmulateInstruction::Context &context,
+ lldb::addr_t addr, void *dst, size_t length) {
+ EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
+
+ size_t bytes_read;
+ emulator_baton->m_process.ReadMemory(addr, dst, length, bytes_read);
+ return bytes_read;
+}
+
+static bool ReadRegisterCallback(EmulateInstruction *instruction, void *baton,
+ const RegisterInfo *reg_info,
+ RegisterValue ®_value) {
+ EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
+
+ auto it = emulator_baton->m_register_values.find(
+ reg_info->kinds[eRegisterKindDWARF]);
+ if (it != emulator_baton->m_register_values.end()) {
+ reg_value = it->second;
+ return true;
+ }
+
+ // The emulator only fill in the dwarf regsiter numbers (and in some case the
+ // generic register numbers). Get the full register info from the register
+ // context based on the dwarf register numbers.
+ const RegisterInfo *full_reg_info =
+ emulator_baton->m_reg_context.GetRegisterInfo(
+ eRegisterKindDWARF, reg_info->kinds[eRegisterKindDWARF]);
+
+ Status error =
+ emulator_baton->m_reg_context.ReadRegister(full_reg_info, reg_value);
+ if (error.Success())
+ return true;
+
+ return false;
+}
+
+static bool WriteRegisterCallback(EmulateInstruction *instruction, void *baton,
+ const EmulateInstruction::Context &context,
+ const RegisterInfo *reg_info,
+ const RegisterValue ®_value) {
+ EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);
+ emulator_baton->m_register_values[reg_info->kinds[eRegisterKindDWARF]] =
+ reg_value;
+ return true;
+}
+
+static size_t WriteMemoryCallback(EmulateInstruction *instruction, void *baton,
+ const EmulateInstruction::Context &context,
+ lldb::addr_t addr, const void *dst,
+ size_t length) {
+ return length;
+}
+
+static lldb::addr_t ReadFlags(NativeRegisterContext ®siter_context) {
+ const RegisterInfo *flags_info = regsiter_context.GetRegisterInfo(
+ eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
+ return regsiter_context.ReadRegisterAsUnsigned(flags_info,
+ LLDB_INVALID_ADDRESS);
+}
+
+Status NativeProcessSoftwareSingleStep::SetupSoftwareSingleStepping(
+ NativeThreadProtocol &thread) {
+ Status error;
+ NativeProcessProtocol &process = thread.GetProcess();
+ NativeRegisterContext ®ister_context = thread.GetRegisterContext();
+ const ArchSpec &arch = process.GetArchitecture();
+
+ std::unique_ptr<EmulateInstruction> emulator_up(
+ EmulateInstruction::FindPlugin(arch, eInstructionTypePCModifying,
+ nullptr));
+
+ if (emulator_up == nullptr)
+ return Status("Instruction emulator not found!");
+
+ EmulatorBaton baton(process, register_context);
+ emulator_up->SetBaton(&baton);
+ emulator_up->SetReadMemCallback(&ReadMemoryCallback);
+ emulator_up->SetReadRegCallback(&ReadRegisterCallback);
+ emulator_up->SetWriteMemCallback(&WriteMemoryCallback);
+ emulator_up->SetWriteRegCallback(&WriteRegisterCallback);
+
+ if (!emulator_up->ReadInstruction())
+ return Status("Read instruction failed!");
+
+ bool emulation_result =
+ emulator_up->EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC);
+
+ const RegisterInfo *reg_info_pc = register_context.GetRegisterInfo(
+ eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+ const RegisterInfo *reg_info_flags = register_context.GetRegisterInfo(
+ eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
+
+ auto pc_it =
+ baton.m_register_values.find(reg_info_pc->kinds[eRegisterKindDWARF]);
+ auto flags_it =
+ baton.m_register_values.find(reg_info_flags->kinds[eRegisterKindDWARF]);
+
+ lldb::addr_t next_pc;
+ lldb::addr_t next_flags;
+ if (emulation_result) {
+ assert(pc_it != baton.m_register_values.end() &&
+ "Emulation was successfull but PC wasn't updated");
+ next_pc = pc_it->second.GetAsUInt64();
+
+ if (flags_it != baton.m_register_values.end())
+ next_flags = flags_it->second.GetAsUInt64();
+ else
+ next_flags = ReadFlags(register_context);
+ } else if (pc_it == baton.m_register_values.end()) {
+ // Emulate instruction failed and it haven't changed PC. Advance PC with
+ // the size of the current opcode because the emulation of all
+ // PC modifying instruction should be successful. The failure most
+ // likely caused by a not supported instruction which don't modify PC.
+ next_pc = register_context.GetPC() + emulator_up->GetOpcode().GetByteSize();
+ next_flags = ReadFlags(register_context);
+ } else {
+ // The instruction emulation failed after it modified the PC. It is an
+ // unknown error where we can't continue because the next instruction is
+ // modifying the PC but we don't know how.
+ return Status("Instruction emulation failed unexpectedly.");
+ }
+
+ int size_hint = 0;
+ if (arch.GetMachine() == llvm::Triple::arm) {
+ if (next_flags & 0x20) {
+ // Thumb mode
+ size_hint = 2;
+ } else {
+ // Arm mode
+ size_hint = 4;
+ }
+ } else if (arch.IsMIPS() || arch.GetTriple().isPPC64())
+ size_hint = 4;
+ error = process.SetBreakpoint(next_pc, size_hint, /*hardware=*/false);
+
+ // If setting the breakpoint fails because next_pc is out of the address
+ // space, ignore it and let the debugee segfault.
+ if (error.GetError() == EIO || error.GetError() == EFAULT) {
+ return Status();
+ } else if (error.Fail())
+ return error;
+
+ m_threads_stepping_with_breakpoint.insert({thread.GetID(), next_pc});
+
+ return Status();
+}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/NativeProcessSoftwareSingleStep.h b/src/llvm-project/lldb/source/Plugins/Process/Utility/NativeProcessSoftwareSingleStep.h
new file mode 100644
index 0000000..f9435b7
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/NativeProcessSoftwareSingleStep.h
@@ -0,0 +1,31 @@
+//===-- NativeProcessSoftwareSingleStep.h -----------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_NativeProcessSoftwareSingleStep_h
+#define lldb_NativeProcessSoftwareSingleStep_h
+
+#include "lldb/Host/common/NativeProcessProtocol.h"
+#include "lldb/Host/common/NativeThreadProtocol.h"
+
+#include <map>
+
+namespace lldb_private {
+
+class NativeProcessSoftwareSingleStep {
+public:
+ Status SetupSoftwareSingleStepping(NativeThreadProtocol &thread);
+
+protected:
+ // List of thread ids stepping with a breakpoint with the address of
+ // the relevan breakpoint
+ std::map<lldb::tid_t, lldb::addr_t> m_threads_stepping_with_breakpoint;
+};
+
+} // namespace lldb_private
+
+#endif // #ifndef lldb_NativeProcessSoftwareSingleStep_h
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.cpp
new file mode 100644
index 0000000..feee857
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.cpp
@@ -0,0 +1,469 @@
+//===-- NativeRegisterContextDBReg_arm64.cpp ------------------------------===//
+//
+// 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 "NativeRegisterContextDBReg_arm64.h"
+
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
+
+using namespace lldb_private;
+
+// E (bit 0), used to enable breakpoint/watchpoint
+constexpr uint32_t g_enable_bit = 1;
+// PAC (bits 2:1): 0b10
+constexpr uint32_t g_pac_bits = (2 << 1);
+
+// Returns appropriate control register bits for the specified size
+static constexpr inline uint64_t GetSizeBits(int size) {
+ // BAS (bits 12:5) hold a bit-mask of addresses to watch
+ // e.g. 0b00000001 means 1 byte at address
+ // 0b00000011 means 2 bytes (addr..addr+1)
+ // ...
+ // 0b11111111 means 8 bytes (addr..addr+7)
+ return ((1 << size) - 1) << 5;
+}
+
+uint32_t NativeRegisterContextDBReg_arm64::NumSupportedHardwareBreakpoints() {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+ llvm::Error error = ReadHardwareDebugInfo();
+ if (error) {
+ LLDB_LOG_ERROR(log, std::move(error),
+ "failed to read debug registers: {0}");
+ return 0;
+ }
+
+ return m_max_hbp_supported;
+}
+
+uint32_t
+NativeRegisterContextDBReg_arm64::SetHardwareBreakpoint(lldb::addr_t addr,
+ size_t size) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+ LLDB_LOG(log, "addr: {0:x}, size: {1:x}", addr, size);
+
+ // Read hardware breakpoint and watchpoint information.
+ llvm::Error error = ReadHardwareDebugInfo();
+ if (error) {
+ LLDB_LOG_ERROR(
+ log, std::move(error),
+ "unable to set breakpoint: failed to read debug registers: {0}");
+ return LLDB_INVALID_INDEX32;
+ }
+
+ uint32_t control_value = 0, bp_index = 0;
+
+ // Check if size has a valid hardware breakpoint length.
+ if (size != 4)
+ return LLDB_INVALID_INDEX32; // Invalid size for a AArch64 hardware
+ // breakpoint
+
+ // Check 4-byte alignment for hardware breakpoint target address.
+ if (addr & 0x03)
+ return LLDB_INVALID_INDEX32; // Invalid address, should be 4-byte aligned.
+
+ // Setup control value
+ control_value = g_enable_bit | g_pac_bits | GetSizeBits(size);
+
+ // Iterate over stored breakpoints and find a free bp_index
+ bp_index = LLDB_INVALID_INDEX32;
+ for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
+ if (!BreakpointIsEnabled(i))
+ bp_index = i; // Mark last free slot
+ else if (m_hbp_regs[i].address == addr)
+ return LLDB_INVALID_INDEX32; // We do not support duplicate breakpoints.
+ }
+
+ if (bp_index == LLDB_INVALID_INDEX32)
+ return LLDB_INVALID_INDEX32;
+
+ // Update breakpoint in local cache
+ m_hbp_regs[bp_index].real_addr = addr;
+ m_hbp_regs[bp_index].address = addr;
+ m_hbp_regs[bp_index].control = control_value;
+
+ // PTRACE call to set corresponding hardware breakpoint register.
+ error = WriteHardwareDebugRegs(eDREGTypeBREAK);
+
+ if (error) {
+ m_hbp_regs[bp_index].address = 0;
+ m_hbp_regs[bp_index].control &= ~1;
+
+ LLDB_LOG_ERROR(
+ log, std::move(error),
+ "unable to set breakpoint: failed to write debug registers: {0}");
+ return LLDB_INVALID_INDEX32;
+ }
+
+ return bp_index;
+}
+
+bool NativeRegisterContextDBReg_arm64::ClearHardwareBreakpoint(
+ uint32_t hw_idx) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+ LLDB_LOG(log, "hw_idx: {0}", hw_idx);
+
+ // Read hardware breakpoint and watchpoint information.
+ llvm::Error error = ReadHardwareDebugInfo();
+ if (error) {
+ LLDB_LOG_ERROR(
+ log, std::move(error),
+ "unable to clear breakpoint: failed to read debug registers: {0}");
+ return false;
+ }
+
+ if (hw_idx >= m_max_hbp_supported)
+ return false;
+
+ // Create a backup we can revert to in case of failure.
+ lldb::addr_t tempAddr = m_hbp_regs[hw_idx].address;
+ uint32_t tempControl = m_hbp_regs[hw_idx].control;
+
+ m_hbp_regs[hw_idx].control &= ~g_enable_bit;
+ m_hbp_regs[hw_idx].address = 0;
+
+ // PTRACE call to clear corresponding hardware breakpoint register.
+ error = WriteHardwareDebugRegs(eDREGTypeBREAK);
+
+ if (error) {
+ m_hbp_regs[hw_idx].control = tempControl;
+ m_hbp_regs[hw_idx].address = tempAddr;
+
+ LLDB_LOG_ERROR(
+ log, std::move(error),
+ "unable to clear breakpoint: failed to write debug registers: {0}");
+ return false;
+ }
+
+ return true;
+}
+
+Status NativeRegisterContextDBReg_arm64::GetHardwareBreakHitIndex(
+ uint32_t &bp_index, lldb::addr_t trap_addr) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+
+ LLDB_LOGF(log, "NativeRegisterContextDBReg_arm64::%s()", __FUNCTION__);
+
+ lldb::addr_t break_addr;
+
+ for (bp_index = 0; bp_index < m_max_hbp_supported; ++bp_index) {
+ break_addr = m_hbp_regs[bp_index].address;
+
+ if (BreakpointIsEnabled(bp_index) && trap_addr == break_addr) {
+ m_hbp_regs[bp_index].hit_addr = trap_addr;
+ return Status();
+ }
+ }
+
+ bp_index = LLDB_INVALID_INDEX32;
+ return Status();
+}
+
+Status NativeRegisterContextDBReg_arm64::ClearAllHardwareBreakpoints() {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+
+ LLDB_LOGF(log, "NativeRegisterContextDBReg_arm64::%s()", __FUNCTION__);
+
+ // Read hardware breakpoint and watchpoint information.
+ llvm::Error error = ReadHardwareDebugInfo();
+ if (error)
+ return Status(std::move(error));
+
+ for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
+ if (BreakpointIsEnabled(i)) {
+ // Create a backup we can revert to in case of failure.
+ lldb::addr_t tempAddr = m_hbp_regs[i].address;
+ uint32_t tempControl = m_hbp_regs[i].control;
+
+ // Clear watchpoints in local cache
+ m_hbp_regs[i].control &= ~g_enable_bit;
+ m_hbp_regs[i].address = 0;
+
+ // Ptrace call to update hardware debug registers
+ error = WriteHardwareDebugRegs(eDREGTypeBREAK);
+
+ if (error) {
+ m_hbp_regs[i].control = tempControl;
+ m_hbp_regs[i].address = tempAddr;
+
+ return Status(std::move(error));
+ }
+ }
+ }
+
+ return Status();
+}
+
+bool NativeRegisterContextDBReg_arm64::BreakpointIsEnabled(uint32_t bp_index) {
+ if ((m_hbp_regs[bp_index].control & g_enable_bit) != 0)
+ return true;
+ else
+ return false;
+}
+
+uint32_t NativeRegisterContextDBReg_arm64::NumSupportedHardwareWatchpoints() {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ llvm::Error error = ReadHardwareDebugInfo();
+ if (error) {
+ LLDB_LOG_ERROR(log, std::move(error),
+ "failed to read debug registers: {0}");
+ return 0;
+ }
+
+ return m_max_hwp_supported;
+}
+
+uint32_t NativeRegisterContextDBReg_arm64::SetHardwareWatchpoint(
+ lldb::addr_t addr, size_t size, uint32_t watch_flags) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ LLDB_LOG(log, "addr: {0:x}, size: {1:x} watch_flags: {2:x}", addr, size,
+ watch_flags);
+
+ // Read hardware breakpoint and watchpoint information.
+ llvm::Error error = ReadHardwareDebugInfo();
+ if (error) {
+ LLDB_LOG_ERROR(
+ log, std::move(error),
+ "unable to set watchpoint: failed to read debug registers: {0}");
+ return LLDB_INVALID_INDEX32;
+ }
+
+ uint32_t control_value = 0, wp_index = 0;
+ lldb::addr_t real_addr = addr;
+
+ // Check if we are setting watchpoint other than read/write/access Also
+ // update watchpoint flag to match AArch64 write-read bit configuration.
+ switch (watch_flags) {
+ case 1:
+ watch_flags = 2;
+ break;
+ case 2:
+ watch_flags = 1;
+ break;
+ case 3:
+ break;
+ default:
+ return LLDB_INVALID_INDEX32;
+ }
+
+ // Check if size has a valid hardware watchpoint length.
+ if (size != 1 && size != 2 && size != 4 && size != 8)
+ return LLDB_INVALID_INDEX32;
+
+ // Check 8-byte alignment for hardware watchpoint target address. Below is a
+ // hack to recalculate address and size in order to make sure we can watch
+ // non 8-byte aligned addresses as well.
+ if (addr & 0x07) {
+ uint8_t watch_mask = (addr & 0x07) + size;
+
+ if (watch_mask > 0x08)
+ return LLDB_INVALID_INDEX32;
+ else if (watch_mask <= 0x02)
+ size = 2;
+ else if (watch_mask <= 0x04)
+ size = 4;
+ else
+ size = 8;
+
+ addr = addr & (~0x07);
+ }
+
+ // Setup control value
+ control_value = g_enable_bit | g_pac_bits | GetSizeBits(size);
+ control_value |= watch_flags << 3;
+
+ // Iterate over stored watchpoints and find a free wp_index
+ wp_index = LLDB_INVALID_INDEX32;
+ for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
+ if (!WatchpointIsEnabled(i))
+ wp_index = i; // Mark last free slot
+ else if (m_hwp_regs[i].address == addr) {
+ return LLDB_INVALID_INDEX32; // We do not support duplicate watchpoints.
+ }
+ }
+
+ if (wp_index == LLDB_INVALID_INDEX32)
+ return LLDB_INVALID_INDEX32;
+
+ // Update watchpoint in local cache
+ m_hwp_regs[wp_index].real_addr = real_addr;
+ m_hwp_regs[wp_index].address = addr;
+ m_hwp_regs[wp_index].control = control_value;
+
+ // PTRACE call to set corresponding watchpoint register.
+ error = WriteHardwareDebugRegs(eDREGTypeWATCH);
+
+ if (error) {
+ m_hwp_regs[wp_index].address = 0;
+ m_hwp_regs[wp_index].control &= ~g_enable_bit;
+
+ LLDB_LOG_ERROR(
+ log, std::move(error),
+ "unable to set watchpoint: failed to write debug registers: {0}");
+ return LLDB_INVALID_INDEX32;
+ }
+
+ return wp_index;
+}
+
+bool NativeRegisterContextDBReg_arm64::ClearHardwareWatchpoint(
+ uint32_t wp_index) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ LLDB_LOG(log, "wp_index: {0}", wp_index);
+
+ // Read hardware breakpoint and watchpoint information.
+ llvm::Error error = ReadHardwareDebugInfo();
+ if (error) {
+ LLDB_LOG_ERROR(
+ log, std::move(error),
+ "unable to clear watchpoint: failed to read debug registers: {0}");
+ return false;
+ }
+
+ if (wp_index >= m_max_hwp_supported)
+ return false;
+
+ // Create a backup we can revert to in case of failure.
+ lldb::addr_t tempAddr = m_hwp_regs[wp_index].address;
+ uint32_t tempControl = m_hwp_regs[wp_index].control;
+
+ // Update watchpoint in local cache
+ m_hwp_regs[wp_index].control &= ~g_enable_bit;
+ m_hwp_regs[wp_index].address = 0;
+
+ // Ptrace call to update hardware debug registers
+ error = WriteHardwareDebugRegs(eDREGTypeWATCH);
+
+ if (error) {
+ m_hwp_regs[wp_index].control = tempControl;
+ m_hwp_regs[wp_index].address = tempAddr;
+
+ LLDB_LOG_ERROR(
+ log, std::move(error),
+ "unable to clear watchpoint: failed to write debug registers: {0}");
+ return false;
+ }
+
+ return true;
+}
+
+Status NativeRegisterContextDBReg_arm64::ClearAllHardwareWatchpoints() {
+ // Read hardware breakpoint and watchpoint information.
+ llvm::Error error = ReadHardwareDebugInfo();
+ if (error)
+ return Status(std::move(error));
+
+ for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
+ if (WatchpointIsEnabled(i)) {
+ // Create a backup we can revert to in case of failure.
+ lldb::addr_t tempAddr = m_hwp_regs[i].address;
+ uint32_t tempControl = m_hwp_regs[i].control;
+
+ // Clear watchpoints in local cache
+ m_hwp_regs[i].control &= ~g_enable_bit;
+ m_hwp_regs[i].address = 0;
+
+ // Ptrace call to update hardware debug registers
+ error = WriteHardwareDebugRegs(eDREGTypeWATCH);
+
+ if (error) {
+ m_hwp_regs[i].control = tempControl;
+ m_hwp_regs[i].address = tempAddr;
+
+ return Status(std::move(error));
+ }
+ }
+ }
+
+ return Status();
+}
+
+uint32_t
+NativeRegisterContextDBReg_arm64::GetWatchpointSize(uint32_t wp_index) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ LLDB_LOG(log, "wp_index: {0}", wp_index);
+
+ switch ((m_hwp_regs[wp_index].control >> 5) & 0xff) {
+ case 0x01:
+ return 1;
+ case 0x03:
+ return 2;
+ case 0x0f:
+ return 4;
+ case 0xff:
+ return 8;
+ default:
+ return 0;
+ }
+}
+
+bool NativeRegisterContextDBReg_arm64::WatchpointIsEnabled(uint32_t wp_index) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ LLDB_LOG(log, "wp_index: {0}", wp_index);
+
+ if ((m_hwp_regs[wp_index].control & g_enable_bit) != 0)
+ return true;
+ else
+ return false;
+}
+
+Status NativeRegisterContextDBReg_arm64::GetWatchpointHitIndex(
+ uint32_t &wp_index, lldb::addr_t trap_addr) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ LLDB_LOG(log, "wp_index: {0}, trap_addr: {1:x}", wp_index, trap_addr);
+
+ // Read hardware breakpoint and watchpoint information.
+ llvm::Error error = ReadHardwareDebugInfo();
+ if (error)
+ return Status(std::move(error));
+
+ // Mask off ignored bits from watchpoint trap address.
+ trap_addr = FixWatchpointHitAddress(trap_addr);
+
+ uint32_t watch_size;
+ lldb::addr_t watch_addr;
+
+ for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) {
+ watch_size = GetWatchpointSize(wp_index);
+ watch_addr = m_hwp_regs[wp_index].address;
+
+ if (WatchpointIsEnabled(wp_index) && trap_addr >= watch_addr &&
+ trap_addr < watch_addr + watch_size) {
+ m_hwp_regs[wp_index].hit_addr = trap_addr;
+ return Status();
+ }
+ }
+
+ wp_index = LLDB_INVALID_INDEX32;
+ return Status();
+}
+
+lldb::addr_t
+NativeRegisterContextDBReg_arm64::GetWatchpointAddress(uint32_t wp_index) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ LLDB_LOG(log, "wp_index: {0}", wp_index);
+
+ if (wp_index >= m_max_hwp_supported)
+ return LLDB_INVALID_ADDRESS;
+
+ if (WatchpointIsEnabled(wp_index))
+ return m_hwp_regs[wp_index].real_addr;
+ return LLDB_INVALID_ADDRESS;
+}
+
+lldb::addr_t
+NativeRegisterContextDBReg_arm64::GetWatchpointHitAddress(uint32_t wp_index) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ LLDB_LOG(log, "wp_index: {0}", wp_index);
+
+ if (wp_index >= m_max_hwp_supported)
+ return LLDB_INVALID_ADDRESS;
+
+ if (WatchpointIsEnabled(wp_index))
+ return m_hwp_regs[wp_index].hit_addr;
+ return LLDB_INVALID_ADDRESS;
+}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.h b/src/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.h
new file mode 100644
index 0000000..3da0b04
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.h
@@ -0,0 +1,82 @@
+//===-- NativeRegisterContextDBReg_arm64.h ----------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_NativeRegisterContextDBReg_arm64_h
+#define lldb_NativeRegisterContextDBReg_arm64_h
+
+#include "Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h"
+
+#include <array>
+
+namespace lldb_private {
+
+class NativeRegisterContextDBReg_arm64
+ : public virtual NativeRegisterContextRegisterInfo {
+public:
+ uint32_t NumSupportedHardwareBreakpoints() override;
+
+ uint32_t SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override;
+
+ bool ClearHardwareBreakpoint(uint32_t hw_idx) override;
+
+ Status ClearAllHardwareBreakpoints() override;
+
+ Status GetHardwareBreakHitIndex(uint32_t &bp_index,
+ lldb::addr_t trap_addr) override;
+
+ bool BreakpointIsEnabled(uint32_t bp_index);
+
+ uint32_t NumSupportedHardwareWatchpoints() override;
+
+ uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size,
+ uint32_t watch_flags) override;
+
+ bool ClearHardwareWatchpoint(uint32_t hw_index) override;
+
+ Status ClearAllHardwareWatchpoints() override;
+
+ Status GetWatchpointHitIndex(uint32_t &wp_index,
+ lldb::addr_t trap_addr) override;
+
+ lldb::addr_t GetWatchpointHitAddress(uint32_t wp_index) override;
+
+ lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override;
+
+ uint32_t GetWatchpointSize(uint32_t wp_index);
+
+ bool WatchpointIsEnabled(uint32_t wp_index);
+
+ // Debug register type select
+ enum DREGType { eDREGTypeWATCH = 0, eDREGTypeBREAK };
+
+protected:
+ // Debug register info for hardware breakpoints and watchpoints management.
+ struct DREG {
+ lldb::addr_t address; // Breakpoint/watchpoint address value.
+ lldb::addr_t hit_addr; // Address at which last watchpoint trigger exception
+ // occurred.
+ lldb::addr_t real_addr; // Address value that should cause target to stop.
+ uint32_t control; // Breakpoint/watchpoint control value.
+ };
+
+ std::array<struct DREG, 16> m_hbp_regs; // hardware breakpoints
+ std::array<struct DREG, 16> m_hwp_regs; // hardware watchpoints
+
+ uint32_t m_max_hbp_supported;
+ uint32_t m_max_hwp_supported;
+
+ virtual llvm::Error ReadHardwareDebugInfo() = 0;
+ virtual llvm::Error WriteHardwareDebugRegs(DREGType hwbType) = 0;
+ virtual lldb::addr_t FixWatchpointHitAddress(lldb::addr_t hit_addr) {
+ return hit_addr;
+ }
+};
+
+} // namespace lldb_private
+
+#endif // #ifndef lldb_NativeRegisterContextDBReg_arm64_h
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextWatchpoint_x86.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_x86.cpp
similarity index 86%
rename from src/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextWatchpoint_x86.cpp
rename to src/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_x86.cpp
index 0f57f2e..56c1757 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextWatchpoint_x86.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_x86.cpp
@@ -1,4 +1,4 @@
-//===-- NativeRegisterContextWatchpoint_x86.cpp ---------------------------===//
+//===-- NativeRegisterContextDBReg_x86.cpp --------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "NativeRegisterContextWatchpoint_x86.h"
+#include "NativeRegisterContextDBReg_x86.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegisterValue.h"
@@ -80,7 +80,7 @@
// Bit mask for control bits regarding all watchpoints.
static constexpr uint64_t watchpoint_all_control_bit_mask = 0xFFFF00FF;
-const RegisterInfo *NativeRegisterContextWatchpoint_x86::GetDR(int num) const {
+const RegisterInfo *NativeRegisterContextDBReg_x86::GetDR(int num) const {
assert(num >= 0 && num <= 7);
switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
case llvm::Triple::x86:
@@ -92,8 +92,8 @@
}
}
-Status NativeRegisterContextWatchpoint_x86::IsWatchpointHit(uint32_t wp_index,
- bool &is_hit) {
+Status NativeRegisterContextDBReg_x86::IsWatchpointHit(uint32_t wp_index,
+ bool &is_hit) {
if (wp_index >= NumSupportedHardwareWatchpoints())
return Status("Watchpoint index out of range");
@@ -107,8 +107,9 @@
return error;
}
-Status NativeRegisterContextWatchpoint_x86::GetWatchpointHitIndex(
- uint32_t &wp_index, lldb::addr_t trap_addr) {
+Status
+NativeRegisterContextDBReg_x86::GetWatchpointHitIndex(uint32_t &wp_index,
+ lldb::addr_t trap_addr) {
uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) {
bool is_hit;
@@ -124,9 +125,8 @@
return Status();
}
-Status
-NativeRegisterContextWatchpoint_x86::IsWatchpointVacant(uint32_t wp_index,
- bool &is_vacant) {
+Status NativeRegisterContextDBReg_x86::IsWatchpointVacant(uint32_t wp_index,
+ bool &is_vacant) {
if (wp_index >= NumSupportedHardwareWatchpoints())
return Status("Watchpoint index out of range");
@@ -140,7 +140,7 @@
return error;
}
-Status NativeRegisterContextWatchpoint_x86::SetHardwareWatchpointWithIndex(
+Status NativeRegisterContextDBReg_x86::SetHardwareWatchpointWithIndex(
lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) {
if (wp_index >= NumSupportedHardwareWatchpoints())
@@ -202,7 +202,7 @@
return error;
}
-bool NativeRegisterContextWatchpoint_x86::ClearHardwareWatchpoint(
+bool NativeRegisterContextDBReg_x86::ClearHardwareWatchpoint(
uint32_t wp_index) {
if (wp_index >= NumSupportedHardwareWatchpoints())
return false;
@@ -217,8 +217,7 @@
.Success();
}
-Status
-NativeRegisterContextWatchpoint_x86::ClearWatchpointHit(uint32_t wp_index) {
+Status NativeRegisterContextDBReg_x86::ClearWatchpointHit(uint32_t wp_index) {
if (wp_index >= NumSupportedHardwareWatchpoints())
return Status("Watchpoint index out of range");
@@ -231,7 +230,7 @@
GetDR(6), RegisterValue(dr6.GetAsUInt64() & ~GetStatusBit(wp_index)));
}
-Status NativeRegisterContextWatchpoint_x86::ClearAllHardwareWatchpoints() {
+Status NativeRegisterContextDBReg_x86::ClearAllHardwareWatchpoints() {
RegisterValue dr7;
Status error = ReadRegister(GetDR(7), dr7);
if (error.Fail())
@@ -241,7 +240,7 @@
RegisterValue(dr7.GetAsUInt64() & ~watchpoint_all_control_bit_mask));
}
-uint32_t NativeRegisterContextWatchpoint_x86::SetHardwareWatchpoint(
+uint32_t NativeRegisterContextDBReg_x86::SetHardwareWatchpoint(
lldb::addr_t addr, size_t size, uint32_t watch_flags) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
@@ -254,7 +253,7 @@
return wp_index;
}
if (error.Fail() && log) {
- LLDB_LOGF(log, "NativeRegisterContextWatchpoint_x86::%s Error: %s",
+ LLDB_LOGF(log, "NativeRegisterContextDBReg_x86::%s Error: %s",
__FUNCTION__, error.AsCString());
}
}
@@ -262,7 +261,7 @@
}
lldb::addr_t
-NativeRegisterContextWatchpoint_x86::GetWatchpointAddress(uint32_t wp_index) {
+NativeRegisterContextDBReg_x86::GetWatchpointAddress(uint32_t wp_index) {
if (wp_index >= NumSupportedHardwareWatchpoints())
return LLDB_INVALID_ADDRESS;
RegisterValue drN;
@@ -271,8 +270,7 @@
return drN.GetAsUInt64();
}
-uint32_t
-NativeRegisterContextWatchpoint_x86::NumSupportedHardwareWatchpoints() {
+uint32_t NativeRegisterContextDBReg_x86::NumSupportedHardwareWatchpoints() {
// Available debug address registers: dr0, dr1, dr2, dr3
return 4;
}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextWatchpoint_x86.h b/src/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_x86.h
similarity index 71%
rename from src/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextWatchpoint_x86.h
rename to src/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_x86.h
index cfb8900..a4ed8bf 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextWatchpoint_x86.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_x86.h
@@ -1,4 +1,4 @@
-//===-- NativeRegisterContextWatchpoint_x86.h -------------------*- C++ -*-===//
+//===-- NativeRegisterContextDBReg_x86.h ------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -6,16 +6,22 @@
//
//===----------------------------------------------------------------------===//
-#ifndef lldb_NativeRegisterContextWatchpoint_x86_h
-#define lldb_NativeRegisterContextWatchpoint_x86_h
+#ifndef lldb_NativeRegisterContextDBReg_x86_h
+#define lldb_NativeRegisterContextDBReg_x86_h
#include "Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h"
namespace lldb_private {
-class NativeRegisterContextWatchpoint_x86
+class NativeRegisterContextDBReg_x86
: public virtual NativeRegisterContextRegisterInfo {
public:
+ // NB: This constructor is here only because gcc<=6.5 requires a virtual base
+ // class initializer on abstract class (even though it is never used). It can
+ // be deleted once we move to gcc>=7.0.
+ NativeRegisterContextDBReg_x86(NativeThreadProtocol &thread)
+ : NativeRegisterContextRegisterInfo(thread, nullptr) {}
+
Status IsWatchpointHit(uint32_t wp_index, bool &is_hit) override;
Status GetWatchpointHitIndex(uint32_t &wp_index,
@@ -45,4 +51,4 @@
} // namespace lldb_private
-#endif // #ifndef lldb_NativeRegisterContextWatchpoint_x86_h
+#endif // #ifndef lldb_NativeRegisterContextDBReg_x86_h
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
index eef4541..7e38091 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
@@ -922,7 +922,7 @@
}
}
-RegisterContextDarwin_arm::~RegisterContextDarwin_arm() {}
+RegisterContextDarwin_arm::~RegisterContextDarwin_arm() = default;
void RegisterContextDarwin_arm::InvalidateAllRegisters() {
InvalidateAllRegisterStates();
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
index 9fc2752..b98b2f3 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
@@ -104,7 +104,7 @@
}
}
-RegisterContextDarwin_arm64::~RegisterContextDarwin_arm64() {}
+RegisterContextDarwin_arm64::~RegisterContextDarwin_arm64() = default;
void RegisterContextDarwin_arm64::InvalidateAllRegisters() {
InvalidateAllRegisterStates();
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
index c5ebddc..95f8132 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
@@ -15,7 +15,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Compiler.h"
-#include <stddef.h>
+#include <cstddef>
#include <memory>
@@ -405,7 +405,7 @@
}
}
-RegisterContextDarwin_i386::~RegisterContextDarwin_i386() {}
+RegisterContextDarwin_i386::~RegisterContextDarwin_i386() = default;
void RegisterContextDarwin_i386::InvalidateAllRegisters() {
InvalidateAllRegisterStates();
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
index 38cd00a..03e5ea4 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
@@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//
-#include <inttypes.h>
-#include <stdarg.h>
-#include <stddef.h>
+#include <cinttypes>
+#include <cstdarg>
+#include <cstddef>
#include <memory>
@@ -467,7 +467,7 @@
}
}
-RegisterContextDarwin_x86_64::~RegisterContextDarwin_x86_64() {}
+RegisterContextDarwin_x86_64::~RegisterContextDarwin_x86_64() = default;
void RegisterContextDarwin_x86_64::InvalidateAllRegisters() {
InvalidateAllRegisterStates();
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp
index 9fe6255..2991bd3 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp
@@ -178,7 +178,7 @@
const ArchSpec &target_arch)
: RegisterInfoInterface(target_arch) {}
-RegisterContextFreeBSD_powerpc::~RegisterContextFreeBSD_powerpc() {}
+RegisterContextFreeBSD_powerpc::~RegisterContextFreeBSD_powerpc() = default;
size_t RegisterContextFreeBSD_powerpc::GetGPRSize() const {
// This is an 'abstract' base, so no GPR struct.
@@ -197,7 +197,7 @@
const ArchSpec &target_arch)
: RegisterContextFreeBSD_powerpc(target_arch) {}
-RegisterContextFreeBSD_powerpc32::~RegisterContextFreeBSD_powerpc32() {}
+RegisterContextFreeBSD_powerpc32::~RegisterContextFreeBSD_powerpc32() = default;
size_t RegisterContextFreeBSD_powerpc32::GetGPRSize() const {
return sizeof(GPR32);
@@ -217,7 +217,7 @@
const ArchSpec &target_arch)
: RegisterContextFreeBSD_powerpc(target_arch) {}
-RegisterContextFreeBSD_powerpc64::~RegisterContextFreeBSD_powerpc64() {}
+RegisterContextFreeBSD_powerpc64::~RegisterContextFreeBSD_powerpc64() = default;
size_t RegisterContextFreeBSD_powerpc64::GetGPRSize() const {
return sizeof(GPR64);
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp
deleted file mode 100644
index 837549e..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-//===-- RegisterContextLinux_mips.cpp -------------------------------------===//
-//
-// 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 <stddef.h>
-#include <vector>
-
-// For eh_frame and DWARF Register numbers
-#include "RegisterContextLinux_mips.h"
-
-// Internal codes for mips registers
-#include "lldb-mips-linux-register-enums.h"
-
-// For GP and FP buffers
-#include "RegisterContext_mips.h"
-
-using namespace lldb_private;
-using namespace lldb;
-
-// Include RegisterInfos_mips to declare our g_register_infos_mips structure.
-#define DECLARE_REGISTER_INFOS_MIPS_STRUCT
-#include "RegisterInfos_mips.h"
-#undef DECLARE_REGISTER_INFOS_MIPS_STRUCT
-
-// mips general purpose registers.
-const uint32_t g_gp_regnums_mips[] = {
- gpr_zero_mips, gpr_r1_mips, gpr_r2_mips, gpr_r3_mips,
- gpr_r4_mips, gpr_r5_mips, gpr_r6_mips, gpr_r7_mips,
- gpr_r8_mips, gpr_r9_mips, gpr_r10_mips, gpr_r11_mips,
- gpr_r12_mips, gpr_r13_mips, gpr_r14_mips, gpr_r15_mips,
- gpr_r16_mips, gpr_r17_mips, gpr_r18_mips, gpr_r19_mips,
- gpr_r20_mips, gpr_r21_mips, gpr_r22_mips, gpr_r23_mips,
- gpr_r24_mips, gpr_r25_mips, gpr_r26_mips, gpr_r27_mips,
- gpr_gp_mips, gpr_sp_mips, gpr_r30_mips, gpr_ra_mips,
- gpr_sr_mips, gpr_mullo_mips, gpr_mulhi_mips, gpr_badvaddr_mips,
- gpr_cause_mips, gpr_pc_mips, gpr_config5_mips,
- LLDB_INVALID_REGNUM // register sets need to end with this flag
-};
-
-static_assert((sizeof(g_gp_regnums_mips) / sizeof(g_gp_regnums_mips[0])) - 1 ==
- k_num_gpr_registers_mips,
- "g_gp_regnums_mips has wrong number of register infos");
-// mips floating point registers.
-const uint32_t g_fp_regnums_mips[] = {
- fpr_f0_mips, fpr_f1_mips, fpr_f2_mips, fpr_f3_mips,
- fpr_f4_mips, fpr_f5_mips, fpr_f6_mips, fpr_f7_mips,
- fpr_f8_mips, fpr_f9_mips, fpr_f10_mips, fpr_f11_mips,
- fpr_f12_mips, fpr_f13_mips, fpr_f14_mips, fpr_f15_mips,
- fpr_f16_mips, fpr_f17_mips, fpr_f18_mips, fpr_f19_mips,
- fpr_f20_mips, fpr_f21_mips, fpr_f22_mips, fpr_f23_mips,
- fpr_f24_mips, fpr_f25_mips, fpr_f26_mips, fpr_f27_mips,
- fpr_f28_mips, fpr_f29_mips, fpr_f30_mips, fpr_f31_mips,
- fpr_fcsr_mips, fpr_fir_mips, fpr_config5_mips,
- LLDB_INVALID_REGNUM // register sets need to end with this flag
-};
-
-static_assert((sizeof(g_fp_regnums_mips) / sizeof(g_fp_regnums_mips[0])) - 1 ==
- k_num_fpr_registers_mips,
- "g_fp_regnums_mips has wrong number of register infos");
-
-// mips MSA registers.
-const uint32_t g_msa_regnums_mips[] = {
- msa_w0_mips, msa_w1_mips, msa_w2_mips, msa_w3_mips,
- msa_w4_mips, msa_w5_mips, msa_w6_mips, msa_w7_mips,
- msa_w8_mips, msa_w9_mips, msa_w10_mips, msa_w11_mips,
- msa_w12_mips, msa_w13_mips, msa_w14_mips, msa_w15_mips,
- msa_w16_mips, msa_w17_mips, msa_w18_mips, msa_w19_mips,
- msa_w20_mips, msa_w21_mips, msa_w22_mips, msa_w23_mips,
- msa_w24_mips, msa_w25_mips, msa_w26_mips, msa_w27_mips,
- msa_w28_mips, msa_w29_mips, msa_w30_mips, msa_w31_mips,
- msa_fcsr_mips, msa_fir_mips, msa_mcsr_mips, msa_mir_mips,
- msa_config5_mips,
- LLDB_INVALID_REGNUM // register sets need to end with this flag
-};
-
-static_assert((sizeof(g_msa_regnums_mips) / sizeof(g_msa_regnums_mips[0])) -
- 1 ==
- k_num_msa_registers_mips,
- "g_msa_regnums_mips has wrong number of register infos");
-
-// Number of register sets provided by this context.
-constexpr size_t k_num_register_sets = 3;
-
-// Register sets for mips.
-static const RegisterSet g_reg_sets_mips[k_num_register_sets] = {
- {"General Purpose Registers", "gpr", k_num_gpr_registers_mips,
- g_gp_regnums_mips},
- {"Floating Point Registers", "fpu", k_num_fpr_registers_mips,
- g_fp_regnums_mips},
- {"MSA Registers", "msa", k_num_msa_registers_mips, g_msa_regnums_mips}};
-
-uint32_t GetUserRegisterInfoCount(bool msa_present) {
- if (msa_present)
- return static_cast<uint32_t>(k_num_user_registers_mips);
- return static_cast<uint32_t>(k_num_user_registers_mips -
- k_num_msa_registers_mips);
-}
-
-RegisterContextLinux_mips::RegisterContextLinux_mips(
- const ArchSpec &target_arch, bool msa_present)
- : RegisterInfoInterface(target_arch),
- m_user_register_count(GetUserRegisterInfoCount(msa_present)) {}
-
-size_t RegisterContextLinux_mips::GetGPRSize() const {
- return sizeof(GPR_linux_mips);
-}
-
-const RegisterInfo *RegisterContextLinux_mips::GetRegisterInfo() const {
- switch (m_target_arch.GetMachine()) {
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- return g_register_infos_mips;
- default:
- assert(false && "Unhandled target architecture.");
- return nullptr;
- }
-}
-
-const RegisterSet *
-RegisterContextLinux_mips::GetRegisterSet(size_t set) const {
- if (set >= k_num_register_sets)
- return nullptr;
- switch (m_target_arch.GetMachine()) {
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- return &g_reg_sets_mips[set];
- default:
- assert(false && "Unhandled target architecture.");
- return nullptr;
- }
-}
-
-size_t
-RegisterContextLinux_mips::GetRegisterSetCount() const {
- return k_num_register_sets;
-}
-
-uint32_t RegisterContextLinux_mips::GetRegisterCount() const {
- return static_cast<uint32_t>(sizeof(g_register_infos_mips) /
- sizeof(g_register_infos_mips[0]));
-}
-
-uint32_t RegisterContextLinux_mips::GetUserRegisterCount() const {
- return static_cast<uint32_t>(m_user_register_count);
-}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.h b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.h
deleted file mode 100644
index 9b59ab4..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//===-- RegisterContextLinux_mips.h ---------------------------*- 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTLINUX_MIPS_H
-#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTLINUX_MIPS_H
-
-#include "RegisterInfoInterface.h"
-#include "lldb/lldb-private.h"
-
-class RegisterContextLinux_mips : public lldb_private::RegisterInfoInterface {
-public:
- RegisterContextLinux_mips(const lldb_private::ArchSpec &target_arch,
- bool msa_present = true);
-
- size_t GetGPRSize() const override;
-
- const lldb_private::RegisterInfo *GetRegisterInfo() const override;
-
- const lldb_private::RegisterSet *GetRegisterSet(size_t set) const;
-
- size_t GetRegisterSetCount() const;
-
- uint32_t GetRegisterCount() const override;
-
- uint32_t GetUserRegisterCount() const override;
-
-private:
- uint32_t m_user_register_count;
-};
-
-#endif
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp
deleted file mode 100644
index 432a781..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-//===-- RegisterContextLinux_mips64.cpp -----------------------------------===//
-//
-// 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 <stddef.h>
-#include <vector>
-
-// For eh_frame and DWARF Register numbers
-#include "RegisterContextLinux_mips64.h"
-
-// For GP and FP buffers
-#include "RegisterContext_mips.h"
-
-// Internal codes for all mips32 and mips64 registers
-#include "lldb-mips-linux-register-enums.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-// Include RegisterInfos_mips64 to declare our g_register_infos_mips64
-// structure.
-#define DECLARE_REGISTER_INFOS_MIPS64_STRUCT
-#define LINUX_MIPS64
-#include "RegisterInfos_mips64.h"
-#undef LINUX_MIPS64
-#undef DECLARE_REGISTER_INFOS_MIPS64_STRUCT
-
-// Include RegisterInfos_mips to declare our g_register_infos_mips structure.
-#define DECLARE_REGISTER_INFOS_MIPS_STRUCT
-#include "RegisterInfos_mips.h"
-#undef DECLARE_REGISTER_INFOS_MIPS_STRUCT
-
-// mips64 general purpose registers.
-const uint32_t g_gp_regnums_mips64[] = {
- gpr_zero_mips64, gpr_r1_mips64, gpr_r2_mips64,
- gpr_r3_mips64, gpr_r4_mips64, gpr_r5_mips64,
- gpr_r6_mips64, gpr_r7_mips64, gpr_r8_mips64,
- gpr_r9_mips64, gpr_r10_mips64, gpr_r11_mips64,
- gpr_r12_mips64, gpr_r13_mips64, gpr_r14_mips64,
- gpr_r15_mips64, gpr_r16_mips64, gpr_r17_mips64,
- gpr_r18_mips64, gpr_r19_mips64, gpr_r20_mips64,
- gpr_r21_mips64, gpr_r22_mips64, gpr_r23_mips64,
- gpr_r24_mips64, gpr_r25_mips64, gpr_r26_mips64,
- gpr_r27_mips64, gpr_gp_mips64, gpr_sp_mips64,
- gpr_r30_mips64, gpr_ra_mips64, gpr_sr_mips64,
- gpr_mullo_mips64, gpr_mulhi_mips64, gpr_badvaddr_mips64,
- gpr_cause_mips64, gpr_pc_mips64, gpr_config5_mips64,
- LLDB_INVALID_REGNUM // register sets need to end with this flag
-};
-
-static_assert((sizeof(g_gp_regnums_mips64) / sizeof(g_gp_regnums_mips64[0])) -
- 1 ==
- k_num_gpr_registers_mips64,
- "g_gp_regnums_mips64 has wrong number of register infos");
-
-// mips64 floating point registers.
-const uint32_t g_fp_regnums_mips64[] = {
- fpr_f0_mips64, fpr_f1_mips64, fpr_f2_mips64, fpr_f3_mips64,
- fpr_f4_mips64, fpr_f5_mips64, fpr_f6_mips64, fpr_f7_mips64,
- fpr_f8_mips64, fpr_f9_mips64, fpr_f10_mips64, fpr_f11_mips64,
- fpr_f12_mips64, fpr_f13_mips64, fpr_f14_mips64, fpr_f15_mips64,
- fpr_f16_mips64, fpr_f17_mips64, fpr_f18_mips64, fpr_f19_mips64,
- fpr_f20_mips64, fpr_f21_mips64, fpr_f22_mips64, fpr_f23_mips64,
- fpr_f24_mips64, fpr_f25_mips64, fpr_f26_mips64, fpr_f27_mips64,
- fpr_f28_mips64, fpr_f29_mips64, fpr_f30_mips64, fpr_f31_mips64,
- fpr_fcsr_mips64, fpr_fir_mips64, fpr_config5_mips64,
- LLDB_INVALID_REGNUM // register sets need to end with this flag
-};
-
-static_assert((sizeof(g_fp_regnums_mips64) / sizeof(g_fp_regnums_mips64[0])) -
- 1 ==
- k_num_fpr_registers_mips64,
- "g_fp_regnums_mips64 has wrong number of register infos");
-
-// mips64 MSA registers.
-const uint32_t g_msa_regnums_mips64[] = {
- msa_w0_mips64, msa_w1_mips64, msa_w2_mips64, msa_w3_mips64,
- msa_w4_mips64, msa_w5_mips64, msa_w6_mips64, msa_w7_mips64,
- msa_w8_mips64, msa_w9_mips64, msa_w10_mips64, msa_w11_mips64,
- msa_w12_mips64, msa_w13_mips64, msa_w14_mips64, msa_w15_mips64,
- msa_w16_mips64, msa_w17_mips64, msa_w18_mips64, msa_w19_mips64,
- msa_w20_mips64, msa_w21_mips64, msa_w22_mips64, msa_w23_mips64,
- msa_w24_mips64, msa_w25_mips64, msa_w26_mips64, msa_w27_mips64,
- msa_w28_mips64, msa_w29_mips64, msa_w30_mips64, msa_w31_mips64,
- msa_fcsr_mips64, msa_fir_mips64, msa_mcsr_mips64, msa_mir_mips64,
- msa_config5_mips64,
- LLDB_INVALID_REGNUM // register sets need to end with this flag
-};
-
-static_assert((sizeof(g_msa_regnums_mips64) / sizeof(g_msa_regnums_mips64[0])) -
- 1 ==
- k_num_msa_registers_mips64,
- "g_msa_regnums_mips64 has wrong number of register infos");
-
-// Number of register sets provided by this context.
-constexpr size_t k_num_register_sets = 3;
-
-// Register sets for mips64.
-static const RegisterSet g_reg_sets_mips64[k_num_register_sets] = {
- {"General Purpose Registers", "gpr", k_num_gpr_registers_mips64,
- g_gp_regnums_mips64},
- {"Floating Point Registers", "fpu", k_num_fpr_registers_mips64,
- g_fp_regnums_mips64},
- {"MSA Registers", "msa", k_num_msa_registers_mips64, g_msa_regnums_mips64},
-};
-
-const RegisterSet *
-RegisterContextLinux_mips64::GetRegisterSet(size_t set) const {
- if (set >= k_num_register_sets)
- return nullptr;
-
- switch (m_target_arch.GetMachine()) {
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- return &g_reg_sets_mips64[set];
- default:
- assert(false && "Unhandled target architecture.");
- return nullptr;
- }
- return nullptr;
-}
-
-size_t
-RegisterContextLinux_mips64::GetRegisterSetCount() const {
- return k_num_register_sets;
-}
-
-static const RegisterInfo *GetRegisterInfoPtr(const ArchSpec &target_arch) {
- switch (target_arch.GetMachine()) {
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- return g_register_infos_mips64;
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- return g_register_infos_mips;
- default:
- assert(false && "Unhandled target architecture.");
- return nullptr;
- }
-}
-
-static uint32_t GetRegisterInfoCount(const ArchSpec &target_arch) {
- switch (target_arch.GetMachine()) {
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- return static_cast<uint32_t>(sizeof(g_register_infos_mips64) /
- sizeof(g_register_infos_mips64[0]));
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- return static_cast<uint32_t>(sizeof(g_register_infos_mips) /
- sizeof(g_register_infos_mips[0]));
- default:
- assert(false && "Unhandled target architecture.");
- return 0;
- }
-}
-
-uint32_t GetUserRegisterInfoCount(const ArchSpec &target_arch,
- bool msa_present) {
- switch (target_arch.GetMachine()) {
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- if (msa_present)
- return static_cast<uint32_t>(k_num_user_registers_mips);
- return static_cast<uint32_t>(k_num_user_registers_mips -
- k_num_msa_registers_mips);
- case llvm::Triple::mips64el:
- case llvm::Triple::mips64:
- if (msa_present)
- return static_cast<uint32_t>(k_num_user_registers_mips64);
- return static_cast<uint32_t>(k_num_user_registers_mips64 -
- k_num_msa_registers_mips64);
- default:
- assert(false && "Unhandled target architecture.");
- return 0;
- }
-}
-
-RegisterContextLinux_mips64::RegisterContextLinux_mips64(
- const ArchSpec &target_arch, bool msa_present)
- : lldb_private::RegisterInfoInterface(target_arch),
- m_register_info_p(GetRegisterInfoPtr(target_arch)),
- m_register_info_count(GetRegisterInfoCount(target_arch)),
- m_user_register_count(
- GetUserRegisterInfoCount(target_arch, msa_present)) {}
-
-size_t RegisterContextLinux_mips64::GetGPRSize() const {
- return sizeof(GPR_linux_mips);
-}
-
-const RegisterInfo *RegisterContextLinux_mips64::GetRegisterInfo() const {
- return m_register_info_p;
-}
-
-uint32_t RegisterContextLinux_mips64::GetRegisterCount() const {
- return m_register_info_count;
-}
-
-uint32_t RegisterContextLinux_mips64::GetUserRegisterCount() const {
- return m_user_register_count;
-}
-
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h
deleted file mode 100644
index 899f0a4..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//===-- RegisterContextLinux_mips64.h ---------------------------*- 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTLINUX_MIPS64_H
-#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTLINUX_MIPS64_H
-
-#include "RegisterInfoInterface.h"
-#include "lldb/lldb-private.h"
-
-class RegisterContextLinux_mips64 : public lldb_private::RegisterInfoInterface {
-public:
- RegisterContextLinux_mips64(const lldb_private::ArchSpec &target_arch,
- bool msa_present = true);
-
- size_t GetGPRSize() const override;
-
- const lldb_private::RegisterInfo *GetRegisterInfo() const override;
-
- const lldb_private::RegisterSet *GetRegisterSet(size_t set) const;
-
- size_t GetRegisterSetCount() const;
-
- uint32_t GetRegisterCount() const override;
-
- uint32_t GetUserRegisterCount() const override;
-
-private:
- const lldb_private::RegisterInfo *m_register_info_p;
- uint32_t m_register_info_count;
- uint32_t m_user_register_count;
-};
-
-#endif
-
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp
index 1394cb7..067d1c3 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp
@@ -21,7 +21,7 @@
uint32_t concrete_frame_idx)
: RegisterContextDarwin_arm(thread, concrete_frame_idx) {}
-RegisterContextMach_arm::~RegisterContextMach_arm() {}
+RegisterContextMach_arm::~RegisterContextMach_arm() = default;
int RegisterContextMach_arm::DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) {
mach_msg_type_number_t count = GPRWordCount;
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp
index b97166b..fe5cece 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp
@@ -19,7 +19,7 @@
uint32_t concrete_frame_idx)
: RegisterContextDarwin_i386(thread, concrete_frame_idx) {}
-RegisterContextMach_i386::~RegisterContextMach_i386() {}
+RegisterContextMach_i386::~RegisterContextMach_i386() = default;
int RegisterContextMach_i386::DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) {
mach_msg_type_number_t count = GPRWordCount;
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp
index 8933f13..a3d8c4f 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp
@@ -19,7 +19,7 @@
Thread &thread, uint32_t concrete_frame_idx)
: RegisterContextDarwin_x86_64(thread, concrete_frame_idx) {}
-RegisterContextMach_x86_64::~RegisterContextMach_x86_64() {}
+RegisterContextMach_x86_64::~RegisterContextMach_x86_64() = default;
int RegisterContextMach_x86_64::DoReadGPR(lldb::tid_t tid, int flavor,
GPR &gpr) {
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp
index f2d230b..c55ffeb 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp
@@ -39,7 +39,7 @@
}
// Destructor
-RegisterContextMemory::~RegisterContextMemory() {}
+RegisterContextMemory::~RegisterContextMemory() = default;
void RegisterContextMemory::InvalidateAllRegisters() {
if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp
index 97a7603..684176b 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp
@@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//
+#include <cerrno>
+#include <cstdint>
#include <cstring>
-#include <errno.h>
-#include <stdint.h>
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -45,7 +45,7 @@
: lldb_private::RegisterContext(thread, 0),
m_register_info_up(std::move(register_info)) {}
-RegisterContextPOSIX_arm::~RegisterContextPOSIX_arm() {}
+RegisterContextPOSIX_arm::~RegisterContextPOSIX_arm() = default;
void RegisterContextPOSIX_arm::Invalidate() {}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
index 3f52501..676e450 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
@@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//
+#include <cerrno>
+#include <cstdint>
#include <cstring>
-#include <errno.h>
-#include <stdint.h>
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -40,10 +40,11 @@
}
bool RegisterContextPOSIX_arm64::IsSVE(unsigned reg) const {
- if (m_register_info_up->GetRegisterSetFromRegisterIndex(reg) ==
- RegisterInfoPOSIX_arm64::SVERegSet)
- return true;
- return false;
+ return m_register_info_up->IsSVEReg(reg);
+}
+
+bool RegisterContextPOSIX_arm64::IsPAuth(unsigned reg) const {
+ return m_register_info_up->IsPAuthReg(reg);
}
RegisterContextPOSIX_arm64::RegisterContextPOSIX_arm64(
@@ -52,7 +53,7 @@
: lldb_private::RegisterContext(thread, 0),
m_register_info_up(std::move(register_info)) {}
-RegisterContextPOSIX_arm64::~RegisterContextPOSIX_arm64() {}
+RegisterContextPOSIX_arm64::~RegisterContextPOSIX_arm64() = default;
void RegisterContextPOSIX_arm64::Invalidate() {}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h
index a3f07bb..7c30159 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h
@@ -54,6 +54,7 @@
size_t GetFPUSize() { return sizeof(RegisterInfoPOSIX_arm64::FPU); }
bool IsSVE(unsigned reg) const;
+ bool IsPAuth(unsigned reg) const;
bool IsSVEZ(unsigned reg) const { return m_register_info_up->IsSVEZReg(reg); }
bool IsSVEP(unsigned reg) const { return m_register_info_up->IsSVEPReg(reg); }
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp
index c41c4bd..9e05737 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp
@@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//
+#include <cerrno>
+#include <cstdint>
#include <cstring>
-#include <errno.h>
-#include <stdint.h>
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -22,8 +22,6 @@
#include "RegisterContextPOSIX_mips64.h"
#include "RegisterContextFreeBSD_mips64.h"
-#include "RegisterContextLinux_mips64.h"
-#include "RegisterContextLinux_mips.h"
using namespace lldb_private;
using namespace lldb;
@@ -60,7 +58,7 @@
m_registers_count[msa_registers_count]));
}
-RegisterContextPOSIX_mips64::~RegisterContextPOSIX_mips64() {}
+RegisterContextPOSIX_mips64::~RegisterContextPOSIX_mips64() = default;
void RegisterContextPOSIX_mips64::Invalidate() {}
@@ -102,17 +100,6 @@
size_t RegisterContextPOSIX_mips64::GetRegisterSetCount() {
ArchSpec target_arch = m_register_info_up->GetTargetArchitecture();
switch (target_arch.GetTriple().getOS()) {
- case llvm::Triple::Linux: {
- if ((target_arch.GetMachine() == llvm::Triple::mipsel) ||
- (target_arch.GetMachine() == llvm::Triple::mips)) {
- const auto *context = static_cast<const RegisterContextLinux_mips *>(
- m_register_info_up.get());
- return context->GetRegisterSetCount();
- }
- const auto *context = static_cast<const RegisterContextLinux_mips64 *>(
- m_register_info_up.get());
- return context->GetRegisterSetCount();
- }
default: {
const auto *context = static_cast<const RegisterContextFreeBSD_mips64 *>(
m_register_info_up.get());
@@ -125,17 +112,6 @@
const RegisterSet *RegisterContextPOSIX_mips64::GetRegisterSet(size_t set) {
ArchSpec target_arch = m_register_info_up->GetTargetArchitecture();
switch (target_arch.GetTriple().getOS()) {
- case llvm::Triple::Linux: {
- if ((target_arch.GetMachine() == llvm::Triple::mipsel) ||
- (target_arch.GetMachine() == llvm::Triple::mips)) {
- const auto *context = static_cast<const RegisterContextLinux_mips *>(
- m_register_info_up.get());
- return context->GetRegisterSet(set);
- }
- const auto *context = static_cast<const RegisterContextLinux_mips64 *>(
- m_register_info_up.get());
- return context->GetRegisterSet(set);
- }
default: {
const auto *context = static_cast<const RegisterContextFreeBSD_mips64 *>(
m_register_info_up.get());
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp
index cd65b96..cffd286 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp
@@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//
+#include <cerrno>
+#include <cstdint>
#include <cstring>
-#include <errno.h>
-#include <stdint.h>
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -95,7 +95,7 @@
m_register_info_up.reset(register_info);
}
-RegisterContextPOSIX_powerpc::~RegisterContextPOSIX_powerpc() {}
+RegisterContextPOSIX_powerpc::~RegisterContextPOSIX_powerpc() = default;
void RegisterContextPOSIX_powerpc::Invalidate() {}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp
index f670be2..f70ddeb 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp
@@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//
+#include <cerrno>
+#include <cstdint>
#include <cstring>
-#include <errno.h>
-#include <stdint.h>
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp
index e746ec6..21c8160 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp
@@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//
+#include <cerrno>
+#include <cstdint>
#include <cstring>
-#include <errno.h>
-#include <stdint.h>
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -98,7 +98,7 @@
}
}
-RegisterContextPOSIX_s390x::~RegisterContextPOSIX_s390x() {}
+RegisterContextPOSIX_s390x::~RegisterContextPOSIX_s390x() = default;
void RegisterContextPOSIX_s390x::Invalidate() {}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp
index 2c7f635..67e03ff 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp
@@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//
+#include <cerrno>
+#include <cstdint>
#include <cstring>
-#include <errno.h>
-#include <stdint.h>
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -448,7 +448,7 @@
m_fpr_type = eNotValid;
}
-RegisterContextPOSIX_x86::~RegisterContextPOSIX_x86() {}
+RegisterContextPOSIX_x86::~RegisterContextPOSIX_x86() = default;
RegisterContextPOSIX_x86::FPRType RegisterContextPOSIX_x86::GetFPRType() {
if (m_fpr_type == eNotValid) {
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp
index 31e2944..4866cbd 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp
@@ -22,7 +22,7 @@
: RegisterContext(thread, 0), m_thread_wp(thread.shared_from_this()),
m_reg_ctx_sp(), m_register_data_addr(register_data_addr), m_stop_id(0) {}
-RegisterContextThreadMemory::~RegisterContextThreadMemory() {}
+RegisterContextThreadMemory::~RegisterContextThreadMemory() = default;
void RegisterContextThreadMemory::UpdateRegisterContext() {
ThreadSP thread_sp(m_thread_wp.lock());
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h
index 88c2ae7..c054383 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h
@@ -22,7 +22,7 @@
public:
RegisterInfoInterface(const lldb_private::ArchSpec &target_arch)
: m_target_arch(target_arch) {}
- virtual ~RegisterInfoInterface() {}
+ virtual ~RegisterInfoInterface() = default;
virtual size_t GetGPRSize() const = 0;
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.cpp
index 17b96f9..63461f7 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.cpp
@@ -7,7 +7,7 @@
//===---------------------------------------------------------------------===//
#include <cassert>
-#include <stddef.h>
+#include <cstddef>
#include <vector>
#include "lldb/lldb-defines.h"
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
index 515c9f4..b878534 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp
@@ -7,7 +7,7 @@
//===---------------------------------------------------------------------===//
#include <cassert>
-#include <stddef.h>
+#include <cstddef>
#include <vector>
#include "lldb/lldb-defines.h"
@@ -72,23 +72,14 @@
#include "RegisterInfos_arm64_sve.h"
#undef DECLARE_REGISTER_INFOS_ARM64_STRUCT
-static const lldb_private::RegisterInfo *
-GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) {
- switch (target_arch.GetMachine()) {
- case llvm::Triple::aarch64:
- case llvm::Triple::aarch64_32:
- return g_register_infos_arm64_le;
- default:
- assert(false && "Unhandled target architecture.");
- return nullptr;
- }
-}
-
// Number of register sets provided by this context.
enum {
k_num_gpr_registers = gpr_w28 - gpr_x0 + 1,
k_num_fpr_registers = fpu_fpcr - fpu_v0 + 1,
k_num_sve_registers = sve_ffr - sve_vg + 1,
+ k_num_mte_register = 1,
+ k_num_pauth_register = 2,
+ k_num_register_sets_default = 2,
k_num_register_sets = 3
};
@@ -186,31 +177,66 @@
{"Scalable Vector Extension Registers", "sve", k_num_sve_registers,
g_sve_regnums_arm64}};
-static uint32_t
-GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch) {
+static const lldb_private::RegisterSet g_reg_set_pauth_arm64 = {
+ "Pointer Authentication Registers", "pauth", k_num_pauth_register, NULL};
+
+static const lldb_private::RegisterSet g_reg_set_mte_arm64 = {
+ "MTE Control Register", "mte", k_num_mte_register, NULL};
+
+RegisterInfoPOSIX_arm64::RegisterInfoPOSIX_arm64(
+ const lldb_private::ArchSpec &target_arch, lldb_private::Flags opt_regsets)
+ : lldb_private::RegisterInfoAndSetInterface(target_arch),
+ m_opt_regsets(opt_regsets) {
switch (target_arch.GetMachine()) {
case llvm::Triple::aarch64:
- case llvm::Triple::aarch64_32:
- return static_cast<uint32_t>(sizeof(g_register_infos_arm64_le) /
- sizeof(g_register_infos_arm64_le[0]));
+ case llvm::Triple::aarch64_32: {
+ m_register_set_p = g_reg_sets_arm64;
+ m_register_set_count = k_num_register_sets_default;
+ m_per_regset_regnum_range[GPRegSet] = std::make_pair(gpr_x0, gpr_w28 + 1);
+ m_per_regset_regnum_range[FPRegSet] = std::make_pair(fpu_v0, fpu_fpcr + 1);
+
+ // Now configure register sets supported by current target. If we have a
+ // dynamic register set like MTE, Pointer Authentication regset then we need
+ // to create dynamic register infos and regset array. Push back all optional
+ // register infos and regset and calculate register offsets accordingly.
+ if (m_opt_regsets.AllSet(eRegsetMaskSVE)) {
+ m_register_info_p = g_register_infos_arm64_sve_le;
+ m_register_info_count = sve_ffr + 1;
+ m_per_regset_regnum_range[m_register_set_count++] =
+ std::make_pair(sve_vg, sve_ffr + 1);
+ } else {
+ m_register_info_p = g_register_infos_arm64_le;
+ m_register_info_count = fpu_fpcr + 1;
+ }
+
+ if (m_opt_regsets.AnySet(eRegsetMaskDynamic)) {
+ llvm::ArrayRef<lldb_private::RegisterInfo> reg_infos_ref =
+ llvm::makeArrayRef(m_register_info_p, m_register_info_count);
+ llvm::ArrayRef<lldb_private::RegisterSet> reg_sets_ref =
+ llvm::makeArrayRef(m_register_set_p, m_register_set_count);
+ llvm::copy(reg_infos_ref, std::back_inserter(m_dynamic_reg_infos));
+ llvm::copy(reg_sets_ref, std::back_inserter(m_dynamic_reg_sets));
+
+ if (m_opt_regsets.AllSet(eRegsetMaskPAuth))
+ AddRegSetPAuth();
+
+ if (m_opt_regsets.AllSet(eRegsetMaskMTE))
+ AddRegSetMTE();
+
+ m_register_info_count = m_dynamic_reg_infos.size();
+ m_register_info_p = m_dynamic_reg_infos.data();
+ m_register_set_p = m_dynamic_reg_sets.data();
+ m_register_set_count = m_dynamic_reg_sets.size();
+ }
+ break;
+ }
default:
assert(false && "Unhandled target architecture.");
- return 0;
}
}
-RegisterInfoPOSIX_arm64::RegisterInfoPOSIX_arm64(
- const lldb_private::ArchSpec &target_arch)
- : lldb_private::RegisterInfoAndSetInterface(target_arch),
- m_register_info_p(GetRegisterInfoPtr(target_arch)),
- m_register_info_count(GetRegisterInfoCount(target_arch)) {
-}
-
uint32_t RegisterInfoPOSIX_arm64::GetRegisterCount() const {
- if (IsSVEEnabled())
- return k_num_gpr_registers + k_num_fpr_registers + k_num_sve_registers;
-
- return k_num_gpr_registers + k_num_fpr_registers;
+ return m_register_info_count;
}
size_t RegisterInfoPOSIX_arm64::GetGPRSize() const {
@@ -227,31 +253,60 @@
}
size_t RegisterInfoPOSIX_arm64::GetRegisterSetCount() const {
- if (IsSVEEnabled())
- return k_num_register_sets;
- return k_num_register_sets - 1;
+ return m_register_set_count;
}
size_t RegisterInfoPOSIX_arm64::GetRegisterSetFromRegisterIndex(
uint32_t reg_index) const {
- if (reg_index <= gpr_w28)
- return GPRegSet;
- if (reg_index <= fpu_fpcr)
- return FPRegSet;
- if (reg_index <= sve_ffr)
- return SVERegSet;
+ for (const auto ®set_range : m_per_regset_regnum_range) {
+ if (reg_index >= regset_range.second.first &&
+ reg_index < regset_range.second.second)
+ return regset_range.first;
+ }
return LLDB_INVALID_REGNUM;
}
const lldb_private::RegisterSet *
RegisterInfoPOSIX_arm64::GetRegisterSet(size_t set_index) const {
if (set_index < GetRegisterSetCount())
- return &g_reg_sets_arm64[set_index];
+ return &m_register_set_p[set_index];
return nullptr;
}
-uint32_t
-RegisterInfoPOSIX_arm64::ConfigureVectorRegisterInfos(uint32_t sve_vq) {
+void RegisterInfoPOSIX_arm64::AddRegSetPAuth() {
+ uint32_t pa_regnum = m_dynamic_reg_infos.size();
+ for (uint32_t i = 0; i < k_num_pauth_register; i++) {
+ pauth_regnum_collection.push_back(pa_regnum + i);
+ m_dynamic_reg_infos.push_back(g_register_infos_pauth[i]);
+ m_dynamic_reg_infos[pa_regnum + i].byte_offset =
+ m_dynamic_reg_infos[pa_regnum + i - 1].byte_offset +
+ m_dynamic_reg_infos[pa_regnum + i - 1].byte_size;
+ m_dynamic_reg_infos[pa_regnum + i].kinds[lldb::eRegisterKindLLDB] =
+ pa_regnum + i;
+ }
+
+ m_per_regset_regnum_range[m_register_set_count] =
+ std::make_pair(pa_regnum, m_dynamic_reg_infos.size());
+ m_dynamic_reg_sets.push_back(g_reg_set_pauth_arm64);
+ m_dynamic_reg_sets.back().registers = pauth_regnum_collection.data();
+}
+
+void RegisterInfoPOSIX_arm64::AddRegSetMTE() {
+ uint32_t mte_regnum = m_dynamic_reg_infos.size();
+ m_mte_regnum_collection.push_back(mte_regnum);
+ m_dynamic_reg_infos.push_back(g_register_infos_mte[0]);
+ m_dynamic_reg_infos[mte_regnum].byte_offset =
+ m_dynamic_reg_infos[mte_regnum - 1].byte_offset +
+ m_dynamic_reg_infos[mte_regnum - 1].byte_size;
+ m_dynamic_reg_infos[mte_regnum].kinds[lldb::eRegisterKindLLDB] = mte_regnum;
+
+ m_per_regset_regnum_range[m_register_set_count] =
+ std::make_pair(mte_regnum, mte_regnum + 1);
+ m_dynamic_reg_sets.push_back(g_reg_set_mte_arm64);
+ m_dynamic_reg_sets.back().registers = m_mte_regnum_collection.data();
+}
+
+uint32_t RegisterInfoPOSIX_arm64::ConfigureVectorLength(uint32_t sve_vq) {
// sve_vq contains SVE Quad vector length in context of AArch64 SVE.
// SVE register infos if enabled cannot be disabled by selecting sve_vq = 0.
// Also if an invalid or previously set vector length is passed to this
@@ -266,28 +321,15 @@
m_vector_reg_vq = sve_vq;
- if (sve_vq == eVectorQuadwordAArch64) {
- m_register_info_count =
- static_cast<uint32_t>(sizeof(g_register_infos_arm64_le) /
- sizeof(g_register_infos_arm64_le[0]));
- m_register_info_p = g_register_infos_arm64_le;
-
+ if (sve_vq == eVectorQuadwordAArch64)
return m_vector_reg_vq;
- }
-
- m_register_info_count =
- static_cast<uint32_t>(sizeof(g_register_infos_arm64_sve_le) /
- sizeof(g_register_infos_arm64_sve_le[0]));
-
std::vector<lldb_private::RegisterInfo> ®_info_ref =
m_per_vq_reg_infos[sve_vq];
if (reg_info_ref.empty()) {
- reg_info_ref = llvm::makeArrayRef(g_register_infos_arm64_sve_le,
- m_register_info_count);
+ reg_info_ref = llvm::makeArrayRef(m_register_info_p, m_register_info_count);
uint32_t offset = SVE_REGS_DEFAULT_OFFSET_LINUX;
-
reg_info_ref[fpu_fpsr].byte_offset = offset;
reg_info_ref[fpu_fpcr].byte_offset = offset + 4;
reg_info_ref[sve_vg].byte_offset = offset + 8;
@@ -316,13 +358,25 @@
offset += reg_info_ref[it].byte_size;
}
+ for (uint32_t it = sve_ffr + 1; it < m_register_info_count; it++) {
+ reg_info_ref[it].byte_offset = offset;
+ offset += reg_info_ref[it].byte_size;
+ }
+
m_per_vq_reg_infos[sve_vq] = reg_info_ref;
}
- m_register_info_p = reg_info_ref.data();
+ m_register_info_p = m_per_vq_reg_infos[sve_vq].data();
return m_vector_reg_vq;
}
+bool RegisterInfoPOSIX_arm64::IsSVEReg(unsigned reg) const {
+ if (m_vector_reg_vq > eVectorQuadwordAArch64)
+ return (sve_vg <= reg && reg <= sve_ffr);
+ else
+ return false;
+}
+
bool RegisterInfoPOSIX_arm64::IsSVEZReg(unsigned reg) const {
return (sve_z0 <= reg && reg <= sve_z31);
}
@@ -335,6 +389,18 @@
return sve_vg == reg;
}
+bool RegisterInfoPOSIX_arm64::IsPAuthReg(unsigned reg) const {
+ return std::find(pauth_regnum_collection.begin(),
+ pauth_regnum_collection.end(),
+ reg) != pauth_regnum_collection.end();
+}
+
+bool RegisterInfoPOSIX_arm64::IsMTEReg(unsigned reg) const {
+ return std::find(m_mte_regnum_collection.begin(),
+ m_mte_regnum_collection.end(),
+ reg) != m_mte_regnum_collection.end();
+}
+
uint32_t RegisterInfoPOSIX_arm64::GetRegNumSVEZ0() const { return sve_z0; }
uint32_t RegisterInfoPOSIX_arm64::GetRegNumSVEFFR() const { return sve_ffr; }
@@ -344,3 +410,11 @@
uint32_t RegisterInfoPOSIX_arm64::GetRegNumFPSR() const { return fpu_fpsr; }
uint32_t RegisterInfoPOSIX_arm64::GetRegNumSVEVG() const { return sve_vg; }
+
+uint32_t RegisterInfoPOSIX_arm64::GetPAuthOffset() const {
+ return m_register_info_p[pauth_regnum_collection[0]].byte_offset;
+}
+
+uint32_t RegisterInfoPOSIX_arm64::GetMTEOffset() const {
+ return m_register_info_p[m_mte_regnum_collection[0]].byte_offset;
+}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h
index 2929f20..ba873ba 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h
@@ -11,6 +11,7 @@
#include "RegisterInfoAndSetInterface.h"
#include "lldb/Target/RegisterContext.h"
+#include "lldb/Utility/Flags.h"
#include "lldb/lldb-private.h"
#include <map>
@@ -19,7 +20,16 @@
class RegisterInfoPOSIX_arm64
: public lldb_private::RegisterInfoAndSetInterface {
public:
- enum { GPRegSet = 0, FPRegSet, SVERegSet };
+ enum { GPRegSet = 0, FPRegSet };
+
+ // AArch64 register set mask value
+ enum {
+ eRegsetMaskDefault = 0,
+ eRegsetMaskSVE = 1,
+ eRegsetMaskPAuth = 2,
+ eRegsetMaskMTE = 4,
+ eRegsetMaskDynamic = ~1,
+ };
// AArch64 Register set FP/SIMD feature configuration
enum {
@@ -68,7 +78,8 @@
uint64_t mdscr_el1;
};
- RegisterInfoPOSIX_arm64(const lldb_private::ArchSpec &target_arch);
+ RegisterInfoPOSIX_arm64(const lldb_private::ArchSpec &target_arch,
+ lldb_private::Flags opt_regsets);
size_t GetGPRSize() const override;
@@ -85,7 +96,11 @@
size_t GetRegisterSetFromRegisterIndex(uint32_t reg_index) const override;
- uint32_t ConfigureVectorRegisterInfos(uint32_t sve_vq);
+ void AddRegSetPAuth();
+
+ void AddRegSetMTE();
+
+ uint32_t ConfigureVectorLength(uint32_t sve_vq);
bool VectorSizeIsValid(uint32_t vq) {
if (vq >= eVectorQuadwordAArch64 && vq <= eVectorQuadwordAArch64SVEMax)
@@ -93,17 +108,23 @@
return false;
}
- bool IsSVEEnabled() const { return m_vector_reg_vq > eVectorQuadwordAArch64; }
+ bool IsSVEEnabled() const { return m_opt_regsets.AnySet(eRegsetMaskSVE); }
+ bool IsPAuthEnabled() const { return m_opt_regsets.AnySet(eRegsetMaskPAuth); }
+ bool IsSVEReg(unsigned reg) const;
bool IsSVEZReg(unsigned reg) const;
bool IsSVEPReg(unsigned reg) const;
bool IsSVERegVG(unsigned reg) const;
+ bool IsPAuthReg(unsigned reg) const;
+ bool IsMTEReg(unsigned reg) const;
uint32_t GetRegNumSVEZ0() const;
uint32_t GetRegNumSVEFFR() const;
uint32_t GetRegNumFPCR() const;
uint32_t GetRegNumFPSR() const;
uint32_t GetRegNumSVEVG() const;
+ uint32_t GetPAuthOffset() const;
+ uint32_t GetMTEOffset() const;
private:
typedef std::map<uint32_t, std::vector<lldb_private::RegisterInfo>>
@@ -115,6 +136,21 @@
const lldb_private::RegisterInfo *m_register_info_p;
uint32_t m_register_info_count;
+
+ const lldb_private::RegisterSet *m_register_set_p;
+ uint32_t m_register_set_count;
+
+ // Contains pair of [start, end] register numbers of a register set with start
+ // and end included.
+ std::map<uint32_t, std::pair<uint32_t, uint32_t>> m_per_regset_regnum_range;
+
+ lldb_private::Flags m_opt_regsets;
+
+ std::vector<lldb_private::RegisterInfo> m_dynamic_reg_infos;
+ std::vector<lldb_private::RegisterSet> m_dynamic_reg_sets;
+
+ std::vector<uint32_t> pauth_regnum_collection;
+ std::vector<uint32_t> m_mte_regnum_collection;
};
#endif
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp
index 3461d38..159fd28 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp
@@ -7,7 +7,7 @@
//===---------------------------------------------------------------------===//
#include <cassert>
-#include <stddef.h>
+#include <cstddef>
#include <vector>
#include "lldb/lldb-defines.h"
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_arm.h b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_arm.h
index 74b9e3b..4af0069 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_arm.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_arm.h
@@ -8,7 +8,7 @@
#ifdef DECLARE_REGISTER_INFOS_ARM_STRUCT
-#include <stddef.h>
+#include <cstddef>
#include "lldb/lldb-defines.h"
#include "lldb/lldb-enumerations.h"
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h
index 4aee55e..47cedc3 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h
@@ -8,7 +8,7 @@
#ifdef DECLARE_REGISTER_INFOS_ARM64_STRUCT
-#include <stddef.h>
+#include <cstddef>
#include "lldb/lldb-defines.h"
#include "lldb/lldb-enumerations.h"
@@ -470,6 +470,13 @@
LLDB_INVALID_REGNUM, lldb_kind \
}
+// Generates register kinds array for registers with only lldb kind
+#define KIND_ALL_INVALID \
+ { \
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM \
+ }
+
// Generates register kinds array for vector registers
#define GPR64_KIND(reg, generic_kind) MISC_KIND(reg, gpr, generic_kind)
#define VREG_KIND(reg) MISC_KIND(reg, fpu, LLDB_INVALID_REGNUM)
@@ -526,6 +533,13 @@
nullptr, 0 \
}
+// Defines pointer authentication mask registers
+#define DEFINE_EXTENSION_REG(reg) \
+ { \
+ #reg, nullptr, 8, 0, lldb::eEncodingUint, lldb::eFormatHex, \
+ KIND_ALL_INVALID, nullptr, nullptr, nullptr, 0 \
+ }
+
static lldb_private::RegisterInfo g_register_infos_arm64_le[] = {
// DEFINE_GPR64(name, GENERIC KIND)
DEFINE_GPR64(x0, LLDB_REGNUM_GENERIC_ARG1),
@@ -772,7 +786,12 @@
{DEFINE_DBG(wcr, 13)},
{DEFINE_DBG(wcr, 14)},
{DEFINE_DBG(wcr, 15)}
- // clang-format on
};
+// clang-format on
+static lldb_private::RegisterInfo g_register_infos_pauth[] = {
+ DEFINE_EXTENSION_REG(data_mask), DEFINE_EXTENSION_REG(code_mask)};
+
+static lldb_private::RegisterInfo g_register_infos_mte[] = {
+ DEFINE_EXTENSION_REG(mte_ctrl)};
#endif // DECLARE_REGISTER_INFOS_ARM64_STRUCT
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_mips.h b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_mips.h
index 08201fd..93f93d5 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_mips.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_mips.h
@@ -6,7 +6,7 @@
//
//===---------------------------------------------------------------------===//
-#include <stddef.h>
+#include <cstddef>
#include "lldb/Core/dwarf.h"
#include "llvm/Support/Compiler.h"
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_mips64.h b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_mips64.h
index b6e218e..b28b918 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_mips64.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_mips64.h
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include <stddef.h>
+#include <cstddef>
#include "lldb/Core/dwarf.h"
#include "llvm/Support/Compiler.h"
@@ -15,37 +15,11 @@
#ifdef DECLARE_REGISTER_INFOS_MIPS64_STRUCT
// Computes the offset of the given GPR in the user data area.
-#ifdef LINUX_MIPS64
-#define GPR_OFFSET(regname) \
- (LLVM_EXTENSION offsetof(UserArea, gpr) + \
- LLVM_EXTENSION offsetof(GPR_linux_mips, regname))
-#else
#define GPR_OFFSET(regname) (LLVM_EXTENSION offsetof(GPR_freebsd_mips, regname))
-#endif
-
-// Computes the offset of the given FPR in the extended data area.
-#define FPR_OFFSET(regname) \
- (LLVM_EXTENSION offsetof(UserArea, fpr) + \
- LLVM_EXTENSION offsetof(FPR_linux_mips, regname))
-
-// Computes the offset of the given MSA in the extended data area.
-#define MSA_OFFSET(regname) \
- (LLVM_EXTENSION offsetof(UserArea, msa) + \
- LLVM_EXTENSION offsetof(MSA_linux_mips, regname))
// RegisterKind: EHFrame, DWARF, Generic, Process Plugin, LLDB
// Note that the size and offset will be updated by platform-specific classes.
-#ifdef LINUX_MIPS64
-#define DEFINE_GPR(reg, alt, kind1, kind2, kind3) \
- { \
- #reg, alt, sizeof(((GPR_linux_mips *) 0)->reg), \
- GPR_OFFSET(reg), eEncodingUint, eFormatHex, \
- {kind1, kind2, kind3, ptrace_##reg##_mips, \
- gpr_##reg##_mips64 }, \
- NULL, NULL, NULL, 0 \
- }
-#else
#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \
{ \
#reg, alt, sizeof(((GPR_freebsd_mips *) 0)->reg), \
@@ -54,63 +28,10 @@
gpr_##reg##_mips64 }, \
NULL, NULL, NULL, 0 \
}
-#endif
-
-#define DEFINE_GPR_INFO(reg, alt, kind1, kind2, kind3) \
- { \
- #reg, alt, sizeof(((GPR_linux_mips *) 0)->reg) / 2, \
- GPR_OFFSET(reg), eEncodingUint, eFormatHex, \
- {kind1, kind2, kind3, ptrace_##reg##_mips, \
- gpr_##reg##_mips64 }, \
- NULL, NULL, NULL, 0 \
- }
-
-const uint8_t dwarf_opcode_mips64[] = {
- llvm::dwarf::DW_OP_regx, dwarf_sr_mips64, llvm::dwarf::DW_OP_lit1,
- llvm::dwarf::DW_OP_lit26, llvm::dwarf::DW_OP_shl, llvm::dwarf::DW_OP_and,
- llvm::dwarf::DW_OP_lit26, llvm::dwarf::DW_OP_shr};
-
-#define DEFINE_FPR(reg, alt, kind1, kind2, kind3) \
- { \
- #reg, alt, sizeof(((FPR_linux_mips *) 0)->reg), \
- FPR_OFFSET(reg), eEncodingIEEE754, eFormatFloat, \
- {kind1, kind2, kind3, ptrace_##reg##_mips, \
- fpr_##reg##_mips64 }, \
- NULL, NULL, dwarf_opcode_mips64, \
- sizeof(dwarf_opcode_mips64) \
- }
-
-#define DEFINE_FPR_INFO(reg, alt, kind1, kind2, kind3) \
- { \
- #reg, alt, sizeof(((FPR_linux_mips *) 0)->reg), \
- FPR_OFFSET(reg), eEncodingUint, eFormatHex, \
- {kind1, kind2, kind3, ptrace_##reg##_mips, \
- fpr_##reg##_mips64 }, \
- NULL, NULL, NULL, 0 \
- }
-
-#define DEFINE_MSA(reg, alt, kind1, kind2, kind3, kind4) \
- { \
- #reg, alt, sizeof(((MSA_linux_mips *) 0)->reg), \
- MSA_OFFSET(reg), eEncodingVector, eFormatVectorOfUInt8, \
- {kind1, kind2, kind3, kind4, \
- msa_##reg##_mips64 }, \
- NULL, NULL, NULL, 0 \
- }
-
-#define DEFINE_MSA_INFO(reg, alt, kind1, kind2, kind3, kind4) \
- { \
- #reg, alt, sizeof(((MSA_linux_mips *) 0)->reg), \
- MSA_OFFSET(reg), eEncodingUint, eFormatHex, \
- {kind1, kind2, kind3, kind4, \
- msa_##reg##_mips64 }, \
- NULL, NULL, NULL, 0 \
- }
static RegisterInfo g_register_infos_mips64[] = {
// General purpose registers. EH_Frame, DWARF,
// Generic, Process Plugin
-#ifndef LINUX_MIPS64
DEFINE_GPR(zero, "r0", dwarf_zero_mips64, dwarf_zero_mips64,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
DEFINE_GPR(r1, nullptr, dwarf_r1_mips64, dwarf_r1_mips64,
@@ -191,231 +112,6 @@
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
DEFINE_GPR(dummy, nullptr, dwarf_dummy_mips64, dwarf_dummy_mips64,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
-#else
- DEFINE_GPR(zero, "r0", dwarf_zero_mips64, dwarf_zero_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r1, nullptr, dwarf_r1_mips64, dwarf_r1_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r2, nullptr, dwarf_r2_mips64, dwarf_r2_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r3, nullptr, dwarf_r3_mips64, dwarf_r3_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r4, nullptr, dwarf_r4_mips64, dwarf_r4_mips64,
- LLDB_REGNUM_GENERIC_ARG1),
- DEFINE_GPR(r5, nullptr, dwarf_r5_mips64, dwarf_r5_mips64,
- LLDB_REGNUM_GENERIC_ARG2),
- DEFINE_GPR(r6, nullptr, dwarf_r6_mips64, dwarf_r6_mips64,
- LLDB_REGNUM_GENERIC_ARG3),
- DEFINE_GPR(r7, nullptr, dwarf_r7_mips64, dwarf_r7_mips64,
- LLDB_REGNUM_GENERIC_ARG4),
- DEFINE_GPR(r8, nullptr, dwarf_r8_mips64, dwarf_r8_mips64,
- LLDB_REGNUM_GENERIC_ARG5),
- DEFINE_GPR(r9, nullptr, dwarf_r9_mips64, dwarf_r9_mips64,
- LLDB_REGNUM_GENERIC_ARG6),
- DEFINE_GPR(r10, nullptr, dwarf_r10_mips64, dwarf_r10_mips64,
- LLDB_REGNUM_GENERIC_ARG7),
- DEFINE_GPR(r11, nullptr, dwarf_r11_mips64, dwarf_r11_mips64,
- LLDB_REGNUM_GENERIC_ARG8),
- DEFINE_GPR(r12, nullptr, dwarf_r12_mips64, dwarf_r12_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r13, nullptr, dwarf_r13_mips64, dwarf_r13_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r14, nullptr, dwarf_r14_mips64, dwarf_r14_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r15, nullptr, dwarf_r15_mips64, dwarf_r15_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r16, nullptr, dwarf_r16_mips64, dwarf_r16_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r17, nullptr, dwarf_r17_mips64, dwarf_r17_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r18, nullptr, dwarf_r18_mips64, dwarf_r18_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r19, nullptr, dwarf_r19_mips64, dwarf_r19_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r20, nullptr, dwarf_r20_mips64, dwarf_r20_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r21, nullptr, dwarf_r21_mips64, dwarf_r21_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r22, nullptr, dwarf_r22_mips64, dwarf_r22_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r23, nullptr, dwarf_r23_mips64, dwarf_r23_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r24, nullptr, dwarf_r24_mips64, dwarf_r24_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r25, nullptr, dwarf_r25_mips64, dwarf_r25_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r26, nullptr, dwarf_r26_mips64, dwarf_r26_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r27, nullptr, dwarf_r27_mips64, dwarf_r27_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(gp, "r28", dwarf_gp_mips64, dwarf_gp_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(sp, "r29", dwarf_sp_mips64, dwarf_sp_mips64,
- LLDB_REGNUM_GENERIC_SP),
- DEFINE_GPR(r30, nullptr, dwarf_r30_mips64, dwarf_r30_mips64,
- LLDB_REGNUM_GENERIC_FP),
- DEFINE_GPR(ra, "r31", dwarf_ra_mips64, dwarf_ra_mips64,
- LLDB_REGNUM_GENERIC_RA),
- DEFINE_GPR_INFO(sr, nullptr, dwarf_sr_mips64, dwarf_sr_mips64,
- LLDB_REGNUM_GENERIC_FLAGS),
- DEFINE_GPR(mullo, nullptr, dwarf_lo_mips64, dwarf_lo_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(mulhi, nullptr, dwarf_hi_mips64, dwarf_hi_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(badvaddr, nullptr, dwarf_bad_mips64, dwarf_bad_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR_INFO(cause, nullptr, dwarf_cause_mips64, dwarf_cause_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(pc, "pc", dwarf_pc_mips64, dwarf_pc_mips64,
- LLDB_REGNUM_GENERIC_PC),
- DEFINE_GPR_INFO(config5, nullptr, dwarf_config5_mips64,
- dwarf_config5_mips64, LLDB_INVALID_REGNUM),
- DEFINE_FPR(f0, nullptr, dwarf_f0_mips64, dwarf_f0_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f1, nullptr, dwarf_f1_mips64, dwarf_f1_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f2, nullptr, dwarf_f2_mips64, dwarf_f2_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f3, nullptr, dwarf_f3_mips64, dwarf_f3_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f4, nullptr, dwarf_f4_mips64, dwarf_f4_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f5, nullptr, dwarf_f5_mips64, dwarf_f5_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f6, nullptr, dwarf_f6_mips64, dwarf_f6_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f7, nullptr, dwarf_f7_mips64, dwarf_f7_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f8, nullptr, dwarf_f8_mips64, dwarf_f8_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f9, nullptr, dwarf_f9_mips64, dwarf_f9_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f10, nullptr, dwarf_f10_mips64, dwarf_f10_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f11, nullptr, dwarf_f11_mips64, dwarf_f11_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f12, nullptr, dwarf_f12_mips64, dwarf_f12_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f13, nullptr, dwarf_f13_mips64, dwarf_f13_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f14, nullptr, dwarf_f14_mips64, dwarf_f14_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f15, nullptr, dwarf_f15_mips64, dwarf_f15_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f16, nullptr, dwarf_f16_mips64, dwarf_f16_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f17, nullptr, dwarf_f17_mips64, dwarf_f17_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f18, nullptr, dwarf_f18_mips64, dwarf_f18_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f19, nullptr, dwarf_f19_mips64, dwarf_f19_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f20, nullptr, dwarf_f20_mips64, dwarf_f20_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f21, nullptr, dwarf_f21_mips64, dwarf_f21_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f22, nullptr, dwarf_f22_mips64, dwarf_f22_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f23, nullptr, dwarf_f23_mips64, dwarf_f23_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f24, nullptr, dwarf_f24_mips64, dwarf_f24_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f25, nullptr, dwarf_f25_mips64, dwarf_f25_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f26, nullptr, dwarf_f26_mips64, dwarf_f26_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f27, nullptr, dwarf_f27_mips64, dwarf_f27_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f28, nullptr, dwarf_f28_mips64, dwarf_f28_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f29, nullptr, dwarf_f29_mips64, dwarf_f29_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f30, nullptr, dwarf_f30_mips64, dwarf_f30_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR(f31, nullptr, dwarf_f31_mips64, dwarf_f31_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR_INFO(fcsr, nullptr, dwarf_fcsr_mips64, dwarf_fcsr_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR_INFO(fir, nullptr, dwarf_fir_mips64, dwarf_fir_mips64,
- LLDB_INVALID_REGNUM),
- DEFINE_FPR_INFO(config5, nullptr, dwarf_config5_mips64,
- dwarf_config5_mips64, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w0, nullptr, dwarf_w0_mips64, dwarf_w0_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w1, nullptr, dwarf_w1_mips64, dwarf_w1_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w2, nullptr, dwarf_w2_mips64, dwarf_w2_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w3, nullptr, dwarf_w3_mips64, dwarf_w3_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w4, nullptr, dwarf_w4_mips64, dwarf_w4_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w5, nullptr, dwarf_w5_mips64, dwarf_w5_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w6, nullptr, dwarf_w6_mips64, dwarf_w6_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w7, nullptr, dwarf_w7_mips64, dwarf_w7_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w8, nullptr, dwarf_w8_mips64, dwarf_w8_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w9, nullptr, dwarf_w9_mips64, dwarf_w9_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w10, nullptr, dwarf_w10_mips64, dwarf_w10_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w11, nullptr, dwarf_w11_mips64, dwarf_w11_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w12, nullptr, dwarf_w12_mips64, dwarf_w12_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w13, nullptr, dwarf_w13_mips64, dwarf_w13_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w14, nullptr, dwarf_w14_mips64, dwarf_w14_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w15, nullptr, dwarf_w15_mips64, dwarf_w15_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w16, nullptr, dwarf_w16_mips64, dwarf_w16_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w17, nullptr, dwarf_w17_mips64, dwarf_w17_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w18, nullptr, dwarf_w18_mips64, dwarf_w18_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w19, nullptr, dwarf_w19_mips64, dwarf_w19_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w20, nullptr, dwarf_w10_mips64, dwarf_w20_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w21, nullptr, dwarf_w21_mips64, dwarf_w21_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w22, nullptr, dwarf_w22_mips64, dwarf_w22_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w23, nullptr, dwarf_w23_mips64, dwarf_w23_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w24, nullptr, dwarf_w24_mips64, dwarf_w24_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w25, nullptr, dwarf_w25_mips64, dwarf_w25_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w26, nullptr, dwarf_w26_mips64, dwarf_w26_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w27, nullptr, dwarf_w27_mips64, dwarf_w27_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w28, nullptr, dwarf_w28_mips64, dwarf_w28_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w29, nullptr, dwarf_w29_mips64, dwarf_w29_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w30, nullptr, dwarf_w30_mips64, dwarf_w30_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA(w31, nullptr, dwarf_w31_mips64, dwarf_w31_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA_INFO(mcsr, nullptr, dwarf_mcsr_mips64, dwarf_mcsr_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA_INFO(mir, nullptr, dwarf_mir_mips64, dwarf_mir_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA_INFO(fcsr, nullptr, dwarf_fcsr_mips64, dwarf_fcsr_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA_INFO(fir, nullptr, dwarf_fir_mips64, dwarf_fir_mips64,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_MSA_INFO(config5, nullptr, dwarf_config5_mips64,
- dwarf_config5_mips64, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM)
-#endif
};
static_assert((sizeof(g_register_infos_mips64) /
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h
index 51be31f..04b4171 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h
@@ -6,12 +6,12 @@
//
//===---------------------------------------------------------------------===//
-#include <stddef.h>
+#include <cstddef>
// Computes the offset of the given GPR in the user data area.
#define GPR_OFFSET(regname) (offsetof(GPR, regname))
-#define FPR_OFFSET(regname) (offsetof(FPR, regname))
-#define VMX_OFFSET(regname) (offsetof(VMX, regname))
+#define FPR_OFFSET(regname) (sizeof(GPR) + offsetof(FPR, regname))
+#define VMX_OFFSET(regname) (sizeof(GPR) + sizeof(FPR) + offsetof(VMX, regname))
#define GPR_SIZE(regname) (sizeof(((GPR *)NULL)->regname))
#ifdef DECLARE_REGISTER_INFOS_POWERPC_STRUCT
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64.h b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64.h
index 1086d3d..059dba4 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64.h
@@ -8,7 +8,7 @@
#ifdef DECLARE_REGISTER_INFOS_PPC64_STRUCT
-#include <stddef.h>
+#include <cstddef>
// Computes the offset of the given GPR_PPC64 in the user data area.
#define GPR_PPC64_OFFSET(regname) (offsetof(GPR_PPC64, regname))
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64le.h b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64le.h
index 0b099a5..9937da2 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64le.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64le.h
@@ -8,7 +8,7 @@
#ifdef DECLARE_REGISTER_INFOS_PPC64LE_STRUCT
-#include <stddef.h>
+#include <cstddef>
// Computes the offset of the given GPR in the user data area.
#define GPR_OFFSET(regname) (offsetof(GPR, regname))
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_s390x.h b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_s390x.h
index 11344ff..d1df7c6 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_s390x.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_s390x.h
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include <stddef.h>
+#include <cstddef>
#include "llvm/Support/Compiler.h"
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp b/src/llvm-project/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
index 2d8e8ef..85785a2 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
@@ -509,7 +509,7 @@
// operating system thread ID, so we can't make any assumptions about
// the thread ID so we must always report the breakpoint regardless
// of the thread.
- if (bp_site_sp->ValidForThisThread(&thread) ||
+ if (bp_site_sp->ValidForThisThread(thread) ||
thread.GetProcess()->GetOperatingSystem() != nullptr)
return StopInfo::CreateStopReasonWithBreakpointSiteID(
thread, bp_site_sp->GetID());
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Utility/lldb-mips-linux-register-enums.h b/src/llvm-project/lldb/source/Plugins/Process/Utility/lldb-mips-linux-register-enums.h
deleted file mode 100644
index 348af27..0000000
--- a/src/llvm-project/lldb/source/Plugins/Process/Utility/lldb-mips-linux-register-enums.h
+++ /dev/null
@@ -1,360 +0,0 @@
-//===-- lldb-mips-linux-register-enums.h -------------------------------*- 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_MIPS_LINUX_REGISTER_ENUMS_H
-#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_MIPS_LINUX_REGISTER_ENUMS_H
-
-namespace lldb_private {
-// LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB)
-
-// Internal codes for all mips registers.
-enum {
- k_first_gpr_mips,
- gpr_zero_mips = k_first_gpr_mips,
- gpr_r1_mips,
- gpr_r2_mips,
- gpr_r3_mips,
- gpr_r4_mips,
- gpr_r5_mips,
- gpr_r6_mips,
- gpr_r7_mips,
- gpr_r8_mips,
- gpr_r9_mips,
- gpr_r10_mips,
- gpr_r11_mips,
- gpr_r12_mips,
- gpr_r13_mips,
- gpr_r14_mips,
- gpr_r15_mips,
- gpr_r16_mips,
- gpr_r17_mips,
- gpr_r18_mips,
- gpr_r19_mips,
- gpr_r20_mips,
- gpr_r21_mips,
- gpr_r22_mips,
- gpr_r23_mips,
- gpr_r24_mips,
- gpr_r25_mips,
- gpr_r26_mips,
- gpr_r27_mips,
- gpr_gp_mips,
- gpr_sp_mips,
- gpr_r30_mips,
- gpr_ra_mips,
- gpr_sr_mips,
- gpr_mullo_mips,
- gpr_mulhi_mips,
- gpr_badvaddr_mips,
- gpr_cause_mips,
- gpr_pc_mips,
- gpr_config5_mips,
-
- k_last_gpr_mips = gpr_config5_mips,
-
- k_first_fpr_mips,
- fpr_f0_mips = k_first_fpr_mips,
- fpr_f1_mips,
- fpr_f2_mips,
- fpr_f3_mips,
- fpr_f4_mips,
- fpr_f5_mips,
- fpr_f6_mips,
- fpr_f7_mips,
- fpr_f8_mips,
- fpr_f9_mips,
- fpr_f10_mips,
- fpr_f11_mips,
- fpr_f12_mips,
- fpr_f13_mips,
- fpr_f14_mips,
- fpr_f15_mips,
- fpr_f16_mips,
- fpr_f17_mips,
- fpr_f18_mips,
- fpr_f19_mips,
- fpr_f20_mips,
- fpr_f21_mips,
- fpr_f22_mips,
- fpr_f23_mips,
- fpr_f24_mips,
- fpr_f25_mips,
- fpr_f26_mips,
- fpr_f27_mips,
- fpr_f28_mips,
- fpr_f29_mips,
- fpr_f30_mips,
- fpr_f31_mips,
- fpr_fcsr_mips,
- fpr_fir_mips,
- fpr_config5_mips,
- k_last_fpr_mips = fpr_config5_mips,
-
- k_first_msa_mips,
- msa_w0_mips = k_first_msa_mips,
- msa_w1_mips,
- msa_w2_mips,
- msa_w3_mips,
- msa_w4_mips,
- msa_w5_mips,
- msa_w6_mips,
- msa_w7_mips,
- msa_w8_mips,
- msa_w9_mips,
- msa_w10_mips,
- msa_w11_mips,
- msa_w12_mips,
- msa_w13_mips,
- msa_w14_mips,
- msa_w15_mips,
- msa_w16_mips,
- msa_w17_mips,
- msa_w18_mips,
- msa_w19_mips,
- msa_w20_mips,
- msa_w21_mips,
- msa_w22_mips,
- msa_w23_mips,
- msa_w24_mips,
- msa_w25_mips,
- msa_w26_mips,
- msa_w27_mips,
- msa_w28_mips,
- msa_w29_mips,
- msa_w30_mips,
- msa_w31_mips,
- msa_fcsr_mips,
- msa_fir_mips,
- msa_mcsr_mips,
- msa_mir_mips,
- msa_config5_mips,
- k_last_msa_mips = msa_config5_mips,
-
- k_num_registers_mips,
-
- k_num_gpr_registers_mips = k_last_gpr_mips - k_first_gpr_mips + 1,
- k_num_fpr_registers_mips = k_last_fpr_mips - k_first_fpr_mips + 1,
- k_num_msa_registers_mips = k_last_msa_mips - k_first_msa_mips + 1,
- k_num_user_registers_mips = k_num_gpr_registers_mips +
- k_num_fpr_registers_mips +
- k_num_msa_registers_mips
-};
-
-// Internal codes for all mips64 registers.
-enum {
- k_first_gpr_mips64,
- gpr_zero_mips64 = k_first_gpr_mips64,
- gpr_r1_mips64,
- gpr_r2_mips64,
- gpr_r3_mips64,
- gpr_r4_mips64,
- gpr_r5_mips64,
- gpr_r6_mips64,
- gpr_r7_mips64,
- gpr_r8_mips64,
- gpr_r9_mips64,
- gpr_r10_mips64,
- gpr_r11_mips64,
- gpr_r12_mips64,
- gpr_r13_mips64,
- gpr_r14_mips64,
- gpr_r15_mips64,
- gpr_r16_mips64,
- gpr_r17_mips64,
- gpr_r18_mips64,
- gpr_r19_mips64,
- gpr_r20_mips64,
- gpr_r21_mips64,
- gpr_r22_mips64,
- gpr_r23_mips64,
- gpr_r24_mips64,
- gpr_r25_mips64,
- gpr_r26_mips64,
- gpr_r27_mips64,
- gpr_gp_mips64,
- gpr_sp_mips64,
- gpr_r30_mips64,
- gpr_ra_mips64,
- gpr_sr_mips64,
- gpr_mullo_mips64,
- gpr_mulhi_mips64,
- gpr_badvaddr_mips64,
- gpr_cause_mips64,
- gpr_pc_mips64,
- gpr_config5_mips64,
- k_last_gpr_mips64 = gpr_config5_mips64,
-
- k_first_fpr_mips64,
- fpr_f0_mips64 = k_first_fpr_mips64,
- fpr_f1_mips64,
- fpr_f2_mips64,
- fpr_f3_mips64,
- fpr_f4_mips64,
- fpr_f5_mips64,
- fpr_f6_mips64,
- fpr_f7_mips64,
- fpr_f8_mips64,
- fpr_f9_mips64,
- fpr_f10_mips64,
- fpr_f11_mips64,
- fpr_f12_mips64,
- fpr_f13_mips64,
- fpr_f14_mips64,
- fpr_f15_mips64,
- fpr_f16_mips64,
- fpr_f17_mips64,
- fpr_f18_mips64,
- fpr_f19_mips64,
- fpr_f20_mips64,
- fpr_f21_mips64,
- fpr_f22_mips64,
- fpr_f23_mips64,
- fpr_f24_mips64,
- fpr_f25_mips64,
- fpr_f26_mips64,
- fpr_f27_mips64,
- fpr_f28_mips64,
- fpr_f29_mips64,
- fpr_f30_mips64,
- fpr_f31_mips64,
- fpr_fcsr_mips64,
- fpr_fir_mips64,
- fpr_config5_mips64,
- k_last_fpr_mips64 = fpr_config5_mips64,
-
- k_first_msa_mips64,
- msa_w0_mips64 = k_first_msa_mips64,
- msa_w1_mips64,
- msa_w2_mips64,
- msa_w3_mips64,
- msa_w4_mips64,
- msa_w5_mips64,
- msa_w6_mips64,
- msa_w7_mips64,
- msa_w8_mips64,
- msa_w9_mips64,
- msa_w10_mips64,
- msa_w11_mips64,
- msa_w12_mips64,
- msa_w13_mips64,
- msa_w14_mips64,
- msa_w15_mips64,
- msa_w16_mips64,
- msa_w17_mips64,
- msa_w18_mips64,
- msa_w19_mips64,
- msa_w20_mips64,
- msa_w21_mips64,
- msa_w22_mips64,
- msa_w23_mips64,
- msa_w24_mips64,
- msa_w25_mips64,
- msa_w26_mips64,
- msa_w27_mips64,
- msa_w28_mips64,
- msa_w29_mips64,
- msa_w30_mips64,
- msa_w31_mips64,
- msa_fcsr_mips64,
- msa_fir_mips64,
- msa_mcsr_mips64,
- msa_mir_mips64,
- msa_config5_mips64,
- k_last_msa_mips64 = msa_config5_mips64,
-
- k_num_registers_mips64,
-
- k_num_gpr_registers_mips64 = k_last_gpr_mips64 - k_first_gpr_mips64 + 1,
- k_num_fpr_registers_mips64 = k_last_fpr_mips64 - k_first_fpr_mips64 + 1,
- k_num_msa_registers_mips64 = k_last_msa_mips64 - k_first_msa_mips64 + 1,
- k_num_user_registers_mips64 = k_num_gpr_registers_mips64 +
- k_num_fpr_registers_mips64 +
- k_num_msa_registers_mips64
-};
-
-// Register no. for RegisterKind = eRegisterKindProcessPlugin
-// The ptrace request PTRACE_PEEKUSER/PTRACE_POKEUSER used this number
-enum {
- ptrace_zero_mips,
- ptrace_r1_mips,
- ptrace_r2_mips,
- ptrace_r3_mips,
- ptrace_r4_mips,
- ptrace_r5_mips,
- ptrace_r6_mips,
- ptrace_r7_mips,
- ptrace_r8_mips,
- ptrace_r9_mips,
- ptrace_r10_mips,
- ptrace_r11_mips,
- ptrace_r12_mips,
- ptrace_r13_mips,
- ptrace_r14_mips,
- ptrace_r15_mips,
- ptrace_r16_mips,
- ptrace_r17_mips,
- ptrace_r18_mips,
- ptrace_r19_mips,
- ptrace_r20_mips,
- ptrace_r21_mips,
- ptrace_r22_mips,
- ptrace_r23_mips,
- ptrace_r24_mips,
- ptrace_r25_mips,
- ptrace_r26_mips,
- ptrace_r27_mips,
- ptrace_gp_mips,
- ptrace_sp_mips,
- ptrace_r30_mips,
- ptrace_ra_mips,
- ptrace_f0_mips,
- ptrace_f1_mips,
- ptrace_f2_mips,
- ptrace_f3_mips,
- ptrace_f4_mips,
- ptrace_f5_mips,
- ptrace_f6_mips,
- ptrace_f7_mips,
- ptrace_f8_mips,
- ptrace_f9_mips,
- ptrace_f10_mips,
- ptrace_f11_mips,
- ptrace_f12_mips,
- ptrace_f13_mips,
- ptrace_f14_mips,
- ptrace_f15_mips,
- ptrace_f16_mips,
- ptrace_f17_mips,
- ptrace_f18_mips,
- ptrace_f19_mips,
- ptrace_f20_mips,
- ptrace_f21_mips,
- ptrace_f22_mips,
- ptrace_f23_mips,
- ptrace_f24_mips,
- ptrace_f25_mips,
- ptrace_f26_mips,
- ptrace_f27_mips,
- ptrace_f28_mips,
- ptrace_f29_mips,
- ptrace_f30_mips,
- ptrace_f31_mips,
- ptrace_pc_mips,
- ptrace_cause_mips,
- ptrace_badvaddr_mips,
- ptrace_mulhi_mips,
- ptrace_mullo_mips,
- ptrace_fcsr_mips,
- ptrace_fir_mips,
- ptrace_sr_mips,
- ptrace_config5_mips
-};
-}
-
-#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_MIPS_LINUX_REGISTER_ENUMS_H
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm64.cpp b/src/llvm-project/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm64.cpp
index 8205c8e..1294928 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm64.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Windows/Common/NativeRegisterContextWindows_arm64.cpp
@@ -98,7 +98,8 @@
CreateRegisterInfoInterface(const ArchSpec &target_arch) {
assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
"Register setting path assumes this is a 64-bit host");
- return new RegisterInfoPOSIX_arm64(target_arch);
+ return new RegisterInfoPOSIX_arm64(
+ target_arch, RegisterInfoPOSIX_arm64::eRegsetMaskDefault);
}
static Status GetThreadContextHelper(lldb::thread_t thread_handle,
diff --git a/src/llvm-project/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp b/src/llvm-project/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
index 899d090..379496b 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
@@ -86,10 +86,10 @@
static bool ShouldUseLLDBServer() {
llvm::StringRef use_lldb_server = ::getenv("LLDB_USE_LLDB_SERVER");
- return use_lldb_server.equals_lower("on") ||
- use_lldb_server.equals_lower("yes") ||
- use_lldb_server.equals_lower("1") ||
- use_lldb_server.equals_lower("true");
+ return use_lldb_server.equals_insensitive("on") ||
+ use_lldb_server.equals_insensitive("yes") ||
+ use_lldb_server.equals_insensitive("1") ||
+ use_lldb_server.equals_insensitive("true");
}
void ProcessWindows::Initialize() {
@@ -394,7 +394,7 @@
RegisterContextSP register_context = stop_thread->GetRegisterContext();
const uint64_t pc = register_context->GetPC();
BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc));
- if (site && site->ValidForThisThread(stop_thread.get())) {
+ if (site && site->ValidForThisThread(*stop_thread)) {
LLDB_LOG(log,
"Single-stepped onto a breakpoint in process {0} at "
"address {1:x} with breakpoint site {2}",
@@ -449,7 +449,7 @@
m_session_data->m_debugger->GetProcess().GetProcessId(), pc,
site->GetID());
- if (site->ValidForThisThread(stop_thread.get())) {
+ if (site->ValidForThisThread(*stop_thread)) {
LLDB_LOG(log,
"Breakpoint site {0} is valid for this thread ({1:x}), "
"creating stop info.",
diff --git a/src/llvm-project/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/src/llvm-project/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index ae19367..12bc739 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include <stdlib.h>
+#include <cstdlib>
#include <memory>
#include <mutex>
@@ -353,7 +353,6 @@
const lldb::addr_t file_end = address_range->data.GetRangeEnd();
size_t bytes_to_read = size; // Number of bytes to read from the core file
size_t bytes_copied = 0; // Number of bytes actually read from the core file
- size_t zero_fill_size = 0; // Padding
lldb::addr_t bytes_left =
0; // Number of bytes available in the core file from the given address
@@ -367,24 +366,15 @@
if (file_end > file_start + offset)
bytes_left = file_end - (file_start + offset);
- // Figure out how many bytes we need to zero-fill if we are reading more
- // bytes than available in the on-disk segment
- if (bytes_to_read > bytes_left) {
- zero_fill_size = bytes_to_read - bytes_left;
+ if (bytes_to_read > bytes_left)
bytes_to_read = bytes_left;
- }
// If there is data available on the core file read it
if (bytes_to_read)
bytes_copied =
core_objfile->CopyData(offset + file_start, bytes_to_read, buf);
- assert(zero_fill_size <= size);
- // Pad remaining bytes
- if (zero_fill_size)
- memset(((char *)buf) + bytes_copied, 0, zero_fill_size);
-
- return bytes_copied + zero_fill_size;
+ return bytes_copied;
}
void ProcessElfCore::Clear() {
@@ -414,12 +404,8 @@
// Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details.
static void ParseFreeBSDPrStatus(ThreadData &thread_data,
const DataExtractor &data,
- const ArchSpec &arch) {
+ bool lp64) {
lldb::offset_t offset = 0;
- bool lp64 = (arch.GetMachine() == llvm::Triple::aarch64 ||
- arch.GetMachine() == llvm::Triple::mips64 ||
- arch.GetMachine() == llvm::Triple::ppc64 ||
- arch.GetMachine() == llvm::Triple::x86_64);
int pr_version = data.GetU32(&offset);
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
@@ -443,6 +429,27 @@
thread_data.gpregset = DataExtractor(data, offset, len);
}
+// Parse a FreeBSD NT_PRPSINFO note - see FreeBSD sys/procfs.h for details.
+static void ParseFreeBSDPrPsInfo(ProcessElfCore &process,
+ const DataExtractor &data,
+ bool lp64) {
+ lldb::offset_t offset = 0;
+ int pr_version = data.GetU32(&offset);
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log) {
+ if (pr_version > 1)
+ LLDB_LOGF(log, "FreeBSD PRPSINFO unexpected version %d", pr_version);
+ }
+
+ // Skip pr_psinfosz, pr_fname, pr_psargs
+ offset += 108;
+ if (lp64)
+ offset += 4;
+
+ process.SetID(data.GetU32(&offset)); // pr_pid
+}
+
static llvm::Error ParseNetBSDProcInfo(const DataExtractor &data,
uint32_t &cpi_nlwps,
uint32_t &cpi_signo,
@@ -522,6 +529,11 @@
}
llvm::Error ProcessElfCore::parseFreeBSDNotes(llvm::ArrayRef<CoreNote> notes) {
+ ArchSpec arch = GetArchitecture();
+ bool lp64 = (arch.GetMachine() == llvm::Triple::aarch64 ||
+ arch.GetMachine() == llvm::Triple::mips64 ||
+ arch.GetMachine() == llvm::Triple::ppc64 ||
+ arch.GetMachine() == llvm::Triple::x86_64);
bool have_prstatus = false;
bool have_prpsinfo = false;
ThreadData thread_data;
@@ -542,10 +554,11 @@
switch (note.info.n_type) {
case ELF::NT_PRSTATUS:
have_prstatus = true;
- ParseFreeBSDPrStatus(thread_data, note.data, GetArchitecture());
+ ParseFreeBSDPrStatus(thread_data, note.data, lp64);
break;
case ELF::NT_PRPSINFO:
have_prpsinfo = true;
+ ParseFreeBSDPrPsInfo(*this, note.data, lp64);
break;
case ELF::NT_FREEBSD_THRMISC: {
lldb::offset_t offset = 0;
@@ -651,6 +664,32 @@
thread_data.notes.push_back(note);
}
} break;
+ case llvm::Triple::x86: {
+ // Assume order PT_GETREGS, PT_GETFPREGS
+ if (note.info.n_type == NETBSD::I386::NT_REGS) {
+ // If this is the next thread, push the previous one first.
+ if (had_nt_regs) {
+ m_thread_data.push_back(thread_data);
+ thread_data = ThreadData();
+ had_nt_regs = false;
+ }
+
+ thread_data.gpregset = note.data;
+ thread_data.tid = tid;
+ if (thread_data.gpregset.GetByteSize() == 0)
+ return llvm::make_error<llvm::StringError>(
+ "Could not find general purpose registers note in core file.",
+ llvm::inconvertibleErrorCode());
+ had_nt_regs = true;
+ } else if (note.info.n_type == NETBSD::I386::NT_FPREGS) {
+ if (!had_nt_regs || tid != thread_data.tid)
+ return llvm::make_error<llvm::StringError>(
+ "Error parsing NetBSD core(5) notes: Unexpected order "
+ "of NOTEs PT_GETFPREG before PT_GETREG",
+ llvm::inconvertibleErrorCode());
+ thread_data.notes.push_back(note);
+ }
+ } break;
case llvm::Triple::x86_64: {
// Assume order PT_GETREGS, PT_GETFPREGS
if (note.info.n_type == NETBSD::AMD64::NT_REGS) {
diff --git a/src/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp b/src/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp
index 2f71f17..f0aee04 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp
@@ -25,7 +25,7 @@
m_gpr.SetByteOrder(gpregset.GetByteOrder());
}
-RegisterContextCorePOSIX_arm::~RegisterContextCorePOSIX_arm() {}
+RegisterContextCorePOSIX_arm::~RegisterContextCorePOSIX_arm() = default;
bool RegisterContextCorePOSIX_arm::ReadGPR() { return true; }
diff --git a/src/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp b/src/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
index 129a887..e56aa88 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
@@ -17,26 +17,52 @@
using namespace lldb_private;
+std::unique_ptr<RegisterContextCorePOSIX_arm64>
+RegisterContextCorePOSIX_arm64::Create(Thread &thread, const ArchSpec &arch,
+ const DataExtractor &gpregset,
+ llvm::ArrayRef<CoreNote> notes) {
+ Flags opt_regsets = RegisterInfoPOSIX_arm64::eRegsetMaskDefault;
+
+ DataExtractor sve_data = getRegset(notes, arch.GetTriple(), AARCH64_SVE_Desc);
+ if (sve_data.GetByteSize() > sizeof(sve::user_sve_header))
+ opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskSVE);
+
+ // Pointer Authentication register set data is based on struct
+ // user_pac_mask declared in ptrace.h. See reference implementation
+ // in Linux kernel source at arch/arm64/include/uapi/asm/ptrace.h.
+ DataExtractor pac_data = getRegset(notes, arch.GetTriple(), AARCH64_PAC_Desc);
+ if (pac_data.GetByteSize() >= sizeof(uint64_t) * 2)
+ opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskPAuth);
+
+ auto register_info_up =
+ std::make_unique<RegisterInfoPOSIX_arm64>(arch, opt_regsets);
+ return std::unique_ptr<RegisterContextCorePOSIX_arm64>(
+ new RegisterContextCorePOSIX_arm64(thread, std::move(register_info_up),
+ gpregset, notes));
+}
+
RegisterContextCorePOSIX_arm64::RegisterContextCorePOSIX_arm64(
Thread &thread, std::unique_ptr<RegisterInfoPOSIX_arm64> register_info,
const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes)
: RegisterContextPOSIX_arm64(thread, std::move(register_info)) {
- m_gpr_buffer = std::make_shared<DataBufferHeap>(gpregset.GetDataStart(),
- gpregset.GetByteSize());
- m_gpr.SetData(m_gpr_buffer);
- m_gpr.SetByteOrder(gpregset.GetByteOrder());
+ m_gpr_data.SetData(std::make_shared<DataBufferHeap>(gpregset.GetDataStart(),
+ gpregset.GetByteSize()));
+ m_gpr_data.SetByteOrder(gpregset.GetByteOrder());
- m_fpregset = getRegset(
- notes, m_register_info_up->GetTargetArchitecture().GetTriple(), FPR_Desc);
+ const llvm::Triple &target_triple =
+ m_register_info_up->GetTargetArchitecture().GetTriple();
+ m_fpr_data = getRegset(notes, target_triple, FPR_Desc);
- m_sveregset =
- getRegset(notes, m_register_info_up->GetTargetArchitecture().GetTriple(),
- AARCH64_SVE_Desc);
+ if (m_register_info_up->IsSVEEnabled())
+ m_sve_data = getRegset(notes, target_triple, AARCH64_SVE_Desc);
+
+ if (m_register_info_up->IsPAuthEnabled())
+ m_pac_data = getRegset(notes, target_triple, AARCH64_PAC_Desc);
ConfigureRegisterContext();
}
-RegisterContextCorePOSIX_arm64::~RegisterContextCorePOSIX_arm64() {}
+RegisterContextCorePOSIX_arm64::~RegisterContextCorePOSIX_arm64() = default;
bool RegisterContextCorePOSIX_arm64::ReadGPR() { return true; }
@@ -53,16 +79,16 @@
}
const uint8_t *RegisterContextCorePOSIX_arm64::GetSVEBuffer(uint64_t offset) {
- return m_sveregset.GetDataStart() + offset;
+ return m_sve_data.GetDataStart() + offset;
}
void RegisterContextCorePOSIX_arm64::ConfigureRegisterContext() {
- if (m_sveregset.GetByteSize() > sizeof(sve::user_sve_header)) {
+ if (m_sve_data.GetByteSize() > sizeof(sve::user_sve_header)) {
uint64_t sve_header_field_offset = 8;
- m_sve_vector_length = m_sveregset.GetU16(&sve_header_field_offset);
+ m_sve_vector_length = m_sve_data.GetU16(&sve_header_field_offset);
sve_header_field_offset = 12;
uint16_t sve_header_flags_field =
- m_sveregset.GetU16(&sve_header_field_offset);
+ m_sve_data.GetU16(&sve_header_field_offset);
if ((sve_header_flags_field & sve::ptrace_regs_mask) ==
sve::ptrace_regs_fpsimd)
m_sve_state = SVEState::FPSIMD;
@@ -70,15 +96,16 @@
sve::ptrace_regs_sve)
m_sve_state = SVEState::Full;
- if (sve::vl_valid(m_sve_vector_length))
- m_register_info_up->ConfigureVectorRegisterInfos(
- sve::vq_from_vl(m_sve_vector_length));
- else {
+ if (!sve::vl_valid(m_sve_vector_length)) {
m_sve_state = SVEState::Disabled;
m_sve_vector_length = 0;
}
} else
m_sve_state = SVEState::Disabled;
+
+ if (m_sve_state != SVEState::Disabled)
+ m_register_info_up->ConfigureVectorLength(
+ sve::vq_from_vl(m_sve_vector_length));
}
uint32_t RegisterContextCorePOSIX_arm64::CalculateSVEOffset(
@@ -104,7 +131,7 @@
offset = reg_info->byte_offset;
if (offset + reg_info->byte_size <= GetGPRSize()) {
- uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size);
+ uint64_t v = m_gpr_data.GetMaxU64(&offset, reg_info->byte_size);
if (offset == reg_info->byte_offset + reg_info->byte_size) {
value = v;
return true;
@@ -119,8 +146,8 @@
if (m_sve_state == SVEState::Disabled) {
// SVE is disabled take legacy route for FPU register access
offset -= GetGPRSize();
- if (offset < m_fpregset.GetByteSize()) {
- value.SetFromMemoryData(reg_info, m_fpregset.GetDataStart() + offset,
+ if (offset < m_fpr_data.GetByteSize()) {
+ value.SetFromMemoryData(reg_info, m_fpr_data.GetDataStart() + offset,
reg_info->byte_size, lldb::eByteOrderLittle,
error);
return error.Success();
@@ -152,7 +179,7 @@
}
assert(sve_reg_num != LLDB_INVALID_REGNUM);
- assert(offset < m_sveregset.GetByteSize());
+ assert(offset < m_sve_data.GetByteSize());
value.SetFromMemoryData(reg_info, GetSVEBuffer(offset),
reg_info->byte_size, lldb::eByteOrderLittle,
error);
@@ -174,7 +201,7 @@
if (IsSVEZ(reg)) {
byte_size = 16;
offset = CalculateSVEOffset(reg_info);
- assert(offset < m_sveregset.GetByteSize());
+ assert(offset < m_sve_data.GetByteSize());
src = GetSVEBuffer(offset);
}
value.SetFromMemoryData(reg_info, src, byte_size, lldb::eByteOrderLittle,
@@ -182,7 +209,7 @@
} break;
case SVEState::Full:
offset = CalculateSVEOffset(reg_info);
- assert(offset < m_sveregset.GetByteSize());
+ assert(offset < m_sve_data.GetByteSize());
value.SetFromMemoryData(reg_info, GetSVEBuffer(offset),
reg_info->byte_size, lldb::eByteOrderLittle,
error);
@@ -191,6 +218,11 @@
default:
return false;
}
+ } else if (IsPAuth(reg)) {
+ offset = reg_info->byte_offset - m_register_info_up->GetPAuthOffset();
+ assert(offset < m_pac_data.GetByteSize());
+ value.SetFromMemoryData(reg_info, m_pac_data.GetDataStart() + offset,
+ reg_info->byte_size, lldb::eByteOrderLittle, error);
} else
return false;
diff --git a/src/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h b/src/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
index a4fdc4f..3988e35 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
@@ -18,11 +18,10 @@
class RegisterContextCorePOSIX_arm64 : public RegisterContextPOSIX_arm64 {
public:
- RegisterContextCorePOSIX_arm64(
- lldb_private::Thread &thread,
- std::unique_ptr<RegisterInfoPOSIX_arm64> register_info,
- const lldb_private::DataExtractor &gpregset,
- llvm::ArrayRef<lldb_private::CoreNote> notes);
+ static std::unique_ptr<RegisterContextCorePOSIX_arm64>
+ Create(lldb_private::Thread &thread, const lldb_private::ArchSpec &arch,
+ const lldb_private::DataExtractor &gpregset,
+ llvm::ArrayRef<lldb_private::CoreNote> notes);
~RegisterContextCorePOSIX_arm64() override;
@@ -39,6 +38,12 @@
bool HardwareSingleStep(bool enable) override;
protected:
+ RegisterContextCorePOSIX_arm64(
+ lldb_private::Thread &thread,
+ std::unique_ptr<RegisterInfoPOSIX_arm64> register_info,
+ const lldb_private::DataExtractor &gpregset,
+ llvm::ArrayRef<lldb_private::CoreNote> notes);
+
bool ReadGPR() override;
bool ReadFPR() override;
@@ -48,10 +53,10 @@
bool WriteFPR() override;
private:
- lldb::DataBufferSP m_gpr_buffer;
- lldb_private::DataExtractor m_gpr;
- lldb_private::DataExtractor m_fpregset;
- lldb_private::DataExtractor m_sveregset;
+ lldb_private::DataExtractor m_gpr_data;
+ lldb_private::DataExtractor m_fpr_data;
+ lldb_private::DataExtractor m_sve_data;
+ lldb_private::DataExtractor m_pac_data;
SVEState m_sve_state;
uint16_t m_sve_vector_length = 0;
diff --git a/src/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp b/src/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
index b5b83d8..5b1eb8b 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
@@ -32,7 +32,7 @@
m_fpr.SetByteOrder(fpregset.GetByteOrder());
}
-RegisterContextCorePOSIX_mips64::~RegisterContextCorePOSIX_mips64() {}
+RegisterContextCorePOSIX_mips64::~RegisterContextCorePOSIX_mips64() = default;
bool RegisterContextCorePOSIX_mips64::ReadGPR() { return true; }
diff --git a/src/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp b/src/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp
index e15cd47..8380731 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp
@@ -39,7 +39,7 @@
m_vec.SetByteOrder(vregset.GetByteOrder());
}
-RegisterContextCorePOSIX_powerpc::~RegisterContextCorePOSIX_powerpc() {}
+RegisterContextCorePOSIX_powerpc::~RegisterContextCorePOSIX_powerpc() = default;
bool RegisterContextCorePOSIX_powerpc::ReadGPR() { return true; }
diff --git a/src/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp b/src/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp
index c3aa92c..f1cd689 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp
@@ -33,7 +33,7 @@
m_fpr.SetByteOrder(fpregset.GetByteOrder());
}
-RegisterContextCorePOSIX_s390x::~RegisterContextCorePOSIX_s390x() {}
+RegisterContextCorePOSIX_s390x::~RegisterContextCorePOSIX_s390x() = default;
bool RegisterContextCorePOSIX_s390x::ReadGPR() { return true; }
diff --git a/src/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h b/src/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h
index 25abd7e..f6a2fbd 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h
@@ -55,6 +55,10 @@
enum { NT_REGS = 33, NT_FPREGS = 35 };
}
+namespace I386 {
+enum { NT_REGS = 33, NT_FPREGS = 35 };
+}
+
} // namespace NETBSD
namespace OPENBSD {
@@ -96,6 +100,9 @@
llvm::ArrayRef<RegsetDesc> RegsetDescs);
constexpr RegsetDesc FPR_Desc[] = {
+ // FreeBSD/i386 core NT_FPREGSET is x87 FSAVE result but the XSAVE dump
+ // starts with FXSAVE struct, so use that instead if available.
+ {llvm::Triple::FreeBSD, llvm::Triple::x86, llvm::ELF::NT_X86_XSTATE},
{llvm::Triple::FreeBSD, llvm::Triple::UnknownArch, llvm::ELF::NT_FPREGSET},
// In a i386 core file NT_FPREGSET is present, but it's not the result
// of the FXSAVE instruction like in 64 bit files.
@@ -103,6 +110,7 @@
{llvm::Triple::Linux, llvm::Triple::x86, llvm::ELF::NT_PRXFPREG},
{llvm::Triple::Linux, llvm::Triple::UnknownArch, llvm::ELF::NT_FPREGSET},
{llvm::Triple::NetBSD, llvm::Triple::aarch64, NETBSD::AARCH64::NT_FPREGS},
+ {llvm::Triple::NetBSD, llvm::Triple::x86, NETBSD::I386::NT_FPREGS},
{llvm::Triple::NetBSD, llvm::Triple::x86_64, NETBSD::AMD64::NT_FPREGS},
{llvm::Triple::OpenBSD, llvm::Triple::UnknownArch, OPENBSD::NT_FPREGS},
};
@@ -111,6 +119,10 @@
{llvm::Triple::Linux, llvm::Triple::aarch64, llvm::ELF::NT_ARM_SVE},
};
+constexpr RegsetDesc AARCH64_PAC_Desc[] = {
+ {llvm::Triple::Linux, llvm::Triple::aarch64, llvm::ELF::NT_ARM_PAC_MASK},
+};
+
constexpr RegsetDesc PPC_VMX_Desc[] = {
{llvm::Triple::FreeBSD, llvm::Triple::UnknownArch, llvm::ELF::NT_PPC_VMX},
{llvm::Triple::Linux, llvm::Triple::UnknownArch, llvm::ELF::NT_PPC_VMX},
diff --git a/src/llvm-project/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/src/llvm-project/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
index 76c0c28..937d074 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
@@ -18,10 +18,9 @@
#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h"
#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
-#include "Plugins/Process/Utility/RegisterContextLinux_mips.h"
-#include "Plugins/Process/Utility/RegisterContextLinux_mips64.h"
#include "Plugins/Process/Utility/RegisterContextLinux_s390x.h"
#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
+#include "Plugins/Process/Utility/RegisterContextNetBSD_i386.h"
#include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h"
#include "Plugins/Process/Utility/RegisterContextOpenBSD_i386.h"
#include "Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.h"
@@ -109,6 +108,9 @@
switch (arch.GetMachine()) {
case llvm::Triple::aarch64:
break;
+ case llvm::Triple::x86:
+ reg_interface = new RegisterContextNetBSD_i386(arch);
+ break;
case llvm::Triple::x86_64:
reg_interface = new RegisterContextNetBSD_x86_64(arch);
break;
@@ -122,14 +124,6 @@
switch (arch.GetMachine()) {
case llvm::Triple::aarch64:
break;
- case llvm::Triple::mipsel:
- case llvm::Triple::mips:
- reg_interface = new RegisterContextLinux_mips(arch);
- break;
- case llvm::Triple::mips64el:
- case llvm::Triple::mips64:
- reg_interface = new RegisterContextLinux_mips64(arch);
- break;
case llvm::Triple::ppc64le:
reg_interface = new RegisterInfoPOSIX_ppc64le(arch);
break;
@@ -177,9 +171,8 @@
switch (arch.GetMachine()) {
case llvm::Triple::aarch64:
- m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_arm64>(
- *this, std::make_unique<RegisterInfoPOSIX_arm64>(arch),
- m_gpregset_data, m_notes);
+ m_thread_reg_ctx_sp = RegisterContextCorePOSIX_arm64::Create(
+ *this, arch, m_gpregset_data, m_notes);
break;
case llvm::Triple::arm:
m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_arm>(
diff --git a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
index fdaa60e..a4c71e8 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
@@ -20,7 +20,10 @@
using namespace lldb_private::process_gdb_remote;
using namespace std::chrono;
-static const seconds kInterruptTimeout(5);
+// When we've sent a continue packet and are waiting for the target to stop,
+// we wake up the wait with this interval to make sure the stub hasn't gone
+// away while we were waiting.
+static const seconds kWakeupInterval(5);
/////////////////////////
// GDBRemoteClientBase //
@@ -35,7 +38,8 @@
StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse(
ContinueDelegate &delegate, const UnixSignals &signals,
- llvm::StringRef payload, StringExtractorGDBRemote &response) {
+ llvm::StringRef payload, std::chrono::seconds interrupt_timeout,
+ StringExtractorGDBRemote &response) {
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
response.Clear();
@@ -48,16 +52,37 @@
if (!cont_lock)
return eStateInvalid;
OnRunPacketSent(true);
-
+ // The main ReadPacket loop wakes up at computed_timeout intervals, just to
+ // check that the connection hasn't dropped. When we wake up we also check
+ // whether there is an interrupt request that has reached its endpoint.
+ // If we want a shorter interrupt timeout that kWakeupInterval, we need to
+ // choose the shorter interval for the wake up as well.
+ std::chrono::seconds computed_timeout = std::min(interrupt_timeout,
+ kWakeupInterval);
for (;;) {
- PacketResult read_result = ReadPacket(response, kInterruptTimeout, false);
+ PacketResult read_result = ReadPacket(response, computed_timeout, false);
+ // Reset the computed_timeout to the default value in case we are going
+ // round again.
+ computed_timeout = std::min(interrupt_timeout, kWakeupInterval);
switch (read_result) {
case PacketResult::ErrorReplyTimeout: {
std::lock_guard<std::mutex> lock(m_mutex);
- if (m_async_count == 0)
+ if (m_async_count == 0) {
continue;
- if (steady_clock::now() >= m_interrupt_time + kInterruptTimeout)
+ }
+ auto cur_time = steady_clock::now();
+ if (cur_time >= m_interrupt_endpoint)
return eStateInvalid;
+ else {
+ // We woke up and found an interrupt is in flight, but we haven't
+ // exceeded the interrupt wait time. So reset the wait time to the
+ // time left till the interrupt timeout. But don't wait longer
+ // than our wakeup timeout.
+ auto new_wait = m_interrupt_endpoint - cur_time;
+ computed_timeout = std::min(kWakeupInterval,
+ std::chrono::duration_cast<std::chrono::seconds>(new_wait));
+ continue;
+ }
break;
}
case PacketResult::Success:
@@ -133,8 +158,9 @@
}
}
-bool GDBRemoteClientBase::SendAsyncSignal(int signo) {
- Lock lock(*this, true);
+bool GDBRemoteClientBase::SendAsyncSignal(
+ int signo, std::chrono::seconds interrupt_timeout) {
+ Lock lock(*this, interrupt_timeout);
if (!lock || !lock.DidInterrupt())
return false;
@@ -144,25 +170,26 @@
return true;
}
-bool GDBRemoteClientBase::Interrupt() {
- Lock lock(*this, true);
+bool GDBRemoteClientBase::Interrupt(std::chrono::seconds interrupt_timeout) {
+ Lock lock(*this, interrupt_timeout);
if (!lock.DidInterrupt())
return false;
m_should_stop = true;
return true;
}
+
GDBRemoteCommunication::PacketResult
GDBRemoteClientBase::SendPacketAndWaitForResponse(
llvm::StringRef payload, StringExtractorGDBRemote &response,
- bool send_async) {
- Lock lock(*this, send_async);
+ std::chrono::seconds interrupt_timeout) {
+ Lock lock(*this, interrupt_timeout);
if (!lock) {
if (Log *log =
ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS))
LLDB_LOGF(log,
"GDBRemoteClientBase::%s failed to get mutex, not sending "
- "packet '%.*s' (send_async=%d)",
- __FUNCTION__, int(payload.size()), payload.data(), send_async);
+ "packet '%.*s'",
+ __FUNCTION__, int(payload.size()), payload.data());
return PacketResult::ErrorSendFailed;
}
@@ -172,16 +199,16 @@
GDBRemoteCommunication::PacketResult
GDBRemoteClientBase::SendPacketAndReceiveResponseWithOutputSupport(
llvm::StringRef payload, StringExtractorGDBRemote &response,
- bool send_async,
+ std::chrono::seconds interrupt_timeout,
llvm::function_ref<void(llvm::StringRef)> output_callback) {
- Lock lock(*this, send_async);
+ Lock lock(*this, interrupt_timeout);
if (!lock) {
if (Log *log =
ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS))
LLDB_LOGF(log,
"GDBRemoteClientBase::%s failed to get mutex, not sending "
- "packet '%.*s' (send_async=%d)",
- __FUNCTION__, int(payload.size()), payload.data(), send_async);
+ "packet '%.*s'",
+ __FUNCTION__, int(payload.size()), payload.data());
return PacketResult::ErrorSendFailed;
}
@@ -222,13 +249,14 @@
return packet_result;
}
-bool GDBRemoteClientBase::SendvContPacket(llvm::StringRef payload,
- StringExtractorGDBRemote &response) {
+bool GDBRemoteClientBase::SendvContPacket(
+ llvm::StringRef payload, std::chrono::seconds interrupt_timeout,
+ StringExtractorGDBRemote &response) {
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
LLDB_LOGF(log, "GDBRemoteCommunicationClient::%s ()", __FUNCTION__);
// we want to lock down packet sending while we continue
- Lock lock(*this, true);
+ Lock lock(*this, interrupt_timeout);
LLDB_LOGF(log,
"GDBRemoteCommunicationClient::%s () sending vCont packet: %.*s",
@@ -336,18 +364,20 @@
// GDBRemoteClientBase::Lock //
///////////////////////////////
-GDBRemoteClientBase::Lock::Lock(GDBRemoteClientBase &comm, bool interrupt)
+GDBRemoteClientBase::Lock::Lock(GDBRemoteClientBase &comm,
+ std::chrono::seconds interrupt_timeout)
: m_async_lock(comm.m_async_mutex, std::defer_lock), m_comm(comm),
- m_acquired(false), m_did_interrupt(false) {
- SyncWithContinueThread(interrupt);
+ m_interrupt_timeout(interrupt_timeout), m_acquired(false),
+ m_did_interrupt(false) {
+ SyncWithContinueThread();
if (m_acquired)
m_async_lock.lock();
}
-void GDBRemoteClientBase::Lock::SyncWithContinueThread(bool interrupt) {
+void GDBRemoteClientBase::Lock::SyncWithContinueThread() {
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
std::unique_lock<std::mutex> lock(m_comm.m_mutex);
- if (m_comm.m_is_running && !interrupt)
+ if (m_comm.m_is_running && m_interrupt_timeout == std::chrono::seconds(0))
return; // We were asked to avoid interrupting the sender. Lock is not
// acquired.
@@ -365,9 +395,9 @@
"interrupt packet");
return;
}
+ m_comm.m_interrupt_endpoint = steady_clock::now() + m_interrupt_timeout;
if (log)
log->PutCString("GDBRemoteClientBase::Lock::Lock sent packet: \\x03");
- m_comm.m_interrupt_time = steady_clock::now();
}
m_comm.m_cv.wait(lock, [this] { return !m_comm.m_is_running; });
m_did_interrupt = true;
diff --git a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h
index cd9f6eb..518b813 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h
@@ -33,29 +33,46 @@
GDBRemoteClientBase(const char *comm_name, const char *listener_name);
- bool SendAsyncSignal(int signo);
+ bool SendAsyncSignal(int signo, std::chrono::seconds interrupt_timeout);
- bool Interrupt();
+ bool Interrupt(std::chrono::seconds interrupt_timeout);
lldb::StateType SendContinuePacketAndWaitForResponse(
ContinueDelegate &delegate, const UnixSignals &signals,
- llvm::StringRef payload, StringExtractorGDBRemote &response);
+ llvm::StringRef payload, std::chrono::seconds interrupt_timeout,
+ StringExtractorGDBRemote &response);
- PacketResult SendPacketAndWaitForResponse(llvm::StringRef payload,
- StringExtractorGDBRemote &response,
- bool send_async);
+ // If interrupt_timeout == 0 seconds, don't interrupt the target.
+ // Only send the packet if the target is stopped.
+ // If you want to use this mode, use the fact that the timeout is defaulted
+ // so it's clear from the call-site that you are using no-interrupt.
+ // If it is non-zero, interrupt the target if it is running, and
+ // send the packet.
+ // It the target doesn't respond within the given timeout, it returns
+ // ErrorReplyTimeout.
+ PacketResult SendPacketAndWaitForResponse(
+ llvm::StringRef payload, StringExtractorGDBRemote &response,
+ std::chrono::seconds interrupt_timeout = std::chrono::seconds(0));
PacketResult SendPacketAndReceiveResponseWithOutputSupport(
llvm::StringRef payload, StringExtractorGDBRemote &response,
- bool send_async,
+ std::chrono::seconds interrupt_timeout,
llvm::function_ref<void(llvm::StringRef)> output_callback);
bool SendvContPacket(llvm::StringRef payload,
+ std::chrono::seconds interrupt_timeout,
StringExtractorGDBRemote &response);
class Lock {
public:
- Lock(GDBRemoteClientBase &comm, bool interrupt);
+ // If interrupt_timeout == 0 seconds, only take the lock if the target is
+ // not running. If using this option, use the fact that the
+ // interrupt_timeout is defaulted so it will be obvious at the call site
+ // that you are choosing this mode. If it is non-zero, interrupt the target
+ // if it is running, waiting for the given timeout for the interrupt to
+ // succeed.
+ Lock(GDBRemoteClientBase &comm,
+ std::chrono::seconds interrupt_timeout = std::chrono::seconds(0));
~Lock();
explicit operator bool() { return m_acquired; }
@@ -67,10 +84,11 @@
private:
std::unique_lock<std::recursive_mutex> m_async_lock;
GDBRemoteClientBase &m_comm;
+ std::chrono::seconds m_interrupt_timeout;
bool m_acquired;
bool m_did_interrupt;
- void SyncWithContinueThread(bool interrupt);
+ void SyncWithContinueThread();
};
protected:
@@ -109,7 +127,7 @@
/// When was the interrupt packet sent. Used to make sure we time out if the
/// stub does not respond to interrupt requests.
- std::chrono::time_point<std::chrono::steady_clock> m_interrupt_time;
+ std::chrono::time_point<std::chrono::steady_clock> m_interrupt_endpoint;
/// Number of threads interested in sending.
uint32_t m_async_count;
diff --git a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 4981345..013d407 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -8,9 +8,9 @@
#include "GDBRemoteCommunication.h"
+#include <climits>
+#include <cstring>
#include <future>
-#include <limits.h>
-#include <string.h>
#include <sys/stat.h>
#include "lldb/Core/StreamFile.h"
diff --git a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index d375a31..b16aed4 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -8,7 +8,7 @@
#include "GDBRemoteCommunicationClient.h"
-#include <math.h>
+#include <cmath>
#include <sys/stat.h>
#include <numeric>
@@ -16,6 +16,7 @@
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Host/HostInfo.h"
+#include "lldb/Host/StringConvert.h"
#include "lldb/Host/XML.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/MemoryRegionInfo.h"
@@ -55,40 +56,7 @@
// GDBRemoteCommunicationClient constructor
GDBRemoteCommunicationClient::GDBRemoteCommunicationClient()
: GDBRemoteClientBase("gdb-remote.client", "gdb-remote.client.rx_packet"),
- m_supports_not_sending_acks(eLazyBoolCalculate),
- m_supports_thread_suffix(eLazyBoolCalculate),
- m_supports_threads_in_stop_reply(eLazyBoolCalculate),
- m_supports_vCont_all(eLazyBoolCalculate),
- m_supports_vCont_any(eLazyBoolCalculate),
- m_supports_vCont_c(eLazyBoolCalculate),
- m_supports_vCont_C(eLazyBoolCalculate),
- m_supports_vCont_s(eLazyBoolCalculate),
- m_supports_vCont_S(eLazyBoolCalculate),
- m_qHostInfo_is_valid(eLazyBoolCalculate),
- m_curr_pid_is_valid(eLazyBoolCalculate),
- m_qProcessInfo_is_valid(eLazyBoolCalculate),
- m_qGDBServerVersion_is_valid(eLazyBoolCalculate),
- m_supports_alloc_dealloc_memory(eLazyBoolCalculate),
- m_supports_memory_region_info(eLazyBoolCalculate),
- m_supports_watchpoint_support_info(eLazyBoolCalculate),
- m_supports_detach_stay_stopped(eLazyBoolCalculate),
- m_watchpoints_trigger_after_instruction(eLazyBoolCalculate),
- m_attach_or_wait_reply(eLazyBoolCalculate),
- m_prepare_for_reg_writing_reply(eLazyBoolCalculate),
- m_supports_p(eLazyBoolCalculate), m_supports_x(eLazyBoolCalculate),
- m_avoid_g_packets(eLazyBoolCalculate),
- m_supports_QSaveRegisterState(eLazyBoolCalculate),
- m_supports_qXfer_auxv_read(eLazyBoolCalculate),
- m_supports_qXfer_libraries_read(eLazyBoolCalculate),
- m_supports_qXfer_libraries_svr4_read(eLazyBoolCalculate),
- m_supports_qXfer_features_read(eLazyBoolCalculate),
- m_supports_qXfer_memory_map_read(eLazyBoolCalculate),
- m_supports_augmented_libraries_svr4_read(eLazyBoolCalculate),
- m_supports_jThreadExtendedInfo(eLazyBoolCalculate),
- m_supports_jLoadedDynamicLibrariesInfos(eLazyBoolCalculate),
- m_supports_jGetSharedCacheInfo(eLazyBoolCalculate),
- m_supports_QPassSignals(eLazyBoolCalculate),
- m_supports_error_string_reply(eLazyBoolCalculate),
+
m_supports_qProcessInfoPID(true), m_supports_qfProcessInfo(true),
m_supports_qUserName(true), m_supports_qGroupName(true),
m_supports_qThreadStopInfo(true), m_supports_z0(true),
@@ -97,15 +65,11 @@
m_supports_QEnvironmentHexEncoded(true), m_supports_qSymbol(true),
m_qSymbol_requests_done(false), m_supports_qModuleInfo(true),
m_supports_jThreadsInfo(true), m_supports_jModulesInfo(true),
- m_curr_pid(LLDB_INVALID_PROCESS_ID), m_curr_tid(LLDB_INVALID_THREAD_ID),
- m_curr_tid_run(LLDB_INVALID_THREAD_ID),
- m_num_supported_hardware_watchpoints(0), m_host_arch(), m_process_arch(),
- m_os_build(), m_os_kernel(), m_hostname(), m_gdb_server_name(),
- m_gdb_server_version(UINT32_MAX), m_default_packet_timeout(0),
- m_max_packet_size(0), m_qSupported_response(),
- m_supported_async_json_packets_is_valid(false),
- m_supported_async_json_packets_sp(), m_qXfer_memory_map(),
- m_qXfer_memory_map_loaded(false) {}
+
+ m_host_arch(), m_process_arch(), m_os_build(), m_os_kernel(),
+ m_hostname(), m_gdb_server_name(), m_default_packet_timeout(0),
+ m_qSupported_response(), m_supported_async_json_packets_sp(),
+ m_qXfer_memory_map() {}
// Destructor
GDBRemoteCommunicationClient::~GDBRemoteCommunicationClient() {
@@ -218,7 +182,7 @@
ScopedTimeout timeout(*this, std::max(GetPacketTimeout(), seconds(6)));
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("QStartNoAckMode", response, false) ==
+ if (SendPacketAndWaitForResponse("QStartNoAckMode", response) ==
PacketResult::Success) {
if (response.IsOKResponse()) {
m_send_acks = false;
@@ -235,8 +199,8 @@
m_supports_threads_in_stop_reply = eLazyBoolNo;
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("QListThreadsInStopReply", response,
- false) == PacketResult::Success) {
+ if (SendPacketAndWaitForResponse("QListThreadsInStopReply", response) ==
+ PacketResult::Success) {
if (response.IsOKResponse())
m_supports_threads_in_stop_reply = eLazyBoolYes;
}
@@ -248,8 +212,8 @@
m_attach_or_wait_reply = eLazyBoolNo;
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qVAttachOrWaitSupported", response,
- false) == PacketResult::Success) {
+ if (SendPacketAndWaitForResponse("qVAttachOrWaitSupported", response) ==
+ PacketResult::Success) {
if (response.IsOKResponse())
m_attach_or_wait_reply = eLazyBoolYes;
}
@@ -262,8 +226,8 @@
m_prepare_for_reg_writing_reply = eLazyBoolNo;
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qSyncThreadStateSupported", response,
- false) == PacketResult::Success) {
+ if (SendPacketAndWaitForResponse("qSyncThreadStateSupported", response) ==
+ PacketResult::Success) {
if (response.IsOKResponse())
m_prepare_for_reg_writing_reply = eLazyBoolYes;
}
@@ -292,6 +256,7 @@
m_prepare_for_reg_writing_reply = eLazyBoolCalculate;
m_attach_or_wait_reply = eLazyBoolCalculate;
m_avoid_g_packets = eLazyBoolCalculate;
+ m_supports_multiprocess = eLazyBoolCalculate;
m_supports_qXfer_auxv_read = eLazyBoolCalculate;
m_supports_qXfer_libraries_read = eLazyBoolCalculate;
m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate;
@@ -321,6 +286,7 @@
m_gdb_server_name.clear();
m_gdb_server_version = UINT32_MAX;
m_default_packet_timeout = seconds(0);
+ m_target_vm_page_size = 0;
m_max_packet_size = 0;
m_qSupported_response.clear();
m_supported_async_json_packets_is_valid = false;
@@ -342,11 +308,17 @@
m_supports_augmented_libraries_svr4_read = eLazyBoolNo;
m_supports_qXfer_features_read = eLazyBoolNo;
m_supports_qXfer_memory_map_read = eLazyBoolNo;
+ m_supports_multiprocess = eLazyBoolNo;
+ m_supports_qEcho = eLazyBoolNo;
+ m_supports_QPassSignals = eLazyBoolNo;
+ m_supports_memory_tagging = eLazyBoolNo;
+
m_max_packet_size = UINT64_MAX; // It's supposed to always be there, but if
// not, we assume no limit
// build the qSupported packet
- std::vector<std::string> features = {"xmlRegisters=i386,arm,mips,arc"};
+ std::vector<std::string> features = {"xmlRegisters=i386,arm,mips,arc",
+ "multiprocess+"};
StreamString packet;
packet.PutCString("qSupported");
for (uint32_t i = 0; i < features.size(); ++i) {
@@ -355,95 +327,55 @@
}
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet.GetString(), response,
- /*send_async=*/false) ==
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
PacketResult::Success) {
- const char *response_cstr = response.GetStringRef().data();
-
// Hang on to the qSupported packet, so that platforms can do custom
// configuration of the transport before attaching/launching the process.
- m_qSupported_response = response_cstr;
+ m_qSupported_response = response.GetStringRef().str();
- if (::strstr(response_cstr, "qXfer:auxv:read+"))
- m_supports_qXfer_auxv_read = eLazyBoolYes;
- if (::strstr(response_cstr, "qXfer:libraries-svr4:read+"))
- m_supports_qXfer_libraries_svr4_read = eLazyBoolYes;
- if (::strstr(response_cstr, "augmented-libraries-svr4-read")) {
- m_supports_qXfer_libraries_svr4_read = eLazyBoolYes; // implied
- m_supports_augmented_libraries_svr4_read = eLazyBoolYes;
- }
- if (::strstr(response_cstr, "qXfer:libraries:read+"))
- m_supports_qXfer_libraries_read = eLazyBoolYes;
- if (::strstr(response_cstr, "qXfer:features:read+"))
- m_supports_qXfer_features_read = eLazyBoolYes;
- if (::strstr(response_cstr, "qXfer:memory-map:read+"))
- m_supports_qXfer_memory_map_read = eLazyBoolYes;
+ llvm::SmallVector<llvm::StringRef, 16> server_features;
+ response.GetStringRef().split(server_features, ';');
- // Look for a list of compressions in the features list e.g.
- // qXfer:features:read+;PacketSize=20000;qEcho+;SupportedCompressions=zlib-
- // deflate,lzma
- const char *features_list = ::strstr(response_cstr, "qXfer:features:");
- if (features_list) {
- const char *compressions =
- ::strstr(features_list, "SupportedCompressions=");
- if (compressions) {
- std::vector<std::string> supported_compressions;
- compressions += sizeof("SupportedCompressions=") - 1;
- const char *end_of_compressions = strchr(compressions, ';');
- if (end_of_compressions == nullptr) {
- end_of_compressions = strchr(compressions, '\0');
+ for (llvm::StringRef x : server_features) {
+ if (x == "qXfer:auxv:read+")
+ m_supports_qXfer_auxv_read = eLazyBoolYes;
+ else if (x == "qXfer:libraries-svr4:read+")
+ m_supports_qXfer_libraries_svr4_read = eLazyBoolYes;
+ else if (x == "augmented-libraries-svr4-read") {
+ m_supports_qXfer_libraries_svr4_read = eLazyBoolYes; // implied
+ m_supports_augmented_libraries_svr4_read = eLazyBoolYes;
+ } else if (x == "qXfer:libraries:read+")
+ m_supports_qXfer_libraries_read = eLazyBoolYes;
+ else if (x == "qXfer:features:read+")
+ m_supports_qXfer_features_read = eLazyBoolYes;
+ else if (x == "qXfer:memory-map:read+")
+ m_supports_qXfer_memory_map_read = eLazyBoolYes;
+ else if (x == "qEcho")
+ m_supports_qEcho = eLazyBoolYes;
+ else if (x == "QPassSignals+")
+ m_supports_QPassSignals = eLazyBoolYes;
+ else if (x == "multiprocess+")
+ m_supports_multiprocess = eLazyBoolYes;
+ else if (x == "memory-tagging+")
+ m_supports_memory_tagging = eLazyBoolYes;
+ // Look for a list of compressions in the features list e.g.
+ // qXfer:features:read+;PacketSize=20000;qEcho+;SupportedCompressions=zlib-
+ // deflate,lzma
+ else if (x.consume_front("SupportedCompressions=")) {
+ llvm::SmallVector<llvm::StringRef, 4> compressions;
+ x.split(compressions, ',');
+ if (!compressions.empty())
+ MaybeEnableCompression(compressions);
+ } else if (x.consume_front("PacketSize=")) {
+ StringExtractorGDBRemote packet_response(x);
+ m_max_packet_size =
+ packet_response.GetHexMaxU64(/*little_endian=*/false, UINT64_MAX);
+ if (m_max_packet_size == 0) {
+ m_max_packet_size = UINT64_MAX; // Must have been a garbled response
+ Log *log(
+ ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ LLDB_LOGF(log, "Garbled PacketSize spec in qSupported response");
}
- const char *current_compression = compressions;
- while (current_compression < end_of_compressions) {
- const char *next_compression_name = strchr(current_compression, ',');
- const char *end_of_this_word = next_compression_name;
- if (next_compression_name == nullptr ||
- end_of_compressions < next_compression_name) {
- end_of_this_word = end_of_compressions;
- }
-
- if (end_of_this_word) {
- if (end_of_this_word == current_compression) {
- current_compression++;
- } else {
- std::string this_compression(
- current_compression, end_of_this_word - current_compression);
- supported_compressions.push_back(this_compression);
- current_compression = end_of_this_word + 1;
- }
- } else {
- supported_compressions.push_back(current_compression);
- current_compression = end_of_compressions;
- }
- }
-
- if (supported_compressions.size() > 0) {
- MaybeEnableCompression(supported_compressions);
- }
- }
- }
-
- if (::strstr(response_cstr, "qEcho"))
- m_supports_qEcho = eLazyBoolYes;
- else
- m_supports_qEcho = eLazyBoolNo;
-
- if (::strstr(response_cstr, "QPassSignals+"))
- m_supports_QPassSignals = eLazyBoolYes;
- else
- m_supports_QPassSignals = eLazyBoolNo;
-
- const char *packet_size_str = ::strstr(response_cstr, "PacketSize=");
- if (packet_size_str) {
- StringExtractorGDBRemote packet_response(packet_size_str +
- strlen("PacketSize="));
- m_max_packet_size =
- packet_response.GetHexMaxU64(/*little_endian=*/false, UINT64_MAX);
- if (m_max_packet_size == 0) {
- m_max_packet_size = UINT64_MAX; // Must have been a garbled response
- Log *log(
- ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
- LLDB_LOGF(log, "Garbled PacketSize spec in qSupported response");
}
}
}
@@ -453,8 +385,8 @@
if (m_supports_thread_suffix == eLazyBoolCalculate) {
StringExtractorGDBRemote response;
m_supports_thread_suffix = eLazyBoolNo;
- if (SendPacketAndWaitForResponse("QThreadSuffixSupported", response,
- false) == PacketResult::Success) {
+ if (SendPacketAndWaitForResponse("QThreadSuffixSupported", response) ==
+ PacketResult::Success) {
if (response.IsOKResponse())
m_supports_thread_suffix = eLazyBoolYes;
}
@@ -470,7 +402,7 @@
m_supports_vCont_C = eLazyBoolNo;
m_supports_vCont_s = eLazyBoolNo;
m_supports_vCont_S = eLazyBoolNo;
- if (SendPacketAndWaitForResponse("vCont?", response, false) ==
+ if (SendPacketAndWaitForResponse("vCont?", response) ==
PacketResult::Success) {
const char *response_cstr = response.GetStringRef().data();
if (::strstr(response_cstr, ";c"))
@@ -522,9 +454,9 @@
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationClient::SendThreadSpecificPacketAndWaitForResponse(
- lldb::tid_t tid, StreamString &&payload, StringExtractorGDBRemote &response,
- bool send_async) {
- Lock lock(*this, send_async);
+ lldb::tid_t tid, StreamString &&payload,
+ StringExtractorGDBRemote &response) {
+ Lock lock(*this);
if (!lock) {
if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(
GDBR_LOG_PROCESS | GDBR_LOG_PACKETS))
@@ -561,7 +493,7 @@
payload.PutCString(packetStr);
StringExtractorGDBRemote response;
if (SendThreadSpecificPacketAndWaitForResponse(
- tid, std::move(payload), response, false) == PacketResult::Success &&
+ tid, std::move(payload), response) == PacketResult::Success &&
response.IsNormalResponse()) {
return eLazyBoolYes;
}
@@ -575,7 +507,7 @@
if (m_supports_jThreadsInfo) {
StringExtractorGDBRemote response;
response.SetResponseValidatorToJSON();
- if (SendPacketAndWaitForResponse("jThreadsInfo", response, false) ==
+ if (SendPacketAndWaitForResponse("jThreadsInfo", response) ==
PacketResult::Success) {
if (response.IsUnsupportedResponse()) {
m_supports_jThreadsInfo = false;
@@ -592,7 +524,7 @@
if (m_supports_jThreadExtendedInfo == eLazyBoolCalculate) {
StringExtractorGDBRemote response;
m_supports_jThreadExtendedInfo = eLazyBoolNo;
- if (SendPacketAndWaitForResponse("jThreadExtendedInfo:", response, false) ==
+ if (SendPacketAndWaitForResponse("jThreadExtendedInfo:", response) ==
PacketResult::Success) {
if (response.IsOKResponse()) {
m_supports_jThreadExtendedInfo = eLazyBoolYes;
@@ -608,7 +540,7 @@
// We try to enable error strings in remote packets but if we fail, we just
// work in the older way.
m_supports_error_string_reply = eLazyBoolNo;
- if (SendPacketAndWaitForResponse("QEnableErrorStrings", response, false) ==
+ if (SendPacketAndWaitForResponse("QEnableErrorStrings", response) ==
PacketResult::Success) {
if (response.IsOKResponse()) {
m_supports_error_string_reply = eLazyBoolYes;
@@ -622,8 +554,7 @@
StringExtractorGDBRemote response;
m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolNo;
if (SendPacketAndWaitForResponse("jGetLoadedDynamicLibrariesInfos:",
- response,
- false) == PacketResult::Success) {
+ response) == PacketResult::Success) {
if (response.IsOKResponse()) {
m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolYes;
}
@@ -636,7 +567,7 @@
if (m_supports_jGetSharedCacheInfo == eLazyBoolCalculate) {
StringExtractorGDBRemote response;
m_supports_jGetSharedCacheInfo = eLazyBoolNo;
- if (SendPacketAndWaitForResponse("jGetSharedCacheInfo:", response, false) ==
+ if (SendPacketAndWaitForResponse("jGetSharedCacheInfo:", response) ==
PacketResult::Success) {
if (response.IsOKResponse()) {
m_supports_jGetSharedCacheInfo = eLazyBoolYes;
@@ -646,13 +577,82 @@
return m_supports_jGetSharedCacheInfo;
}
+bool GDBRemoteCommunicationClient::GetMemoryTaggingSupported() {
+ if (m_supports_memory_tagging == eLazyBoolCalculate) {
+ GetRemoteQSupported();
+ }
+ return m_supports_memory_tagging == eLazyBoolYes;
+}
+
+DataBufferSP GDBRemoteCommunicationClient::ReadMemoryTags(lldb::addr_t addr,
+ size_t len,
+ int32_t type) {
+ StreamString packet;
+ packet.Printf("qMemTags:%" PRIx64 ",%zx:%" PRIx32, addr, len, type);
+ StringExtractorGDBRemote response;
+
+ Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_MEMORY);
+
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) !=
+ PacketResult::Success ||
+ !response.IsNormalResponse()) {
+ LLDB_LOGF(log, "GDBRemoteCommunicationClient::%s: qMemTags packet failed",
+ __FUNCTION__);
+ return nullptr;
+ }
+
+ // We are expecting
+ // m<hex encoded bytes>
+
+ if (response.GetChar() != 'm') {
+ LLDB_LOGF(log,
+ "GDBRemoteCommunicationClient::%s: qMemTags response did not "
+ "begin with \"m\"",
+ __FUNCTION__);
+ return nullptr;
+ }
+
+ size_t expected_bytes = response.GetBytesLeft() / 2;
+ DataBufferSP buffer_sp(new DataBufferHeap(expected_bytes, 0));
+ size_t got_bytes = response.GetHexBytesAvail(buffer_sp->GetData());
+ // Check both because in some situations chars are consumed even
+ // if the decoding fails.
+ if (response.GetBytesLeft() || (expected_bytes != got_bytes)) {
+ LLDB_LOGF(
+ log,
+ "GDBRemoteCommunicationClient::%s: Invalid data in qMemTags response",
+ __FUNCTION__);
+ return nullptr;
+ }
+
+ return buffer_sp;
+}
+
+Status GDBRemoteCommunicationClient::WriteMemoryTags(
+ lldb::addr_t addr, size_t len, int32_t type,
+ const std::vector<uint8_t> &tags) {
+ // Format QMemTags:address,length:type:tags
+ StreamString packet;
+ packet.Printf("QMemTags:%" PRIx64 ",%zx:%" PRIx32 ":", addr, len, type);
+ packet.PutBytesAsRawHex8(tags.data(), tags.size());
+
+ Status status;
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) !=
+ PacketResult::Success ||
+ !response.IsOKResponse()) {
+ status.SetErrorString("QMemTags packet failed");
+ }
+ return status;
+}
+
bool GDBRemoteCommunicationClient::GetxPacketSupported() {
if (m_supports_x == eLazyBoolCalculate) {
StringExtractorGDBRemote response;
m_supports_x = eLazyBoolNo;
char packet[256];
snprintf(packet, sizeof(packet), "x0,0");
- if (SendPacketAndWaitForResponse(packet, response, false) ==
+ if (SendPacketAndWaitForResponse(packet, response) ==
PacketResult::Success) {
if (response.IsOKResponse())
m_supports_x = eLazyBoolYes;
@@ -664,7 +664,7 @@
GDBRemoteCommunicationClient::PacketResult
GDBRemoteCommunicationClient::SendPacketsAndConcatenateResponses(
const char *payload_prefix, std::string &response_string) {
- Lock lock(*this, false);
+ Lock lock(*this);
if (!lock) {
Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS |
GDBR_LOG_PACKETS));
@@ -725,11 +725,11 @@
// the thread id, which newer debugserver and lldb-gdbserver stubs return
// correctly.
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qC", response, false) ==
- PacketResult::Success) {
+ if (SendPacketAndWaitForResponse("qC", response) == PacketResult::Success) {
if (response.GetChar() == 'Q') {
if (response.GetChar() == 'C') {
- m_curr_pid = response.GetHexMaxU32(false, LLDB_INVALID_PROCESS_ID);
+ m_curr_pid_run = m_curr_pid =
+ response.GetHexMaxU64(false, LLDB_INVALID_PROCESS_ID);
if (m_curr_pid != LLDB_INVALID_PROCESS_ID) {
m_curr_pid_is_valid = eLazyBoolYes;
return m_curr_pid;
@@ -741,12 +741,14 @@
// If we don't get a response for $qC, check if $qfThreadID gives us a
// result.
if (m_curr_pid == LLDB_INVALID_PROCESS_ID) {
- std::vector<lldb::tid_t> thread_ids;
bool sequence_mutex_unavailable;
- size_t size;
- size = GetCurrentThreadIDs(thread_ids, sequence_mutex_unavailable);
- if (size && !sequence_mutex_unavailable) {
- m_curr_pid = thread_ids.front();
+ auto ids = GetCurrentProcessAndThreadIDs(sequence_mutex_unavailable);
+ if (!ids.empty() && !sequence_mutex_unavailable) {
+ // If server returned an explicit PID, use that.
+ m_curr_pid_run = m_curr_pid = ids.front().first;
+ // Otherwise, use the TID of the first thread (Linux hack).
+ if (m_curr_pid == LLDB_INVALID_PROCESS_ID)
+ m_curr_pid_run = m_curr_pid = ids.front().second;
m_curr_pid_is_valid = eLazyBoolYes;
return m_curr_pid;
}
@@ -759,7 +761,7 @@
bool GDBRemoteCommunicationClient::GetLaunchSuccess(std::string &error_str) {
error_str.clear();
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qLaunchSuccess", response, false) ==
+ if (SendPacketAndWaitForResponse("qLaunchSuccess", response) ==
PacketResult::Success) {
if (response.IsOKResponse())
return true;
@@ -813,7 +815,7 @@
}
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
PacketResult::Success) {
if (response.IsOKResponse())
return 0;
@@ -863,7 +865,7 @@
if (m_supports_QEnvironmentHexEncoded) {
packet.PutCString("QEnvironmentHexEncoded:");
packet.PutBytesAsRawHex8(name_equal_value, strlen(name_equal_value));
- if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
PacketResult::Success) {
if (response.IsOKResponse())
return 0;
@@ -877,7 +879,7 @@
} else if (m_supports_QEnvironment) {
packet.Printf("QEnvironment:%s", name_equal_value);
- if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
PacketResult::Success) {
if (response.IsOKResponse())
return 0;
@@ -897,7 +899,7 @@
StreamString packet;
packet.Printf("QLaunchArch:%s", arch);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
PacketResult::Success) {
if (response.IsOKResponse())
return 0;
@@ -915,7 +917,7 @@
StreamString packet;
packet.Printf("QSetProcessEvent:%s", data);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
PacketResult::Success) {
if (response.IsOKResponse()) {
if (was_supported)
@@ -1000,7 +1002,7 @@
m_qGDBServerVersion_is_valid = eLazyBoolNo;
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qGDBServerVersion", response, false) ==
+ if (SendPacketAndWaitForResponse("qGDBServerVersion", response) ==
PacketResult::Success) {
if (response.IsNormalResponse()) {
llvm::StringRef name, value;
@@ -1025,9 +1027,9 @@
}
void GDBRemoteCommunicationClient::MaybeEnableCompression(
- std::vector<std::string> supported_compressions) {
+ llvm::ArrayRef<llvm::StringRef> supported_compressions) {
CompressionType avail_type = CompressionType::None;
- std::string avail_name;
+ llvm::StringRef avail_name;
#if defined(HAVE_LIBCOMPRESSION)
if (avail_type == CompressionType::None) {
@@ -1091,8 +1093,8 @@
if (avail_type != CompressionType::None) {
StringExtractorGDBRemote response;
- std::string packet = "QEnableCompression:type:" + avail_name + ";";
- if (SendPacketAndWaitForResponse(packet, response, false) !=
+ llvm::Twine packet = "QEnableCompression:type:" + avail_name + ";";
+ if (SendPacketAndWaitForResponse(packet.str(), response) !=
PacketResult::Success)
return;
@@ -1118,15 +1120,29 @@
bool GDBRemoteCommunicationClient::GetDefaultThreadId(lldb::tid_t &tid) {
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qC", response, false) !=
- PacketResult::Success)
+ if (SendPacketAndWaitForResponse("qC", response) != PacketResult::Success)
return false;
if (!response.IsNormalResponse())
return false;
- if (response.GetChar() == 'Q' && response.GetChar() == 'C')
- tid = response.GetHexMaxU32(true, -1);
+ if (response.GetChar() == 'Q' && response.GetChar() == 'C') {
+ auto pid_tid = response.GetPidTid(0);
+ if (!pid_tid)
+ return false;
+
+ lldb::pid_t pid = pid_tid->first;
+ // invalid
+ if (pid == StringExtractorGDBRemote::AllProcesses)
+ return false;
+
+ // if we get pid as well, update m_curr_pid
+ if (pid != 0) {
+ m_curr_pid_run = m_curr_pid = pid;
+ m_curr_pid_is_valid = eLazyBoolYes;
+ }
+ tid = pid_tid->second;
+ }
return true;
}
@@ -1154,7 +1170,7 @@
ScopedTimeout timeout(*this, seconds(10));
m_qHostInfo_is_valid = eLazyBoolNo;
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qHostInfo", response, false) ==
+ if (SendPacketAndWaitForResponse("qHostInfo", response) ==
PacketResult::Success) {
if (response.IsNormalResponse()) {
llvm::StringRef name;
@@ -1219,11 +1235,13 @@
} else if (name.equals("ptrsize")) {
if (!value.getAsInteger(0, pointer_byte_size))
++num_keys_decoded;
+ } else if (name.equals("addressing_bits")) {
+ if (!value.getAsInteger(0, m_addressing_bits))
+ ++num_keys_decoded;
} else if (name.equals("os_version") ||
- name.equals(
- "version")) // Older debugserver binaries used the
- // "version" key instead of
- // "os_version"...
+ name.equals("version")) // Older debugserver binaries used
+ // the "version" key instead of
+ // "os_version"...
{
if (!m_os_version.tryParse(value))
++num_keys_decoded;
@@ -1245,6 +1263,12 @@
SetPacketTimeout(m_default_packet_timeout);
++num_keys_decoded;
}
+ } else if (name.equals("vm-page-size")) {
+ int page_size;
+ if (!value.getAsInteger(0, page_size)) {
+ m_target_vm_page_size = page_size;
+ ++num_keys_decoded;
+ }
}
}
@@ -1344,7 +1368,7 @@
::snprintf(packet, sizeof(packet), "vAttach;%" PRIx64, pid);
UNUSED_IF_ASSERT_DISABLED(packet_len);
assert(packet_len < (int)sizeof(packet));
- if (SendPacketAndWaitForResponse(packet, response, false) ==
+ if (SendPacketAndWaitForResponse(packet, response) ==
PacketResult::Success) {
if (response.IsErrorResponse())
return response.GetError();
@@ -1360,7 +1384,7 @@
packet.PutCString("I");
packet.PutBytesAsRawHex8(data, data_len);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
PacketResult::Success) {
return 0;
}
@@ -1374,6 +1398,11 @@
return m_host_arch;
}
+uint32_t GDBRemoteCommunicationClient::GetAddressingBits() {
+ if (m_qHostInfo_is_valid == eLazyBoolCalculate)
+ GetHostInfo();
+ return m_addressing_bits;
+}
seconds GDBRemoteCommunicationClient::GetHostDefaultPacketTimeout() {
if (m_qHostInfo_is_valid == eLazyBoolCalculate)
GetHostInfo();
@@ -1393,7 +1422,7 @@
assert(packet_len < (int)sizeof(packet));
UNUSED_IF_ASSERT_DISABLED(packet_len);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, response, false) ==
+ if (SendPacketAndWaitForResponse(packet, response) ==
PacketResult::Success) {
if (response.IsUnsupportedResponse())
m_supports_alloc_dealloc_memory = eLazyBoolNo;
@@ -1415,7 +1444,7 @@
assert(packet_len < (int)sizeof(packet));
UNUSED_IF_ASSERT_DISABLED(packet_len);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, response, false) ==
+ if (SendPacketAndWaitForResponse(packet, response) ==
PacketResult::Success) {
if (response.IsUnsupportedResponse())
m_supports_alloc_dealloc_memory = eLazyBoolNo;
@@ -1439,7 +1468,7 @@
assert(packet_len < (int)sizeof(packet));
UNUSED_IF_ASSERT_DISABLED(packet_len);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, response, false) ==
+ if (SendPacketAndWaitForResponse(packet, response) ==
PacketResult::Success &&
response.IsOKResponse()) {
m_supports_detach_stay_stopped = eLazyBoolYes;
@@ -1453,15 +1482,13 @@
return error;
} else {
StringExtractorGDBRemote response;
- PacketResult packet_result =
- SendPacketAndWaitForResponse("D1", response, false);
+ PacketResult packet_result = SendPacketAndWaitForResponse("D1", response);
if (packet_result != PacketResult::Success)
error.SetErrorString("Sending extended disconnect packet failed.");
}
} else {
StringExtractorGDBRemote response;
- PacketResult packet_result =
- SendPacketAndWaitForResponse("D", response, false);
+ PacketResult packet_result = SendPacketAndWaitForResponse("D", response);
if (packet_result != PacketResult::Success)
error.SetErrorString("Sending disconnect packet failed.");
}
@@ -1481,7 +1508,7 @@
assert(packet_len < (int)sizeof(packet));
UNUSED_IF_ASSERT_DISABLED(packet_len);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, response, false) ==
+ if (SendPacketAndWaitForResponse(packet, response) ==
PacketResult::Success &&
response.GetResponseType() == StringExtractorGDBRemote::eResponse) {
llvm::StringRef name;
@@ -1551,9 +1578,30 @@
// Now convert the HEX bytes into a string value
error_extractor.GetHexByteString(error_string);
error.SetErrorString(error_string.c_str());
+ } else if (name.equals("dirty-pages")) {
+ std::vector<addr_t> dirty_page_list;
+ std::string comma_sep_str = value.str();
+ size_t comma_pos;
+ addr_t page;
+ while ((comma_pos = comma_sep_str.find(',')) != std::string::npos) {
+ comma_sep_str[comma_pos] = '\0';
+ page = StringConvert::ToUInt64(comma_sep_str.c_str(),
+ LLDB_INVALID_ADDRESS, 16);
+ if (page != LLDB_INVALID_ADDRESS)
+ dirty_page_list.push_back(page);
+ comma_sep_str.erase(0, comma_pos + 1);
+ }
+ page = StringConvert::ToUInt64(comma_sep_str.c_str(),
+ LLDB_INVALID_ADDRESS, 16);
+ if (page != LLDB_INVALID_ADDRESS)
+ dirty_page_list.push_back(page);
+ region_info.SetDirtyPageList(dirty_page_list);
}
}
+ if (m_target_vm_page_size != 0)
+ region_info.SetPageSize(m_target_vm_page_size);
+
if (region_info.GetRange().IsValid()) {
// We got a valid address range back but no permissions -- which means
// this is an unmapped page
@@ -1718,8 +1766,8 @@
num = 0;
if (m_supports_watchpoint_support_info != eLazyBoolNo) {
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qWatchpointSupportInfo:", response,
- false) == PacketResult::Success) {
+ if (SendPacketAndWaitForResponse("qWatchpointSupportInfo:", response) ==
+ PacketResult::Success) {
m_supports_watchpoint_support_info = eLazyBoolYes;
llvm::StringRef name;
llvm::StringRef value;
@@ -1787,7 +1835,7 @@
packet.PutStringAsRawHex8(path);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
PacketResult::Success) {
if (response.IsOKResponse())
return 0;
@@ -1807,7 +1855,7 @@
packet.PutStringAsRawHex8(path);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
PacketResult::Success) {
if (response.IsOKResponse())
return 0;
@@ -1827,7 +1875,7 @@
packet.PutStringAsRawHex8(path);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
PacketResult::Success) {
if (response.IsOKResponse())
return 0;
@@ -1841,7 +1889,7 @@
bool GDBRemoteCommunicationClient::GetWorkingDir(FileSpec &working_dir) {
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qGetWorkingDir", response, false) ==
+ if (SendPacketAndWaitForResponse("qGetWorkingDir", response) ==
PacketResult::Success) {
if (response.IsUnsupportedResponse())
return false;
@@ -1863,7 +1911,7 @@
packet.PutStringAsRawHex8(path);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
PacketResult::Success) {
if (response.IsOKResponse())
return 0;
@@ -1882,8 +1930,7 @@
assert(packet_len < (int)sizeof(packet));
UNUSED_IF_ASSERT_DISABLED(packet_len);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, response, false) ==
- PacketResult::Success) {
+ if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) {
if (response.IsOKResponse())
return 0;
uint8_t error = response.GetError();
@@ -1900,8 +1947,7 @@
assert(packet_len < (int)sizeof(packet));
UNUSED_IF_ASSERT_DISABLED(packet_len);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, response, false) ==
- PacketResult::Success) {
+ if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) {
if (response.IsOKResponse())
return 0;
uint8_t error = response.GetError();
@@ -2019,7 +2065,7 @@
assert(packet_len < (int)sizeof(packet));
UNUSED_IF_ASSERT_DISABLED(packet_len);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, response, false) ==
+ if (SendPacketAndWaitForResponse(packet, response) ==
PacketResult::Success) {
return DecodeProcessInfoResponse(response, process_info);
} else {
@@ -2044,7 +2090,7 @@
GetHostInfo();
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qProcessInfo", response, false) ==
+ if (SendPacketAndWaitForResponse("qProcessInfo", response) ==
PacketResult::Success) {
if (response.IsNormalResponse()) {
llvm::StringRef name;
@@ -2102,7 +2148,7 @@
m_qProcessInfo_is_valid = eLazyBoolYes;
if (pid != LLDB_INVALID_PROCESS_ID) {
m_curr_pid_is_valid = eLazyBoolYes;
- m_curr_pid = pid;
+ m_curr_pid_run = m_curr_pid = pid;
}
// Set the ArchSpec from the triple if we have it.
@@ -2240,7 +2286,7 @@
// Increase timeout as the first qfProcessInfo packet takes a long time on
// Android. The value of 1min was arrived at empirically.
ScopedTimeout timeout(*this, minutes(1));
- if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
PacketResult::Success) {
do {
ProcessInstanceInfo process_info;
@@ -2248,7 +2294,7 @@
break;
process_infos.push_back(process_info);
response = StringExtractorGDBRemote();
- } while (SendPacketAndWaitForResponse("qsProcessInfo", response, false) ==
+ } while (SendPacketAndWaitForResponse("qsProcessInfo", response) ==
PacketResult::Success);
} else {
m_supports_qfProcessInfo = false;
@@ -2267,7 +2313,7 @@
assert(packet_len < (int)sizeof(packet));
UNUSED_IF_ASSERT_DISABLED(packet_len);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, response, false) ==
+ if (SendPacketAndWaitForResponse(packet, response) ==
PacketResult::Success) {
if (response.IsNormalResponse()) {
// Make sure we parsed the right number of characters. The response is
@@ -2294,7 +2340,7 @@
assert(packet_len < (int)sizeof(packet));
UNUSED_IF_ASSERT_DISABLED(packet_len);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, response, false) ==
+ if (SendPacketAndWaitForResponse(packet, response) ==
PacketResult::Success) {
if (response.IsNormalResponse()) {
// Make sure we parsed the right number of characters. The response is
@@ -2322,8 +2368,7 @@
StringExtractorGDBRemote response;
// Send to target
- if (SendPacketAndWaitForResponse(packet, response, false) ==
- PacketResult::Success)
+ if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success)
if (response.IsOKResponse())
return true;
@@ -2395,7 +2440,7 @@
for (i = 0; i < num_packets; ++i) {
const auto packet_start_time = steady_clock::now();
StringExtractorGDBRemote response;
- SendPacketAndWaitForResponse(packet.GetString(), response, false);
+ SendPacketAndWaitForResponse(packet.GetString(), response);
const auto packet_end_time = steady_clock::now();
packet_times.push_back(packet_end_time - packet_start_time);
}
@@ -2449,7 +2494,7 @@
uint32_t packet_count = 0;
while (bytes_read < recv_amount) {
StringExtractorGDBRemote response;
- SendPacketAndWaitForResponse(packet.GetString(), response, false);
+ SendPacketAndWaitForResponse(packet.GetString(), response);
bytes_read += recv_size;
++packet_count;
}
@@ -2503,7 +2548,7 @@
}
StringExtractorGDBRemote response;
- return SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ return SendPacketAndWaitForResponse(packet.GetString(), response) ==
PacketResult::Success;
}
@@ -2533,7 +2578,7 @@
// give the process a few seconds to startup
ScopedTimeout timeout(*this, seconds(10));
- if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
llvm::StringRef name;
llvm::StringRef value;
@@ -2557,7 +2602,7 @@
connection_urls.clear();
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qQueryGDBServer", response, false) !=
+ if (SendPacketAndWaitForResponse("qQueryGDBServer", response) !=
PacketResult::Success)
return 0;
@@ -2596,7 +2641,7 @@
stream.Printf("qKillSpawnedProcess:%" PRId64, pid);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
if (response.IsOKResponse())
return true;
@@ -2604,25 +2649,27 @@
return false;
}
-bool GDBRemoteCommunicationClient::SetCurrentThread(uint64_t tid) {
- if (m_curr_tid == tid)
- return true;
+llvm::Optional<PidTid>
+GDBRemoteCommunicationClient::SendSetCurrentThreadPacket(uint64_t tid,
+ uint64_t pid,
+ char op) {
+ lldb_private::StreamString packet;
+ packet.PutChar('H');
+ packet.PutChar(op);
- char packet[32];
- int packet_len;
+ if (pid != LLDB_INVALID_PROCESS_ID)
+ packet.Printf("p%" PRIx64 ".", pid);
+
if (tid == UINT64_MAX)
- packet_len = ::snprintf(packet, sizeof(packet), "Hg-1");
+ packet.PutCString("-1");
else
- packet_len = ::snprintf(packet, sizeof(packet), "Hg%" PRIx64, tid);
- assert(packet_len + 1 < (int)sizeof(packet));
- UNUSED_IF_ASSERT_DISABLED(packet_len);
+ packet.Printf("%" PRIx64, tid);
+
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, response, false) ==
- PacketResult::Success) {
- if (response.IsOKResponse()) {
- m_curr_tid = tid;
- return true;
- }
+ if (SendPacketAndWaitForResponse(packet.GetString(), response)
+ == PacketResult::Success) {
+ if (response.IsOKResponse())
+ return {{pid, tid}};
/*
* Connected bare-iron target (like YAMON gdb-stub) may not have support for
@@ -2630,55 +2677,46 @@
* The reply from '?' packet could be as simple as 'S05'. There is no packet
* which can
* give us pid and/or tid. Assume pid=tid=1 in such cases.
- */
- if (response.IsUnsupportedResponse() && IsConnected()) {
- m_curr_tid = 1;
- return true;
- }
+ */
+ if (response.IsUnsupportedResponse() && IsConnected())
+ return {{1, 1}};
}
- return false;
+ return llvm::None;
}
-bool GDBRemoteCommunicationClient::SetCurrentThreadForRun(uint64_t tid) {
- if (m_curr_tid_run == tid)
+bool GDBRemoteCommunicationClient::SetCurrentThread(uint64_t tid,
+ uint64_t pid) {
+ if (m_curr_tid == tid &&
+ (m_curr_pid == pid || LLDB_INVALID_PROCESS_ID == pid))
return true;
- char packet[32];
- int packet_len;
- if (tid == UINT64_MAX)
- packet_len = ::snprintf(packet, sizeof(packet), "Hc-1");
- else
- packet_len = ::snprintf(packet, sizeof(packet), "Hc%" PRIx64, tid);
-
- assert(packet_len + 1 < (int)sizeof(packet));
- UNUSED_IF_ASSERT_DISABLED(packet_len);
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, response, false) ==
- PacketResult::Success) {
- if (response.IsOKResponse()) {
- m_curr_tid_run = tid;
- return true;
- }
-
- /*
- * Connected bare-iron target (like YAMON gdb-stub) may not have support for
- * Hc packet.
- * The reply from '?' packet could be as simple as 'S05'. There is no packet
- * which can
- * give us pid and/or tid. Assume pid=tid=1 in such cases.
- */
- if (response.IsUnsupportedResponse() && IsConnected()) {
- m_curr_tid_run = 1;
- return true;
- }
+ llvm::Optional<PidTid> ret = SendSetCurrentThreadPacket(tid, pid, 'g');
+ if (ret.hasValue()) {
+ if (ret->pid != LLDB_INVALID_PROCESS_ID)
+ m_curr_pid = ret->pid;
+ m_curr_tid = ret->tid;
}
- return false;
+ return ret.hasValue();
+}
+
+bool GDBRemoteCommunicationClient::SetCurrentThreadForRun(uint64_t tid,
+ uint64_t pid) {
+ if (m_curr_tid_run == tid &&
+ (m_curr_pid_run == pid || LLDB_INVALID_PROCESS_ID == pid))
+ return true;
+
+ llvm::Optional<PidTid> ret = SendSetCurrentThreadPacket(tid, pid, 'c');
+ if (ret.hasValue()) {
+ if (ret->pid != LLDB_INVALID_PROCESS_ID)
+ m_curr_pid_run = ret->pid;
+ m_curr_tid_run = ret->tid;
+ }
+ return ret.hasValue();
}
bool GDBRemoteCommunicationClient::GetStopReply(
StringExtractorGDBRemote &response) {
- if (SendPacketAndWaitForResponse("?", response, false) ==
- PacketResult::Success)
+ if (SendPacketAndWaitForResponse("?", response) == PacketResult::Success)
return response.IsNormalResponse();
return false;
}
@@ -2691,7 +2729,7 @@
::snprintf(packet, sizeof(packet), "qThreadStopInfo%" PRIx64, tid);
assert(packet_len < (int)sizeof(packet));
UNUSED_IF_ASSERT_DISABLED(packet_len);
- if (SendPacketAndWaitForResponse(packet, response, false) ==
+ if (SendPacketAndWaitForResponse(packet, response) ==
PacketResult::Success) {
if (response.IsUnsupportedResponse())
m_supports_qThreadStopInfo = false;
@@ -2707,7 +2745,8 @@
}
uint8_t GDBRemoteCommunicationClient::SendGDBStoppointTypePacket(
- GDBStoppointType type, bool insert, addr_t addr, uint32_t length) {
+ GDBStoppointType type, bool insert, addr_t addr, uint32_t length,
+ std::chrono::seconds timeout) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
LLDB_LOGF(log, "GDBRemoteCommunicationClient::%s() %s at addr = 0x%" PRIx64,
__FUNCTION__, insert ? "add" : "remove", addr);
@@ -2728,7 +2767,7 @@
// or "" (unsupported)
response.SetResponseValidatorToOKErrorNotSupported();
// Try to send the breakpoint packet, and check that it was correctly sent
- if (SendPacketAndWaitForResponse(packet, response, true) ==
+ if (SendPacketAndWaitForResponse(packet, response, timeout) ==
PacketResult::Success) {
// Receive and OK packet when the breakpoint successfully placed
if (response.IsOKResponse())
@@ -2766,11 +2805,12 @@
return UINT8_MAX;
}
-size_t GDBRemoteCommunicationClient::GetCurrentThreadIDs(
- std::vector<lldb::tid_t> &thread_ids, bool &sequence_mutex_unavailable) {
- thread_ids.clear();
+std::vector<std::pair<lldb::pid_t, lldb::tid_t>>
+GDBRemoteCommunicationClient::GetCurrentProcessAndThreadIDs(
+ bool &sequence_mutex_unavailable) {
+ std::vector<std::pair<lldb::pid_t, lldb::tid_t>> ids;
- Lock lock(*this, false);
+ Lock lock(*this);
if (lock) {
sequence_mutex_unavailable = false;
StringExtractorGDBRemote response;
@@ -2786,11 +2826,11 @@
break;
if (ch == 'm') {
do {
- tid_t tid = response.GetHexMaxU64(false, LLDB_INVALID_THREAD_ID);
+ auto pid_tid = response.GetPidTid(LLDB_INVALID_PROCESS_ID);
+ if (!pid_tid)
+ return {};
- if (tid != LLDB_INVALID_THREAD_ID) {
- thread_ids.push_back(tid);
- }
+ ids.push_back(pid_tid.getValue());
ch = response.GetChar(); // Skip the command separator
} while (ch == ','); // Make sure we got a comma separator
}
@@ -2803,10 +2843,10 @@
* be as simple as 'S05'. There is no packet which can give us pid and/or
* tid.
* Assume pid=tid=1 in such cases.
- */
+ */
if ((response.IsUnsupportedResponse() || response.IsNormalResponse()) &&
- thread_ids.size() == 0 && IsConnected()) {
- thread_ids.push_back(1);
+ ids.size() == 0 && IsConnected()) {
+ ids.emplace_back(1, 1);
}
} else {
Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS |
@@ -2815,12 +2855,34 @@
"packet 'qfThreadInfo'");
sequence_mutex_unavailable = true;
}
+
+ return ids;
+}
+
+size_t GDBRemoteCommunicationClient::GetCurrentThreadIDs(
+ std::vector<lldb::tid_t> &thread_ids, bool &sequence_mutex_unavailable) {
+ lldb::pid_t pid = GetCurrentProcessID();
+ thread_ids.clear();
+
+ auto ids = GetCurrentProcessAndThreadIDs(sequence_mutex_unavailable);
+ if (ids.empty() || sequence_mutex_unavailable)
+ return 0;
+
+ for (auto id : ids) {
+ // skip threads that do not belong to the current process
+ if (id.first != LLDB_INVALID_PROCESS_ID && id.first != pid)
+ continue;
+ if (id.second != LLDB_INVALID_THREAD_ID &&
+ id.second != StringExtractorGDBRemote::AllThreads)
+ thread_ids.push_back(id.second);
+ }
+
return thread_ids.size();
}
lldb::addr_t GDBRemoteCommunicationClient::GetShlibInfoAddr() {
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qShlibInfoAddr", response, false) !=
+ if (SendPacketAndWaitForResponse("qShlibInfoAddr", response) !=
PacketResult::Success ||
!response.IsNormalResponse())
return LLDB_INVALID_ADDRESS;
@@ -2853,7 +2915,7 @@
stream.PutStringAsRawHex8(path);
}
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
if (response.GetChar() != 'F')
return Status("malformed reply");
@@ -2891,8 +2953,7 @@
llvm::StringRef packet = stream.GetString();
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, response, false) !=
- PacketResult::Success)
+ if (SendPacketAndWaitForResponse(packet, response) != PacketResult::Success)
return Status("failed to send '%s' packet", packet.str().c_str());
if (response.GetChar() != 'F')
@@ -2913,8 +2974,7 @@
llvm::StringRef packet = stream.GetString();
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, response, false) !=
- PacketResult::Success)
+ if (SendPacketAndWaitForResponse(packet, response) != PacketResult::Success)
return Status("failed to send '%s' packet", stream.GetData());
if (response.GetChar() != 'F')
@@ -2956,7 +3016,7 @@
stream.PutChar(',');
stream.PutHex32(mode);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
return ParseHostIOPacketResponse(response, UINT64_MAX, error);
}
@@ -2968,7 +3028,7 @@
lldb_private::StreamString stream;
stream.Printf("vFile:close:%i", (int)fd);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
return ParseHostIOPacketResponse(response, -1, error) == 0;
}
@@ -2983,7 +3043,7 @@
stream.PutCString("vFile:size:");
stream.PutStringAsRawHex8(path);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
if (response.GetChar() != 'F')
return UINT64_MAX;
@@ -3001,7 +3061,7 @@
stream.PutChar(',');
stream.PutStringAsRawHex8(request.GetCursorArgumentPrefix());
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
StreamString strm;
char ch = response.GetChar();
@@ -3027,7 +3087,7 @@
stream.PutCString("vFile:mode:");
stream.PutStringAsRawHex8(path);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
if (response.GetChar() != 'F') {
error.SetErrorStringWithFormat("invalid response to '%s' packet",
@@ -3062,7 +3122,7 @@
stream.Printf("vFile:pread:%i,%" PRId64 ",%" PRId64, (int)fd, dst_len,
offset);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
if (response.GetChar() != 'F')
return 0;
@@ -3096,7 +3156,7 @@
stream.Printf("vFile:pwrite:%i,%" PRId64 ",", (int)fd, offset);
stream.PutEscapedBytes(src, src_len);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
if (response.GetChar() != 'F') {
error.SetErrorStringWithFormat("write file failed");
@@ -3131,7 +3191,7 @@
stream.PutChar(',');
stream.PutStringAsRawHex8(src_path);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
if (response.GetChar() == 'F') {
uint32_t result = response.GetU32(UINT32_MAX);
@@ -3162,7 +3222,7 @@
// so we follow suit here
stream.PutStringAsRawHex8(path);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
if (response.GetChar() == 'F') {
uint32_t result = response.GetU32(UINT32_MAX);
@@ -3192,7 +3252,7 @@
stream.PutCString("vFile:exists:");
stream.PutStringAsRawHex8(path);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
if (response.GetChar() != 'F')
return false;
@@ -3211,7 +3271,7 @@
stream.PutCString("vFile:MD5:");
stream.PutStringAsRawHex8(path);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
if (response.GetChar() != 'F')
return false;
@@ -3258,7 +3318,7 @@
payload.Printf("p%x", reg);
StringExtractorGDBRemote response;
if (SendThreadSpecificPacketAndWaitForResponse(
- tid, std::move(payload), response, false) != PacketResult::Success ||
+ tid, std::move(payload), response) != PacketResult::Success ||
!response.IsNormalResponse())
return nullptr;
@@ -3273,7 +3333,7 @@
payload.PutChar('g');
StringExtractorGDBRemote response;
if (SendThreadSpecificPacketAndWaitForResponse(
- tid, std::move(payload), response, false) != PacketResult::Success ||
+ tid, std::move(payload), response) != PacketResult::Success ||
!response.IsNormalResponse())
return nullptr;
@@ -3292,9 +3352,8 @@
endian::InlHostByteOrder(),
endian::InlHostByteOrder());
StringExtractorGDBRemote response;
- return SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload),
- response, false) ==
- PacketResult::Success &&
+ return SendThreadSpecificPacketAndWaitForResponse(
+ tid, std::move(payload), response) == PacketResult::Success &&
response.IsOKResponse();
}
@@ -3306,9 +3365,8 @@
endian::InlHostByteOrder(),
endian::InlHostByteOrder());
StringExtractorGDBRemote response;
- return SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload),
- response, false) ==
- PacketResult::Success &&
+ return SendThreadSpecificPacketAndWaitForResponse(
+ tid, std::move(payload), response) == PacketResult::Success &&
response.IsOKResponse();
}
@@ -3323,7 +3381,7 @@
payload.PutCString("QSaveRegisterState");
StringExtractorGDBRemote response;
if (SendThreadSpecificPacketAndWaitForResponse(
- tid, std::move(payload), response, false) != PacketResult::Success)
+ tid, std::move(payload), response) != PacketResult::Success)
return false;
if (response.IsUnsupportedResponse())
@@ -3349,7 +3407,7 @@
payload.Printf("QRestoreRegisterState:%u", save_id);
StringExtractorGDBRemote response;
if (SendThreadSpecificPacketAndWaitForResponse(
- tid, std::move(payload), response, false) != PacketResult::Success)
+ tid, std::move(payload), response) != PacketResult::Success)
return false;
if (response.IsOKResponse())
@@ -3367,251 +3425,179 @@
StreamString packet;
StringExtractorGDBRemote response;
packet.Printf("QSyncThreadState:%4.4" PRIx64 ";", tid);
- return SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ return SendPacketAndWaitForResponse(packet.GetString(), response) ==
GDBRemoteCommunication::PacketResult::Success &&
response.IsOKResponse();
}
-lldb::user_id_t
-GDBRemoteCommunicationClient::SendStartTracePacket(const TraceOptions &options,
- Status &error) {
- Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
- lldb::user_id_t ret_uid = LLDB_INVALID_UID;
-
- StreamGDBRemote escaped_packet;
- escaped_packet.PutCString("jTraceStart:");
-
- StructuredData::Dictionary json_packet;
- json_packet.AddIntegerItem("type", options.getType());
- json_packet.AddIntegerItem("buffersize", options.getTraceBufferSize());
- json_packet.AddIntegerItem("metabuffersize", options.getMetaDataBufferSize());
-
- if (options.getThreadID() != LLDB_INVALID_THREAD_ID)
- json_packet.AddIntegerItem("threadid", options.getThreadID());
-
- StructuredData::DictionarySP custom_params = options.getTraceParams();
- if (custom_params)
- json_packet.AddItem("params", custom_params);
-
- StreamString json_string;
- json_packet.Dump(json_string, false);
- escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize());
-
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
- true) ==
- GDBRemoteCommunication::PacketResult::Success) {
- if (!response.IsNormalResponse()) {
- error = response.GetStatus();
- LLDB_LOG(log, "Target does not support Tracing , error {0}", error);
- } else {
- ret_uid = response.GetHexMaxU64(false, LLDB_INVALID_UID);
- }
- } else {
- LLDB_LOG(log, "failed to send packet");
- error.SetErrorStringWithFormat("failed to send packet: '%s'",
- escaped_packet.GetData());
- }
- return ret_uid;
-}
-
-Status
-GDBRemoteCommunicationClient::SendStopTracePacket(lldb::user_id_t uid,
- lldb::tid_t thread_id) {
- Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
- StringExtractorGDBRemote response;
- Status error;
-
- StructuredData::Dictionary json_packet;
- StreamGDBRemote escaped_packet;
- StreamString json_string;
- escaped_packet.PutCString("jTraceStop:");
-
- json_packet.AddIntegerItem("traceid", uid);
-
- if (thread_id != LLDB_INVALID_THREAD_ID)
- json_packet.AddIntegerItem("threadid", thread_id);
-
- json_packet.Dump(json_string, false);
-
- escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize());
-
- if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
- true) ==
- GDBRemoteCommunication::PacketResult::Success) {
- if (!response.IsOKResponse()) {
- error = response.GetStatus();
- LLDB_LOG(log, "stop tracing failed");
- }
- } else {
- LLDB_LOG(log, "failed to send packet");
- error.SetErrorStringWithFormat(
- "failed to send packet: '%s' with error '%d'", escaped_packet.GetData(),
- response.GetError());
- }
- return error;
-}
-
-Status GDBRemoteCommunicationClient::SendGetDataPacket(
- lldb::user_id_t uid, lldb::tid_t thread_id,
- llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) {
-
- StreamGDBRemote escaped_packet;
- escaped_packet.PutCString("jTraceBufferRead:");
- return SendGetTraceDataPacket(escaped_packet, uid, thread_id, buffer, offset);
-}
-
-Status GDBRemoteCommunicationClient::SendGetMetaDataPacket(
- lldb::user_id_t uid, lldb::tid_t thread_id,
- llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) {
-
- StreamGDBRemote escaped_packet;
- escaped_packet.PutCString("jTraceMetaRead:");
- return SendGetTraceDataPacket(escaped_packet, uid, thread_id, buffer, offset);
-}
-
-llvm::Expected<TraceTypeInfo>
-GDBRemoteCommunicationClient::SendGetSupportedTraceType() {
+llvm::Expected<TraceSupportedResponse>
+GDBRemoteCommunicationClient::SendTraceSupported(std::chrono::seconds timeout) {
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
StreamGDBRemote escaped_packet;
- escaped_packet.PutCString("jLLDBTraceSupportedType");
+ escaped_packet.PutCString("jLLDBTraceSupported");
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
- true) ==
+ timeout) ==
GDBRemoteCommunication::PacketResult::Success) {
if (response.IsErrorResponse())
return response.GetStatus().ToError();
if (response.IsUnsupportedResponse())
return llvm::createStringError(llvm::inconvertibleErrorCode(),
- "jLLDBTraceSupportedType is unsupported");
+ "jLLDBTraceSupported is unsupported");
- if (llvm::Expected<TraceTypeInfo> type =
- llvm::json::parse<TraceTypeInfo>(response.Peek()))
- return *type;
- else
- return type.takeError();
+ return llvm::json::parse<TraceSupportedResponse>(response.Peek(),
+ "TraceSupportedResponse");
}
- LLDB_LOG(log, "failed to send packet: jLLDBTraceSupportedType");
+ LLDB_LOG(log, "failed to send packet: jLLDBTraceSupported");
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "failed to send packet: jLLDBTraceSupported");
+}
+
+llvm::Error
+GDBRemoteCommunicationClient::SendTraceStop(const TraceStopRequest &request,
+ std::chrono::seconds timeout) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+
+ StreamGDBRemote escaped_packet;
+ escaped_packet.PutCString("jLLDBTraceStop:");
+
+ std::string json_string;
+ llvm::raw_string_ostream os(json_string);
+ os << toJSON(request);
+ os.flush();
+
+ escaped_packet.PutEscapedBytes(json_string.c_str(), json_string.size());
+
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
+ timeout) ==
+ GDBRemoteCommunication::PacketResult::Success) {
+ if (response.IsErrorResponse())
+ return response.GetStatus().ToError();
+ if (response.IsUnsupportedResponse())
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "jLLDBTraceStop is unsupported");
+ if (response.IsOKResponse())
+ return llvm::Error::success();
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Invalid jLLDBTraceStart response");
+ }
+ LLDB_LOG(log, "failed to send packet: jLLDBTraceStop");
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "failed to send packet: jLLDBTraceStop '%s'",
+ escaped_packet.GetData());
+}
+
+llvm::Error
+GDBRemoteCommunicationClient::SendTraceStart(const llvm::json::Value ¶ms,
+ std::chrono::seconds timeout) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+
+ StreamGDBRemote escaped_packet;
+ escaped_packet.PutCString("jLLDBTraceStart:");
+
+ std::string json_string;
+ llvm::raw_string_ostream os(json_string);
+ os << params;
+ os.flush();
+
+ escaped_packet.PutEscapedBytes(json_string.c_str(), json_string.size());
+
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
+ timeout) ==
+ GDBRemoteCommunication::PacketResult::Success) {
+ if (response.IsErrorResponse())
+ return response.GetStatus().ToError();
+ if (response.IsUnsupportedResponse())
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "jLLDBTraceStart is unsupported");
+ if (response.IsOKResponse())
+ return llvm::Error::success();
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Invalid jLLDBTraceStart response");
+ }
+ LLDB_LOG(log, "failed to send packet: jLLDBTraceStart");
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "failed to send packet: jLLDBTraceStart '%s'",
+ escaped_packet.GetData());
+}
+
+llvm::Expected<std::string>
+GDBRemoteCommunicationClient::SendTraceGetState(llvm::StringRef type,
+ std::chrono::seconds timeout) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+
+ StreamGDBRemote escaped_packet;
+ escaped_packet.PutCString("jLLDBTraceGetState:");
+
+ std::string json_string;
+ llvm::raw_string_ostream os(json_string);
+ os << toJSON(TraceGetStateRequest{type.str()});
+ os.flush();
+
+ escaped_packet.PutEscapedBytes(json_string.c_str(), json_string.size());
+
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
+ timeout) ==
+ GDBRemoteCommunication::PacketResult::Success) {
+ if (response.IsErrorResponse())
+ return response.GetStatus().ToError();
+ if (response.IsUnsupportedResponse())
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "jLLDBTraceGetState is unsupported");
+ return std::string(response.Peek());
+ }
+
+ LLDB_LOG(log, "failed to send packet: jLLDBTraceGetState");
return llvm::createStringError(
llvm::inconvertibleErrorCode(),
- "failed to send packet: jLLDBTraceSupportedType");
+ "failed to send packet: jLLDBTraceGetState '%s'",
+ escaped_packet.GetData());
}
-Status
-GDBRemoteCommunicationClient::SendGetTraceConfigPacket(lldb::user_id_t uid,
- TraceOptions &options) {
+llvm::Expected<std::vector<uint8_t>>
+GDBRemoteCommunicationClient::SendTraceGetBinaryData(
+ const TraceGetBinaryDataRequest &request, std::chrono::seconds timeout) {
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
- StringExtractorGDBRemote response;
- Status error;
- StreamString json_string;
StreamGDBRemote escaped_packet;
- escaped_packet.PutCString("jTraceConfigRead:");
+ escaped_packet.PutCString("jLLDBTraceGetBinaryData:");
- StructuredData::Dictionary json_packet;
- json_packet.AddIntegerItem("traceid", uid);
+ std::string json_string;
+ llvm::raw_string_ostream os(json_string);
+ os << toJSON(request);
+ os.flush();
- if (options.getThreadID() != LLDB_INVALID_THREAD_ID)
- json_packet.AddIntegerItem("threadid", options.getThreadID());
+ escaped_packet.PutEscapedBytes(json_string.c_str(), json_string.size());
- json_packet.Dump(json_string, false);
- escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize());
-
- if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
- true) ==
- GDBRemoteCommunication::PacketResult::Success) {
- if (response.IsNormalResponse()) {
- uint64_t type = std::numeric_limits<uint64_t>::max();
- uint64_t buffersize = std::numeric_limits<uint64_t>::max();
- uint64_t metabuffersize = std::numeric_limits<uint64_t>::max();
-
- auto json_object = StructuredData::ParseJSON(response.Peek());
-
- if (!json_object ||
- json_object->GetType() != lldb::eStructuredDataTypeDictionary) {
- error.SetErrorString("Invalid Configuration obtained");
- return error;
- }
-
- auto json_dict = json_object->GetAsDictionary();
-
- json_dict->GetValueForKeyAsInteger<uint64_t>("metabuffersize",
- metabuffersize);
- options.setMetaDataBufferSize(metabuffersize);
-
- json_dict->GetValueForKeyAsInteger<uint64_t>("buffersize", buffersize);
- options.setTraceBufferSize(buffersize);
-
- json_dict->GetValueForKeyAsInteger<uint64_t>("type", type);
- options.setType(static_cast<lldb::TraceType>(type));
-
- StructuredData::ObjectSP custom_params_sp =
- json_dict->GetValueForKey("params");
- if (custom_params_sp) {
- if (custom_params_sp->GetType() !=
- lldb::eStructuredDataTypeDictionary) {
- error.SetErrorString("Invalid Configuration obtained");
- return error;
- } else
- options.setTraceParams(
- std::static_pointer_cast<StructuredData::Dictionary>(
- custom_params_sp));
- }
- } else {
- error = response.GetStatus();
- }
- } else {
- LLDB_LOG(log, "failed to send packet");
- error.SetErrorStringWithFormat("failed to send packet: '%s'",
- escaped_packet.GetData());
- }
- return error;
-}
-
-Status GDBRemoteCommunicationClient::SendGetTraceDataPacket(
- StreamGDBRemote &packet, lldb::user_id_t uid, lldb::tid_t thread_id,
- llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) {
- Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
- Status error;
-
- StructuredData::Dictionary json_packet;
-
- json_packet.AddIntegerItem("traceid", uid);
- json_packet.AddIntegerItem("offset", offset);
- json_packet.AddIntegerItem("buffersize", buffer.size());
-
- if (thread_id != LLDB_INVALID_THREAD_ID)
- json_packet.AddIntegerItem("threadid", thread_id);
-
- StreamString json_string;
- json_packet.Dump(json_string, false);
-
- packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize());
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet.GetString(), response, true) ==
+ if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
+ timeout) ==
GDBRemoteCommunication::PacketResult::Success) {
- if (response.IsNormalResponse()) {
- size_t filled_size = response.GetHexBytesAvail(buffer);
- buffer = llvm::MutableArrayRef<uint8_t>(buffer.data(), filled_size);
- } else {
- error = response.GetStatus();
- buffer = buffer.slice(buffer.size());
- }
- } else {
- LLDB_LOG(log, "failed to send packet");
- error.SetErrorStringWithFormat("failed to send packet: '%s'",
- packet.GetData());
- buffer = buffer.slice(buffer.size());
+ if (response.IsErrorResponse())
+ return response.GetStatus().ToError();
+ if (response.IsUnsupportedResponse())
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "jLLDBTraceGetBinaryData is unsupported");
+ std::string data;
+ response.GetEscapedBinaryData(data);
+ return std::vector<uint8_t>(data.begin(), data.end());
}
- return error;
+ LLDB_LOG(log, "failed to send packet: jLLDBTraceGetBinaryData");
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "failed to send packet: jLLDBTraceGetBinaryData '%s'",
+ escaped_packet.GetData());
}
llvm::Optional<QOffsets> GDBRemoteCommunicationClient::GetQOffsets() {
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(
- "qOffsets", response, /*send_async=*/false) != PacketResult::Success)
+ if (SendPacketAndWaitForResponse("qOffsets", response) !=
+ PacketResult::Success)
return llvm::None;
if (!response.IsNormalResponse())
return llvm::None;
@@ -3666,7 +3652,7 @@
packet.PutStringAsRawHex8(triple);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet.GetString(), response, false) !=
+ if (SendPacketAndWaitForResponse(packet.GetString(), response) !=
PacketResult::Success)
return false;
@@ -3773,7 +3759,7 @@
ScopedTimeout timeout(*this, std::chrono::seconds(10));
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(payload.GetString(), response, false) !=
+ if (SendPacketAndWaitForResponse(payload.GetString(), response) !=
PacketResult::Success ||
response.IsErrorResponse())
return llvm::None;
@@ -3832,7 +3818,7 @@
<< "," << std::hex << size;
GDBRemoteCommunication::PacketResult res =
- SendPacketAndWaitForResponse(packet.str(), chunk, false);
+ SendPacketAndWaitForResponse(packet.str(), chunk);
if (res != GDBRemoteCommunication::PacketResult::Success) {
err.SetErrorString("Error sending $qXfer packet");
@@ -3921,7 +3907,7 @@
bool first_qsymbol_query = true;
if (m_supports_qSymbol && !m_qSymbol_requests_done) {
- Lock lock(*this, false);
+ Lock lock(*this);
if (lock) {
StreamString packet;
packet.PutCString("qSymbol::");
@@ -4049,9 +4035,8 @@
// Poll it now.
StringExtractorGDBRemote response;
- const bool send_async = false;
- if (SendPacketAndWaitForResponse("qStructuredDataPlugins", response,
- send_async) == PacketResult::Success) {
+ if (SendPacketAndWaitForResponse("qStructuredDataPlugins", response) ==
+ PacketResult::Success) {
m_supported_async_json_packets_sp =
StructuredData::ParseJSON(std::string(response.GetStringRef()));
if (m_supported_async_json_packets_sp &&
@@ -4095,7 +4080,7 @@
std::string packet = formatv("QPassSignals:{0:$[;]@(x-2)}", range).str();
StringExtractorGDBRemote response;
- auto send_status = SendPacketAndWaitForResponse(packet, response, false);
+ auto send_status = SendPacketAndWaitForResponse(packet, response);
if (send_status != GDBRemoteCommunication::PacketResult::Success)
return Status("Sending QPassSignals packet failed");
@@ -4134,10 +4119,8 @@
stream.Flush();
// Send the packet.
- const bool send_async = false;
StringExtractorGDBRemote response;
- auto result =
- SendPacketAndWaitForResponse(stream.GetString(), response, send_async);
+ auto result = SendPacketAndWaitForResponse(stream.GetString(), response);
if (result == PacketResult::Success) {
// We failed if the config result comes back other than OK.
if (strcmp(response.GetStringRef().data(), "OK") == 0) {
diff --git a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index af3755f..1e1797c 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -22,7 +22,7 @@
#include "lldb/Utility/GDBRemote.h"
#include "lldb/Utility/ProcessInfo.h"
#include "lldb/Utility/StructuredData.h"
-#include "lldb/Utility/TraceOptions.h"
+#include "lldb/Utility/TraceGDBRemotePackets.h"
#if defined(_WIN32)
#include "lldb/Host/windows/PosixApi.h"
#endif
@@ -49,6 +49,12 @@
}
llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const QOffsets &offsets);
+// A trivial struct used to return a pair of PID and TID.
+struct PidTid {
+ uint64_t pid;
+ uint64_t tid;
+};
+
class GDBRemoteCommunicationClient : public GDBRemoteClientBase {
public:
GDBRemoteCommunicationClient();
@@ -275,6 +281,8 @@
ArchSpec GetSystemArchitecture();
+ uint32_t GetAddressingBits();
+
bool GetHostname(std::string &s);
lldb::addr_t GetShlibInfoAddr();
@@ -319,7 +327,8 @@
GDBStoppointType type, // Type of breakpoint or watchpoint
bool insert, // Insert or remove?
lldb::addr_t addr, // Address of breakpoint or watchpoint
- uint32_t length); // Byte Size of breakpoint or watchpoint
+ uint32_t length, // Byte Size of breakpoint or watchpoint
+ std::chrono::seconds interrupt_timeout); // Time to wait for an interrupt
bool SetNonStopMode(const bool enable);
@@ -334,9 +343,14 @@
// and response times.
bool SendSpeedTestPacket(uint32_t send_size, uint32_t recv_size);
- bool SetCurrentThread(uint64_t tid);
+ llvm::Optional<PidTid>
+ SendSetCurrentThreadPacket(uint64_t tid, uint64_t pid, char op);
- bool SetCurrentThreadForRun(uint64_t tid);
+ bool SetCurrentThread(uint64_t tid,
+ lldb::pid_t pid = LLDB_INVALID_PROCESS_ID);
+
+ bool SetCurrentThreadForRun(uint64_t tid,
+ lldb::pid_t pid = LLDB_INVALID_PROCESS_ID);
bool GetQXferAuxvReadSupported();
@@ -366,6 +380,9 @@
return m_supports_alloc_dealloc_memory;
}
+ std::vector<std::pair<lldb::pid_t, lldb::tid_t>>
+ GetCurrentProcessAndThreadIDs(bool &sequence_mutex_unavailable);
+
size_t GetCurrentThreadIDs(std::vector<lldb::tid_t> &thread_ids,
bool &sequence_mutex_unavailable);
@@ -446,6 +463,14 @@
bool GetSharedCacheInfoSupported();
+ bool GetMemoryTaggingSupported();
+
+ lldb::DataBufferSP ReadMemoryTags(lldb::addr_t addr, size_t len,
+ int32_t type);
+
+ Status WriteMemoryTags(lldb::addr_t addr, size_t len, int32_t type,
+ const std::vector<uint8_t> &tags);
+
/// Use qOffsets to query the offset used when relocating the target
/// executable. If successful, the returned structure will contain at least
/// one value in the offsets field.
@@ -505,59 +530,61 @@
ConfigureRemoteStructuredData(ConstString type_name,
const StructuredData::ObjectSP &config_sp);
- lldb::user_id_t SendStartTracePacket(const TraceOptions &options,
- Status &error);
+ llvm::Expected<TraceSupportedResponse>
+ SendTraceSupported(std::chrono::seconds interrupt_timeout);
- Status SendStopTracePacket(lldb::user_id_t uid, lldb::tid_t thread_id);
+ llvm::Error SendTraceStart(const llvm::json::Value &request,
+ std::chrono::seconds interrupt_timeout);
- Status SendGetDataPacket(lldb::user_id_t uid, lldb::tid_t thread_id,
- llvm::MutableArrayRef<uint8_t> &buffer,
- size_t offset = 0);
+ llvm::Error SendTraceStop(const TraceStopRequest &request,
+ std::chrono::seconds interrupt_timeout);
- Status SendGetMetaDataPacket(lldb::user_id_t uid, lldb::tid_t thread_id,
- llvm::MutableArrayRef<uint8_t> &buffer,
- size_t offset = 0);
+ llvm::Expected<std::string>
+ SendTraceGetState(llvm::StringRef type,
+ std::chrono::seconds interrupt_timeout);
- Status SendGetTraceConfigPacket(lldb::user_id_t uid, TraceOptions &options);
-
- llvm::Expected<TraceTypeInfo> SendGetSupportedTraceType();
+ llvm::Expected<std::vector<uint8_t>>
+ SendTraceGetBinaryData(const TraceGetBinaryDataRequest &request,
+ std::chrono::seconds interrupt_timeout);
protected:
- LazyBool m_supports_not_sending_acks;
- LazyBool m_supports_thread_suffix;
- LazyBool m_supports_threads_in_stop_reply;
- LazyBool m_supports_vCont_all;
- LazyBool m_supports_vCont_any;
- LazyBool m_supports_vCont_c;
- LazyBool m_supports_vCont_C;
- LazyBool m_supports_vCont_s;
- LazyBool m_supports_vCont_S;
- LazyBool m_qHostInfo_is_valid;
- LazyBool m_curr_pid_is_valid;
- LazyBool m_qProcessInfo_is_valid;
- LazyBool m_qGDBServerVersion_is_valid;
- LazyBool m_supports_alloc_dealloc_memory;
- LazyBool m_supports_memory_region_info;
- LazyBool m_supports_watchpoint_support_info;
- LazyBool m_supports_detach_stay_stopped;
- LazyBool m_watchpoints_trigger_after_instruction;
- LazyBool m_attach_or_wait_reply;
- LazyBool m_prepare_for_reg_writing_reply;
- LazyBool m_supports_p;
- LazyBool m_supports_x;
- LazyBool m_avoid_g_packets;
- LazyBool m_supports_QSaveRegisterState;
- LazyBool m_supports_qXfer_auxv_read;
- LazyBool m_supports_qXfer_libraries_read;
- LazyBool m_supports_qXfer_libraries_svr4_read;
- LazyBool m_supports_qXfer_features_read;
- LazyBool m_supports_qXfer_memory_map_read;
- LazyBool m_supports_augmented_libraries_svr4_read;
- LazyBool m_supports_jThreadExtendedInfo;
- LazyBool m_supports_jLoadedDynamicLibrariesInfos;
- LazyBool m_supports_jGetSharedCacheInfo;
- LazyBool m_supports_QPassSignals;
- LazyBool m_supports_error_string_reply;
+ LazyBool m_supports_not_sending_acks = eLazyBoolCalculate;
+ LazyBool m_supports_thread_suffix = eLazyBoolCalculate;
+ LazyBool m_supports_threads_in_stop_reply = eLazyBoolCalculate;
+ LazyBool m_supports_vCont_all = eLazyBoolCalculate;
+ LazyBool m_supports_vCont_any = eLazyBoolCalculate;
+ LazyBool m_supports_vCont_c = eLazyBoolCalculate;
+ LazyBool m_supports_vCont_C = eLazyBoolCalculate;
+ LazyBool m_supports_vCont_s = eLazyBoolCalculate;
+ LazyBool m_supports_vCont_S = eLazyBoolCalculate;
+ LazyBool m_qHostInfo_is_valid = eLazyBoolCalculate;
+ LazyBool m_curr_pid_is_valid = eLazyBoolCalculate;
+ LazyBool m_qProcessInfo_is_valid = eLazyBoolCalculate;
+ LazyBool m_qGDBServerVersion_is_valid = eLazyBoolCalculate;
+ LazyBool m_supports_alloc_dealloc_memory = eLazyBoolCalculate;
+ LazyBool m_supports_memory_region_info = eLazyBoolCalculate;
+ LazyBool m_supports_watchpoint_support_info = eLazyBoolCalculate;
+ LazyBool m_supports_detach_stay_stopped = eLazyBoolCalculate;
+ LazyBool m_watchpoints_trigger_after_instruction = eLazyBoolCalculate;
+ LazyBool m_attach_or_wait_reply = eLazyBoolCalculate;
+ LazyBool m_prepare_for_reg_writing_reply = eLazyBoolCalculate;
+ LazyBool m_supports_p = eLazyBoolCalculate;
+ LazyBool m_supports_x = eLazyBoolCalculate;
+ LazyBool m_avoid_g_packets = eLazyBoolCalculate;
+ LazyBool m_supports_QSaveRegisterState = eLazyBoolCalculate;
+ LazyBool m_supports_qXfer_auxv_read = eLazyBoolCalculate;
+ LazyBool m_supports_qXfer_libraries_read = eLazyBoolCalculate;
+ LazyBool m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate;
+ LazyBool m_supports_qXfer_features_read = eLazyBoolCalculate;
+ LazyBool m_supports_qXfer_memory_map_read = eLazyBoolCalculate;
+ LazyBool m_supports_augmented_libraries_svr4_read = eLazyBoolCalculate;
+ LazyBool m_supports_jThreadExtendedInfo = eLazyBoolCalculate;
+ LazyBool m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolCalculate;
+ LazyBool m_supports_jGetSharedCacheInfo = eLazyBoolCalculate;
+ LazyBool m_supports_QPassSignals = eLazyBoolCalculate;
+ LazyBool m_supports_error_string_reply = eLazyBoolCalculate;
+ LazyBool m_supports_multiprocess = eLazyBoolCalculate;
+ LazyBool m_supports_memory_tagging = eLazyBoolCalculate;
bool m_supports_qProcessInfoPID : 1, m_supports_qfProcessInfo : 1,
m_supports_qUserName : 1, m_supports_qGroupName : 1,
@@ -568,13 +595,17 @@
m_supports_qModuleInfo : 1, m_supports_jThreadsInfo : 1,
m_supports_jModulesInfo : 1;
- lldb::pid_t m_curr_pid;
- lldb::tid_t m_curr_tid; // Current gdb remote protocol thread index for all
- // other operations
- lldb::tid_t m_curr_tid_run; // Current gdb remote protocol thread index for
- // continue, step, etc
+ /// Current gdb remote protocol process identifier for all other operations
+ lldb::pid_t m_curr_pid = LLDB_INVALID_PROCESS_ID;
+ /// Current gdb remote protocol process identifier for continue, step, etc
+ lldb::pid_t m_curr_pid_run = LLDB_INVALID_PROCESS_ID;
+ /// Current gdb remote protocol thread identifier for all other operations
+ lldb::tid_t m_curr_tid = LLDB_INVALID_THREAD_ID;
+ /// Current gdb remote protocol thread identifier for continue, step, etc
+ lldb::tid_t m_curr_tid_run = LLDB_INVALID_THREAD_ID;
- uint32_t m_num_supported_hardware_watchpoints;
+ uint32_t m_num_supported_hardware_watchpoints = 0;
+ uint32_t m_addressing_bits = 0;
ArchSpec m_host_arch;
ArchSpec m_process_arch;
@@ -585,17 +616,19 @@
std::string m_hostname;
std::string m_gdb_server_name; // from reply to qGDBServerVersion, empty if
// qGDBServerVersion is not supported
- uint32_t m_gdb_server_version; // from reply to qGDBServerVersion, zero if
- // qGDBServerVersion is not supported
+ uint32_t m_gdb_server_version =
+ UINT32_MAX; // from reply to qGDBServerVersion, zero if
+ // qGDBServerVersion is not supported
std::chrono::seconds m_default_packet_timeout;
- uint64_t m_max_packet_size; // as returned by qSupported
+ int m_target_vm_page_size = 0; // target system VM page size; 0 unspecified
+ uint64_t m_max_packet_size = 0; // as returned by qSupported
std::string m_qSupported_response; // the complete response to qSupported
- bool m_supported_async_json_packets_is_valid;
+ bool m_supported_async_json_packets_is_valid = false;
lldb_private::StructuredData::ObjectSP m_supported_async_json_packets_sp;
std::vector<MemoryRegionInfo> m_qXfer_memory_map;
- bool m_qXfer_memory_map_loaded;
+ bool m_qXfer_memory_map_loaded = false;
bool GetCurrentProcessInfo(bool allow_lazy_pid = true);
@@ -603,7 +636,8 @@
// Given the list of compression types that the remote debug stub can support,
// possibly enable compression if we find an encoding we can handle.
- void MaybeEnableCompression(std::vector<std::string> supported_compressions);
+ void MaybeEnableCompression(
+ llvm::ArrayRef<llvm::StringRef> supported_compressions);
bool DecodeProcessInfoResponse(StringExtractorGDBRemote &response,
ProcessInstanceInfo &process_info);
@@ -612,7 +646,7 @@
PacketResult SendThreadSpecificPacketAndWaitForResponse(
lldb::tid_t tid, StreamString &&payload,
- StringExtractorGDBRemote &response, bool send_async);
+ StringExtractorGDBRemote &response);
Status SendGetTraceDataPacket(StreamGDBRemote &packet, lldb::user_id_t uid,
lldb::tid_t thread_id,
diff --git a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp
index 3984a45..d92c97e 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp
@@ -19,13 +19,12 @@
using namespace lldb_private::process_gdb_remote;
GDBRemoteCommunicationHistory::GDBRemoteCommunicationHistory(uint32_t size)
- : m_packets(), m_curr_idx(0), m_total_packet_count(0),
- m_dumped_to_log(false) {
+ : m_packets() {
if (size)
m_packets.resize(size);
}
-GDBRemoteCommunicationHistory::~GDBRemoteCommunicationHistory() {}
+GDBRemoteCommunicationHistory::~GDBRemoteCommunicationHistory() = default;
void GDBRemoteCommunicationHistory::AddPacket(char packet_char,
GDBRemotePacket::Type type,
diff --git a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h
index e783e59..eda464a 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h
@@ -74,9 +74,9 @@
}
std::vector<GDBRemotePacket> m_packets;
- uint32_t m_curr_idx;
- uint32_t m_total_packet_count;
- mutable bool m_dumped_to_log;
+ uint32_t m_curr_idx = 0;
+ uint32_t m_total_packet_count = 0;
+ mutable bool m_dumped_to_log = false;
repro::PacketRecorder *m_recorder = nullptr;
};
diff --git a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp
index 920327e..c91d7cb 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include <errno.h>
+#include <cerrno>
#include "lldb/Host/Config.h"
#include "llvm/ADT/ScopeExit.h"
@@ -74,7 +74,7 @@
m_async_broadcaster(nullptr, "lldb.gdb-replay.async-broadcaster"),
m_async_listener_sp(
Listener::MakeListener("lldb.gdb-replay.async-listener")),
- m_async_thread_state_mutex(), m_skip_acks(false) {
+ m_async_thread_state_mutex() {
m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue,
"async thread continue");
m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit,
diff --git a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h
index c13e5ee..2f8770d 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h
@@ -73,7 +73,7 @@
HostThread m_async_thread;
std::recursive_mutex m_async_thread_state_mutex;
- bool m_skip_acks;
+ bool m_skip_acks = false;
private:
GDBRemoteCommunicationReplayServer(
diff --git a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
index 60548ef..11cac9f 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include <errno.h>
+#include <cerrno>
#include "lldb/Host/Config.h"
@@ -16,11 +16,13 @@
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/StringExtractorGDBRemote.h"
#include "lldb/Utility/UnimplementedError.h"
+#include "llvm/Support/JSON.h"
#include <cstring>
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_gdb_remote;
+using namespace llvm;
GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(
const char *comm_name, const char *listener_name)
@@ -31,7 +33,7 @@
bool &quit) { return this->Handle_QErrorStringEnable(packet); });
}
-GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer() {}
+GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer() = default;
void GDBRemoteCommunicationServer::RegisterPacketHandler(
StringExtractorGDBRemote::ServerPacketType packet_type,
@@ -151,3 +153,21 @@
bool GDBRemoteCommunicationServer::HandshakeWithClient() {
return GetAck() == PacketResult::Success;
}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServer::SendJSONResponse(const json::Value &value) {
+ std::string json_string;
+ raw_string_ostream os(json_string);
+ os << value;
+ os.flush();
+ StreamGDBRemote escaped_response;
+ escaped_response.PutEscapedBytes(json_string.c_str(), json_string.size());
+ return SendPacketNoLock(escaped_response.GetString());
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServer::SendJSONResponse(Expected<json::Value> value) {
+ if (!value)
+ return SendErrorResponse(value.takeError());
+ return SendJSONResponse(*value);
+}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
index a1cf70f..68448ea 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
@@ -72,6 +72,13 @@
PacketResult SendOKResponse();
+ /// Serialize and send a JSON object response.
+ PacketResult SendJSONResponse(const llvm::json::Value &value);
+
+ /// Serialize and send a JSON object response, or respond with an error if the
+ /// input object is an \a llvm::Error.
+ PacketResult SendJSONResponse(llvm::Expected<llvm::json::Value> value);
+
private:
GDBRemoteCommunicationServer(const GDBRemoteCommunicationServer &) = delete;
const GDBRemoteCommunicationServer &
diff --git a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
index 1ca0290..b2b8025 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
@@ -8,7 +8,7 @@
#include "GDBRemoteCommunicationServerCommon.h"
-#include <errno.h>
+#include <cerrno>
#ifdef __APPLE__
#include <TargetConditionals.h>
@@ -60,8 +60,7 @@
const char *comm_name, const char *listener_name)
: GDBRemoteCommunicationServer(comm_name, listener_name),
m_process_launch_info(), m_process_launch_error(), m_proc_infos(),
- m_proc_infos_index(0), m_thread_suffix_supported(false),
- m_list_threads_in_stop_reply(false) {
+ m_proc_infos_index(0) {
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_A,
&GDBRemoteCommunicationServerCommon::Handle_A);
RegisterMemberFunctionHandler(
@@ -86,9 +85,6 @@
StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess,
&GDBRemoteCommunicationServerCommon::Handle_qLaunchSuccess);
RegisterMemberFunctionHandler(
- StringExtractorGDBRemote::eServerPacketType_QListThreadsInStopReply,
- &GDBRemoteCommunicationServerCommon::Handle_QListThreadsInStopReply);
- RegisterMemberFunctionHandler(
StringExtractorGDBRemote::eServerPacketType_qEcho,
&GDBRemoteCommunicationServerCommon::Handle_qEcho);
RegisterMemberFunctionHandler(
@@ -134,9 +130,6 @@
StringExtractorGDBRemote::eServerPacketType_qSupported,
&GDBRemoteCommunicationServerCommon::Handle_qSupported);
RegisterMemberFunctionHandler(
- StringExtractorGDBRemote::eServerPacketType_QThreadSuffixSupported,
- &GDBRemoteCommunicationServerCommon::Handle_QThreadSuffixSupported);
- RegisterMemberFunctionHandler(
StringExtractorGDBRemote::eServerPacketType_qUserName,
&GDBRemoteCommunicationServerCommon::Handle_qUserName);
RegisterMemberFunctionHandler(
@@ -175,7 +168,8 @@
}
// Destructor
-GDBRemoteCommunicationServerCommon::~GDBRemoteCommunicationServerCommon() {}
+GDBRemoteCommunicationServerCommon::~GDBRemoteCommunicationServerCommon() =
+ default;
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerCommon::Handle_qHostInfo(
@@ -831,39 +825,10 @@
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerCommon::Handle_qSupported(
StringExtractorGDBRemote &packet) {
- StreamGDBRemote response;
-
- // Features common to lldb-platform and llgs.
- uint32_t max_packet_size = 128 * 1024; // 128KBytes is a reasonable max packet
- // size--debugger can always use less
- response.Printf("PacketSize=%x", max_packet_size);
-
- response.PutCString(";QStartNoAckMode+");
- response.PutCString(";QThreadSuffixSupported+");
- response.PutCString(";QListThreadsInStopReply+");
- response.PutCString(";qEcho+");
- response.PutCString(";qXfer:features:read+");
-#if defined(__linux__) || defined(__NetBSD__) || defined(__FreeBSD__)
- response.PutCString(";QPassSignals+");
- response.PutCString(";qXfer:auxv:read+");
- response.PutCString(";qXfer:libraries-svr4:read+");
-#endif
-
- return SendPacketNoLock(response.GetString());
-}
-
-GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_QThreadSuffixSupported(
- StringExtractorGDBRemote &packet) {
- m_thread_suffix_supported = true;
- return SendOKResponse();
-}
-
-GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_QListThreadsInStopReply(
- StringExtractorGDBRemote &packet) {
- m_list_threads_in_stop_reply = true;
- return SendOKResponse();
+ // Parse client-indicated features.
+ llvm::SmallVector<llvm::StringRef, 4> client_features;
+ packet.GetStringRef().split(client_features, ';');
+ return SendPacketNoLock(llvm::join(HandleFeatures(client_features), ";"));
}
GDBRemoteCommunication::PacketResult
@@ -1311,3 +1276,16 @@
return matched_module_spec;
}
+
+std::vector<std::string> GDBRemoteCommunicationServerCommon::HandleFeatures(
+ const llvm::ArrayRef<llvm::StringRef> client_features) {
+ // 128KBytes is a reasonable max packet size--debugger can always use less.
+ constexpr uint32_t max_packet_size = 128 * 1024;
+
+ // Features common to platform server and llgs.
+ return {
+ llvm::formatv("PacketSize={0}", max_packet_size),
+ "QStartNoAckMode+",
+ "qEcho+",
+ };
+}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h
index 0f933c0..ecd8092 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h
@@ -36,8 +36,6 @@
Status m_process_launch_error;
ProcessInstanceInfoList m_proc_infos;
uint32_t m_proc_infos_index;
- bool m_thread_suffix_supported;
- bool m_list_threads_in_stop_reply;
PacketResult Handle_A(StringExtractorGDBRemote &packet);
@@ -91,10 +89,6 @@
PacketResult Handle_qSupported(StringExtractorGDBRemote &packet);
- PacketResult Handle_QThreadSuffixSupported(StringExtractorGDBRemote &packet);
-
- PacketResult Handle_QListThreadsInStopReply(StringExtractorGDBRemote &packet);
-
PacketResult Handle_QSetDetachOnError(StringExtractorGDBRemote &packet);
PacketResult Handle_QStartNoAckMode(StringExtractorGDBRemote &packet);
@@ -145,6 +139,11 @@
virtual FileSpec FindModuleFile(const std::string &module_path,
const ArchSpec &arch);
+ // Process client_features (qSupported) and return an array of server features
+ // to be returned in response.
+ virtual std::vector<std::string>
+ HandleFeatures(llvm::ArrayRef<llvm::StringRef> client_features);
+
private:
ModuleSpec GetModuleInfo(llvm::StringRef module_path, llvm::StringRef triple);
};
diff --git a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index 62a09a2..8e1f6bc 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -6,13 +6,14 @@
//
//===----------------------------------------------------------------------===//
-#include <errno.h>
+#include <cerrno>
#include "lldb/Host/Config.h"
#include <chrono>
#include <cstring>
+#include <limits>
#include <thread>
#include "GDBRemoteCommunicationServerLLGS.h"
@@ -70,6 +71,7 @@
: GDBRemoteCommunicationServerCommon("gdb-remote.server",
"gdb-remote.server.rx_packet"),
m_mainloop(mainloop), m_process_factory(process_factory),
+ m_current_process(nullptr), m_continue_process(nullptr),
m_stdio_communication("process.stdio") {
RegisterPacketHandlers();
}
@@ -113,6 +115,12 @@
StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir,
&GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir);
RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_QThreadSuffixSupported,
+ &GDBRemoteCommunicationServerLLGS::Handle_QThreadSuffixSupported);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_QListThreadsInStopReply,
+ &GDBRemoteCommunicationServerLLGS::Handle_QListThreadsInStopReply);
+ RegisterMemberFunctionHandler(
StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfo,
&GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo);
RegisterMemberFunctionHandler(
@@ -186,27 +194,32 @@
&GDBRemoteCommunicationServerLLGS::Handle_QPassSignals);
RegisterMemberFunctionHandler(
- StringExtractorGDBRemote::eServerPacketType_jTraceStart,
- &GDBRemoteCommunicationServerLLGS::Handle_jTraceStart);
+ StringExtractorGDBRemote::eServerPacketType_jLLDBTraceSupported,
+ &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceSupported);
RegisterMemberFunctionHandler(
- StringExtractorGDBRemote::eServerPacketType_jTraceBufferRead,
- &GDBRemoteCommunicationServerLLGS::Handle_jTraceRead);
+ StringExtractorGDBRemote::eServerPacketType_jLLDBTraceStart,
+ &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceStart);
RegisterMemberFunctionHandler(
- StringExtractorGDBRemote::eServerPacketType_jTraceMetaRead,
- &GDBRemoteCommunicationServerLLGS::Handle_jTraceRead);
+ StringExtractorGDBRemote::eServerPacketType_jLLDBTraceStop,
+ &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceStop);
RegisterMemberFunctionHandler(
- StringExtractorGDBRemote::eServerPacketType_jTraceStop,
- &GDBRemoteCommunicationServerLLGS::Handle_jTraceStop);
+ StringExtractorGDBRemote::eServerPacketType_jLLDBTraceGetState,
+ &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetState);
RegisterMemberFunctionHandler(
- StringExtractorGDBRemote::eServerPacketType_jTraceConfigRead,
- &GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead);
- RegisterMemberFunctionHandler(
- StringExtractorGDBRemote::eServerPacketType_jLLDBTraceSupportedType,
- &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceSupportedType);
+ StringExtractorGDBRemote::eServerPacketType_jLLDBTraceGetBinaryData,
+ &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetBinaryData);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_g,
&GDBRemoteCommunicationServerLLGS::Handle_g);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qMemTags,
+ &GDBRemoteCommunicationServerLLGS::Handle_qMemTags);
+
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_QMemTags,
+ &GDBRemoteCommunicationServerLLGS::Handle_QMemTags);
+
RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_k,
[this](StringExtractorGDBRemote packet, Status &error,
bool &interrupt, bool &quit) {
@@ -245,15 +258,18 @@
{
std::lock_guard<std::recursive_mutex> guard(m_debugged_process_mutex);
- assert(!m_debugged_process_up && "lldb-server creating debugged "
- "process but one already exists");
+ assert(m_debugged_processes.empty() && "lldb-server creating debugged "
+ "process but one already exists");
auto process_or =
m_process_factory.Launch(m_process_launch_info, *this, m_mainloop);
if (!process_or)
return Status(process_or.takeError());
- m_debugged_process_up = std::move(*process_or);
+ m_continue_process = m_current_process = process_or->get();
+ m_debugged_processes[m_current_process->GetID()] = std::move(*process_or);
}
+ SetEnabledExtensions(*m_current_process);
+
// Handle mirroring of inferior stdout/stderr over the gdb-remote protocol as
// needed. llgs local-process debugging may specify PTY paths, which will
// make these file actions non-null process launch -i/e/o will also make
@@ -266,10 +282,10 @@
LLDB_LOG(log,
"pid = {0}: setting up stdout/stderr redirection via $O "
"gdb-remote commands",
- m_debugged_process_up->GetID());
+ m_current_process->GetID());
// Setup stdout/stderr mapping from inferior to $O
- auto terminal_fd = m_debugged_process_up->GetTerminalFileDescriptor();
+ auto terminal_fd = m_current_process->GetTerminalFileDescriptor();
if (terminal_fd >= 0) {
LLDB_LOGF(log,
"ProcessGDBRemoteCommunicationServerLLGS::%s setting "
@@ -288,12 +304,12 @@
LLDB_LOG(log,
"pid = {0} skipping stdout/stderr redirection via $O: inferior "
"will communicate over client-provided file descriptors",
- m_debugged_process_up->GetID());
+ m_current_process->GetID());
}
printf("Launched '%s' as process %" PRIu64 "...\n",
m_process_launch_info.GetArguments().GetArgumentAtIndex(0),
- m_debugged_process_up->GetID());
+ m_current_process->GetID());
return Status();
}
@@ -305,12 +321,11 @@
// Before we try to attach, make sure we aren't already monitoring something
// else.
- if (m_debugged_process_up &&
- m_debugged_process_up->GetID() != LLDB_INVALID_PROCESS_ID)
+ if (!m_debugged_processes.empty())
return Status("cannot attach to process %" PRIu64
" when another process with pid %" PRIu64
" is being debugged.",
- pid, m_debugged_process_up->GetID());
+ pid, m_current_process->GetID());
// Try to attach.
auto process_or = m_process_factory.Attach(pid, *this, m_mainloop);
@@ -320,10 +335,12 @@
status);
return status;
}
- m_debugged_process_up = std::move(*process_or);
+ m_continue_process = m_current_process = process_or->get();
+ m_debugged_processes[m_current_process->GetID()] = std::move(*process_or);
+ SetEnabledExtensions(*m_current_process);
// Setup stdout/stderr mapping from inferior.
- auto terminal_fd = m_debugged_process_up->GetTerminalFileDescriptor();
+ auto terminal_fd = m_current_process->GetTerminalFileDescriptor();
if (terminal_fd >= 0) {
LLDB_LOGF(log,
"ProcessGDBRemoteCommunicationServerLLGS::%s setting "
@@ -648,6 +665,14 @@
return "exception";
case eStopReasonExec:
return "exec";
+ case eStopReasonProcessorTrace:
+ return "processor trace";
+ case eStopReasonFork:
+ return "fork";
+ case eStopReasonVFork:
+ return "vfork";
+ case eStopReasonVForkDone:
+ return "vforkdone";
case eStopReasonInstrumentation:
case eStopReasonInvalid:
case eStopReasonPlanComplete:
@@ -736,15 +761,15 @@
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
// Ensure we have a debugged process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
return SendErrorResponse(50);
LLDB_LOG(log, "preparing packet for pid {0} tid {1}",
- m_debugged_process_up->GetID(), tid);
+ m_current_process->GetID(), tid);
// Ensure we can get info on the given thread.
- NativeThreadProtocol *thread = m_debugged_process_up->GetThreadByID(tid);
+ NativeThreadProtocol *thread = m_current_process->GetThreadByID(tid);
if (!thread)
return SendErrorResponse(51);
@@ -767,7 +792,7 @@
LLDB_LOG(
log,
"pid {0}, tid {1}, got signal signo = {2}, reason = {3}, exc_type = {4}",
- m_debugged_process_up->GetID(), tid, signum, int(tid_stop_info.reason),
+ m_current_process->GetID(), tid, signum, int(tid_stop_info.reason),
tid_stop_info.details.exception.type);
// Print the signal number.
@@ -805,9 +830,9 @@
uint32_t thread_index = 0;
NativeThreadProtocol *listed_thread;
- for (listed_thread = m_debugged_process_up->GetThreadAtIndex(thread_index);
+ for (listed_thread = m_current_process->GetThreadAtIndex(thread_index);
listed_thread; ++thread_index,
- listed_thread = m_debugged_process_up->GetThreadAtIndex(thread_index)) {
+ listed_thread = m_current_process->GetThreadAtIndex(thread_index)) {
if (thread_index > 0)
response.PutChar(',');
response.Printf("%" PRIx64, listed_thread->GetID());
@@ -822,7 +847,7 @@
if (thread_index > 1) {
const bool threads_with_valid_stop_info_only = true;
llvm::Expected<json::Array> threads_info = GetJSONThreadsInfo(
- *m_debugged_process_up, threads_with_valid_stop_info_only);
+ *m_current_process, threads_with_valid_stop_info_only);
if (threads_info) {
response.PutCString("jstopinfo:");
StreamString unescaped_response;
@@ -832,7 +857,7 @@
} else {
LLDB_LOG_ERROR(log, threads_info.takeError(),
"failed to prepare a jstopinfo field for pid {1}: {0}",
- m_debugged_process_up->GetID());
+ m_current_process->GetID());
}
}
@@ -840,8 +865,7 @@
response.PutCString("thread-pcs");
char delimiter = ':';
for (NativeThreadProtocol *thread;
- (thread = m_debugged_process_up->GetThreadAtIndex(i)) != nullptr;
- ++i) {
+ (thread = m_current_process->GetThreadAtIndex(i)) != nullptr; ++i) {
NativeRegisterContext& reg_ctx = thread->GetRegisterContext();
uint32_t reg_to_read = reg_ctx.ConvertRegisterKindToRegisterNumber(
@@ -924,6 +948,22 @@
}
}
+ // Include child process PID/TID for forks.
+ if (tid_stop_info.reason == eStopReasonFork ||
+ tid_stop_info.reason == eStopReasonVFork) {
+ assert(bool(m_extensions_supported &
+ NativeProcessProtocol::Extension::multiprocess));
+ if (tid_stop_info.reason == eStopReasonFork)
+ assert(bool(m_extensions_supported &
+ NativeProcessProtocol::Extension::fork));
+ if (tid_stop_info.reason == eStopReasonVFork)
+ assert(bool(m_extensions_supported &
+ NativeProcessProtocol::Extension::vfork));
+ response.Printf("%s:p%" PRIx64 ".%" PRIx64 ";", reason_str,
+ tid_stop_info.details.fork.child_pid,
+ tid_stop_info.details.fork.child_tid);
+ }
+
return SendPacketNoLock(response.GetString());
}
@@ -1028,6 +1068,15 @@
ClearProcessSpecificData();
}
+void GDBRemoteCommunicationServerLLGS::NewSubprocess(
+ NativeProcessProtocol *parent_process,
+ std::unique_ptr<NativeProcessProtocol> child_process) {
+ lldb::pid_t child_pid = child_process->GetID();
+ assert(child_pid != LLDB_INVALID_PROCESS_ID);
+ assert(m_debugged_processes.find(child_pid) == m_debugged_processes.end());
+ m_debugged_processes[child_pid] = std::move(child_process);
+}
+
void GDBRemoteCommunicationServerLLGS::DataAvailableCallback() {
Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_COMM));
@@ -1170,266 +1219,110 @@
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_jTraceStart(
+GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceSupported(
StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
- return SendErrorResponse(68);
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse(Status("Process not running."));
- if (!packet.ConsumeFront("jTraceStart:"))
- return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet ");
-
- TraceOptions options;
- uint64_t type = std::numeric_limits<uint64_t>::max();
- uint64_t buffersize = std::numeric_limits<uint64_t>::max();
- lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
- uint64_t metabuffersize = std::numeric_limits<uint64_t>::max();
-
- auto json_object = StructuredData::ParseJSON(packet.Peek());
-
- if (!json_object ||
- json_object->GetType() != lldb::eStructuredDataTypeDictionary)
- return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet ");
-
- auto json_dict = json_object->GetAsDictionary();
-
- json_dict->GetValueForKeyAsInteger("metabuffersize", metabuffersize);
- options.setMetaDataBufferSize(metabuffersize);
-
- json_dict->GetValueForKeyAsInteger("buffersize", buffersize);
- options.setTraceBufferSize(buffersize);
-
- json_dict->GetValueForKeyAsInteger("type", type);
- options.setType(static_cast<lldb::TraceType>(type));
-
- json_dict->GetValueForKeyAsInteger("threadid", tid);
- options.setThreadID(tid);
-
- StructuredData::ObjectSP custom_params_sp =
- json_dict->GetValueForKey("params");
- if (custom_params_sp &&
- custom_params_sp->GetType() != lldb::eStructuredDataTypeDictionary)
- return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet ");
-
- options.setTraceParams(
- std::static_pointer_cast<StructuredData::Dictionary>(custom_params_sp));
-
- if (buffersize == std::numeric_limits<uint64_t>::max() ||
- type != lldb::TraceType::eTraceTypeProcessorTrace) {
- LLDB_LOG(log, "Ill formed packet buffersize = {0} type = {1}", buffersize,
- type);
- return SendIllFormedResponse(packet, "JTrace:start: Ill formed packet ");
- }
-
- Status error;
- lldb::user_id_t uid = LLDB_INVALID_UID;
- uid = m_debugged_process_up->StartTrace(options, error);
- LLDB_LOG(log, "uid is {0} , error is {1}", uid, error.GetError());
- if (error.Fail())
- return SendErrorResponse(error);
-
- StreamGDBRemote response;
- response.Printf("%" PRIx64, uid);
- return SendPacketNoLock(response.GetString());
+ return SendJSONResponse(m_current_process->TraceSupported());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_jTraceStop(
+GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceStop(
StringExtractorGDBRemote &packet) {
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
- return SendErrorResponse(68);
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse(Status("Process not running."));
- if (!packet.ConsumeFront("jTraceStop:"))
- return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet ");
+ packet.ConsumeFront("jLLDBTraceStop:");
+ Expected<TraceStopRequest> stop_request =
+ json::parse<TraceStopRequest>(packet.Peek(), "TraceStopRequest");
+ if (!stop_request)
+ return SendErrorResponse(stop_request.takeError());
- lldb::user_id_t uid = LLDB_INVALID_UID;
- lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
-
- auto json_object = StructuredData::ParseJSON(packet.Peek());
-
- if (!json_object ||
- json_object->GetType() != lldb::eStructuredDataTypeDictionary)
- return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet ");
-
- auto json_dict = json_object->GetAsDictionary();
-
- if (!json_dict->GetValueForKeyAsInteger("traceid", uid))
- return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet ");
-
- json_dict->GetValueForKeyAsInteger("threadid", tid);
-
- Status error = m_debugged_process_up->StopTrace(uid, tid);
-
- if (error.Fail())
- return SendErrorResponse(error);
+ if (Error err = m_current_process->TraceStop(*stop_request))
+ return SendErrorResponse(std::move(err));
return SendOKResponse();
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceSupportedType(
+GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceStart(
StringExtractorGDBRemote &packet) {
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
return SendErrorResponse(Status("Process not running."));
- llvm::Expected<TraceTypeInfo> supported_trace_type =
- m_debugged_process_up->GetSupportedTraceType();
- if (!supported_trace_type)
- return SendErrorResponse(supported_trace_type.takeError());
+ packet.ConsumeFront("jLLDBTraceStart:");
+ Expected<TraceStartRequest> request =
+ json::parse<TraceStartRequest>(packet.Peek(), "TraceStartRequest");
+ if (!request)
+ return SendErrorResponse(request.takeError());
- StreamGDBRemote escaped_response;
- StructuredData::Dictionary json_packet;
+ if (Error err = m_current_process->TraceStart(packet.Peek(), request->type))
+ return SendErrorResponse(std::move(err));
- json_packet.AddStringItem("name", supported_trace_type->name);
- json_packet.AddStringItem("description", supported_trace_type->description);
-
- StreamString json_string;
- json_packet.Dump(json_string, false);
- escaped_response.PutEscapedBytes(json_string.GetData(),
- json_string.GetSize());
- return SendPacketNoLock(escaped_response.GetString());
+ return SendOKResponse();
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead(
+GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetState(
StringExtractorGDBRemote &packet) {
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
- return SendErrorResponse(68);
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse(Status("Process not running."));
- if (!packet.ConsumeFront("jTraceConfigRead:"))
- return SendIllFormedResponse(packet,
- "jTraceConfigRead: Ill formed packet ");
+ packet.ConsumeFront("jLLDBTraceGetState:");
+ Expected<TraceGetStateRequest> request =
+ json::parse<TraceGetStateRequest>(packet.Peek(), "TraceGetStateRequest");
+ if (!request)
+ return SendErrorResponse(request.takeError());
- lldb::user_id_t uid = LLDB_INVALID_UID;
- lldb::tid_t threadid = LLDB_INVALID_THREAD_ID;
-
- auto json_object = StructuredData::ParseJSON(packet.Peek());
-
- if (!json_object ||
- json_object->GetType() != lldb::eStructuredDataTypeDictionary)
- return SendIllFormedResponse(packet,
- "jTraceConfigRead: Ill formed packet ");
-
- auto json_dict = json_object->GetAsDictionary();
-
- if (!json_dict->GetValueForKeyAsInteger("traceid", uid))
- return SendIllFormedResponse(packet,
- "jTraceConfigRead: Ill formed packet ");
-
- json_dict->GetValueForKeyAsInteger("threadid", threadid);
-
- TraceOptions options;
- StreamGDBRemote response;
-
- options.setThreadID(threadid);
- Status error = m_debugged_process_up->GetTraceConfig(uid, options);
-
- if (error.Fail())
- return SendErrorResponse(error);
-
- StreamGDBRemote escaped_response;
- StructuredData::Dictionary json_packet;
-
- json_packet.AddIntegerItem("type", options.getType());
- json_packet.AddIntegerItem("buffersize", options.getTraceBufferSize());
- json_packet.AddIntegerItem("metabuffersize", options.getMetaDataBufferSize());
-
- StructuredData::DictionarySP custom_params = options.getTraceParams();
- if (custom_params)
- json_packet.AddItem("params", custom_params);
-
- StreamString json_string;
- json_packet.Dump(json_string, false);
- escaped_response.PutEscapedBytes(json_string.GetData(),
- json_string.GetSize());
- return SendPacketNoLock(escaped_response.GetString());
+ return SendJSONResponse(m_current_process->TraceGetState(request->type));
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_jTraceRead(
+GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetBinaryData(
StringExtractorGDBRemote &packet) {
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
- return SendErrorResponse(68);
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse(Status("Process not running."));
- enum PacketType { MetaData, BufferData };
- PacketType tracetype = MetaData;
+ packet.ConsumeFront("jLLDBTraceGetBinaryData:");
+ llvm::Expected<TraceGetBinaryDataRequest> request =
+ llvm::json::parse<TraceGetBinaryDataRequest>(packet.Peek(),
+ "TraceGetBinaryDataRequest");
+ if (!request)
+ return SendErrorResponse(Status(request.takeError()));
- if (packet.ConsumeFront("jTraceBufferRead:"))
- tracetype = BufferData;
- else if (packet.ConsumeFront("jTraceMetaRead:"))
- tracetype = MetaData;
- else {
- return SendIllFormedResponse(packet, "jTrace: Ill formed packet ");
- }
-
- lldb::user_id_t uid = LLDB_INVALID_UID;
-
- uint64_t byte_count = std::numeric_limits<uint64_t>::max();
- lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
- uint64_t offset = std::numeric_limits<uint64_t>::max();
-
- auto json_object = StructuredData::ParseJSON(packet.Peek());
-
- if (!json_object ||
- json_object->GetType() != lldb::eStructuredDataTypeDictionary)
- return SendIllFormedResponse(packet, "jTrace: Ill formed packet ");
-
- auto json_dict = json_object->GetAsDictionary();
-
- if (!json_dict->GetValueForKeyAsInteger("traceid", uid) ||
- !json_dict->GetValueForKeyAsInteger("offset", offset) ||
- !json_dict->GetValueForKeyAsInteger("buffersize", byte_count))
- return SendIllFormedResponse(packet, "jTrace: Ill formed packet ");
-
- json_dict->GetValueForKeyAsInteger("threadid", tid);
-
- // Allocate the response buffer.
- std::unique_ptr<uint8_t[]> buffer (new (std::nothrow) uint8_t[byte_count]);
- if (!buffer)
- return SendErrorResponse(0x78);
-
- StreamGDBRemote response;
- Status error;
- llvm::MutableArrayRef<uint8_t> buf(buffer.get(), byte_count);
-
- if (tracetype == BufferData)
- error = m_debugged_process_up->GetData(uid, tid, buf, offset);
- else if (tracetype == MetaData)
- error = m_debugged_process_up->GetMetaData(uid, tid, buf, offset);
-
- if (error.Fail())
- return SendErrorResponse(error);
-
- for (auto i : buf)
- response.PutHex8(i);
-
- StreamGDBRemote escaped_response;
- escaped_response.PutEscapedBytes(response.GetData(), response.GetSize());
- return SendPacketNoLock(escaped_response.GetString());
+ if (Expected<std::vector<uint8_t>> bytes =
+ m_current_process->TraceGetBinaryData(*request)) {
+ StreamGDBRemote response;
+ response.PutEscapedBytes(bytes->data(), bytes->size());
+ return SendPacketNoLock(response.GetString());
+ } else
+ return SendErrorResponse(bytes.takeError());
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo(
StringExtractorGDBRemote &packet) {
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
return SendErrorResponse(68);
- lldb::pid_t pid = m_debugged_process_up->GetID();
+ lldb::pid_t pid = m_current_process->GetID();
if (pid == LLDB_INVALID_PROCESS_ID)
return SendErrorResponse(1);
@@ -1446,16 +1339,16 @@
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qC(StringExtractorGDBRemote &packet) {
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
return SendErrorResponse(68);
// Make sure we set the current thread so g and p packets return the data the
// gdb will expect.
- lldb::tid_t tid = m_debugged_process_up->GetCurrentThreadID();
+ lldb::tid_t tid = m_current_process->GetCurrentThreadID();
SetCurrentThreadID(tid);
- NativeThreadProtocol *thread = m_debugged_process_up->GetCurrentThread();
+ NativeThreadProtocol *thread = m_current_process->GetCurrentThread();
if (!thread)
return SendErrorResponse(69);
@@ -1471,15 +1364,15 @@
StopSTDIOForwarding();
- if (!m_debugged_process_up) {
+ if (!m_current_process) {
LLDB_LOG(log, "No debugged process found.");
return PacketResult::Success;
}
- Status error = m_debugged_process_up->Kill();
+ Status error = m_current_process->Kill();
if (error.Fail())
LLDB_LOG(log, "Failed to kill debugged process {0}: {1}",
- m_debugged_process_up->GetID(), error);
+ m_current_process->GetID(), error);
// No OK response for kill packet.
// return SendOKResponse ();
@@ -1521,12 +1414,26 @@
}
GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_QThreadSuffixSupported(
+ StringExtractorGDBRemote &packet) {
+ m_thread_suffix_supported = true;
+ return SendOKResponse();
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_QListThreadsInStopReply(
+ StringExtractorGDBRemote &packet) {
+ m_list_threads_in_stop_reply = true;
+ return SendOKResponse();
+}
+
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
// Ensure we have a native process.
- if (!m_debugged_process_up) {
+ if (!m_continue_process) {
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s no debugged process "
"shared pointer",
@@ -1579,20 +1486,20 @@
} else {
// Send the signal to the process since we weren't targeting a specific
// continue thread with the signal.
- error = m_debugged_process_up->Signal(signo);
+ error = m_continue_process->Signal(signo);
if (error.Fail()) {
LLDB_LOG(log, "failed to send signal for process {0}: {1}",
- m_debugged_process_up->GetID(), error);
+ m_continue_process->GetID(), error);
return SendErrorResponse(0x52);
}
}
// Resume the threads.
- error = m_debugged_process_up->Resume(resume_actions);
+ error = m_continue_process->Resume(resume_actions);
if (error.Fail()) {
LLDB_LOG(log, "failed to resume threads for process {0}: {1}",
- m_debugged_process_up->GetID(), error);
+ m_continue_process->GetID(), error);
return SendErrorResponse(0x38);
}
@@ -1617,7 +1524,7 @@
}
// Ensure we have a native process.
- if (!m_debugged_process_up) {
+ if (!m_continue_process) {
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s no debugged process "
"shared pointer",
@@ -1629,14 +1536,14 @@
ResumeActionList actions(StateType::eStateRunning,
LLDB_INVALID_SIGNAL_NUMBER);
- Status error = m_debugged_process_up->Resume(actions);
+ Status error = m_continue_process->Resume(actions);
if (error.Fail()) {
- LLDB_LOG(log, "c failed for process {0}: {1}",
- m_debugged_process_up->GetID(), error);
+ LLDB_LOG(log, "c failed for process {0}: {1}", m_continue_process->GetID(),
+ error);
return SendErrorResponse(GDBRemoteServerError::eErrorResume);
}
- LLDB_LOG(log, "continued process {0}", m_debugged_process_up->GetID());
+ LLDB_LOG(log, "continued process {0}", m_continue_process->GetID());
// No response required from continue.
return PacketResult::Success;
}
@@ -1679,7 +1586,7 @@
}
// Ensure we have a native process.
- if (!m_debugged_process_up) {
+ if (!m_continue_process) {
LLDB_LOG(log, "no debugged process");
return SendErrorResponse(0x36);
}
@@ -1732,23 +1639,27 @@
// Consume the separator.
packet.GetChar();
- thread_action.tid = packet.GetHexMaxU32(false, LLDB_INVALID_THREAD_ID);
- if (thread_action.tid == LLDB_INVALID_THREAD_ID)
- return SendIllFormedResponse(
- packet, "Could not parse thread number in vCont packet");
+ llvm::Expected<lldb::tid_t> tid_ret =
+ ReadTid(packet, /*allow_all=*/true, m_continue_process->GetID());
+ if (!tid_ret)
+ return SendErrorResponse(tid_ret.takeError());
+
+ thread_action.tid = tid_ret.get();
+ if (thread_action.tid == StringExtractorGDBRemote::AllThreads)
+ thread_action.tid = LLDB_INVALID_THREAD_ID;
}
thread_actions.Append(thread_action);
}
- Status error = m_debugged_process_up->Resume(thread_actions);
+ Status error = m_continue_process->Resume(thread_actions);
if (error.Fail()) {
LLDB_LOG(log, "vCont failed for process {0}: {1}",
- m_debugged_process_up->GetID(), error);
+ m_continue_process->GetID(), error);
return SendErrorResponse(GDBRemoteServerError::eErrorResume);
}
- LLDB_LOG(log, "continued process {0}", m_debugged_process_up->GetID());
+ LLDB_LOG(log, "continued process {0}", m_continue_process->GetID());
// No response required from vCont.
return PacketResult::Success;
}
@@ -1758,8 +1669,8 @@
LLDB_LOG(log, "setting current thread id to {0}", tid);
m_current_tid = tid;
- if (m_debugged_process_up)
- m_debugged_process_up->SetCurrentThreadID(m_current_tid);
+ if (m_current_process)
+ m_current_process->SetCurrentThreadID(m_current_tid);
}
void GDBRemoteCommunicationServerLLGS::SetContinueThreadID(lldb::tid_t tid) {
@@ -1775,10 +1686,10 @@
// Handle the $? gdbremote command.
// If no process, indicate error
- if (!m_debugged_process_up)
+ if (!m_current_process)
return SendErrorResponse(02);
- return SendStopReasonForState(m_debugged_process_up->GetState());
+ return SendStopReasonForState(m_current_process->GetState());
}
GDBRemoteCommunication::PacketResult
@@ -1799,8 +1710,8 @@
case eStateSuspended:
case eStateStopped:
case eStateCrashed: {
- assert(m_debugged_process_up != nullptr);
- lldb::tid_t tid = m_debugged_process_up->GetCurrentThreadID();
+ assert(m_current_process != nullptr);
+ lldb::tid_t tid = m_current_process->GetCurrentThreadID();
// Make sure we set the current thread so g and p packets return the data
// the gdb will expect.
SetCurrentThreadID(tid);
@@ -1810,11 +1721,11 @@
case eStateInvalid:
case eStateUnloaded:
case eStateExited:
- return SendWResponse(m_debugged_process_up.get());
+ return SendWResponse(m_current_process);
default:
LLDB_LOG(log, "pid {0}, current state reporting not handled: {1}",
- m_debugged_process_up->GetID(), process_state);
+ m_current_process->GetID(), process_state);
break;
}
@@ -1825,12 +1736,12 @@
GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo(
StringExtractorGDBRemote &packet) {
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
return SendErrorResponse(68);
// Ensure we have a thread.
- NativeThreadProtocol *thread = m_debugged_process_up->GetThreadAtIndex(0);
+ NativeThreadProtocol *thread = m_current_process->GetThreadAtIndex(0);
if (!thread)
return SendErrorResponse(69);
@@ -1925,11 +1836,11 @@
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOG(log, "no process ({0}), returning OK",
- m_debugged_process_up ? "invalid process id"
- : "null m_debugged_process_up");
+ m_current_process ? "invalid process id"
+ : "null m_current_process");
return SendOKResponse();
}
@@ -1940,9 +1851,9 @@
NativeThreadProtocol *thread;
uint32_t thread_index;
for (thread_index = 0,
- thread = m_debugged_process_up->GetThreadAtIndex(thread_index);
+ thread = m_current_process->GetThreadAtIndex(thread_index);
thread; ++thread_index,
- thread = m_debugged_process_up->GetThreadAtIndex(thread_index)) {
+ thread = m_current_process->GetThreadAtIndex(thread_index)) {
LLDB_LOG(log, "iterated thread {0}(tid={2})", thread_index,
thread->GetID());
if (thread_index > 0)
@@ -2163,9 +2074,8 @@
// Build the reginfos response.
StreamGDBRemote response;
- RegisterValue reg_value(
- makeArrayRef(reg_bytes, reg_size),
- m_debugged_process_up->GetArchitecture().GetByteOrder());
+ RegisterValue reg_value(makeArrayRef(reg_bytes, reg_size),
+ m_current_process->GetArchitecture().GetByteOrder());
Status error = reg_context.WriteRegister(reg_info, reg_value);
if (error.Fail()) {
LLDB_LOGF(log,
@@ -2182,16 +2092,6 @@
GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
- // Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
- LLDB_LOGF(
- log,
- "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
- __FUNCTION__);
- return SendErrorResponse(0x15);
- }
-
// Parse out which variant of $H is requested.
packet.SetFilePos(strlen("H"));
if (packet.GetBytesLeft() < 1) {
@@ -2203,11 +2103,14 @@
}
const char h_variant = packet.GetChar();
+ NativeProcessProtocol *default_process;
switch (h_variant) {
case 'g':
+ default_process = m_current_process;
break;
case 'c':
+ default_process = m_continue_process;
break;
default:
@@ -2220,14 +2123,32 @@
}
// Parse out the thread number.
- // FIXME return a parse success/fail value. All values are valid here.
- const lldb::tid_t tid =
- packet.GetHexMaxU64(false, std::numeric_limits<lldb::tid_t>::max());
+ auto pid_tid = packet.GetPidTid(default_process ? default_process->GetID()
+ : LLDB_INVALID_PROCESS_ID);
+ if (!pid_tid)
+ return SendErrorResponse(llvm::make_error<StringError>(
+ inconvertibleErrorCode(), "Malformed thread-id"));
+
+ lldb::pid_t pid = pid_tid->first;
+ lldb::tid_t tid = pid_tid->second;
+
+ if (pid == StringExtractorGDBRemote::AllProcesses)
+ return SendUnimplementedResponse("Selecting all processes not supported");
+ if (pid == LLDB_INVALID_PROCESS_ID)
+ return SendErrorResponse(llvm::make_error<StringError>(
+ inconvertibleErrorCode(), "No current process and no PID provided"));
+
+ // Check the process ID and find respective process instance.
+ auto new_process_it = m_debugged_processes.find(pid);
+ if (new_process_it == m_debugged_processes.end())
+ return SendErrorResponse(llvm::make_error<StringError>(
+ inconvertibleErrorCode(),
+ llvm::formatv("No process with PID {0} debugged", pid)));
// Ensure we have the given thread when not specifying -1 (all threads) or 0
// (any thread).
if (tid != LLDB_INVALID_THREAD_ID && tid != 0) {
- NativeThreadProtocol *thread = m_debugged_process_up->GetThreadByID(tid);
+ NativeThreadProtocol *thread = new_process_it->second->GetThreadByID(tid);
if (!thread) {
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s failed, tid %" PRIu64
@@ -2237,13 +2158,15 @@
}
}
- // Now switch the given thread type.
+ // Now switch the given process and thread type.
switch (h_variant) {
case 'g':
+ m_current_process = new_process_it->second.get();
SetCurrentThreadID(tid);
break;
case 'c':
+ m_continue_process = new_process_it->second.get();
SetContinueThreadID(tid);
break;
@@ -2261,8 +2184,8 @@
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOGF(
log,
"GDBRemoteCommunicationServerLLGS::%s failed, no process available",
@@ -2297,21 +2220,21 @@
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOG(log, "failed, no process available");
return SendErrorResponse(0x15);
}
// Interrupt the process.
- Status error = m_debugged_process_up->Interrupt();
+ Status error = m_current_process->Interrupt();
if (error.Fail()) {
- LLDB_LOG(log, "failed for process {0}: {1}", m_debugged_process_up->GetID(),
+ LLDB_LOG(log, "failed for process {0}: {1}", m_current_process->GetID(),
error);
return SendErrorResponse(GDBRemoteServerError::eErrorResume);
}
- LLDB_LOG(log, "stopped process {0}", m_debugged_process_up->GetID());
+ LLDB_LOG(log, "stopped process {0}", m_current_process->GetID());
// No response required from stop all.
return PacketResult::Success;
@@ -2322,8 +2245,8 @@
StringExtractorGDBRemote &packet) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOGF(
log,
"GDBRemoteCommunicationServerLLGS::%s failed, no process available",
@@ -2365,13 +2288,13 @@
// Retrieve the process memory.
size_t bytes_read = 0;
- Status error = m_debugged_process_up->ReadMemoryWithoutTrap(
+ Status error = m_current_process->ReadMemoryWithoutTrap(
read_addr, &buf[0], byte_count, bytes_read);
if (error.Fail()) {
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
" mem 0x%" PRIx64 ": failed to read. Error: %s",
- __FUNCTION__, m_debugged_process_up->GetID(), read_addr,
+ __FUNCTION__, m_current_process->GetID(), read_addr,
error.AsCString());
return SendErrorResponse(0x08);
}
@@ -2380,8 +2303,7 @@
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
" mem 0x%" PRIx64 ": read 0 of %" PRIu64 " requested bytes",
- __FUNCTION__, m_debugged_process_up->GetID(), read_addr,
- byte_count);
+ __FUNCTION__, m_current_process->GetID(), read_addr, byte_count);
return SendErrorResponse(0x08);
}
@@ -2403,8 +2325,8 @@
GDBRemoteCommunicationServerLLGS::Handle__M(StringExtractorGDBRemote &packet) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOGF(
log,
"GDBRemoteCommunicationServerLLGS::%s failed, no process available",
@@ -2439,8 +2361,7 @@
}
}
- llvm::Expected<addr_t> addr =
- m_debugged_process_up->AllocateMemory(size, perms);
+ llvm::Expected<addr_t> addr = m_current_process->AllocateMemory(size, perms);
if (!addr)
return SendErrorResponse(addr.takeError());
@@ -2453,8 +2374,8 @@
GDBRemoteCommunicationServerLLGS::Handle__m(StringExtractorGDBRemote &packet) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOGF(
log,
"GDBRemoteCommunicationServerLLGS::%s failed, no process available",
@@ -2471,7 +2392,7 @@
if (addr == LLDB_INVALID_ADDRESS)
return SendIllFormedResponse(packet, "Address not valid");
- if (llvm::Error Err = m_debugged_process_up->DeallocateMemory(addr))
+ if (llvm::Error Err = m_current_process->DeallocateMemory(addr))
return SendErrorResponse(std::move(Err));
return SendOKResponse();
@@ -2481,8 +2402,8 @@
GDBRemoteCommunicationServerLLGS::Handle_M(StringExtractorGDBRemote &packet) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOGF(
log,
"GDBRemoteCommunicationServerLLGS::%s failed, no process available",
@@ -2531,8 +2452,7 @@
LLDB_LOG(log,
"pid {0} mem {1:x}: asked to write {2} bytes, but only found {3} "
"to convert.",
- m_debugged_process_up->GetID(), write_addr, byte_count,
- convert_count);
+ m_current_process->GetID(), write_addr, byte_count, convert_count);
return SendIllFormedResponse(packet, "M content byte length specified did "
"not match hex-encoded content "
"length");
@@ -2540,17 +2460,17 @@
// Write the process memory.
size_t bytes_written = 0;
- Status error = m_debugged_process_up->WriteMemory(write_addr, &buf[0],
- byte_count, bytes_written);
+ Status error = m_current_process->WriteMemory(write_addr, &buf[0], byte_count,
+ bytes_written);
if (error.Fail()) {
LLDB_LOG(log, "pid {0} mem {1:x}: failed to write. Error: {2}",
- m_debugged_process_up->GetID(), write_addr, error);
+ m_current_process->GetID(), write_addr, error);
return SendErrorResponse(0x09);
}
if (bytes_written == 0) {
LLDB_LOG(log, "pid {0} mem {1:x}: wrote 0 of {2} requested bytes",
- m_debugged_process_up->GetID(), write_addr, byte_count);
+ m_current_process->GetID(), write_addr, byte_count);
return SendErrorResponse(0x09);
}
@@ -2569,8 +2489,8 @@
// Ensure we have a process running; otherwise, we can't figure this out
// since we won't have a NativeProcessProtocol.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOGF(
log,
"GDBRemoteCommunicationServerLLGS::%s failed, no process available",
@@ -2580,8 +2500,7 @@
// Test if we can get any region back when asking for the region around NULL.
MemoryRegionInfo region_info;
- const Status error =
- m_debugged_process_up->GetMemoryRegionInfo(0, region_info);
+ const Status error = m_current_process->GetMemoryRegionInfo(0, region_info);
if (error.Fail()) {
// We don't support memory region info collection for this
// NativeProcessProtocol.
@@ -2597,8 +2516,8 @@
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
// Ensure we have a process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOGF(
log,
"GDBRemoteCommunicationServerLLGS::%s failed, no process available",
@@ -2619,7 +2538,7 @@
// Get the memory region info for the target address.
MemoryRegionInfo region_info;
const Status error =
- m_debugged_process_up->GetMemoryRegionInfo(read_addr, region_info);
+ m_current_process->GetMemoryRegionInfo(read_addr, region_info);
if (error.Fail()) {
// Return the error message.
@@ -2674,8 +2593,8 @@
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) {
// Ensure we have a process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
LLDB_LOG(log, "failed, no process available");
return SendErrorResponse(0x15);
@@ -2745,22 +2664,22 @@
if (want_breakpoint) {
// Try to set the breakpoint.
const Status error =
- m_debugged_process_up->SetBreakpoint(addr, size, want_hardware);
+ m_current_process->SetBreakpoint(addr, size, want_hardware);
if (error.Success())
return SendOKResponse();
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
LLDB_LOG(log, "pid {0} failed to set breakpoint: {1}",
- m_debugged_process_up->GetID(), error);
+ m_current_process->GetID(), error);
return SendErrorResponse(0x09);
} else {
// Try to set the watchpoint.
- const Status error = m_debugged_process_up->SetWatchpoint(
+ const Status error = m_current_process->SetWatchpoint(
addr, size, watch_flags, want_hardware);
if (error.Success())
return SendOKResponse();
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
LLDB_LOG(log, "pid {0} failed to set watchpoint: {1}",
- m_debugged_process_up->GetID(), error);
+ m_current_process->GetID(), error);
return SendErrorResponse(0x09);
}
}
@@ -2768,8 +2687,8 @@
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) {
// Ensure we have a process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
LLDB_LOG(log, "failed, no process available");
return SendErrorResponse(0x15);
@@ -2833,21 +2752,21 @@
if (want_breakpoint) {
// Try to clear the breakpoint.
const Status error =
- m_debugged_process_up->RemoveBreakpoint(addr, want_hardware);
+ m_current_process->RemoveBreakpoint(addr, want_hardware);
if (error.Success())
return SendOKResponse();
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
LLDB_LOG(log, "pid {0} failed to remove breakpoint: {1}",
- m_debugged_process_up->GetID(), error);
+ m_current_process->GetID(), error);
return SendErrorResponse(0x09);
} else {
// Try to clear the watchpoint.
- const Status error = m_debugged_process_up->RemoveWatchpoint(addr);
+ const Status error = m_current_process->RemoveWatchpoint(addr);
if (error.Success())
return SendOKResponse();
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
LLDB_LOG(log, "pid {0} failed to remove watchpoint: {1}",
- m_debugged_process_up->GetID(), error);
+ m_current_process->GetID(), error);
return SendErrorResponse(0x09);
}
}
@@ -2857,8 +2776,8 @@
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
// Ensure we have a process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_continue_process ||
+ (m_continue_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
LLDB_LOGF(
log,
"GDBRemoteCommunicationServerLLGS::%s failed, no process available",
@@ -2876,7 +2795,7 @@
// Double check that we have such a thread.
// TODO investigate: on MacOSX we might need to do an UpdateThreads () here.
- NativeThreadProtocol *thread = m_debugged_process_up->GetThreadByID(tid);
+ NativeThreadProtocol *thread = m_continue_process->GetThreadByID(tid);
if (!thread)
return SendErrorResponse(0x33);
@@ -2889,12 +2808,12 @@
// All other threads stop while we're single stepping a thread.
actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
- Status error = m_debugged_process_up->Resume(actions);
+ Status error = m_continue_process->Resume(actions);
if (error.Fail()) {
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
" tid %" PRIu64 " Resume() failed with error: %s",
- __FUNCTION__, m_debugged_process_up->GetID(), tid,
+ __FUNCTION__, m_continue_process->GetID(), tid,
error.AsCString());
return SendErrorResponse(0x49);
}
@@ -2906,7 +2825,7 @@
llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
GDBRemoteCommunicationServerLLGS::BuildTargetXml() {
// Ensure we have a thread.
- NativeThreadProtocol *thread = m_debugged_process_up->GetThreadAtIndex(0);
+ NativeThreadProtocol *thread = m_current_process->GetThreadAtIndex(0);
if (!thread)
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"No thread available");
@@ -2921,7 +2840,7 @@
response.Printf("<target version=\"1.0\">");
response.Printf("<architecture>%s</architecture>",
- m_debugged_process_up->GetArchitecture()
+ m_current_process->GetArchitecture()
.GetTriple()
.getArchName()
.str()
@@ -3010,22 +2929,22 @@
GDBRemoteCommunicationServerLLGS::ReadXferObject(llvm::StringRef object,
llvm::StringRef annex) {
// Make sure we have a valid process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"No process available");
}
if (object == "auxv") {
// Grab the auxv data.
- auto buffer_or_error = m_debugged_process_up->GetAuxvData();
+ auto buffer_or_error = m_current_process->GetAuxvData();
if (!buffer_or_error)
return llvm::errorCodeToError(buffer_or_error.getError());
return std::move(*buffer_or_error);
}
if (object == "libraries-svr4") {
- auto library_list = m_debugged_process_up->GetLoadedSVR4Libraries();
+ auto library_list = m_current_process->GetLoadedSVR4Libraries();
if (!library_list)
return library_list.takeError();
@@ -3148,7 +3067,7 @@
Status error = reg_context.ReadAllRegisterValues(register_data_sp);
if (error.Fail()) {
LLDB_LOG(log, "pid {0} failed to save all register values: {1}",
- m_debugged_process_up->GetID(), error);
+ m_current_process->GetID(), error);
return SendErrorResponse(0x75);
}
@@ -3211,7 +3130,7 @@
if (it == m_saved_registers_map.end()) {
LLDB_LOG(log,
"pid {0} does not have a register set save buffer for id {1}",
- m_debugged_process_up->GetID(), save_id);
+ m_current_process->GetID(), save_id);
return SendErrorResponse(0x77);
}
register_data_sp = it->second;
@@ -3223,7 +3142,7 @@
Status error = reg_context.WriteAllRegisterValues(register_data_sp);
if (error.Fail()) {
LLDB_LOG(log, "pid {0} failed to restore all register values: {1}",
- m_debugged_process_up->GetID(), error);
+ m_current_process->GetID(), error);
return SendErrorResponse(0x77);
}
@@ -3263,7 +3182,7 @@
}
// Notify we attached by sending a stop packet.
- return SendStopReasonForState(m_debugged_process_up->GetState());
+ return SendStopReasonForState(m_current_process->GetState());
}
GDBRemoteCommunication::PacketResult
@@ -3293,7 +3212,7 @@
}
// Notify we attached by sending a stop packet.
- return SendStopReasonForState(m_debugged_process_up->GetState());
+ return SendStopReasonForState(m_current_process->GetState());
}
GDBRemoteCommunication::PacketResult
@@ -3329,25 +3248,13 @@
}
// Notify we attached by sending a stop packet.
- return SendStopReasonForState(m_debugged_process_up->GetState());
+ return SendStopReasonForState(m_current_process->GetState());
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
-
StopSTDIOForwarding();
- // Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
- LLDB_LOGF(
- log,
- "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
- __FUNCTION__);
- return SendErrorResponse(0x15);
- }
-
lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
// Consume the ';' after D.
@@ -3362,19 +3269,32 @@
return SendIllFormedResponse(packet, "D failed to parse the process id");
}
- if (pid != LLDB_INVALID_PROCESS_ID && m_debugged_process_up->GetID() != pid) {
- return SendIllFormedResponse(packet, "Invalid pid");
+ // Detach forked children if their PID was specified *or* no PID was requested
+ // (i.e. detach-all packet).
+ llvm::Error detach_error = llvm::Error::success();
+ bool detached = false;
+ for (auto it = m_debugged_processes.begin();
+ it != m_debugged_processes.end();) {
+ if (pid == LLDB_INVALID_PROCESS_ID || pid == it->first) {
+ if (llvm::Error e = it->second->Detach().ToError())
+ detach_error = llvm::joinErrors(std::move(detach_error), std::move(e));
+ else {
+ if (it->second.get() == m_current_process)
+ m_current_process = nullptr;
+ if (it->second.get() == m_continue_process)
+ m_continue_process = nullptr;
+ it = m_debugged_processes.erase(it);
+ detached = true;
+ continue;
+ }
+ }
+ ++it;
}
- const Status error = m_debugged_process_up->Detach();
- if (error.Fail()) {
- LLDB_LOGF(log,
- "GDBRemoteCommunicationServerLLGS::%s failed to detach from "
- "pid %" PRIu64 ": %s\n",
- __FUNCTION__, m_debugged_process_up->GetID(), error.AsCString());
- return SendErrorResponse(0x01);
- }
-
+ if (detach_error)
+ return SendErrorResponse(std::move(detach_error));
+ if (!detached)
+ return SendErrorResponse(Status("PID %" PRIu64 " not traced", pid));
return SendOKResponse();
}
@@ -3384,7 +3304,7 @@
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
packet.SetFilePos(strlen("qThreadStopInfo"));
- const lldb::tid_t tid = packet.GetHexMaxU32(false, LLDB_INVALID_THREAD_ID);
+ const lldb::tid_t tid = packet.GetHexMaxU64(false, LLDB_INVALID_THREAD_ID);
if (tid == LLDB_INVALID_THREAD_ID) {
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s failed, could not "
@@ -3401,19 +3321,19 @@
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
// Ensure we have a debugged process.
- if (!m_debugged_process_up ||
- (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
return SendErrorResponse(50);
- LLDB_LOG(log, "preparing packet for pid {0}", m_debugged_process_up->GetID());
+ LLDB_LOG(log, "preparing packet for pid {0}", m_current_process->GetID());
StreamString response;
const bool threads_with_valid_stop_info_only = false;
- llvm::Expected<json::Value> threads_info = GetJSONThreadsInfo(
- *m_debugged_process_up, threads_with_valid_stop_info_only);
+ llvm::Expected<json::Value> threads_info =
+ GetJSONThreadsInfo(*m_current_process, threads_with_valid_stop_info_only);
if (!threads_info) {
LLDB_LOG_ERROR(log, threads_info.takeError(),
"failed to prepare a packet for pid {1}: {0}",
- m_debugged_process_up->GetID());
+ m_current_process->GetID());
return SendErrorResponse(52);
}
@@ -3427,8 +3347,8 @@
GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo(
StringExtractorGDBRemote &packet) {
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)
+ if (!m_current_process ||
+ m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)
return SendErrorResponse(68);
packet.SetFilePos(strlen("qWatchpointSupportInfo"));
@@ -3437,7 +3357,7 @@
if (packet.GetChar() != ':')
return SendErrorResponse(67);
- auto hw_debug_cap = m_debugged_process_up->GetHardwareDebugSupportInfo();
+ auto hw_debug_cap = m_current_process->GetHardwareDebugSupportInfo();
StreamGDBRemote response;
if (hw_debug_cap == llvm::None)
@@ -3452,8 +3372,8 @@
GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress(
StringExtractorGDBRemote &packet) {
// Fail if we don't have a current process.
- if (!m_debugged_process_up ||
- m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)
+ if (!m_current_process ||
+ m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)
return SendErrorResponse(67);
packet.SetFilePos(strlen("qFileLoadAddress:"));
@@ -3465,7 +3385,7 @@
lldb::addr_t file_load_address = LLDB_INVALID_ADDRESS;
Status error =
- m_debugged_process_up->GetFileLoadAddress(file_name, file_load_address);
+ m_current_process->GetFileLoadAddress(file_name, file_load_address);
if (error.Fail())
return SendErrorResponse(69);
@@ -3501,16 +3421,189 @@
}
// Fail if we don't have a current process.
- if (!m_debugged_process_up)
+ if (!m_current_process)
return SendErrorResponse(68);
- Status error = m_debugged_process_up->IgnoreSignals(signals);
+ Status error = m_current_process->IgnoreSignals(signals);
if (error.Fail())
return SendErrorResponse(69);
return SendOKResponse();
}
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_qMemTags(
+ StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ // Ensure we have a process.
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ LLDB_LOGF(
+ log,
+ "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
+ __FUNCTION__);
+ return SendErrorResponse(1);
+ }
+
+ // We are expecting
+ // qMemTags:<hex address>,<hex length>:<hex type>
+
+ // Address
+ packet.SetFilePos(strlen("qMemTags:"));
+ const char *current_char = packet.Peek();
+ if (!current_char || *current_char == ',')
+ return SendIllFormedResponse(packet, "Missing address in qMemTags packet");
+ const lldb::addr_t addr = packet.GetHexMaxU64(/*little_endian=*/false, 0);
+
+ // Length
+ char previous_char = packet.GetChar();
+ current_char = packet.Peek();
+ // If we don't have a separator or the length field is empty
+ if (previous_char != ',' || (current_char && *current_char == ':'))
+ return SendIllFormedResponse(packet,
+ "Invalid addr,length pair in qMemTags packet");
+
+ if (packet.GetBytesLeft() < 1)
+ return SendIllFormedResponse(
+ packet, "Too short qMemtags: packet (looking for length)");
+ const size_t length = packet.GetHexMaxU64(/*little_endian=*/false, 0);
+
+ // Type
+ const char *invalid_type_err = "Invalid type field in qMemTags: packet";
+ if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':')
+ return SendIllFormedResponse(packet, invalid_type_err);
+
+ // Type is a signed integer but packed into the packet as its raw bytes.
+ // However, our GetU64 uses strtoull which allows +/-. We do not want this.
+ const char *first_type_char = packet.Peek();
+ if (first_type_char && (*first_type_char == '+' || *first_type_char == '-'))
+ return SendIllFormedResponse(packet, invalid_type_err);
+
+ // Extract type as unsigned then cast to signed.
+ // Using a uint64_t here so that we have some value outside of the 32 bit
+ // range to use as the invalid return value.
+ uint64_t raw_type =
+ packet.GetU64(std::numeric_limits<uint64_t>::max(), /*base=*/16);
+
+ if ( // Make sure the cast below would be valid
+ raw_type > std::numeric_limits<uint32_t>::max() ||
+ // To catch inputs like "123aardvark" that will parse but clearly aren't
+ // valid in this case.
+ packet.GetBytesLeft()) {
+ return SendIllFormedResponse(packet, invalid_type_err);
+ }
+
+ // First narrow to 32 bits otherwise the copy into type would take
+ // the wrong 4 bytes on big endian.
+ uint32_t raw_type_32 = raw_type;
+ int32_t type = reinterpret_cast<int32_t &>(raw_type_32);
+
+ StreamGDBRemote response;
+ std::vector<uint8_t> tags;
+ Status error = m_current_process->ReadMemoryTags(type, addr, length, tags);
+ if (error.Fail())
+ return SendErrorResponse(1);
+
+ // This m is here in case we want to support multi part replies in the future.
+ // In the same manner as qfThreadInfo/qsThreadInfo.
+ response.PutChar('m');
+ response.PutBytesAsRawHex8(tags.data(), tags.size());
+ return SendPacketNoLock(response.GetString());
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_QMemTags(
+ StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ // Ensure we have a process.
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ LLDB_LOGF(
+ log,
+ "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
+ __FUNCTION__);
+ return SendErrorResponse(1);
+ }
+
+ // We are expecting
+ // QMemTags:<hex address>,<hex length>:<hex type>:<tags as hex bytes>
+
+ // Address
+ packet.SetFilePos(strlen("QMemTags:"));
+ const char *current_char = packet.Peek();
+ if (!current_char || *current_char == ',')
+ return SendIllFormedResponse(packet, "Missing address in QMemTags packet");
+ const lldb::addr_t addr = packet.GetHexMaxU64(/*little_endian=*/false, 0);
+
+ // Length
+ char previous_char = packet.GetChar();
+ current_char = packet.Peek();
+ // If we don't have a separator or the length field is empty
+ if (previous_char != ',' || (current_char && *current_char == ':'))
+ return SendIllFormedResponse(packet,
+ "Invalid addr,length pair in QMemTags packet");
+
+ if (packet.GetBytesLeft() < 1)
+ return SendIllFormedResponse(
+ packet, "Too short QMemtags: packet (looking for length)");
+ const size_t length = packet.GetHexMaxU64(/*little_endian=*/false, 0);
+
+ // Type
+ const char *invalid_type_err = "Invalid type field in QMemTags: packet";
+ if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':')
+ return SendIllFormedResponse(packet, invalid_type_err);
+
+ // Our GetU64 uses strtoull which allows leading +/-, we don't want that.
+ const char *first_type_char = packet.Peek();
+ if (first_type_char && (*first_type_char == '+' || *first_type_char == '-'))
+ return SendIllFormedResponse(packet, invalid_type_err);
+
+ // The type is a signed integer but is in the packet as its raw bytes.
+ // So parse first as unsigned then cast to signed later.
+ // We extract to 64 bit, even though we only expect 32, so that we've
+ // got some invalid value we can check for.
+ uint64_t raw_type =
+ packet.GetU64(std::numeric_limits<uint64_t>::max(), /*base=*/16);
+ if (raw_type > std::numeric_limits<uint32_t>::max())
+ return SendIllFormedResponse(packet, invalid_type_err);
+
+ // First narrow to 32 bits. Otherwise the copy below would get the wrong
+ // 4 bytes on big endian.
+ uint32_t raw_type_32 = raw_type;
+ int32_t type = reinterpret_cast<int32_t &>(raw_type_32);
+
+ // Tag data
+ if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':')
+ return SendIllFormedResponse(packet,
+ "Missing tag data in QMemTags: packet");
+
+ // Must be 2 chars per byte
+ const char *invalid_data_err = "Invalid tag data in QMemTags: packet";
+ if (packet.GetBytesLeft() % 2)
+ return SendIllFormedResponse(packet, invalid_data_err);
+
+ // This is bytes here and is unpacked into target specific tags later
+ // We cannot assume that number of bytes == length here because the server
+ // can repeat tags to fill a given range.
+ std::vector<uint8_t> tag_data;
+ // Zero length writes will not have any tag data
+ // (but we pass them on because it will still check that tagging is enabled)
+ if (packet.GetBytesLeft()) {
+ size_t byte_count = packet.GetBytesLeft() / 2;
+ tag_data.resize(byte_count);
+ size_t converted_bytes = packet.GetHexBytes(tag_data, 0);
+ if (converted_bytes != byte_count) {
+ return SendIllFormedResponse(packet, invalid_data_err);
+ }
+ }
+
+ Status status =
+ m_current_process->WriteMemoryTags(type, addr, length, tag_data);
+ return status.Success() ? SendOKResponse() : SendErrorResponse(1);
+}
+
void GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection() {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
@@ -3539,8 +3632,8 @@
NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix(
StringExtractorGDBRemote &packet) {
// We have no thread if we don't have a process.
- if (!m_debugged_process_up ||
- m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)
+ if (!m_current_process ||
+ m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)
return nullptr;
// If the client hasn't asked for thread suffix support, there will not be a
@@ -3551,9 +3644,9 @@
return nullptr;
else if (current_tid == 0) {
// Pick a thread.
- return m_debugged_process_up->GetThreadAtIndex(0);
+ return m_current_process->GetThreadAtIndex(0);
} else
- return m_debugged_process_up->GetThreadByID(current_tid);
+ return m_current_process->GetThreadByID(current_tid);
}
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
@@ -3583,7 +3676,7 @@
packet.SetFilePos(packet.GetFilePos() + strlen("thread:"));
const lldb::tid_t tid = packet.GetHexMaxU64(false, 0);
if (tid != 0)
- return m_debugged_process_up->GetThreadByID(tid);
+ return m_current_process->GetThreadByID(tid);
return nullptr;
}
@@ -3593,9 +3686,9 @@
// Use whatever the debug process says is the current thread id since the
// protocol either didn't specify or specified we want any/all threads
// marked as the current thread.
- if (!m_debugged_process_up)
+ if (!m_current_process)
return LLDB_INVALID_THREAD_ID;
- return m_debugged_process_up->GetCurrentThreadID();
+ return m_current_process->GetCurrentThreadID();
}
// Use the specific current thread id set by the gdb remote protocol.
return m_current_tid;
@@ -3616,9 +3709,9 @@
FileSpec
GDBRemoteCommunicationServerLLGS::FindModuleFile(const std::string &module_path,
const ArchSpec &arch) {
- if (m_debugged_process_up) {
+ if (m_current_process) {
FileSpec file_spec;
- if (m_debugged_process_up
+ if (m_current_process
->GetLoadedModuleFileSpec(module_path.c_str(), file_spec)
.Success()) {
if (FileSystem::Instance().Exists(file_spec))
@@ -3653,3 +3746,93 @@
}
return result;
}
+
+llvm::Expected<lldb::tid_t> GDBRemoteCommunicationServerLLGS::ReadTid(
+ StringExtractorGDBRemote &packet, bool allow_all, lldb::pid_t default_pid) {
+ assert(m_current_process);
+ assert(m_current_process->GetID() != LLDB_INVALID_PROCESS_ID);
+
+ auto pid_tid = packet.GetPidTid(default_pid);
+ if (!pid_tid)
+ return llvm::make_error<StringError>(inconvertibleErrorCode(),
+ "Malformed thread-id");
+
+ lldb::pid_t pid = pid_tid->first;
+ lldb::tid_t tid = pid_tid->second;
+
+ if (!allow_all && pid == StringExtractorGDBRemote::AllProcesses)
+ return llvm::make_error<StringError>(
+ inconvertibleErrorCode(),
+ llvm::formatv("PID value {0} not allowed", pid == 0 ? 0 : -1));
+
+ if (!allow_all && tid == StringExtractorGDBRemote::AllThreads)
+ return llvm::make_error<StringError>(
+ inconvertibleErrorCode(),
+ llvm::formatv("TID value {0} not allowed", tid == 0 ? 0 : -1));
+
+ if (pid != StringExtractorGDBRemote::AllProcesses) {
+ if (pid != m_current_process->GetID())
+ return llvm::make_error<StringError>(
+ inconvertibleErrorCode(), llvm::formatv("PID {0} not debugged", pid));
+ }
+
+ return tid;
+}
+
+std::vector<std::string> GDBRemoteCommunicationServerLLGS::HandleFeatures(
+ const llvm::ArrayRef<llvm::StringRef> client_features) {
+ std::vector<std::string> ret =
+ GDBRemoteCommunicationServerCommon::HandleFeatures(client_features);
+ ret.insert(ret.end(), {
+ "QThreadSuffixSupported+",
+ "QListThreadsInStopReply+",
+ "qXfer:features:read+",
+ });
+
+ // report server-only features
+ using Extension = NativeProcessProtocol::Extension;
+ Extension plugin_features = m_process_factory.GetSupportedExtensions();
+ if (bool(plugin_features & Extension::pass_signals))
+ ret.push_back("QPassSignals+");
+ if (bool(plugin_features & Extension::auxv))
+ ret.push_back("qXfer:auxv:read+");
+ if (bool(plugin_features & Extension::libraries_svr4))
+ ret.push_back("qXfer:libraries-svr4:read+");
+ if (bool(plugin_features & Extension::memory_tagging))
+ ret.push_back("memory-tagging+");
+
+ // check for client features
+ m_extensions_supported = {};
+ for (llvm::StringRef x : client_features)
+ m_extensions_supported |=
+ llvm::StringSwitch<Extension>(x)
+ .Case("multiprocess+", Extension::multiprocess)
+ .Case("fork-events+", Extension::fork)
+ .Case("vfork-events+", Extension::vfork)
+ .Default({});
+
+ m_extensions_supported &= plugin_features;
+
+ // fork & vfork require multiprocess
+ if (!bool(m_extensions_supported & Extension::multiprocess))
+ m_extensions_supported &= ~(Extension::fork | Extension::vfork);
+
+ // report only if actually supported
+ if (bool(m_extensions_supported & Extension::multiprocess))
+ ret.push_back("multiprocess+");
+ if (bool(m_extensions_supported & Extension::fork))
+ ret.push_back("fork-events+");
+ if (bool(m_extensions_supported & Extension::vfork))
+ ret.push_back("vfork-events+");
+
+ for (auto &x : m_debugged_processes)
+ SetEnabledExtensions(*x.second);
+ return ret;
+}
+
+void GDBRemoteCommunicationServerLLGS::SetEnabledExtensions(
+ NativeProcessProtocol &process) {
+ NativeProcessProtocol::Extension flags = m_extensions_supported;
+ assert(!bool(flags & ~m_process_factory.GetSupportedExtensions()));
+ process.SetEnabledExtensions(flags);
+}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
index c511399..04d0605 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
@@ -78,6 +78,10 @@
void DidExec(NativeProcessProtocol *process) override;
+ void
+ NewSubprocess(NativeProcessProtocol *parent_process,
+ std::unique_ptr<NativeProcessProtocol> child_process) override;
+
Status InitializeConnection(std::unique_ptr<Connection> connection);
protected:
@@ -86,8 +90,11 @@
const NativeProcessProtocol::Factory &m_process_factory;
lldb::tid_t m_current_tid = LLDB_INVALID_THREAD_ID;
lldb::tid_t m_continue_tid = LLDB_INVALID_THREAD_ID;
+ NativeProcessProtocol *m_current_process;
+ NativeProcessProtocol *m_continue_process;
std::recursive_mutex m_debugged_process_mutex;
- std::unique_ptr<NativeProcessProtocol> m_debugged_process_up;
+ std::unordered_map<lldb::pid_t, std::unique_ptr<NativeProcessProtocol>>
+ m_debugged_processes;
Communication m_stdio_communication;
MainLoop::ReadHandleUP m_stdio_handle_up;
@@ -98,6 +105,10 @@
std::unordered_map<uint32_t, lldb::DataBufferSP> m_saved_registers_map;
uint32_t m_next_saved_registers_id = 1;
bool m_handshake_completed = false;
+ bool m_thread_suffix_supported = false;
+ bool m_list_threads_in_stop_reply = false;
+
+ NativeProcessProtocol::Extension m_extensions_supported = {};
PacketResult SendONotification(const char *buffer, uint32_t len);
@@ -119,6 +130,10 @@
PacketResult Handle_qGetWorkingDir(StringExtractorGDBRemote &packet);
+ PacketResult Handle_QThreadSuffixSupported(StringExtractorGDBRemote &packet);
+
+ PacketResult Handle_QListThreadsInStopReply(StringExtractorGDBRemote &packet);
+
PacketResult Handle_C(StringExtractorGDBRemote &packet);
PacketResult Handle_c(StringExtractorGDBRemote &packet);
@@ -167,15 +182,15 @@
PacketResult Handle_QSaveRegisterState(StringExtractorGDBRemote &packet);
- PacketResult Handle_jTraceStart(StringExtractorGDBRemote &packet);
+ PacketResult Handle_jLLDBTraceSupported(StringExtractorGDBRemote &packet);
- PacketResult Handle_jTraceRead(StringExtractorGDBRemote &packet);
+ PacketResult Handle_jLLDBTraceStart(StringExtractorGDBRemote &packet);
- PacketResult Handle_jTraceStop(StringExtractorGDBRemote &packet);
+ PacketResult Handle_jLLDBTraceStop(StringExtractorGDBRemote &packet);
- PacketResult Handle_jTraceConfigRead(StringExtractorGDBRemote &packet);
+ PacketResult Handle_jLLDBTraceGetState(StringExtractorGDBRemote &packet);
- PacketResult Handle_jLLDBTraceSupportedType(StringExtractorGDBRemote &packet);
+ PacketResult Handle_jLLDBTraceGetBinaryData(StringExtractorGDBRemote &packet);
PacketResult Handle_QRestoreRegisterState(StringExtractorGDBRemote &packet);
@@ -201,6 +216,10 @@
PacketResult Handle_g(StringExtractorGDBRemote &packet);
+ PacketResult Handle_qMemTags(StringExtractorGDBRemote &packet);
+
+ PacketResult Handle_QMemTags(StringExtractorGDBRemote &packet);
+
void SetCurrentThreadID(lldb::tid_t tid);
lldb::tid_t GetCurrentThreadID() const;
@@ -219,6 +238,9 @@
static std::string XMLEncodeAttributeValue(llvm::StringRef value);
+ virtual std::vector<std::string> HandleFeatures(
+ const llvm::ArrayRef<llvm::StringRef> client_features) override;
+
private:
llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> BuildTargetXml();
@@ -244,6 +266,18 @@
void StopSTDIOForwarding();
+ // Read thread-id from packet. If the thread-id is correct, returns it.
+ // Otherwise, returns the error.
+ //
+ // If allow_all is true, then the pid/tid value of -1 ('all') will be allowed.
+ // In any case, the function assumes that exactly one inferior is being
+ // debugged and rejects pid values that do no match that inferior.
+ llvm::Expected<lldb::tid_t> ReadTid(StringExtractorGDBRemote &packet,
+ bool allow_all, lldb::pid_t default_pid);
+
+ // Call SetEnabledExtensions() with appropriate flags on the process.
+ void SetEnabledExtensions(NativeProcessProtocol &process);
+
// For GDBRemoteCommunicationServerLLGS only
GDBRemoteCommunicationServerLLGS(const GDBRemoteCommunicationServerLLGS &) =
delete;
diff --git a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
index 3462fb7..7c2f80d 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
@@ -8,7 +8,7 @@
#include "GDBRemoteCommunicationServerPlatform.h"
-#include <errno.h>
+#include <cerrno>
#include <chrono>
#include <csignal>
@@ -153,7 +153,8 @@
}
// Destructor
-GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform() {}
+GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform() =
+ default;
Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer(
const lldb_private::Args &args, std::string hostname, lldb::pid_t &pid,
diff --git a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index 1000661..65cf9fb 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -36,7 +36,7 @@
: RegisterContext(thread, concrete_frame_idx),
m_reg_info_sp(std::move(reg_info_sp)), m_reg_valid(), m_reg_data(),
m_read_all_at_once(read_all_at_once),
- m_write_all_at_once(write_all_at_once) {
+ m_write_all_at_once(write_all_at_once), m_gpacket_cached(false) {
// Resize our vector of bools to contain one bool for every register. We will
// use these boolean values to know when a register value is valid in
// m_reg_data.
@@ -50,13 +50,14 @@
}
// Destructor
-GDBRemoteRegisterContext::~GDBRemoteRegisterContext() {}
+GDBRemoteRegisterContext::~GDBRemoteRegisterContext() = default;
void GDBRemoteRegisterContext::InvalidateAllRegisters() {
SetAllRegisterValid(false);
}
void GDBRemoteRegisterContext::SetAllRegisterValid(bool b) {
+ m_gpacket_cached = b;
std::vector<bool>::iterator pos, end = m_reg_valid.end();
for (pos = m_reg_valid.begin(); pos != end; ++pos)
*pos = b;
@@ -200,7 +201,7 @@
const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
if (!GetRegisterIsValid(reg)) {
- if (m_read_all_at_once) {
+ if (m_read_all_at_once && !m_gpacket_cached) {
if (DataBufferSP buffer_sp =
gdb_comm.ReadAllRegisters(m_thread.GetProtocolID())) {
memcpy(const_cast<uint8_t *>(m_reg_data.GetDataStart()),
@@ -221,7 +222,10 @@
m_reg_valid[i] = false;
}
}
- return true;
+
+ m_gpacket_cached = true;
+ if (GetRegisterIsValid(reg))
+ return true;
} else {
Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_THREAD |
GDBR_LOG_PACKETS));
@@ -233,9 +237,9 @@
" bytes "
"but only got %" PRId64 " bytes.",
m_reg_data.GetByteSize(), buffer_sp->GetByteSize());
+ return false;
}
}
- return false;
}
if (reg_info->value_regs) {
// Process this composite register request by delegating to the
@@ -249,7 +253,8 @@
break;
// We have a valid primordial register as our constituent. Grab the
// corresponding register info.
- const RegisterInfo *prim_reg_info = GetRegisterInfoAtIndex(prim_reg);
+ const RegisterInfo *prim_reg_info =
+ GetRegisterInfo(eRegisterKindProcessPlugin, prim_reg);
if (prim_reg_info == nullptr)
success = false;
else {
@@ -359,7 +364,7 @@
reg_info->byte_size, // dst length
m_reg_data.GetByteOrder())) // dst byte order
{
- GDBRemoteClientBase::Lock lock(gdb_comm, false);
+ GDBRemoteClientBase::Lock lock(gdb_comm);
if (lock) {
if (m_write_all_at_once) {
// Invalidate all register values
@@ -395,7 +400,8 @@
break;
// We have a valid primordial register as our constituent. Grab the
// corresponding register info.
- const RegisterInfo *value_reg_info = GetRegisterInfoAtIndex(reg);
+ const RegisterInfo *value_reg_info =
+ GetRegisterInfo(eRegisterKindProcessPlugin, reg);
if (value_reg_info == nullptr)
success = false;
else
@@ -414,9 +420,10 @@
if (reg_info->invalidate_regs) {
for (uint32_t idx = 0, reg = reg_info->invalidate_regs[0];
reg != LLDB_INVALID_REGNUM;
- reg = reg_info->invalidate_regs[++idx]) {
- SetRegisterIsValid(reg, false);
- }
+ reg = reg_info->invalidate_regs[++idx])
+ SetRegisterIsValid(ConvertRegisterKindToRegisterNumber(
+ eRegisterKindProcessPlugin, reg),
+ false);
}
return success;
@@ -501,7 +508,7 @@
const bool use_g_packet =
!gdb_comm.AvoidGPackets((ProcessGDBRemote *)process);
- GDBRemoteClientBase::Lock lock(gdb_comm, false);
+ GDBRemoteClientBase::Lock lock(gdb_comm);
if (lock) {
if (gdb_comm.SyncThreadState(m_thread.GetProtocolID()))
InvalidateAllRegisters();
@@ -567,7 +574,7 @@
const bool use_g_packet =
!gdb_comm.AvoidGPackets((ProcessGDBRemote *)process);
- GDBRemoteClientBase::Lock lock(gdb_comm, false);
+ GDBRemoteClientBase::Lock lock(gdb_comm);
if (lock) {
// The data_sp contains the G response packet.
if (use_g_packet) {
diff --git a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
index 252d7b3..18fcb73 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
@@ -118,6 +118,7 @@
DataExtractor m_reg_data;
bool m_read_all_at_once;
bool m_write_all_at_once;
+ bool m_gpacket_cached;
private:
// Helper function for ReadRegisterBytes().
diff --git a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index aba870c..6914b37 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -8,8 +8,8 @@
#include "lldb/Host/Config.h"
-#include <errno.h>
-#include <stdlib.h>
+#include <cerrno>
+#include <cstdlib>
#if LLDB_ENABLE_POSIX
#include <netinet/in.h>
#include <sys/mman.h>
@@ -20,8 +20,8 @@
#if defined(__APPLE__)
#include <sys/sysctl.h>
#endif
+#include <ctime>
#include <sys/types.h>
-#include <time.h>
#include <algorithm>
#include <csignal>
@@ -135,7 +135,7 @@
m_collection_sp->Initialize(g_processgdbremote_properties);
}
- ~PluginProperties() override {}
+ ~PluginProperties() override = default;
uint64_t GetPacketTimeout() {
const uint32_t idx = ePropertyPacketTimeout;
@@ -213,6 +213,10 @@
return process_sp;
}
+std::chrono::seconds ProcessGDBRemote::GetPacketTimeout() {
+ return std::chrono::seconds(GetGlobalPluginProperties()->GetPacketTimeout());
+}
+
bool ProcessGDBRemote::CanDebug(lldb::TargetSP target_sp,
bool plugin_specified_by_name) {
if (plugin_specified_by_name)
@@ -461,7 +465,7 @@
assert(packet_len < (int)sizeof(packet));
UNUSED_IF_ASSERT_DISABLED(packet_len);
StringExtractorGDBRemote response;
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet, response, false) ==
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet, response) ==
GDBRemoteCommunication::PacketResult::Success) {
response_type = response.GetResponseType();
if (response_type == StringExtractorGDBRemote::eResponse) {
@@ -1011,7 +1015,7 @@
for (size_t idx = 0; idx < num_cmds; idx++) {
StringExtractorGDBRemote response;
m_gdb_comm.SendPacketAndWaitForResponse(
- GetExtraStartupCommands().GetArgumentAtIndex(idx), response, false);
+ GetExtraStartupCommands().GetArgumentAtIndex(idx), response);
}
return error;
}
@@ -1038,6 +1042,12 @@
process_arch.GetTriple().getTriple());
}
+ if (int addresssable_bits = m_gdb_comm.GetAddressingBits()) {
+ lldb::addr_t address_mask = ~((1ULL << addresssable_bits) - 1);
+ SetCodeAddressMask(address_mask);
+ SetDataAddressMask(address_mask);
+ }
+
if (process_arch.IsValid()) {
const ArchSpec &target_arch = GetTarget().GetArchitecture();
if (target_arch.IsValid()) {
@@ -1199,34 +1209,26 @@
return error;
}
-lldb::user_id_t ProcessGDBRemote::StartTrace(const TraceOptions &options,
- Status &error) {
- return m_gdb_comm.SendStartTracePacket(options, error);
+llvm::Expected<TraceSupportedResponse> ProcessGDBRemote::TraceSupported() {
+ return m_gdb_comm.SendTraceSupported(GetInterruptTimeout());
}
-Status ProcessGDBRemote::StopTrace(lldb::user_id_t uid, lldb::tid_t thread_id) {
- return m_gdb_comm.SendStopTracePacket(uid, thread_id);
+llvm::Error ProcessGDBRemote::TraceStop(const TraceStopRequest &request) {
+ return m_gdb_comm.SendTraceStop(request, GetInterruptTimeout());
}
-Status ProcessGDBRemote::GetData(lldb::user_id_t uid, lldb::tid_t thread_id,
- llvm::MutableArrayRef<uint8_t> &buffer,
- size_t offset) {
- return m_gdb_comm.SendGetDataPacket(uid, thread_id, buffer, offset);
+llvm::Error ProcessGDBRemote::TraceStart(const llvm::json::Value &request) {
+ return m_gdb_comm.SendTraceStart(request, GetInterruptTimeout());
}
-Status ProcessGDBRemote::GetMetaData(lldb::user_id_t uid, lldb::tid_t thread_id,
- llvm::MutableArrayRef<uint8_t> &buffer,
- size_t offset) {
- return m_gdb_comm.SendGetMetaDataPacket(uid, thread_id, buffer, offset);
+llvm::Expected<std::string>
+ProcessGDBRemote::TraceGetState(llvm::StringRef type) {
+ return m_gdb_comm.SendTraceGetState(type, GetInterruptTimeout());
}
-Status ProcessGDBRemote::GetTraceConfig(lldb::user_id_t uid,
- TraceOptions &options) {
- return m_gdb_comm.SendGetTraceConfigPacket(uid, options);
-}
-
-llvm::Expected<TraceTypeInfo> ProcessGDBRemote::GetSupportedTraceType() {
- return m_gdb_comm.SendGetSupportedTraceType();
+llvm::Expected<std::vector<uint8_t>>
+ProcessGDBRemote::TraceGetBinaryData(const TraceGetBinaryDataRequest &request) {
+ return m_gdb_comm.SendTraceGetBinaryData(request, GetInterruptTimeout());
}
void ProcessGDBRemote::DidExit() {
@@ -1471,7 +1473,7 @@
while (true) {
// Send vStopped
StringExtractorGDBRemote response;
- m_gdb_comm.SendPacketAndWaitForResponse("vStopped", response, false);
+ m_gdb_comm.SendPacketAndWaitForResponse("vStopped", response);
// OK represents end of signal list
if (response.IsOKResponse())
@@ -1491,22 +1493,22 @@
m_thread_pcs.clear();
}
-size_t
-ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue(std::string &value) {
+size_t ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue(
+ llvm::StringRef value) {
m_thread_ids.clear();
- size_t comma_pos;
- lldb::tid_t tid;
- while ((comma_pos = value.find(',')) != std::string::npos) {
- value[comma_pos] = '\0';
- // thread in big endian hex
- tid = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_THREAD_ID, 16);
- if (tid != LLDB_INVALID_THREAD_ID)
- m_thread_ids.push_back(tid);
- value.erase(0, comma_pos + 1);
- }
- tid = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_THREAD_ID, 16);
- if (tid != LLDB_INVALID_THREAD_ID)
- m_thread_ids.push_back(tid);
+ lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID();
+ StringExtractorGDBRemote thread_ids{value};
+
+ do {
+ auto pid_tid = thread_ids.GetPidTid(pid);
+ if (pid_tid && pid_tid->first == pid) {
+ lldb::tid_t tid = pid_tid->second;
+ if (tid != LLDB_INVALID_THREAD_ID &&
+ tid != StringExtractorGDBRemote::AllProcesses)
+ m_thread_ids.push_back(tid);
+ }
+ } while (thread_ids.GetChar() == ',');
+
return m_thread_ids.size();
}
@@ -1523,7 +1525,7 @@
value.erase(0, comma_pos + 1);
}
pc = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_ADDRESS, 16);
- if (pc != LLDB_INVALID_THREAD_ID)
+ if (pc != LLDB_INVALID_ADDRESS)
m_thread_pcs.push_back(pc);
return m_thread_pcs.size();
}
@@ -1748,7 +1750,9 @@
if (thread_sp) {
ThreadGDBRemote *gdb_thread =
static_cast<ThreadGDBRemote *>(thread_sp.get());
- gdb_thread->GetRegisterContext()->InvalidateIfNeeded(true);
+ RegisterContextSP gdb_reg_ctx_sp(gdb_thread->GetRegisterContext());
+
+ gdb_reg_ctx_sp->InvalidateIfNeeded(true);
auto iter = std::find(m_thread_ids.begin(), m_thread_ids.end(), tid);
if (iter != m_thread_ids.end()) {
@@ -1760,7 +1764,10 @@
DataBufferSP buffer_sp(new DataBufferHeap(
reg_value_extractor.GetStringRef().size() / 2, 0));
reg_value_extractor.GetHexBytes(buffer_sp->GetData(), '\xcc');
- gdb_thread->PrivateSetRegisterValue(pair.first, buffer_sp->GetData());
+ uint32_t lldb_regnum =
+ gdb_reg_ctx_sp->ConvertRegisterKindToRegisterNumber(
+ eRegisterKindProcessPlugin, pair.first);
+ gdb_thread->PrivateSetRegisterValue(lldb_regnum, buffer_sp->GetData());
}
// AArch64 SVE specific code below calls AArch64SVEReconfigure to update
@@ -1825,8 +1832,7 @@
// If the current pc is a breakpoint site then the StopInfo
// should be set to Breakpoint Otherwise, it will be set to
// Trace.
- if (bp_site_sp &&
- bp_site_sp->ValidForThisThread(thread_sp.get())) {
+ if (bp_site_sp && bp_site_sp->ValidForThisThread(*thread_sp)) {
thread_sp->SetStopInfo(
StopInfo::CreateStopReasonWithBreakpointSiteID(
*thread_sp, bp_site_sp->GetID()));
@@ -1846,7 +1852,7 @@
// breakpoint here, that will be taken care of when the thread
// resumes and notices that there's a breakpoint under the pc.
handled = true;
- if (bp_site_sp->ValidForThisThread(thread_sp.get())) {
+ if (bp_site_sp->ValidForThisThread(*thread_sp)) {
thread_sp->SetStopInfo(
StopInfo::CreateStopReasonWithBreakpointSiteID(
*thread_sp, bp_site_sp->GetID()));
@@ -1897,6 +1903,9 @@
thread_sp->SetStopInfo(
StopInfo::CreateStopReasonWithExec(*thread_sp));
handled = true;
+ } else if (reason == "processor trace") {
+ thread_sp->SetStopInfo(StopInfo::CreateStopReasonProcessorTrace(
+ *thread_sp, description.c_str()));
}
} else if (!signo) {
addr_t pc = thread_sp->GetRegisterContext()->GetPC();
@@ -1909,7 +1918,7 @@
// as such. This can happen when the thread is involuntarily
// interrupted (e.g. due to stops on other threads) just as it is
// about to execute the breakpoint instruction.
- if (bp_site_sp && bp_site_sp->ValidForThisThread(thread_sp.get())) {
+ if (bp_site_sp && bp_site_sp->ValidForThisThread(*thread_sp)) {
thread_sp->SetStopInfo(
StopInfo::CreateStopReasonWithBreakpointSiteID(
*thread_sp, bp_site_sp->GetID()));
@@ -1934,7 +1943,7 @@
// reason. We don't need to worry about stepping over the
// breakpoint here, that will be taken care of when the thread
// resumes and notices that there's a breakpoint under the pc.
- if (bp_site_sp->ValidForThisThread(thread_sp.get())) {
+ if (bp_site_sp->ValidForThisThread(*thread_sp)) {
if (m_breakpoint_pc_offset != 0)
thread_sp->GetRegisterContext()->SetPC(pc);
thread_sp->SetStopInfo(
@@ -2137,6 +2146,7 @@
}
StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) {
+ lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID();
stop_packet.SetFilePos(0);
const char stop_type = stop_packet.GetChar();
switch (stop_type) {
@@ -2151,14 +2161,12 @@
if (stop_id == 0) {
// Our first stop, make sure we have a process ID, and also make sure we
// know about our registers
- if (GetID() == LLDB_INVALID_PROCESS_ID) {
- lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID();
- if (pid != LLDB_INVALID_PROCESS_ID)
- SetID(pid);
- }
+ if (GetID() == LLDB_INVALID_PROCESS_ID && pid != LLDB_INVALID_PROCESS_ID)
+ SetID(pid);
BuildDynamicRegisterInfo(true);
}
// Stop with signal and thread info
+ lldb::pid_t stop_pid = LLDB_INVALID_PROCESS_ID;
lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
const uint8_t signo = stop_packet.GetHexU8();
llvm::StringRef key;
@@ -2187,24 +2195,18 @@
value.getAsInteger(16, x);
exc_data.push_back(x);
} else if (key.compare("thread") == 0) {
- // thread in big endian hex
- if (value.getAsInteger(16, tid))
+ // thread-id
+ StringExtractorGDBRemote thread_id{value};
+ auto pid_tid = thread_id.GetPidTid(pid);
+ if (pid_tid) {
+ stop_pid = pid_tid->first;
+ tid = pid_tid->second;
+ } else
tid = LLDB_INVALID_THREAD_ID;
} else if (key.compare("threads") == 0) {
std::lock_guard<std::recursive_mutex> guard(
m_thread_list_real.GetMutex());
-
- m_thread_ids.clear();
- // A comma separated list of all threads in the current
- // process that includes the thread for this stop reply packet
- lldb::tid_t tid;
- while (!value.empty()) {
- llvm::StringRef tid_str;
- std::tie(tid_str, value) = value.split(',');
- if (tid_str.getAsInteger(16, tid))
- tid = LLDB_INVALID_THREAD_ID;
- m_thread_ids.push_back(tid);
- }
+ UpdateThreadIDsFromStopReplyThreadsValue(value);
} else if (key.compare("thread-pcs") == 0) {
m_thread_pcs.clear();
// A comma separated list of all threads in the current
@@ -2317,6 +2319,14 @@
}
}
+ if (stop_pid != LLDB_INVALID_PROCESS_ID && stop_pid != pid) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ LLDB_LOG(log,
+ "Received stop for incorrect PID = {0} (inferior PID = {1})",
+ stop_pid, pid);
+ return eStateInvalid;
+ }
+
if (tid == LLDB_INVALID_THREAD_ID) {
// A thread id may be invalid if the response is old style 'S' packet
// which does not provide the
@@ -2404,7 +2414,7 @@
// file handle and debugserver will go away, and we can be done...
m_gdb_comm.Disconnect();
} else
- caused_stop = m_gdb_comm.Interrupt();
+ caused_stop = m_gdb_comm.Interrupt(GetInterruptTimeout());
return error;
}
@@ -2553,11 +2563,11 @@
if (m_gdb_comm.IsConnected()) {
if (m_public_state.GetValue() != eStateAttaching) {
StringExtractorGDBRemote response;
- bool send_async = true;
GDBRemoteCommunication::ScopedTimeout(m_gdb_comm,
std::chrono::seconds(3));
- if (m_gdb_comm.SendPacketAndWaitForResponse("k", response, send_async) ==
+ if (m_gdb_comm.SendPacketAndWaitForResponse("k", response,
+ GetInterruptTimeout()) ==
GDBRemoteCommunication::PacketResult::Success) {
char packet_cmd = response.GetChar(0);
@@ -2721,7 +2731,8 @@
assert(packet_len + 1 < (int)sizeof(packet));
UNUSED_IF_ASSERT_DISABLED(packet_len);
StringExtractorGDBRemote response;
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet, response, true) ==
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet, response,
+ GetInterruptTimeout()) ==
GDBRemoteCommunication::PacketResult::Success) {
if (response.IsNormalResponse()) {
error.Clear();
@@ -2757,6 +2768,37 @@
return 0;
}
+bool ProcessGDBRemote::SupportsMemoryTagging() {
+ return m_gdb_comm.GetMemoryTaggingSupported();
+}
+
+llvm::Expected<std::vector<uint8_t>>
+ProcessGDBRemote::DoReadMemoryTags(lldb::addr_t addr, size_t len,
+ int32_t type) {
+ // By this point ReadMemoryTags has validated that tagging is enabled
+ // for this target/process/address.
+ DataBufferSP buffer_sp = m_gdb_comm.ReadMemoryTags(addr, len, type);
+ if (!buffer_sp) {
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Error reading memory tags from remote");
+ }
+
+ // Return the raw tag data
+ llvm::ArrayRef<uint8_t> tag_data = buffer_sp->GetData();
+ std::vector<uint8_t> got;
+ got.reserve(tag_data.size());
+ std::copy(tag_data.begin(), tag_data.end(), std::back_inserter(got));
+ return got;
+}
+
+Status ProcessGDBRemote::DoWriteMemoryTags(lldb::addr_t addr, size_t len,
+ int32_t type,
+ const std::vector<uint8_t> &tags) {
+ // By now WriteMemoryTags should have validated that tagging is enabled
+ // for this target/process.
+ return m_gdb_comm.WriteMemoryTags(addr, len, type, tags);
+}
+
Status ProcessGDBRemote::WriteObjectFile(
std::vector<ObjectFile::LoadableData> entries) {
Status error;
@@ -2847,7 +2889,7 @@
StringExtractorGDBRemote response;
if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response,
- true) ==
+ GetInterruptTimeout()) ==
GDBRemoteCommunication::PacketResult::Success) {
if (response.IsOKResponse()) {
m_erased_flash_ranges.Insert(range, true);
@@ -2876,7 +2918,8 @@
if (m_erased_flash_ranges.IsEmpty())
return status;
StringExtractorGDBRemote response;
- if (m_gdb_comm.SendPacketAndWaitForResponse("vFlashDone", response, true) ==
+ if (m_gdb_comm.SendPacketAndWaitForResponse("vFlashDone", response,
+ GetInterruptTimeout()) ==
GDBRemoteCommunication::PacketResult::Success) {
if (response.IsOKResponse()) {
m_erased_flash_ranges.Clear();
@@ -2937,7 +2980,7 @@
}
StringExtractorGDBRemote response;
if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response,
- true) ==
+ GetInterruptTimeout()) ==
GDBRemoteCommunication::PacketResult::Success) {
if (response.IsOKResponse()) {
error.Clear();
@@ -3113,7 +3156,7 @@
(!bp_site->HardwareRequired())) {
// Try to send off a software breakpoint packet ($Z0)
uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket(
- eBreakpointSoftware, true, addr, bp_op_size);
+ eBreakpointSoftware, true, addr, bp_op_size, GetInterruptTimeout());
if (error_no == 0) {
// The breakpoint was placed successfully
bp_site->SetEnabled(true);
@@ -3153,7 +3196,7 @@
if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) {
// Try to send off a hardware breakpoint packet ($Z1)
uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket(
- eBreakpointHardware, true, addr, bp_op_size);
+ eBreakpointHardware, true, addr, bp_op_size, GetInterruptTimeout());
if (error_no == 0) {
// The breakpoint was placed successfully
bp_site->SetEnabled(true);
@@ -3217,13 +3260,15 @@
case BreakpointSite::eHardware:
if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, false,
- addr, bp_op_size))
+ addr, bp_op_size,
+ GetInterruptTimeout()))
error.SetErrorToGenericError();
break;
case BreakpointSite::eExternal: {
if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, false,
- addr, bp_op_size))
+ addr, bp_op_size,
+ GetInterruptTimeout()))
error.SetErrorToGenericError();
} break;
}
@@ -3279,7 +3324,8 @@
// Pass down an appropriate z/Z packet...
if (m_gdb_comm.SupportsGDBStoppointPacket(type)) {
if (m_gdb_comm.SendGDBStoppointTypePacket(type, true, addr,
- wp->GetByteSize()) == 0) {
+ wp->GetByteSize(),
+ GetInterruptTimeout()) == 0) {
wp->SetEnabled(true, notify);
return error;
} else
@@ -3325,7 +3371,8 @@
GDBStoppointType type = GetGDBStoppointType(wp);
// Pass down an appropriate z/Z packet...
if (m_gdb_comm.SendGDBStoppointTypePacket(type, false, addr,
- wp->GetByteSize()) == 0) {
+ wp->GetByteSize(),
+ GetInterruptTimeout()) == 0) {
wp->SetEnabled(false, notify);
return error;
} else
@@ -3350,7 +3397,7 @@
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
LLDB_LOGF(log, "ProcessGDBRemote::DoSignal (signal = %d)", signo);
- if (!m_gdb_comm.SendAsyncSignal(signo))
+ if (!m_gdb_comm.SendAsyncSignal(signo, GetInterruptTimeout()))
error.SetErrorStringWithFormat("failed to send signal %i", signo);
return error;
}
@@ -3678,12 +3725,25 @@
__FUNCTION__, arg, process->GetID());
EventSP event_sp;
+
+ // We need to ignore any packets that come in after we have
+ // have decided the process has exited. There are some
+ // situations, for instance when we try to interrupt a running
+ // process and the interrupt fails, where another packet might
+ // get delivered after we've decided to give up on the process.
+ // But once we've decided we are done with the process we will
+ // not be in a state to do anything useful with new packets.
+ // So it is safer to simply ignore any remaining packets by
+ // explicitly checking for eStateExited before reentering the
+ // fetch loop.
+
bool done = false;
- while (!done) {
+ while (!done && process->GetPrivateState() != eStateExited) {
LLDB_LOGF(log,
"ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
") listener.WaitForEvent (NULL, event_sp)...",
__FUNCTION__, arg, process->GetID());
+
if (process->m_async_listener_sp->GetEvent(event_sp, llvm::None)) {
const uint32_t event_type = event_sp->GetType();
if (event_sp->BroadcasterIs(&process->m_async_broadcaster)) {
@@ -3715,7 +3775,7 @@
// send the vCont packet
if (!process->GetGDBRemote().SendvContPacket(
llvm::StringRef(continue_cstr, continue_cstr_len),
- response)) {
+ process->GetInterruptTimeout(), response)) {
// Something went wrong
done = true;
break;
@@ -3727,6 +3787,7 @@
process->GetGDBRemote().SendContinuePacketAndWaitForResponse(
*process, *process->GetUnixSignals(),
llvm::StringRef(continue_cstr, continue_cstr_len),
+ process->GetInterruptTimeout(),
response);
// We need to immediately clear the thread ID list so we are sure
@@ -3782,6 +3843,7 @@
} else {
process->SetExitStatus(-1, "lost connection");
}
+ done = true;
break;
}
@@ -4020,8 +4082,7 @@
StringExtractorGDBRemote response;
response.SetResponseValidatorToJSON();
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response,
- false) ==
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) ==
GDBRemoteCommunication::PacketResult::Success) {
StringExtractorGDBRemote::ResponseType response_type =
response.GetResponseType();
@@ -4093,8 +4154,7 @@
StringExtractorGDBRemote response;
response.SetResponseValidatorToJSON();
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response,
- false) ==
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) ==
GDBRemoteCommunication::PacketResult::Success) {
StringExtractorGDBRemote::ResponseType response_type =
response.GetResponseType();
@@ -4127,8 +4187,7 @@
StringExtractorGDBRemote response;
response.SetResponseValidatorToJSON();
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response,
- false) ==
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) ==
GDBRemoteCommunication::PacketResult::Success) {
StringExtractorGDBRemote::ResponseType response_type =
response.GetResponseType();
@@ -4894,8 +4953,7 @@
packet.PutStringAsRawHex8(file_path);
StringExtractorGDBRemote response;
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response,
- false) !=
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) !=
GDBRemoteCommunication::PacketResult::Success)
return Status("Sending qFileLoadAddress packet failed");
@@ -5131,7 +5189,7 @@
m_option_group.Finalize();
}
- ~CommandObjectProcessGDBRemoteSpeedTest() override {}
+ ~CommandObjectProcessGDBRemoteSpeedTest() override = default;
Options *GetOptions() override { return &m_option_group; }
@@ -5182,7 +5240,7 @@
: CommandObjectParsed(interpreter, "process plugin packet history",
"Dumps the packet history buffer. ", nullptr) {}
- ~CommandObjectProcessGDBRemotePacketHistory() override {}
+ ~CommandObjectProcessGDBRemotePacketHistory() override = default;
bool DoExecute(Args &command, CommandReturnObject &result) override {
const size_t argc = command.GetArgumentCount();
@@ -5213,7 +5271,7 @@
"Maximum size that lldb will try to read/write one one chunk.",
nullptr) {}
- ~CommandObjectProcessGDBRemotePacketXferSize() override {}
+ ~CommandObjectProcessGDBRemotePacketXferSize() override = default;
bool DoExecute(Args &command, CommandReturnObject &result) override {
const size_t argc = command.GetArgumentCount();
@@ -5222,7 +5280,6 @@
"amount to be transferred when "
"reading/writing",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -5255,7 +5312,7 @@
"stripped from the result.",
nullptr) {}
- ~CommandObjectProcessGDBRemotePacketSend() override {}
+ ~CommandObjectProcessGDBRemotePacketSend() override = default;
bool DoExecute(Args &command, CommandReturnObject &result) override {
const size_t argc = command.GetArgumentCount();
@@ -5263,7 +5320,6 @@
result.AppendErrorWithFormat(
"'%s' takes a one or more packet content arguments",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -5272,10 +5328,9 @@
if (process) {
for (size_t i = 0; i < argc; ++i) {
const char *packet_cstr = command.GetArgumentAtIndex(0);
- bool send_async = true;
StringExtractorGDBRemote response;
process->GetGDBRemote().SendPacketAndWaitForResponse(
- packet_cstr, response, send_async);
+ packet_cstr, response, process->GetInterruptTimeout());
result.SetStatus(eReturnStatusSuccessFinishResult);
Stream &output_strm = result.GetOutputStream();
output_strm.Printf(" packet: %s\n", packet_cstr);
@@ -5306,14 +5361,13 @@
"encoded into a valid 'qRcmd' packet, sent and the "
"response will be printed.") {}
- ~CommandObjectProcessGDBRemotePacketMonitor() override {}
+ ~CommandObjectProcessGDBRemotePacketMonitor() override = default;
bool DoExecute(llvm::StringRef command,
CommandReturnObject &result) override {
if (command.empty()) {
result.AppendErrorWithFormat("'%s' takes a command string argument",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -5324,11 +5378,10 @@
packet.PutCString("qRcmd,");
packet.PutBytesAsRawHex8(command.data(), command.size());
- bool send_async = true;
StringExtractorGDBRemote response;
Stream &output_strm = result.GetOutputStream();
process->GetGDBRemote().SendPacketAndReceiveResponseWithOutputSupport(
- packet.GetString(), response, send_async,
+ packet.GetString(), response, process->GetInterruptTimeout(),
[&output_strm](llvm::StringRef output) { output_strm << output; });
result.SetStatus(eReturnStatusSuccessFinishResult);
output_strm.Printf(" packet: %s\n", packet.GetData());
@@ -5370,7 +5423,7 @@
interpreter)));
}
- ~CommandObjectProcessGDBRemotePacket() override {}
+ ~CommandObjectProcessGDBRemotePacket() override = default;
};
class CommandObjectMultiwordProcessGDBRemote : public CommandObjectMultiword {
@@ -5385,7 +5438,7 @@
CommandObjectSP(new CommandObjectProcessGDBRemotePacket(interpreter)));
}
- ~CommandObjectMultiwordProcessGDBRemote() override {}
+ ~CommandObjectMultiwordProcessGDBRemote() override = default;
};
CommandObject *ProcessGDBRemote::GetPluginCommandObject() {
diff --git a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 0921bf1..fe04cdd 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/src/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -68,6 +68,8 @@
static const char *GetPluginDescriptionStatic();
+ static std::chrono::seconds GetPacketTimeout();
+
// Check if a given Process
bool CanDebug(lldb::TargetSP target_sp,
bool plugin_specified_by_name) override;
@@ -163,22 +165,16 @@
Status GetWatchpointSupportInfo(uint32_t &num) override;
- lldb::user_id_t StartTrace(const TraceOptions &options,
- Status &error) override;
+ llvm::Expected<TraceSupportedResponse> TraceSupported() override;
- Status StopTrace(lldb::user_id_t uid, lldb::tid_t thread_id) override;
+ llvm::Error TraceStop(const TraceStopRequest &request) override;
- Status GetData(lldb::user_id_t uid, lldb::tid_t thread_id,
- llvm::MutableArrayRef<uint8_t> &buffer,
- size_t offset = 0) override;
+ llvm::Error TraceStart(const llvm::json::Value &request) override;
- Status GetMetaData(lldb::user_id_t uid, lldb::tid_t thread_id,
- llvm::MutableArrayRef<uint8_t> &buffer,
- size_t offset = 0) override;
+ llvm::Expected<std::string> TraceGetState(llvm::StringRef type) override;
- llvm::Expected<TraceTypeInfo> GetSupportedTraceType() override;
-
- Status GetTraceConfig(lldb::user_id_t uid, TraceOptions &options) override;
+ llvm::Expected<std::vector<uint8_t>>
+ TraceGetBinaryData(const TraceGetBinaryDataRequest &request) override;
Status GetWatchpointSupportInfo(uint32_t &num, bool &after) override;
@@ -239,6 +235,8 @@
friend class GDBRemoteCommunicationClient;
friend class GDBRemoteRegisterContext;
+ bool SupportsMemoryTagging() override;
+
/// Broadcaster event bits definitions.
enum {
eBroadcastBitAsyncContinue = (1 << 0),
@@ -339,7 +337,7 @@
size_t UpdateThreadPCsFromStopReplyThreadsValue(std::string &value);
- size_t UpdateThreadIDsFromStopReplyThreadsValue(std::string &value);
+ size_t UpdateThreadIDsFromStopReplyThreadsValue(llvm::StringRef value);
bool HandleNotifyPacket(StringExtractorGDBRemote &packet);
@@ -410,6 +408,12 @@
bool HasErased(FlashRange range);
+ llvm::Expected<std::vector<uint8_t>>
+ DoReadMemoryTags(lldb::addr_t addr, size_t len, int32_t type) override;
+
+ Status DoWriteMemoryTags(lldb::addr_t addr, size_t len, int32_t type,
+ const std::vector<uint8_t> &tags) override;
+
private:
// For ProcessGDBRemote only
std::string m_partial_profile_data;
diff --git a/src/llvm-project/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp b/src/llvm-project/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp
index 0f77110..84548ed 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#include <errno.h>
-#include <stdlib.h>
+#include <cerrno>
+#include <cstdlib>
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Threading.h"
@@ -21,6 +21,7 @@
#include "lldb/Symbol/LocateSymbolFile.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/MemoryRegionInfo.h"
+#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBuffer.h"
@@ -36,6 +37,7 @@
#include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h"
#include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h"
+#include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h"
#include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
#include <memory>
@@ -188,6 +190,59 @@
return false;
}
+// We have a hint about a binary -- a UUID, possibly a load address.
+// Try to load a file with that UUID into lldb, and if we have a load
+// address, set it correctly. Else assume that the binary was loaded
+// with no slide.
+static bool load_standalone_binary(UUID uuid, addr_t addr, Target &target) {
+ if (uuid.IsValid()) {
+ ModuleSpec module_spec;
+ module_spec.GetUUID() = uuid;
+
+ // Look up UUID in global module cache before attempting
+ // dsymForUUID-like action.
+ ModuleSP module_sp;
+ Status error = ModuleList::GetSharedModule(module_spec, module_sp, nullptr,
+ nullptr, nullptr);
+
+ if (!module_sp.get()) {
+ // Force a a dsymForUUID lookup, if that tool is available.
+ if (!module_spec.GetSymbolFileSpec())
+ Symbols::DownloadObjectAndSymbolFile(module_spec, true);
+
+ if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) {
+ module_sp = std::make_shared<Module>(module_spec);
+ }
+ }
+
+ if (module_sp.get() && module_sp->GetObjectFile()) {
+ target.SetArchitecture(module_sp->GetObjectFile()->GetArchitecture());
+ target.GetImages().AppendIfNeeded(module_sp, false);
+
+ Address base_addr = module_sp->GetObjectFile()->GetBaseAddress();
+ addr_t slide = 0;
+ if (addr != LLDB_INVALID_ADDRESS && base_addr.IsValid()) {
+ addr_t file_load_addr = base_addr.GetFileAddress();
+ slide = addr - file_load_addr;
+ }
+ bool changed = false;
+ module_sp->SetLoadAddress(target, slide, true, changed);
+
+ ModuleList added_module;
+ added_module.Append(module_sp, false);
+ target.ModulesDidLoad(added_module);
+
+ // Flush info in the process (stack frames, etc).
+ ProcessSP process_sp(target.GetProcessSP());
+ if (process_sp)
+ process_sp->Flush();
+
+ return true;
+ }
+ }
+ return false;
+}
+
// Process Control
Status ProcessMachCore::DoLoadCore() {
Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER |
@@ -277,7 +332,6 @@
m_core_range_infos.Sort();
}
-
bool found_main_binary_definitively = false;
addr_t objfile_binary_addr;
@@ -285,124 +339,86 @@
ObjectFile::BinaryType type;
if (core_objfile->GetCorefileMainBinaryInfo(objfile_binary_addr,
objfile_binary_uuid, type)) {
- if (objfile_binary_addr != LLDB_INVALID_ADDRESS)
- {
- m_mach_kernel_addr = objfile_binary_addr;
+ if (log) {
+ log->Printf(
+ "ProcessMachCore::DoLoadCore: using binary hint from 'main bin spec' "
+ "LC_NOTE with UUID %s address 0x%" PRIx64 " and type %d",
+ objfile_binary_uuid.GetAsString().c_str(), objfile_binary_addr, type);
+ }
+ if (objfile_binary_addr != LLDB_INVALID_ADDRESS) {
+ if (type == ObjectFile::eBinaryTypeUser) {
+ m_dyld_addr = objfile_binary_addr;
+ m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic();
found_main_binary_definitively = true;
- LLDB_LOGF(log,
- "ProcessMachCore::DoLoadCore: using kernel address 0x%" PRIx64
- " from LC_NOTE 'main bin spec' load command.",
- m_mach_kernel_addr);
+ }
+ if (type == ObjectFile::eBinaryTypeKernel) {
+ m_mach_kernel_addr = objfile_binary_addr;
+ m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();
+ found_main_binary_definitively = true;
+ }
+ }
+ if (!found_main_binary_definitively) {
+ // ObjectFile::eBinaryTypeStandalone, undeclared types
+ if (load_standalone_binary(objfile_binary_uuid, objfile_binary_addr,
+ GetTarget())) {
+ found_main_binary_definitively = true;
+ m_dyld_plugin_name = DynamicLoaderStatic::GetPluginNameStatic();
+ }
}
}
// This checks for the presence of an LC_IDENT string in a core file;
// LC_IDENT is very obsolete and should not be used in new code, but if the
// load command is present, let's use the contents.
- std::string corefile_identifier = core_objfile->GetIdentifierString();
- if (!found_main_binary_definitively &&
- corefile_identifier.find("Darwin Kernel") != std::string::npos) {
- UUID uuid;
- addr_t addr = LLDB_INVALID_ADDRESS;
+ UUID ident_uuid;
+ addr_t ident_binary_addr = LLDB_INVALID_ADDRESS;
+ if (!found_main_binary_definitively) {
+ std::string corefile_identifier = core_objfile->GetIdentifierString();
+
+ // Search for UUID= and stext= strings in the identifier str.
if (corefile_identifier.find("UUID=") != std::string::npos) {
size_t p = corefile_identifier.find("UUID=") + strlen("UUID=");
std::string uuid_str = corefile_identifier.substr(p, 36);
- uuid.SetFromStringRef(uuid_str);
+ ident_uuid.SetFromStringRef(uuid_str);
+ if (log)
+ log->Printf("Got a UUID from LC_IDENT/kern ver str LC_NOTE: %s",
+ ident_uuid.GetAsString().c_str());
}
if (corefile_identifier.find("stext=") != std::string::npos) {
size_t p = corefile_identifier.find("stext=") + strlen("stext=");
if (corefile_identifier[p] == '0' && corefile_identifier[p + 1] == 'x') {
- errno = 0;
- addr = ::strtoul(corefile_identifier.c_str() + p, nullptr, 16);
- if (errno != 0 || addr == 0)
- addr = LLDB_INVALID_ADDRESS;
+ ident_binary_addr =
+ ::strtoul(corefile_identifier.c_str() + p, nullptr, 16);
+ if (log)
+ log->Printf("Got a load address from LC_IDENT/kern ver str "
+ "LC_NOTE: 0x%" PRIx64,
+ ident_binary_addr);
}
}
- if (uuid.IsValid() && addr != LLDB_INVALID_ADDRESS) {
- m_mach_kernel_addr = addr;
+
+ // Search for a "Darwin Kernel" str indicating kernel; else treat as
+ // standalone
+ if (corefile_identifier.find("Darwin Kernel") != std::string::npos &&
+ ident_uuid.IsValid() && ident_binary_addr != LLDB_INVALID_ADDRESS) {
+ if (log)
+ log->Printf("ProcessMachCore::DoLoadCore: Found kernel binary via "
+ "LC_IDENT/kern ver str LC_NOTE");
+ m_mach_kernel_addr = ident_binary_addr;
found_main_binary_definitively = true;
- LLDB_LOGF(
- log,
- "ProcessMachCore::DoLoadCore: Using the kernel address 0x%" PRIx64
- " from LC_IDENT/LC_NOTE 'kern ver str' string: '%s'",
- addr, corefile_identifier.c_str());
+ } else if (ident_uuid.IsValid()) {
+ if (load_standalone_binary(ident_uuid, ident_binary_addr, GetTarget())) {
+ found_main_binary_definitively = true;
+ m_dyld_plugin_name = DynamicLoaderStatic::GetPluginNameStatic();
+ }
}
}
- // In the case where we have an LC_NOTE specifying a standalone
- // binary with only a UUID (and no load address) (iBoot, EFI, etc),
- // then let's try to force a load of the binary and set its
- // load address to 0-offset.
- //
- // The two forms this can come in is either a
- // 'kern ver str' LC_NOTE with "EFI UUID=...."
- // 'main bin spec' LC_NOTE with UUID and no load address.
-
+ // If we have a "all image infos" LC_NOTE, try to load all of the
+ // binaries listed, and set their Section load addresses in the Target.
if (found_main_binary_definitively == false &&
- (corefile_identifier.find("EFI ") != std::string::npos ||
- (objfile_binary_uuid.IsValid() &&
- objfile_binary_addr == LLDB_INVALID_ADDRESS))) {
- UUID uuid;
- if (objfile_binary_uuid.IsValid()) {
- uuid = objfile_binary_uuid;
- LLDB_LOGF(log,
- "ProcessMachCore::DoLoadCore: Using the main bin spec "
- "LC_NOTE with UUID %s and no load address",
- uuid.GetAsString().c_str());
- } else {
- if (corefile_identifier.find("UUID=") != std::string::npos) {
- size_t p = corefile_identifier.find("UUID=") + strlen("UUID=");
- std::string uuid_str = corefile_identifier.substr(p, 36);
- uuid.SetFromStringRef(uuid_str);
- if (uuid.IsValid()) {
- LLDB_LOGF(log,
- "ProcessMachCore::DoLoadCore: Using the EFI "
- "from LC_IDENT/LC_NOTE 'kern ver str' string: '%s'",
- corefile_identifier.c_str());
- }
- }
- }
-
- if (uuid.IsValid()) {
- ModuleSpec module_spec;
- module_spec.GetUUID() = uuid;
- module_spec.GetArchitecture() = GetTarget().GetArchitecture();
-
- // Lookup UUID locally, before attempting dsymForUUID-like action
- FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
- module_spec.GetSymbolFileSpec() =
- Symbols::LocateExecutableSymbolFile(module_spec, search_paths);
- if (module_spec.GetSymbolFileSpec()) {
- ModuleSpec executable_module_spec =
- Symbols::LocateExecutableObjectFile(module_spec);
- if (FileSystem::Instance().Exists(
- executable_module_spec.GetFileSpec())) {
- module_spec.GetFileSpec() = executable_module_spec.GetFileSpec();
- }
- }
-
- // Force a a dsymForUUID lookup, if that tool is available.
- if (!module_spec.GetSymbolFileSpec())
- Symbols::DownloadObjectAndSymbolFile(module_spec, true);
-
- // If we found a binary, load it at offset 0 and set our
- // dyld_plugin to be the static plugin.
- if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) {
- ModuleSP module_sp(new Module(module_spec));
- if (module_sp.get() && module_sp->GetObjectFile()) {
- GetTarget().GetImages().AppendIfNeeded(module_sp, true);
- GetTarget().SetExecutableModule(module_sp, eLoadDependentsNo);
- found_main_binary_definitively = true;
- bool changed = true;
- module_sp->SetLoadAddress(GetTarget(), 0, true, changed);
- ModuleList added_module;
- added_module.Append(module_sp, false);
- GetTarget().ModulesDidLoad(added_module);
- m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();
- found_main_binary_definitively = true;
- }
- }
- }
+ core_objfile->LoadCoreFileImages(*this)) {
+ m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();
+ found_main_binary_definitively = true;
}
if (!found_main_binary_definitively &&
@@ -525,6 +541,11 @@
if (arch.IsValid())
GetTarget().SetArchitecture(arch);
+ addr_t address_mask = core_objfile->GetAddressMask();
+ if (address_mask != 0) {
+ SetCodeAddressMask(address_mask);
+ SetDataAddressMask(address_mask);
+ }
return error;
}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/src/llvm-project/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
index 05a48ac..3855574 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
@@ -138,10 +138,10 @@
///
/// \param[in] module_sp The module to grab the .text section from.
///
-/// \param[in/out] breakpad_uuid A vector that will receive the calculated
+/// \param[in,out] breakpad_uuid A vector that will receive the calculated
/// breakpad .text hash.
///
-/// \param[in/out] facebook_uuid A vector that will receive the calculated
+/// \param[in,out] facebook_uuid A vector that will receive the calculated
/// facebook .text hash.
///
void HashElfTextSection(ModuleSP module_sp, std::vector<uint8_t> &breakpad_uuid,
@@ -548,7 +548,7 @@
// check if the process is wow64 - a 32 bit windows process running on a
// 64 bit windows
- if (llvm::StringRef(name).endswith_lower("wow64.dll")) {
+ if (llvm::StringRef(name).endswith_insensitive("wow64.dll")) {
m_is_wow64 = true;
}
@@ -871,7 +871,7 @@
m_option_group.Finalize();
}
- ~CommandObjectProcessMinidumpDump() override {}
+ ~CommandObjectProcessMinidumpDump() override = default;
Options *GetOptions() override { return &m_option_group; }
@@ -880,7 +880,6 @@
if (argc > 0) {
result.AppendErrorWithFormat("'%s' take no arguments, only options",
m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
return false;
}
SetDefaultOptionsIfNoneAreSet();
@@ -1001,7 +1000,7 @@
CommandObjectSP(new CommandObjectProcessMinidumpDump(interpreter)));
}
- ~CommandObjectMultiwordProcessMinidump() override {}
+ ~CommandObjectMultiwordProcessMinidump() override = default;
};
CommandObject *ProcessMinidump::GetPluginCommandObject() {
diff --git a/src/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp b/src/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp
index eb48785..7e309e8 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp
@@ -16,7 +16,7 @@
#include "lldb/lldb-enumerations.h"
// C includes
-#include <assert.h>
+#include <cassert>
// C++ includes
diff --git a/src/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp b/src/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp
index c7809c5..e2b7c0e 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp
@@ -14,7 +14,7 @@
#include "lldb/lldb-enumerations.h"
// C includes
-#include <assert.h>
+#include <cassert>
// C++ includes
diff --git a/src/llvm-project/lldb/source/Plugins/Process/minidump/ThreadMinidump.cpp b/src/llvm-project/lldb/source/Plugins/Process/minidump/ThreadMinidump.cpp
index e146a1a..1fbc528 100644
--- a/src/llvm-project/lldb/source/Plugins/Process/minidump/ThreadMinidump.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Process/minidump/ThreadMinidump.cpp
@@ -38,7 +38,7 @@
: Thread(process, td.ThreadId), m_thread_reg_ctx_sp(),
m_gpregset_data(gpregset_data) {}
-ThreadMinidump::~ThreadMinidump() {}
+ThreadMinidump::~ThreadMinidump() = default;
void ThreadMinidump::RefreshStateAfterStop() {}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/scripted/CMakeLists.txt b/src/llvm-project/lldb/source/Plugins/Process/scripted/CMakeLists.txt
new file mode 100644
index 0000000..e2cfd05
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Process/scripted/CMakeLists.txt
@@ -0,0 +1,13 @@
+add_lldb_library(lldbPluginScriptedProcess PLUGIN
+ ScriptedProcess.cpp
+
+ LINK_LIBS
+ lldbCore
+ lldbTarget
+ lldbUtility
+ lldbPluginProcessUtility
+ LINK_COMPONENTS
+ BinaryFormat
+ Object
+ Support
+ )
diff --git a/src/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp b/src/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
new file mode 100644
index 0000000..09e9375
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp
@@ -0,0 +1,313 @@
+//===-- ScriptedProcess.cpp -----------------------------------------------===//
+//
+// 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 "ScriptedProcess.h"
+
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+
+#include "lldb/Host/OptionParser.h"
+#include "lldb/Host/ThreadLauncher.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/OptionArgParser.h"
+#include "lldb/Interpreter/OptionGroupBoolean.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
+#include "lldb/Target/MemoryRegionInfo.h"
+#include "lldb/Target/RegisterContext.h"
+
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/Logging.h"
+#include "lldb/Utility/State.h"
+
+#include <mutex>
+
+LLDB_PLUGIN_DEFINE(ScriptedProcess)
+
+using namespace lldb;
+using namespace lldb_private;
+
+ConstString ScriptedProcess::GetPluginNameStatic() {
+ static ConstString g_name("ScriptedProcess");
+ return g_name;
+}
+
+const char *ScriptedProcess::GetPluginDescriptionStatic() {
+ return "Scripted Process plug-in.";
+}
+
+static constexpr lldb::ScriptLanguage g_supported_script_languages[] = {
+ ScriptLanguage::eScriptLanguagePython,
+};
+
+bool ScriptedProcess::IsScriptLanguageSupported(lldb::ScriptLanguage language) {
+ llvm::ArrayRef<lldb::ScriptLanguage> supported_languages =
+ llvm::makeArrayRef(g_supported_script_languages);
+
+ return llvm::is_contained(supported_languages, language);
+}
+
+void ScriptedProcess::CheckInterpreterAndScriptObject() const {
+ lldbassert(m_interpreter && "Invalid Script Interpreter.");
+ lldbassert(m_script_object_sp && "Invalid Script Object.");
+}
+
+lldb::ProcessSP ScriptedProcess::CreateInstance(lldb::TargetSP target_sp,
+ lldb::ListenerSP listener_sp,
+ const FileSpec *file,
+ bool can_connect) {
+ if (!target_sp ||
+ !IsScriptLanguageSupported(target_sp->GetDebugger().GetScriptLanguage()))
+ return nullptr;
+
+ Status error;
+ ScriptedProcess::ScriptedProcessInfo scripted_process_info(
+ target_sp->GetProcessLaunchInfo());
+
+ auto process_sp = std::make_shared<ScriptedProcess>(
+ target_sp, listener_sp, scripted_process_info, error);
+
+ if (error.Fail() || !process_sp || !process_sp->m_script_object_sp ||
+ !process_sp->m_script_object_sp->IsValid()) {
+ LLDB_LOGF(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS), "%s",
+ error.AsCString());
+ return nullptr;
+ }
+
+ return process_sp;
+}
+
+bool ScriptedProcess::CanDebug(lldb::TargetSP target_sp,
+ bool plugin_specified_by_name) {
+ return true;
+}
+
+ScriptedProcess::ScriptedProcess(
+ lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
+ const ScriptedProcess::ScriptedProcessInfo &scripted_process_info,
+ Status &error)
+ : Process(target_sp, listener_sp),
+ m_scripted_process_info(scripted_process_info) {
+
+ if (!target_sp) {
+ error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s",
+ __FUNCTION__, "Invalid target");
+ return;
+ }
+
+ m_interpreter = target_sp->GetDebugger().GetScriptInterpreter();
+
+ if (!m_interpreter) {
+ error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s",
+ __FUNCTION__,
+ "Debugger has no Script Interpreter");
+ return;
+ }
+
+ StructuredData::ObjectSP object_sp = GetInterface().CreatePluginObject(
+ m_scripted_process_info.GetClassName().c_str(), target_sp,
+ m_scripted_process_info.GetDictionarySP());
+
+ if (!object_sp || !object_sp->IsValid()) {
+ error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s",
+ __FUNCTION__,
+ "Failed to create valid script object");
+ return;
+ }
+
+ m_script_object_sp = object_sp;
+}
+
+ScriptedProcess::~ScriptedProcess() {
+ Clear();
+ // We need to call finalize on the process before destroying ourselves to
+ // make sure all of the broadcaster cleanup goes as planned. If we destruct
+ // this class, then Process::~Process() might have problems trying to fully
+ // destroy the broadcaster.
+ Finalize();
+}
+
+void ScriptedProcess::Initialize() {
+ static llvm::once_flag g_once_flag;
+
+ llvm::call_once(g_once_flag, []() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance);
+ });
+}
+
+void ScriptedProcess::Terminate() {
+ PluginManager::UnregisterPlugin(ScriptedProcess::CreateInstance);
+}
+
+ConstString ScriptedProcess::GetPluginName() { return GetPluginNameStatic(); }
+
+uint32_t ScriptedProcess::GetPluginVersion() { return 1; }
+
+Status ScriptedProcess::DoLoadCore() {
+ ProcessLaunchInfo launch_info = GetTarget().GetProcessLaunchInfo();
+
+ return DoLaunch(nullptr, launch_info);
+}
+
+Status ScriptedProcess::DoLaunch(Module *exe_module,
+ ProcessLaunchInfo &launch_info) {
+ CheckInterpreterAndScriptObject();
+
+ /* FIXME: This doesn't reflect how lldb actually launches a process.
+ In reality, it attaches to debugserver, then resume the process. */
+ Status error = GetInterface().Launch();
+ SetPrivateState(eStateRunning);
+
+ if (error.Fail())
+ return error;
+
+ // TODO: Fetch next state from stopped event queue then send stop event
+ // const StateType state = SetThreadStopInfo(response);
+ // if (state != eStateInvalid) {
+ // SetPrivateState(state);
+
+ SetPrivateState(eStateStopped);
+
+ UpdateThreadListIfNeeded();
+ GetThreadList();
+
+ return {};
+}
+
+void ScriptedProcess::DidLaunch() {
+ CheckInterpreterAndScriptObject();
+ m_pid = GetInterface().GetProcessID();
+}
+
+Status ScriptedProcess::DoResume() {
+ CheckInterpreterAndScriptObject();
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ // FIXME: Fetch data from thread.
+ const StateType thread_resume_state = eStateRunning;
+ LLDB_LOGF(log, "ScriptedProcess::%s thread_resume_state = %s", __FUNCTION__,
+ StateAsCString(thread_resume_state));
+
+ bool resume = (thread_resume_state == eStateRunning);
+ assert(thread_resume_state == eStateRunning && "invalid thread resume state");
+
+ Status error;
+ if (resume) {
+ LLDB_LOGF(log, "ScriptedProcess::%s sending resume", __FUNCTION__);
+
+ SetPrivateState(eStateRunning);
+ SetPrivateState(eStateStopped);
+ error = GetInterface().Resume();
+ }
+
+ return error;
+}
+
+Status ScriptedProcess::DoStop() {
+ CheckInterpreterAndScriptObject();
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ if (GetInterface().ShouldStop()) {
+ SetPrivateState(eStateStopped);
+ LLDB_LOGF(log, "ScriptedProcess::%s Immediate stop", __FUNCTION__);
+ return {};
+ }
+
+ LLDB_LOGF(log, "ScriptedProcess::%s Delayed stop", __FUNCTION__);
+ return GetInterface().Stop();
+}
+
+Status ScriptedProcess::DoDestroy() { return Status(); }
+
+bool ScriptedProcess::IsAlive() {
+ if (m_interpreter && m_script_object_sp)
+ return GetInterface().IsAlive();
+ return false;
+}
+
+size_t ScriptedProcess::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
+ Status &error) {
+
+ auto error_with_message = [&error](llvm::StringRef message) {
+ error.SetErrorString(message);
+ return 0;
+ };
+
+ if (!m_interpreter)
+ return error_with_message("No interpreter.");
+
+ lldb::DataExtractorSP data_extractor_sp =
+ GetInterface().ReadMemoryAtAddress(addr, size, error);
+
+ if (!data_extractor_sp || error.Fail())
+ return 0;
+
+ offset_t bytes_copied = data_extractor_sp->CopyByteOrderedData(
+ 0, data_extractor_sp->GetByteSize(), buf, size, GetByteOrder());
+
+ if (!bytes_copied || bytes_copied == LLDB_INVALID_OFFSET)
+ return error_with_message("Failed to copy read memory to buffer.");
+
+ return size;
+}
+
+ArchSpec ScriptedProcess::GetArchitecture() {
+ return GetTarget().GetArchitecture();
+}
+
+Status ScriptedProcess::GetMemoryRegionInfo(lldb::addr_t load_addr,
+ MemoryRegionInfo ®ion) {
+ // TODO: Implement
+ return Status();
+}
+
+Status ScriptedProcess::GetMemoryRegions(MemoryRegionInfos ®ion_list) {
+ CheckInterpreterAndScriptObject();
+
+ lldb::addr_t address = 0;
+ lldb::MemoryRegionInfoSP mem_region_sp = nullptr;
+
+ while ((mem_region_sp =
+ GetInterface().GetMemoryRegionContainingAddress(address))) {
+ auto range = mem_region_sp->GetRange();
+ address += range.GetRangeBase() + range.GetByteSize();
+ region_list.push_back(*mem_region_sp.get());
+ }
+
+ return {};
+}
+
+void ScriptedProcess::Clear() { Process::m_thread_list.Clear(); }
+
+bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list,
+ ThreadList &new_thread_list) {
+ // TODO: Implement
+ // This is supposed to get the current set of threads, if any of them are in
+ // old_thread_list then they get copied to new_thread_list, and then any
+ // actually new threads will get added to new_thread_list.
+ return new_thread_list.GetSize(false) > 0;
+}
+
+bool ScriptedProcess::GetProcessInfo(ProcessInstanceInfo &info) {
+ info.Clear();
+ info.SetProcessID(GetID());
+ info.SetArchitecture(GetArchitecture());
+ lldb::ModuleSP module_sp = GetTarget().GetExecutableModule();
+ if (module_sp) {
+ const bool add_exe_file_as_first_arg = false;
+ info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(),
+ add_exe_file_as_first_arg);
+ }
+ return true;
+}
+
+ScriptedProcessInterface &ScriptedProcess::GetInterface() const {
+ return m_interpreter->GetScriptedProcessInterface();
+}
diff --git a/src/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.h b/src/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.h
new file mode 100644
index 0000000..98c1a1c
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.h
@@ -0,0 +1,119 @@
+//===-- ScriptedProcess.h ------------------------------------- -*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_SCRIPTED_PROCESS_H
+#define LLDB_SOURCE_PLUGINS_SCRIPTED_PROCESS_H
+
+#include "lldb/Target/Process.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/Status.h"
+
+#include <mutex>
+
+namespace lldb_private {
+
+class ScriptedProcess : public Process {
+protected:
+ class ScriptedProcessInfo {
+ public:
+ ScriptedProcessInfo(const ProcessLaunchInfo &launch_info) {
+ m_class_name = launch_info.GetScriptedProcessClassName();
+ m_dictionary_sp = launch_info.GetScriptedProcessDictionarySP();
+ }
+
+ std::string GetClassName() const { return m_class_name; }
+ StructuredData::DictionarySP GetDictionarySP() const {
+ return m_dictionary_sp;
+ }
+
+ private:
+ std::string m_class_name;
+ StructuredData::DictionarySP m_dictionary_sp;
+ };
+
+public:
+ static lldb::ProcessSP CreateInstance(lldb::TargetSP target_sp,
+ lldb::ListenerSP listener_sp,
+ const FileSpec *crash_file_path,
+ bool can_connect);
+
+ static void Initialize();
+
+ static void Terminate();
+
+ static ConstString GetPluginNameStatic();
+
+ static const char *GetPluginDescriptionStatic();
+
+ ScriptedProcess(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
+ const ScriptedProcess::ScriptedProcessInfo &launch_info,
+ Status &error);
+
+ ~ScriptedProcess() override;
+
+ bool CanDebug(lldb::TargetSP target_sp,
+ bool plugin_specified_by_name) override;
+
+ DynamicLoader *GetDynamicLoader() override { return nullptr; }
+
+ ConstString GetPluginName() override;
+
+ uint32_t GetPluginVersion() override;
+
+ SystemRuntime *GetSystemRuntime() override { return nullptr; }
+
+ Status DoLoadCore() override;
+
+ Status DoLaunch(Module *exe_module, ProcessLaunchInfo &launch_info) override;
+
+ void DidLaunch() override;
+
+ Status DoResume() override;
+
+ Status DoDestroy() override;
+
+ void RefreshStateAfterStop() override{};
+
+ bool IsAlive() override;
+
+ size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
+ Status &error) override;
+
+ ArchSpec GetArchitecture();
+
+ Status GetMemoryRegionInfo(lldb::addr_t load_addr,
+ MemoryRegionInfo &range_info) override;
+
+ Status
+ GetMemoryRegions(lldb_private::MemoryRegionInfos ®ion_list) override;
+
+ bool GetProcessInfo(ProcessInstanceInfo &info) override;
+
+protected:
+ Status DoStop();
+
+ void Clear();
+
+ bool DoUpdateThreadList(ThreadList &old_thread_list,
+ ThreadList &new_thread_list) override;
+
+private:
+ void CheckInterpreterAndScriptObject() const;
+ ScriptedProcessInterface &GetInterface() const;
+ static bool IsScriptLanguageSupported(lldb::ScriptLanguage language);
+
+ // Member variables.
+ const ScriptedProcessInfo m_scripted_process_info;
+ lldb_private::ScriptInterpreter *m_interpreter = nullptr;
+ lldb_private::StructuredData::ObjectSP m_script_object_sp = nullptr;
+ //@}
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_SCRIPTED_PROCESS_H
diff --git a/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp
index f14e273..e99b7b8 100644
--- a/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp
@@ -30,6 +30,9 @@
lua_State *L, lldb::StackFrameSP stop_frame_sp,
lldb::BreakpointLocationSP bp_loc_sp, StructuredDataImpl *extra_args_impl);
+extern "C" llvm::Expected<bool> LLDBSwigLuaWatchpointCallbackFunction(
+ lua_State *L, lldb::StackFrameSP stop_frame_sp, lldb::WatchpointSP wp_sp);
+
#if _MSC_VER
#pragma warning (pop)
#endif
@@ -113,6 +116,32 @@
bp_loc_sp, extra_args_impl);
}
+llvm::Error Lua::RegisterWatchpointCallback(void *baton, const char *body) {
+ lua_pushlightuserdata(m_lua_state, baton);
+ const char *fmt_str = "return function(frame, wp, ...) {0} end";
+ std::string func_str = llvm::formatv(fmt_str, body).str();
+ if (luaL_dostring(m_lua_state, func_str.c_str()) != LUA_OK) {
+ llvm::Error e = llvm::make_error<llvm::StringError>(
+ llvm::formatv("{0}", lua_tostring(m_lua_state, -1)),
+ llvm::inconvertibleErrorCode());
+ // Pop error message from the stack.
+ lua_pop(m_lua_state, 2);
+ return e;
+ }
+ lua_settable(m_lua_state, LUA_REGISTRYINDEX);
+ return llvm::Error::success();
+}
+
+llvm::Expected<bool>
+Lua::CallWatchpointCallback(void *baton, lldb::StackFrameSP stop_frame_sp,
+ lldb::WatchpointSP wp_sp) {
+
+ lua_pushlightuserdata(m_lua_state, baton);
+ lua_gettable(m_lua_state, LUA_REGISTRYINDEX);
+ return LLDBSwigLuaWatchpointCallbackFunction(m_lua_state, stop_frame_sp,
+ wp_sp);
+}
+
llvm::Error Lua::CheckSyntax(llvm::StringRef buffer) {
int error =
luaL_loadbuffer(m_lua_state, buffer.data(), buffer.size(), "buffer");
diff --git a/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h
index 873440f..5daedf8 100644
--- a/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h
+++ b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h
@@ -37,6 +37,10 @@
CallBreakpointCallback(void *baton, lldb::StackFrameSP stop_frame_sp,
lldb::BreakpointLocationSP bp_loc_sp,
StructuredData::ObjectSP extra_args_sp);
+ llvm::Error RegisterWatchpointCallback(void *baton, const char *body);
+ llvm::Expected<bool> CallWatchpointCallback(void *baton,
+ lldb::StackFrameSP stop_frame_sp,
+ lldb::WatchpointSP wp_sp);
llvm::Error LoadModule(llvm::StringRef filename);
llvm::Error CheckSyntax(llvm::StringRef buffer);
llvm::Error ChangeIO(FILE *out, FILE *err);
diff --git a/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp
index 920e334..ef46401 100644
--- a/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp
@@ -58,7 +58,13 @@
const char *instructions = nullptr;
switch (m_active_io_handler) {
case eIOHandlerNone:
+ break;
case eIOHandlerWatchpoint:
+ instructions = "Enter your Lua command(s). Type 'quit' to end.\n"
+ "The commands are compiled as the body of the following "
+ "Lua function\n"
+ "function (frame, wp) end\n";
+ SetPrompt(llvm::StringRef("..> "));
break;
case eIOHandlerBreakpoint:
instructions = "Enter your Lua command(s). Type 'quit' to end.\n"
@@ -78,7 +84,8 @@
StringList &lines) override {
size_t last = lines.GetSize() - 1;
if (IsQuitCommand(lines.GetStringAtIndex(last))) {
- if (m_active_io_handler == eIOHandlerBreakpoint)
+ if (m_active_io_handler == eIOHandlerBreakpoint ||
+ m_active_io_handler == eIOHandlerWatchpoint)
lines.DeleteStringAtIndex(last);
return true;
}
@@ -90,17 +97,19 @@
// Lua always errors out to incomplete code with '<eof>'
return error_str.find("<eof>") == std::string::npos;
}
- // The breakpoint handler only exits with a explicit 'quit'
- return m_active_io_handler != eIOHandlerBreakpoint;
+ // The breakpoint and watchpoint handler only exits with a explicit 'quit'
+ return m_active_io_handler != eIOHandlerBreakpoint &&
+ m_active_io_handler != eIOHandlerWatchpoint;
}
void IOHandlerInputComplete(IOHandler &io_handler,
std::string &data) override {
switch (m_active_io_handler) {
case eIOHandlerBreakpoint: {
- auto *bp_options_vec = static_cast<std::vector<BreakpointOptions *> *>(
- io_handler.GetUserData());
- for (auto *bp_options : *bp_options_vec) {
+ auto *bp_options_vec =
+ static_cast<std::vector<std::reference_wrapper<BreakpointOptions>> *>(
+ io_handler.GetUserData());
+ for (BreakpointOptions &bp_options : *bp_options_vec) {
Status error = m_script_interpreter.SetBreakpointCommandCallback(
bp_options, data.c_str());
if (error.Fail())
@@ -108,9 +117,13 @@
}
io_handler.SetIsDone(true);
} break;
- case eIOHandlerWatchpoint:
+ case eIOHandlerWatchpoint: {
+ auto *wp_options =
+ static_cast<WatchpointOptions *>(io_handler.GetUserData());
+ m_script_interpreter.SetWatchpointCommandCallback(wp_options,
+ data.c_str());
io_handler.SetIsDone(true);
- break;
+ } break;
case eIOHandlerNone:
if (IsQuitCommand(data)) {
io_handler.SetIsDone(true);
@@ -133,7 +146,7 @@
: ScriptInterpreter(debugger, eScriptLanguageLua),
m_lua(std::make_unique<Lua>()) {}
-ScriptInterpreterLua::~ScriptInterpreterLua() {}
+ScriptInterpreterLua::~ScriptInterpreterLua() = default;
bool ScriptInterpreterLua::ExecuteOneLine(llvm::StringRef command,
CommandReturnObject *result,
@@ -194,8 +207,9 @@
}
bool ScriptInterpreterLua::LoadScriptingModule(
- const char *filename, bool init_session, lldb_private::Status &error,
- StructuredData::ObjectSP *module_sp, FileSpec extra_search_dir) {
+ const char *filename, const LoadScriptOptions &options,
+ lldb_private::Status &error, StructuredData::ObjectSP *module_sp,
+ FileSpec extra_search_dir) {
FileSystem::Instance().Collect(filename);
if (llvm::Error e = m_lua->LoadModule(filename)) {
@@ -275,8 +289,35 @@
return *BoolOrErr;
}
+bool ScriptInterpreterLua::WatchpointCallbackFunction(
+ void *baton, StoppointCallbackContext *context, user_id_t watch_id) {
+ assert(context);
+
+ ExecutionContext exe_ctx(context->exe_ctx_ref);
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target == nullptr)
+ return true;
+
+ StackFrameSP stop_frame_sp(exe_ctx.GetFrameSP());
+ WatchpointSP wp_sp = target->GetWatchpointList().FindByID(watch_id);
+
+ Debugger &debugger = target->GetDebugger();
+ ScriptInterpreterLua *lua_interpreter = static_cast<ScriptInterpreterLua *>(
+ debugger.GetScriptInterpreter(true, eScriptLanguageLua));
+ Lua &lua = lua_interpreter->GetLua();
+
+ llvm::Expected<bool> BoolOrErr =
+ lua.CallWatchpointCallback(baton, stop_frame_sp, wp_sp);
+ if (llvm::Error E = BoolOrErr.takeError()) {
+ debugger.GetErrorStream() << toString(std::move(E));
+ return true;
+ }
+
+ return *BoolOrErr;
+}
+
void ScriptInterpreterLua::CollectDataForBreakpointCommandCallback(
- std::vector<BreakpointOptions *> &bp_options_vec,
+ std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
CommandReturnObject &result) {
IOHandlerSP io_handler_sp(
new IOHandlerLuaInterpreter(m_debugger, *this, eIOHandlerBreakpoint));
@@ -284,8 +325,16 @@
m_debugger.RunIOHandlerAsync(io_handler_sp);
}
+void ScriptInterpreterLua::CollectDataForWatchpointCommandCallback(
+ WatchpointOptions *wp_options, CommandReturnObject &result) {
+ IOHandlerSP io_handler_sp(
+ new IOHandlerLuaInterpreter(m_debugger, *this, eIOHandlerWatchpoint));
+ io_handler_sp->SetUserData(wp_options);
+ m_debugger.RunIOHandlerAsync(io_handler_sp);
+}
+
Status ScriptInterpreterLua::SetBreakpointCommandCallbackFunction(
- BreakpointOptions *bp_options, const char *function_name,
+ BreakpointOptions &bp_options, const char *function_name,
StructuredData::ObjectSP extra_args_sp) {
const char *fmt_str = "return {0}(frame, bp_loc, ...)";
std::string oneliner = llvm::formatv(fmt_str, function_name).str();
@@ -294,12 +343,12 @@
}
Status ScriptInterpreterLua::SetBreakpointCommandCallback(
- BreakpointOptions *bp_options, const char *command_body_text) {
+ BreakpointOptions &bp_options, const char *command_body_text) {
return RegisterBreakpointCallback(bp_options, command_body_text, {});
}
Status ScriptInterpreterLua::RegisterBreakpointCallback(
- BreakpointOptions *bp_options, const char *command_body_text,
+ BreakpointOptions &bp_options, const char *command_body_text,
StructuredData::ObjectSP extra_args_sp) {
Status error;
auto data_up = std::make_unique<CommandDataLua>(extra_args_sp);
@@ -308,7 +357,27 @@
return error;
auto baton_sp =
std::make_shared<BreakpointOptions::CommandBaton>(std::move(data_up));
- bp_options->SetCallback(ScriptInterpreterLua::BreakpointCallbackFunction,
+ bp_options.SetCallback(ScriptInterpreterLua::BreakpointCallbackFunction,
+ baton_sp);
+ return error;
+}
+
+void ScriptInterpreterLua::SetWatchpointCommandCallback(
+ WatchpointOptions *wp_options, const char *command_body_text) {
+ RegisterWatchpointCallback(wp_options, command_body_text, {});
+}
+
+Status ScriptInterpreterLua::RegisterWatchpointCallback(
+ WatchpointOptions *wp_options, const char *command_body_text,
+ StructuredData::ObjectSP extra_args_sp) {
+ Status error;
+ auto data_up = std::make_unique<WatchpointOptions::CommandData>();
+ error = m_lua->RegisterWatchpointCallback(data_up.get(), command_body_text);
+ if (error.Fail())
+ return error;
+ auto baton_sp =
+ std::make_shared<WatchpointOptions::CommandBaton>(std::move(data_up));
+ wp_options->SetCallback(ScriptInterpreterLua::WatchpointCallbackFunction,
baton_sp);
return error;
}
diff --git a/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h
index 1130cee..808000b 100644
--- a/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h
+++ b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h
@@ -9,6 +9,9 @@
#ifndef liblldb_ScriptInterpreterLua_h_
#define liblldb_ScriptInterpreterLua_h_
+#include <vector>
+
+#include "lldb/Breakpoint/WatchpointOptions.h"
#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Utility/Status.h"
@@ -40,7 +43,8 @@
void ExecuteInterpreterLoop() override;
- bool LoadScriptingModule(const char *filename, bool init_session,
+ bool LoadScriptingModule(const char *filename,
+ const LoadScriptOptions &options,
lldb_private::Status &error,
StructuredData::ObjectSP *module_sp = nullptr,
FileSpec extra_search_dir = {}) override;
@@ -61,6 +65,10 @@
lldb::user_id_t break_id,
lldb::user_id_t break_loc_id);
+ static bool WatchpointCallbackFunction(void *baton,
+ StoppointCallbackContext *context,
+ lldb::user_id_t watch_id);
+
// PluginInterface protocol
lldb_private::ConstString GetPluginName() override;
@@ -72,21 +80,32 @@
llvm::Error LeaveSession();
void CollectDataForBreakpointCommandCallback(
- std::vector<BreakpointOptions *> &bp_options_vec,
+ std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
CommandReturnObject &result) override;
- Status SetBreakpointCommandCallback(BreakpointOptions *bp_options,
+ void
+ CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options,
+ CommandReturnObject &result) override;
+
+ Status SetBreakpointCommandCallback(BreakpointOptions &bp_options,
const char *command_body_text) override;
+ void SetWatchpointCommandCallback(WatchpointOptions *wp_options,
+ const char *command_body_text) override;
+
Status SetBreakpointCommandCallbackFunction(
- BreakpointOptions *bp_options, const char *function_name,
+ BreakpointOptions &bp_options, const char *function_name,
StructuredData::ObjectSP extra_args_sp) override;
private:
std::unique_ptr<Lua> m_lua;
bool m_session_is_active = false;
- Status RegisterBreakpointCallback(BreakpointOptions *bp_options,
+ Status RegisterBreakpointCallback(BreakpointOptions &bp_options,
+ const char *command_body_text,
+ StructuredData::ObjectSP extra_args_sp);
+
+ Status RegisterWatchpointCallback(WatchpointOptions *wp_options,
const char *command_body_text,
StructuredData::ObjectSP extra_args_sp);
};
diff --git a/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp
index d9c32cc..f8a3852 100644
--- a/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp
@@ -25,7 +25,7 @@
ScriptInterpreterNone::ScriptInterpreterNone(Debugger &debugger)
: ScriptInterpreter(debugger, eScriptLanguageNone) {}
-ScriptInterpreterNone::~ScriptInterpreterNone() {}
+ScriptInterpreterNone::~ScriptInterpreterNone() = default;
bool ScriptInterpreterNone::ExecuteOneLine(llvm::StringRef command,
CommandReturnObject *,
diff --git a/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt
index 2cbf8bc..84115aa 100644
--- a/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt
+++ b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt
@@ -11,6 +11,8 @@
PythonDataObjects.cpp
PythonReadline.cpp
ScriptInterpreterPython.cpp
+ ScriptedProcessPythonInterface.cpp
+ SWIGPythonBridge.cpp
LINK_LIBS
lldbBreakpoint
diff --git a/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
index 7c49502..f51d9b3a 100644
--- a/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
@@ -24,7 +24,7 @@
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Errno.h"
-#include <stdio.h>
+#include <cstdio>
using namespace lldb_private;
using namespace lldb;
diff --git a/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
index 22f6c67..4577253 100644
--- a/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
+++ b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
@@ -229,7 +229,7 @@
class PythonObject {
public:
- PythonObject() : m_py_obj(nullptr) {}
+ PythonObject() = default;
PythonObject(PyRefType type, PyObject *py_obj) {
m_py_obj = py_obj;
@@ -378,7 +378,7 @@
}
protected:
- PyObject *m_py_obj;
+ PyObject *m_py_obj = nullptr;
};
@@ -421,7 +421,7 @@
Py_DECREF(py_obj);
}
- TypedPythonObject() {}
+ TypedPythonObject() = default;
};
class PythonBytes : public TypedPythonObject<PythonBytes> {
diff --git a/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp
index 5f6429f..95a3365 100644
--- a/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp
@@ -2,7 +2,7 @@
#ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE
-#include <stdio.h>
+#include <cstdio>
#include <editline/readline.h>
diff --git a/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.cpp b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.cpp
new file mode 100644
index 0000000..7c7c5d7
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.cpp
@@ -0,0 +1,48 @@
+//===-- SWIGPythonBridge.cpp ----------------------------------------------===//
+//
+// 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 "lldb/Host/Config.h"
+#include "lldb/lldb-enumerations.h"
+
+#if LLDB_ENABLE_PYTHON
+
+// LLDB Python header must be included first
+#include "lldb-python.h"
+
+#include "SWIGPythonBridge.h"
+
+using namespace lldb;
+
+namespace lldb_private {
+
+template <typename T> const char *GetPythonValueFormatString(T t);
+template <> const char *GetPythonValueFormatString(char *) { return "s"; }
+template <> const char *GetPythonValueFormatString(char) { return "b"; }
+template <> const char *GetPythonValueFormatString(unsigned char) {
+ return "B";
+}
+template <> const char *GetPythonValueFormatString(short) { return "h"; }
+template <> const char *GetPythonValueFormatString(unsigned short) {
+ return "H";
+}
+template <> const char *GetPythonValueFormatString(int) { return "i"; }
+template <> const char *GetPythonValueFormatString(unsigned int) { return "I"; }
+template <> const char *GetPythonValueFormatString(long) { return "l"; }
+template <> const char *GetPythonValueFormatString(unsigned long) {
+ return "k";
+}
+template <> const char *GetPythonValueFormatString(long long) { return "L"; }
+template <> const char *GetPythonValueFormatString(unsigned long long) {
+ return "K";
+}
+template <> const char *GetPythonValueFormatString(float) { return "f"; }
+template <> const char *GetPythonValueFormatString(double) { return "d"; }
+
+} // namespace lldb_private
+
+#endif // LLDB_ENABLE_PYTHON
diff --git a/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
new file mode 100644
index 0000000..1ef792b
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
@@ -0,0 +1,56 @@
+//===-- ScriptInterpreterPython.h -------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SWIGPYTHONBRIDGE_H
+#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SWIGPYTHONBRIDGE_H
+
+#include <string>
+
+#include "lldb/Host/Config.h"
+
+#if LLDB_ENABLE_PYTHON
+
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-types.h"
+
+namespace lldb_private {
+
+// GetPythonValueFormatString provides a system independent type safe way to
+// convert a variable's type into a python value format. Python value formats
+// are defined in terms of builtin C types and could change from system to as
+// the underlying typedef for uint* types, size_t, off_t and other values
+// change.
+
+template <typename T> const char *GetPythonValueFormatString(T t);
+template <> const char *GetPythonValueFormatString(char *);
+template <> const char *GetPythonValueFormatString(char);
+template <> const char *GetPythonValueFormatString(unsigned char);
+template <> const char *GetPythonValueFormatString(short);
+template <> const char *GetPythonValueFormatString(unsigned short);
+template <> const char *GetPythonValueFormatString(int);
+template <> const char *GetPythonValueFormatString(unsigned int);
+template <> const char *GetPythonValueFormatString(long);
+template <> const char *GetPythonValueFormatString(unsigned long);
+template <> const char *GetPythonValueFormatString(long long);
+template <> const char *GetPythonValueFormatString(unsigned long long);
+template <> const char *GetPythonValueFormatString(float t);
+template <> const char *GetPythonValueFormatString(double t);
+
+extern "C" void *LLDBSwigPythonCreateScriptedProcess(
+ const char *python_class_name, const char *session_dictionary_name,
+ const lldb::TargetSP &target_sp, StructuredDataImpl *args_impl,
+ std::string &error_string);
+
+extern "C" void *LLDBSWIGPython_CastPyObjectToSBData(void *data);
+extern "C" void *LLDBSWIGPython_CastPyObjectToSBError(void *data);
+extern "C" void *LLDBSWIGPython_CastPyObjectToSBValue(void *data);
+
+} // namespace lldb_private
+
+#endif // LLDB_ENABLE_PYTHON
+#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SWIGPYTHONBRIDGE_H
diff --git a/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
index 6b53bd3..7ad6372 100644
--- a/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -16,7 +16,11 @@
#include "PythonDataObjects.h"
#include "PythonReadline.h"
+#include "SWIGPythonBridge.h"
#include "ScriptInterpreterPythonImpl.h"
+#include "ScriptedProcessPythonInterface.h"
+
+#include "lldb/API/SBError.h"
#include "lldb/API/SBFrame.h"
#include "lldb/API/SBValue.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
@@ -41,10 +45,10 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatAdapters.h"
+#include <cstdio>
+#include <cstdlib>
#include <memory>
#include <mutex>
-#include <stdio.h>
-#include <stdlib.h>
#include <string>
using namespace lldb;
@@ -148,8 +152,6 @@
extern "C" int LLDBSwigPython_GetIndexOfChildWithName(void *implementor,
const char *child_name);
-extern "C" void *LLDBSWIGPython_CastPyObjectToSBValue(void *data);
-
extern lldb::ValueObjectSP
LLDBSWIGPython_GetValueObjectSPFromSBValue(void *data);
@@ -234,8 +236,7 @@
// save off initial state at the beginning, and restore it at the end
struct InitializePythonRAII {
public:
- InitializePythonRAII()
- : m_gil_state(PyGILState_UNLOCKED), m_was_already_initialized(false) {
+ InitializePythonRAII() {
InitializePythonHome();
#ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE
@@ -355,8 +356,8 @@
}
TerminalState m_stdin_tty_state;
- PyGILState_STATE m_gil_state;
- bool m_was_already_initialized;
+ PyGILState_STATE m_gil_state = PyGILState_UNLOCKED;
+ bool m_was_already_initialized = false;
};
} // namespace
@@ -410,6 +411,32 @@
return g_spec;
}
+void ScriptInterpreterPython::SharedLibraryDirectoryHelper(
+ FileSpec &this_file) {
+ // When we're loaded from python, this_file will point to the file inside the
+ // python package directory. Replace it with the one in the lib directory.
+#ifdef _WIN32
+ // On windows, we need to manually back out of the python tree, and go into
+ // the bin directory. This is pretty much the inverse of what ComputePythonDir
+ // does.
+ if (this_file.GetFileNameExtension() == ConstString(".pyd")) {
+ this_file.RemoveLastPathComponent(); // _lldb.pyd or _lldb_d.pyd
+ this_file.RemoveLastPathComponent(); // lldb
+ llvm::StringRef libdir = LLDB_PYTHON_RELATIVE_LIBDIR;
+ for (auto it = llvm::sys::path::begin(libdir),
+ end = llvm::sys::path::end(libdir);
+ it != end; ++it)
+ this_file.RemoveLastPathComponent();
+ this_file.AppendPathComponent("bin");
+ this_file.AppendPathComponent("liblldb.dll");
+ }
+#else
+ // The python file is a symlink, so we can find the real library by resolving
+ // it. We can do this unconditionally.
+ FileSystem::Instance().ResolveSymbolicLink(this_file, this_file);
+#endif
+}
+
lldb_private::ConstString ScriptInterpreterPython::GetPluginNameStatic() {
static ConstString g_name("script-python");
return g_name;
@@ -506,6 +533,9 @@
m_command_thread_state(nullptr) {
InitializePrivate();
+ m_scripted_process_interface_up =
+ std::make_unique<ScriptedProcessPythonInterface>(*this);
+
m_dictionary_name.append("_dict");
StreamString run_string;
run_string.Printf("%s = dict()", m_dictionary_name.c_str());
@@ -605,11 +635,10 @@
case eIOHandlerNone:
break;
case eIOHandlerBreakpoint: {
- std::vector<BreakpointOptions *> *bp_options_vec =
- (std::vector<BreakpointOptions *> *)io_handler.GetUserData();
- for (auto bp_options : *bp_options_vec) {
- if (!bp_options)
- continue;
+ std::vector<std::reference_wrapper<BreakpointOptions>> *bp_options_vec =
+ (std::vector<std::reference_wrapper<BreakpointOptions>> *)
+ io_handler.GetUserData();
+ for (BreakpointOptions &bp_options : *bp_options_vec) {
auto data_up = std::make_unique<CommandDataPython>();
if (!data_up)
@@ -623,7 +652,7 @@
.Success()) {
auto baton_sp = std::make_shared<BreakpointOptions::CommandBaton>(
std::move(data_up));
- bp_options->SetCallback(
+ bp_options.SetCallback(
ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp);
} else if (!batch_mode) {
StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
@@ -1048,11 +1077,24 @@
llvm::StringRef in_string, ScriptInterpreter::ScriptReturnType return_type,
void *ret_value, const ExecuteScriptOptions &options) {
+ llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
+ io_redirect_or_error = ScriptInterpreterIORedirect::Create(
+ options.GetEnableIO(), m_debugger, /*result=*/nullptr);
+
+ if (!io_redirect_or_error) {
+ llvm::consumeError(io_redirect_or_error.takeError());
+ return false;
+ }
+
+ ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;
+
Locker locker(this,
Locker::AcquireLock | Locker::InitSession |
(options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |
Locker::NoSTDIN,
- Locker::FreeAcquiredLock | Locker::TearDownSession);
+ Locker::FreeAcquiredLock | Locker::TearDownSession,
+ io_redirect.GetInputFile(), io_redirect.GetOutputFile(),
+ io_redirect.GetErrorFile());
PythonModule &main_module = GetMainModule();
PythonDictionary globals = main_module.GetDictionary();
@@ -1161,11 +1203,22 @@
if (in_string == nullptr)
return Status();
+ llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
+ io_redirect_or_error = ScriptInterpreterIORedirect::Create(
+ options.GetEnableIO(), m_debugger, /*result=*/nullptr);
+
+ if (!io_redirect_or_error)
+ return Status(io_redirect_or_error.takeError());
+
+ ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;
+
Locker locker(this,
Locker::AcquireLock | Locker::InitSession |
(options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |
Locker::NoSTDIN,
- Locker::FreeAcquiredLock | Locker::TearDownSession);
+ Locker::FreeAcquiredLock | Locker::TearDownSession,
+ io_redirect.GetInputFile(), io_redirect.GetOutputFile(),
+ io_redirect.GetErrorFile());
PythonModule &main_module = GetMainModule();
PythonDictionary globals = main_module.GetDictionary();
@@ -1196,7 +1249,7 @@
}
void ScriptInterpreterPythonImpl::CollectDataForBreakpointCommandCallback(
- std::vector<BreakpointOptions *> &bp_options_vec,
+ std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
CommandReturnObject &result) {
m_active_io_handler = eIOHandlerBreakpoint;
m_debugger.GetCommandInterpreter().GetPythonCommandsFromIOHandler(
@@ -1211,7 +1264,7 @@
}
Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallbackFunction(
- BreakpointOptions *bp_options, const char *function_name,
+ BreakpointOptions &bp_options, const char *function_name,
StructuredData::ObjectSP extra_args_sp) {
Status error;
// For now just cons up a oneliner that calls the provided function.
@@ -1253,7 +1306,7 @@
}
Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(
- BreakpointOptions *bp_options,
+ BreakpointOptions &bp_options,
std::unique_ptr<BreakpointOptions::CommandData> &cmd_data_up) {
Status error;
error = GenerateBreakpointCommandCallbackData(cmd_data_up->user_source,
@@ -1264,21 +1317,20 @@
}
auto baton_sp =
std::make_shared<BreakpointOptions::CommandBaton>(std::move(cmd_data_up));
- bp_options->SetCallback(
+ bp_options.SetCallback(
ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp);
return error;
}
Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(
- BreakpointOptions *bp_options, const char *command_body_text) {
+ BreakpointOptions &bp_options, const char *command_body_text) {
return SetBreakpointCommandCallback(bp_options, command_body_text, {},false);
}
// Set a Python one-liner as the callback for the breakpoint.
Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(
- BreakpointOptions *bp_options, const char *command_body_text,
- StructuredData::ObjectSP extra_args_sp,
- bool uses_extra_args) {
+ BreakpointOptions &bp_options, const char *command_body_text,
+ StructuredData::ObjectSP extra_args_sp, bool uses_extra_args) {
auto data_up = std::make_unique<CommandDataPython>(extra_args_sp);
// Split the command_body_text into lines, and pass that to
// GenerateBreakpointCommandCallbackData. That will wrap the body in an
@@ -1292,7 +1344,7 @@
if (error.Success()) {
auto baton_sp =
std::make_shared<BreakpointOptions::CommandBaton>(std::move(data_up));
- bp_options->SetCallback(
+ bp_options.SetCallback(
ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp);
return error;
}
@@ -1330,7 +1382,7 @@
Status error = ExecuteMultipleLines(
function_def_string.c_str(),
- ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false));
+ ExecuteScriptOptions().SetEnableIO(false));
return error;
}
@@ -1678,35 +1730,6 @@
return StructuredData::ArraySP();
}
-// GetPythonValueFormatString provides a system independent type safe way to
-// convert a variable's type into a python value format. Python value formats
-// are defined in terms of builtin C types and could change from system to as
-// the underlying typedef for uint* types, size_t, off_t and other values
-// change.
-
-template <typename T> const char *GetPythonValueFormatString(T t);
-template <> const char *GetPythonValueFormatString(char *) { return "s"; }
-template <> const char *GetPythonValueFormatString(char) { return "b"; }
-template <> const char *GetPythonValueFormatString(unsigned char) {
- return "B";
-}
-template <> const char *GetPythonValueFormatString(short) { return "h"; }
-template <> const char *GetPythonValueFormatString(unsigned short) {
- return "H";
-}
-template <> const char *GetPythonValueFormatString(int) { return "i"; }
-template <> const char *GetPythonValueFormatString(unsigned int) { return "I"; }
-template <> const char *GetPythonValueFormatString(long) { return "l"; }
-template <> const char *GetPythonValueFormatString(unsigned long) {
- return "k";
-}
-template <> const char *GetPythonValueFormatString(long long) { return "L"; }
-template <> const char *GetPythonValueFormatString(unsigned long long) {
- return "K";
-}
-template <> const char *GetPythonValueFormatString(float t) { return "f"; }
-template <> const char *GetPythonValueFormatString(double t) { return "d"; }
-
StructuredData::StringSP
ScriptInterpreterPythonImpl::OSPlugin_RegisterContextData(
StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid) {
@@ -2058,7 +2081,10 @@
StructuredData::ObjectSP module_sp;
- if (LoadScriptingModule(file_spec.GetPath().c_str(), true, error, &module_sp))
+ LoadScriptOptions load_script_options =
+ LoadScriptOptions().SetInitSession(true).SetSilent(false);
+ if (LoadScriptingModule(file_spec.GetPath().c_str(), load_script_options,
+ error, &module_sp))
return module_sp;
return StructuredData::ObjectSP();
@@ -2733,26 +2759,44 @@
}
bool ScriptInterpreterPythonImpl::LoadScriptingModule(
- const char *pathname, bool init_session, lldb_private::Status &error,
- StructuredData::ObjectSP *module_sp, FileSpec extra_search_dir) {
+ const char *pathname, const LoadScriptOptions &options,
+ lldb_private::Status &error, StructuredData::ObjectSP *module_sp,
+ FileSpec extra_search_dir) {
namespace fs = llvm::sys::fs;
namespace path = llvm::sys::path;
+ ExecuteScriptOptions exc_options = ExecuteScriptOptions()
+ .SetEnableIO(!options.GetSilent())
+ .SetSetLLDBGlobals(false);
+
if (!pathname || !pathname[0]) {
error.SetErrorString("invalid pathname");
return false;
}
+ llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>>
+ io_redirect_or_error = ScriptInterpreterIORedirect::Create(
+ exc_options.GetEnableIO(), m_debugger, /*result=*/nullptr);
+
+ if (!io_redirect_or_error) {
+ error = io_redirect_or_error.takeError();
+ return false;
+ }
+
+ ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error;
lldb::DebuggerSP debugger_sp = m_debugger.shared_from_this();
// Before executing Python code, lock the GIL.
Locker py_lock(this,
Locker::AcquireLock |
- (init_session ? Locker::InitSession : 0) | Locker::NoSTDIN,
+ (options.GetInitSession() ? Locker::InitSession : 0) |
+ Locker::NoSTDIN,
Locker::FreeAcquiredLock |
- (init_session ? Locker::TearDownSession : 0));
+ (options.GetInitSession() ? Locker::TearDownSession : 0),
+ io_redirect.GetInputFile(), io_redirect.GetOutputFile(),
+ io_redirect.GetErrorFile());
- auto ExtendSysPath = [this](std::string directory) -> llvm::Error {
+ auto ExtendSysPath = [&](std::string directory) -> llvm::Error {
if (directory.empty()) {
return llvm::make_error<llvm::StringError>(
"invalid directory name", llvm::inconvertibleErrorCode());
@@ -2767,11 +2811,7 @@
"sys.path.insert(1,'%s');\n\n",
directory.c_str(), directory.c_str());
bool syspath_retval =
- ExecuteMultipleLines(command_stream.GetData(),
- ScriptInterpreter::ExecuteScriptOptions()
- .SetEnableIO(false)
- .SetSetLLDBGlobals(false))
- .Success();
+ ExecuteMultipleLines(command_stream.GetData(), exc_options).Success();
if (!syspath_retval) {
return llvm::make_error<llvm::StringError>(
"Python sys.path handling failed", llvm::inconvertibleErrorCode());
@@ -2781,6 +2821,7 @@
};
std::string module_name(pathname);
+ bool possible_package = false;
if (extra_search_dir) {
if (llvm::Error e = ExtendSysPath(extra_search_dir.GetPath())) {
@@ -2805,6 +2846,7 @@
return false;
}
// Not a filename, probably a package of some sort, let it go through.
+ possible_package = true;
} else if (is_directory(st) || is_regular_file(st)) {
if (module_file.GetDirectory().IsEmpty()) {
error.SetErrorString("invalid directory name");
@@ -2831,35 +2873,39 @@
module_name.resize(module_name.length() - 4);
}
- // check if the module is already import-ed
+ if (!possible_package && module_name.find('.') != llvm::StringRef::npos) {
+ error.SetErrorStringWithFormat(
+ "Python does not allow dots in module names: %s", module_name.c_str());
+ return false;
+ }
+
+ if (module_name.find('-') != llvm::StringRef::npos) {
+ error.SetErrorStringWithFormat(
+ "Python discourages dashes in module names: %s", module_name.c_str());
+ return false;
+ }
+
+ // Check if the module is already imported.
StreamString command_stream;
command_stream.Clear();
command_stream.Printf("sys.modules.__contains__('%s')", module_name.c_str());
bool does_contain = false;
- // this call will succeed if the module was ever imported in any Debugger
- // in the lifetime of the process in which this LLDB framework is living
- bool was_imported_globally =
- (ExecuteOneLineWithReturn(
- command_stream.GetData(),
- ScriptInterpreterPythonImpl::eScriptReturnTypeBool, &does_contain,
- ScriptInterpreter::ExecuteScriptOptions()
- .SetEnableIO(false)
- .SetSetLLDBGlobals(false)) &&
- does_contain);
- // this call will fail if the module was not imported in this Debugger
- // before
- command_stream.Clear();
- command_stream.Printf("sys.getrefcount(%s)", module_name.c_str());
- bool was_imported_locally = GetSessionDictionary()
- .GetItemForKey(PythonString(module_name))
- .IsAllocated();
+ // This call will succeed if the module was ever imported in any Debugger in
+ // the lifetime of the process in which this LLDB framework is living.
+ const bool does_contain_executed = ExecuteOneLineWithReturn(
+ command_stream.GetData(),
+ ScriptInterpreterPythonImpl::eScriptReturnTypeBool, &does_contain, exc_options);
- bool was_imported = (was_imported_globally || was_imported_locally);
+ const bool was_imported_globally = does_contain_executed && does_contain;
+ const bool was_imported_locally =
+ GetSessionDictionary()
+ .GetItemForKey(PythonString(module_name))
+ .IsAllocated();
// now actually do the import
command_stream.Clear();
- if (was_imported) {
+ if (was_imported_globally || was_imported_locally) {
if (!was_imported_locally)
command_stream.Printf("import %s ; reload_module(%s)",
module_name.c_str(), module_name.c_str());
@@ -2868,10 +2914,7 @@
} else
command_stream.Printf("import %s", module_name.c_str());
- error = ExecuteMultipleLines(command_stream.GetData(),
- ScriptInterpreter::ExecuteScriptOptions()
- .SetEnableIO(false)
- .SetSetLLDBGlobals(false));
+ error = ExecuteMultipleLines(command_stream.GetData(), exc_options);
if (error.Fail())
return false;
@@ -2890,7 +2933,8 @@
void *module_pyobj = nullptr;
if (ExecuteOneLineWithReturn(
command_stream.GetData(),
- ScriptInterpreter::eScriptReturnTypeOpaqueObject, &module_pyobj) &&
+ ScriptInterpreter::eScriptReturnTypeOpaqueObject, &module_pyobj,
+ exc_options) &&
module_pyobj)
*module_sp = std::make_shared<StructuredPythonObject>(module_pyobj);
}
@@ -3047,7 +3091,7 @@
if (ExecuteOneLineWithReturn(
command, ScriptInterpreter::eScriptReturnTypeCharStrOrNone,
&result_ptr,
- ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false))) {
+ ExecuteScriptOptions().SetEnableIO(false))) {
if (result_ptr)
dest.assign(result_ptr);
return true;
diff --git a/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
index e59fedb..b8b9781 100644
--- a/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
+++ b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
@@ -13,6 +13,8 @@
#if LLDB_ENABLE_PYTHON
+#include "ScriptedProcessPythonInterface.h"
+
#include "lldb/Breakpoint/BreakpointOptions.h"
#include "lldb/Core/IOHandler.h"
#include "lldb/Core/StructuredDataImpl.h"
@@ -51,6 +53,7 @@
static lldb_private::ConstString GetPluginNameStatic();
static const char *GetPluginDescriptionStatic();
static FileSpec GetPythonDir();
+ static void SharedLibraryDirectoryHelper(FileSpec &this_file);
protected:
static void ComputePythonDirForApple(llvm::SmallVectorImpl<char> &path);
diff --git a/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
index 45dad42..d1b0b3f 100644
--- a/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
+++ b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
@@ -6,6 +6,9 @@
//
//===----------------------------------------------------------------------===//
+#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H
+#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H
+
#include "lldb/Host/Config.h"
#if LLDB_ENABLE_PYTHON
@@ -231,7 +234,8 @@
bool RunScriptFormatKeyword(const char *impl_function, ValueObject *value,
std::string &output, Status &error) override;
- bool LoadScriptingModule(const char *filename, bool init_session,
+ bool LoadScriptingModule(const char *filename,
+ const LoadScriptOptions &options,
lldb_private::Status &error,
StructuredData::ObjectSP *module_sp = nullptr,
FileSpec extra_search_dir = {}) override;
@@ -241,7 +245,7 @@
std::unique_ptr<ScriptInterpreterLocker> AcquireInterpreterLock() override;
void CollectDataForBreakpointCommandCallback(
- std::vector<BreakpointOptions *> &bp_options_vec,
+ std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
CommandReturnObject &result) override;
void
@@ -249,20 +253,19 @@
CommandReturnObject &result) override;
/// Set the callback body text into the callback for the breakpoint.
- Status SetBreakpointCommandCallback(BreakpointOptions *bp_options,
+ Status SetBreakpointCommandCallback(BreakpointOptions &bp_options,
const char *callback_body) override;
Status SetBreakpointCommandCallbackFunction(
- BreakpointOptions *bp_options,
- const char *function_name,
+ BreakpointOptions &bp_options, const char *function_name,
StructuredData::ObjectSP extra_args_sp) override;
/// This one is for deserialization:
Status SetBreakpointCommandCallback(
- BreakpointOptions *bp_options,
+ BreakpointOptions &bp_options,
std::unique_ptr<BreakpointOptions::CommandData> &data_up) override;
- Status SetBreakpointCommandCallback(BreakpointOptions *bp_options,
+ Status SetBreakpointCommandCallback(BreakpointOptions &bp_options,
const char *command_body_text,
StructuredData::ObjectSP extra_args_sp,
bool uses_extra_args);
@@ -416,7 +419,7 @@
: IOHandler(debugger, IOHandler::Type::PythonInterpreter),
m_python(python) {}
- ~IOHandlerPythonInterpreter() override {}
+ ~IOHandlerPythonInterpreter() override = default;
ConstString GetControlSequence(char ch) override {
if (ch == 'd')
@@ -483,4 +486,5 @@
} // namespace lldb_private
-#endif
+#endif // LLDB_ENABLE_PYTHON
+#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H
diff --git a/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp
new file mode 100644
index 0000000..ce262c9
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp
@@ -0,0 +1,306 @@
+//===-- ScriptedProcessPythonInterface.cpp --------------------------------===//
+//
+// 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 "lldb/Host/Config.h"
+#include "lldb/lldb-enumerations.h"
+
+#if LLDB_ENABLE_PYTHON
+
+// LLDB Python header must be included first
+#include "lldb-python.h"
+
+#include "SWIGPythonBridge.h"
+#include "ScriptInterpreterPythonImpl.h"
+#include "ScriptedProcessPythonInterface.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::python;
+using Locker = ScriptInterpreterPythonImpl::Locker;
+
+StructuredData::GenericSP ScriptedProcessPythonInterface::CreatePluginObject(
+ const llvm::StringRef class_name, lldb::TargetSP target_sp,
+ StructuredData::DictionarySP args_sp) {
+ if (class_name.empty())
+ return {};
+
+ std::string error_string;
+ StructuredDataImpl *args_impl = nullptr;
+ if (args_sp) {
+ args_impl = new StructuredDataImpl();
+ args_impl->SetObjectSP(args_sp);
+ }
+
+ void *ret_val;
+
+ {
+
+ Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
+ Locker::FreeLock);
+
+ ret_val = LLDBSwigPythonCreateScriptedProcess(
+ class_name.str().c_str(), m_interpreter.GetDictionaryName(), target_sp,
+ args_impl, error_string);
+ }
+
+ m_object_instance_sp =
+ StructuredData::GenericSP(new StructuredPythonObject(ret_val));
+
+ return m_object_instance_sp;
+}
+
+Status ScriptedProcessPythonInterface::Launch() {
+ return GetStatusFromMethod("launch");
+}
+
+Status ScriptedProcessPythonInterface::Resume() {
+ return GetStatusFromMethod("resume");
+}
+
+bool ScriptedProcessPythonInterface::ShouldStop() {
+ llvm::Optional<unsigned long long> should_stop =
+ GetGenericInteger("should_stop");
+
+ if (!should_stop)
+ return false;
+
+ return static_cast<bool>(*should_stop);
+}
+
+Status ScriptedProcessPythonInterface::Stop() {
+ return GetStatusFromMethod("stop");
+}
+
+Status ScriptedProcessPythonInterface::GetStatusFromMethod(
+ llvm::StringRef method_name) {
+ Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
+ Locker::FreeLock);
+
+ if (!m_object_instance_sp)
+ return Status("Python object ill-formed.");
+
+ if (!m_object_instance_sp)
+ return Status("Cannot convert Python object to StructuredData::Generic.");
+ PythonObject implementor(PyRefType::Borrowed,
+ (PyObject *)m_object_instance_sp->GetValue());
+
+ if (!implementor.IsAllocated())
+ return Status("Python implementor not allocated.");
+
+ PythonObject pmeth(
+ PyRefType::Owned,
+ PyObject_GetAttrString(implementor.get(), method_name.str().c_str()));
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ if (!pmeth.IsAllocated())
+ return Status("Python method not allocated.");
+
+ if (PyCallable_Check(pmeth.get()) == 0) {
+ if (PyErr_Occurred())
+ PyErr_Clear();
+ return Status("Python method not callable.");
+ }
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ PythonObject py_return(PyRefType::Owned,
+ PyObject_CallMethod(implementor.get(),
+ method_name.str().c_str(),
+ nullptr));
+
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ return Status("Python method could not be called.");
+ }
+
+ if (PyObject *py_ret_ptr = py_return.get()) {
+ lldb::SBError *sb_error =
+ (lldb::SBError *)LLDBSWIGPython_CastPyObjectToSBError(py_ret_ptr);
+
+ if (!sb_error)
+ return Status("Couldn't cast lldb::SBError to lldb::Status.");
+
+ Status status = m_interpreter.GetStatusFromSBError(*sb_error);
+
+ if (status.Fail())
+ return Status("error: %s", status.AsCString());
+
+ return status;
+ }
+
+ return Status("Returned object is null.");
+}
+
+llvm::Optional<unsigned long long>
+ScriptedProcessPythonInterface::GetGenericInteger(llvm::StringRef method_name) {
+ Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
+ Locker::FreeLock);
+
+ if (!m_object_instance_sp)
+ return llvm::None;
+
+ if (!m_object_instance_sp)
+ return llvm::None;
+ PythonObject implementor(PyRefType::Borrowed,
+ (PyObject *)m_object_instance_sp->GetValue());
+
+ if (!implementor.IsAllocated())
+ return llvm::None;
+
+ PythonObject pmeth(
+ PyRefType::Owned,
+ PyObject_GetAttrString(implementor.get(), method_name.str().c_str()));
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ if (!pmeth.IsAllocated())
+ return llvm::None;
+
+ if (PyCallable_Check(pmeth.get()) == 0) {
+ if (PyErr_Occurred())
+ PyErr_Clear();
+ return llvm::None;
+ }
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ PythonObject py_return(PyRefType::Owned,
+ PyObject_CallMethod(implementor.get(),
+ method_name.str().c_str(),
+ nullptr));
+
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ if (!py_return.get())
+ return llvm::None;
+
+ llvm::Expected<unsigned long long> size = py_return.AsUnsignedLongLong();
+ // FIXME: Handle error.
+ if (!size)
+ return llvm::None;
+
+ return *size;
+}
+
+lldb::MemoryRegionInfoSP
+ScriptedProcessPythonInterface::GetMemoryRegionContainingAddress(
+ lldb::addr_t address) {
+ // TODO: Implement
+ return nullptr;
+}
+
+StructuredData::DictionarySP
+ScriptedProcessPythonInterface::GetThreadWithID(lldb::tid_t tid) {
+ // TODO: Implement
+ return nullptr;
+}
+
+StructuredData::DictionarySP
+ScriptedProcessPythonInterface::GetRegistersForThread(lldb::tid_t tid) {
+ // TODO: Implement
+ return nullptr;
+}
+
+lldb::DataExtractorSP ScriptedProcessPythonInterface::ReadMemoryAtAddress(
+ lldb::addr_t address, size_t size, Status &error) {
+ Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
+ Locker::FreeLock);
+
+ auto error_with_message = [&error](llvm::StringRef message) {
+ error.SetErrorString(message);
+ return nullptr;
+ };
+
+ static char callee_name[] = "read_memory_at_address";
+ std::string param_format = GetPythonValueFormatString(address);
+ param_format += GetPythonValueFormatString(size);
+
+ if (!m_object_instance_sp)
+ return error_with_message("Python object ill-formed.");
+
+ if (!m_object_instance_sp)
+ return error_with_message("Python method not callable.");
+
+ PythonObject implementor(PyRefType::Borrowed,
+ (PyObject *)m_object_instance_sp->GetValue());
+
+ if (!implementor.IsAllocated())
+ return error_with_message("Python implementor not allocated.");
+
+ PythonObject pmeth(PyRefType::Owned,
+ PyObject_GetAttrString(implementor.get(), callee_name));
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ if (!pmeth.IsAllocated())
+ return error_with_message("Python method not allocated.");
+
+ if (PyCallable_Check(pmeth.get()) == 0) {
+ if (PyErr_Occurred())
+ PyErr_Clear();
+ return error_with_message("Python method not callable.");
+ }
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ PythonObject py_return(PyRefType::Owned,
+ PyObject_CallMethod(implementor.get(), callee_name,
+ param_format.c_str(), address,
+ size));
+
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ return error_with_message("Python method could not be called.");
+ }
+
+ if (PyObject *py_ret_ptr = py_return.get()) {
+ lldb::SBData *sb_data =
+ (lldb::SBData *)LLDBSWIGPython_CastPyObjectToSBData(py_ret_ptr);
+
+ if (!sb_data)
+ return error_with_message(
+ "Couldn't cast lldb::SBData to lldb::DataExtractor.");
+
+ return m_interpreter.GetDataExtractorFromSBData(*sb_data);
+ }
+
+ return error_with_message("Returned object is null.");
+}
+
+StructuredData::DictionarySP ScriptedProcessPythonInterface::GetLoadedImages() {
+ // TODO: Implement
+ return nullptr;
+}
+
+lldb::pid_t ScriptedProcessPythonInterface::GetProcessID() {
+ llvm::Optional<unsigned long long> pid = GetGenericInteger("get_process_id");
+ return (!pid) ? LLDB_INVALID_PROCESS_ID : *pid;
+}
+
+bool ScriptedProcessPythonInterface::IsAlive() {
+ llvm::Optional<unsigned long long> is_alive = GetGenericInteger("is_alive");
+
+ if (!is_alive)
+ return false;
+
+ return static_cast<bool>(*is_alive);
+}
+
+#endif
diff --git a/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h
new file mode 100644
index 0000000..30cb5a8
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h
@@ -0,0 +1,66 @@
+//===-- ScriptedProcessPythonInterface.h ------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPROCESSPYTHONINTERFACE_H
+#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPROCESSPYTHONINTERFACE_H
+
+#include "lldb/Host/Config.h"
+
+#if LLDB_ENABLE_PYTHON
+
+#include "lldb/Interpreter/ScriptedProcessInterface.h"
+
+namespace lldb_private {
+class ScriptInterpreterPythonImpl;
+class ScriptedProcessPythonInterface : public ScriptedProcessInterface {
+public:
+ ScriptedProcessPythonInterface(ScriptInterpreterPythonImpl &interpreter)
+ : ScriptedProcessInterface(), m_interpreter(interpreter) {}
+
+ StructuredData::GenericSP
+ CreatePluginObject(const llvm::StringRef class_name, lldb::TargetSP target_sp,
+ StructuredData::DictionarySP args_sp) override;
+
+ Status Launch() override;
+
+ Status Resume() override;
+
+ bool ShouldStop() override;
+
+ Status Stop() override;
+
+ lldb::MemoryRegionInfoSP
+ GetMemoryRegionContainingAddress(lldb::addr_t address) override;
+
+ StructuredData::DictionarySP GetThreadWithID(lldb::tid_t tid) override;
+
+ StructuredData::DictionarySP GetRegistersForThread(lldb::tid_t tid) override;
+
+ lldb::DataExtractorSP ReadMemoryAtAddress(lldb::addr_t address, size_t size,
+ Status &error) override;
+
+ StructuredData::DictionarySP GetLoadedImages() override;
+
+ lldb::pid_t GetProcessID() override;
+
+ bool IsAlive() override;
+
+protected:
+ llvm::Optional<unsigned long long>
+ GetGenericInteger(llvm::StringRef method_name);
+ Status GetStatusFromMethod(llvm::StringRef method_name);
+
+private:
+ // The lifetime is managed by the ScriptInterpreter
+ ScriptInterpreterPythonImpl &m_interpreter;
+ StructuredData::GenericSP m_object_instance_sp;
+};
+} // namespace lldb_private
+
+#endif // LLDB_ENABLE_PYTHON
+#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPROCESSPYTHONINTERFACE_H
diff --git a/src/llvm-project/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp b/src/llvm-project/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp
index f669e58..87edf77 100644
--- a/src/llvm-project/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp
+++ b/src/llvm-project/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp
@@ -8,7 +8,7 @@
#include "StructuredDataDarwinLog.h"
-#include <string.h>
+#include <cstring>
#include <memory>
#include <sstream>
@@ -126,7 +126,7 @@
m_collection_sp->Initialize(g_darwinlog_properties);
}
- ~StructuredDataDarwinLogProperties() override {}
+ ~StructuredDataDarwinLogProperties() override = default;
bool GetEnableOnStartup() const {
const uint32_t idx = ePropertyEnableOnStartup;
@@ -181,7 +181,7 @@
class FilterRule {
public:
- virtual ~FilterRule() {}
+ virtual ~FilterRule() = default;
using OperationCreationFunc =
std::function<FilterRuleSP(bool accept, size_t attribute_index,
@@ -473,13 +473,9 @@
class EnableOptions : public Options {
public:
EnableOptions()
- : Options(), m_include_debug_level(false), m_include_info_level(false),
- m_include_any_process(false),
+ : Options(),
m_filter_fall_through_accepts(DEFAULT_FILTER_FALLTHROUGH_ACCEPTS),
- m_echo_to_stderr(false), m_display_timestamp_relative(false),
- m_display_subsystem(false), m_display_category(false),
- m_display_activity_chain(false), m_broadcast_events(true),
- m_live_stream(true), m_filter_rules() {}
+ m_filter_rules() {}
void OptionParsingStarting(ExecutionContext *execution_context) override {
m_include_debug_level = false;
@@ -728,17 +724,17 @@
return -1;
}
- bool m_include_debug_level;
- bool m_include_info_level;
- bool m_include_any_process;
+ bool m_include_debug_level = false;
+ bool m_include_info_level = false;
+ bool m_include_any_process = false;
bool m_filter_fall_through_accepts;
- bool m_echo_to_stderr;
- bool m_display_timestamp_relative;
- bool m_display_subsystem;
- bool m_display_category;
- bool m_display_activity_chain;
- bool m_broadcast_events;
- bool m_live_stream;
+ bool m_echo_to_stderr = false;
+ bool m_display_timestamp_relative = false;
+ bool m_display_subsystem = false;
+ bool m_display_category = false;
+ bool m_display_activity_chain = false;
+ bool m_broadcast_events = true;
+ bool m_live_stream = true;
FilterRules m_filter_rules;
};
@@ -813,7 +809,6 @@
StructuredDataDarwinLog::GetStaticPluginName())) {
result.AppendError("failed to get StructuredDataPlugin for "
"the process");
- result.SetStatus(eReturnStatusFailed);
}
StructuredDataDarwinLog &plugin =
*static_cast<StructuredDataDarwinLog *>(plugin_sp.get());
@@ -837,7 +832,6 @@
// Report results.
if (!error.Success()) {
result.AppendError(error.AsCString());
- result.SetStatus(eReturnStatusFailed);
// Our configuration failed, so we're definitely disabled.
plugin.SetEnabled(false);
} else {
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp b/src/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
index 07e5b28..b815ebb 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
@@ -278,7 +278,7 @@
}
uint32_t SymbolFileBreakpad::ResolveSymbolContext(
- const FileSpec &file_spec, uint32_t line, bool check_inlines,
+ const SourceLocationSpec &src_location_spec,
lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
if (!(resolve_scope & eSymbolContextCompUnit))
@@ -287,8 +287,7 @@
uint32_t old_size = sc_list.GetSize();
for (size_t i = 0, size = GetNumCompileUnits(); i < size; ++i) {
CompileUnit &cu = *GetCompileUnitAtIndex(i);
- cu.ResolveSymbolContext(file_spec, line, check_inlines,
- /*exact*/ false, resolve_scope, sc_list);
+ cu.ResolveSymbolContext(src_location_spec, resolve_scope, sc_list);
}
return sc_list.GetSize() - old_size;
}
@@ -716,10 +715,10 @@
llvm::Optional<addr_t> next_addr;
auto finish_sequence = [&]() {
LineTable::AppendLineEntryToSequence(
- line_seq_up.get(), *next_addr, /*line*/ 0, /*column*/ 0,
- /*file_idx*/ 0, /*is_start_of_statement*/ false,
- /*is_start_of_basic_block*/ false, /*is_prologue_end*/ false,
- /*is_epilogue_begin*/ false, /*is_terminal_entry*/ true);
+ line_seq_up.get(), *next_addr, /*line=*/0, /*column=*/0,
+ /*file_idx=*/0, /*is_start_of_statement=*/false,
+ /*is_start_of_basic_block=*/false, /*is_prologue_end=*/false,
+ /*is_epilogue_begin=*/false, /*is_terminal_entry=*/true);
sequences.push_back(std::move(line_seq_up));
line_seq_up = LineTable::CreateLineSequenceContainer();
};
@@ -739,10 +738,10 @@
finish_sequence();
}
LineTable::AppendLineEntryToSequence(
- line_seq_up.get(), record->Address, record->LineNum, /*column*/ 0,
- map[record->FileNum], /*is_start_of_statement*/ true,
- /*is_start_of_basic_block*/ false, /*is_prologue_end*/ false,
- /*is_epilogue_begin*/ false, /*is_terminal_entry*/ false);
+ line_seq_up.get(), record->Address, record->LineNum, /*column=*/0,
+ map[record->FileNum], /*is_start_of_statement=*/true,
+ /*is_start_of_basic_block=*/false, /*is_prologue_end=*/false,
+ /*is_epilogue_begin=*/false, /*is_terminal_entry=*/false);
next_addr = record->Address + record->Size;
}
if (next_addr)
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h b/src/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
index 90dbcc7..b0a35fa 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
@@ -51,7 +51,7 @@
SymbolFileBreakpad(lldb::ObjectFileSP objfile_sp)
: SymbolFile(std::move(objfile_sp)) {}
- ~SymbolFileBreakpad() override {}
+ ~SymbolFileBreakpad() override = default;
uint32_t CalculateAbilities() override;
@@ -101,8 +101,7 @@
lldb::SymbolContextItem resolve_scope,
SymbolContext &sc) override;
- uint32_t ResolveSymbolContext(const FileSpec &file_spec, uint32_t line,
- bool check_inlines,
+ uint32_t ResolveSymbolContext(const SourceLocationSpec &src_location_spec,
lldb::SymbolContextItem resolve_scope,
SymbolContextList &sc_list) override;
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
index 2e0a7fd..ffe2483 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
@@ -24,7 +24,7 @@
class DWARFASTParser {
public:
- virtual ~DWARFASTParser() {}
+ virtual ~DWARFASTParser() = default;
virtual lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc,
const DWARFDIE &die,
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 188a667..46015f7b 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include <stdlib.h>
+#include <cstdlib>
#include "DWARFASTParserClang.h"
#include "DWARFDebugInfo.h"
@@ -49,7 +49,7 @@
//#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN
#ifdef ENABLE_DEBUG_PRINTF
-#include <stdio.h>
+#include <cstdio>
#define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
#else
#define DEBUG_PRINTF(fmt, ...)
@@ -60,7 +60,7 @@
DWARFASTParserClang::DWARFASTParserClang(TypeSystemClang &ast)
: m_ast(ast), m_die_to_decl_ctx(), m_decl_ctx_to_die() {}
-DWARFASTParserClang::~DWARFASTParserClang() {}
+DWARFASTParserClang::~DWARFASTParserClang() = default;
static AccessType DW_ACCESS_to_AccessType(uint32_t dwarf_accessibility) {
switch (dwarf_accessibility) {
@@ -157,7 +157,7 @@
// The type in the Clang module must have the same language as the current CU.
LanguageSet languages;
- languages.Insert(SymbolFileDWARF::GetLanguage(*die.GetCU()));
+ languages.Insert(SymbolFileDWARF::GetLanguageFamily(*die.GetCU()));
llvm::DenseSet<SymbolFile *> searched_symbol_files;
clang_module_sp->GetSymbolFile()->FindTypes(decl_context, languages,
searched_symbol_files, pcm_types);
@@ -666,8 +666,7 @@
// Blocks have a __FuncPtr inside them which is a pointer to a
// function of the proper type.
- for (DWARFDIE child_die = target_die.GetFirstChild();
- child_die.IsValid(); child_die = child_die.GetSibling()) {
+ for (DWARFDIE child_die : target_die.children()) {
if (!strcmp(child_die.GetAttributeValueAsString(DW_AT_name, ""),
"__FuncPtr")) {
DWARFDIE function_pointer_type =
@@ -1226,6 +1225,7 @@
}
if (!function_decl) {
+ char *name_buf = nullptr;
llvm::StringRef name = attrs.name.GetStringRef();
// We currently generate function templates with template parameters in
@@ -1233,8 +1233,10 @@
// we want to strip these from the name when creating the AST.
if (attrs.mangled_name) {
llvm::ItaniumPartialDemangler D;
- if (!D.partialDemangle(attrs.mangled_name))
- name = D.getFunctionBaseName(nullptr, nullptr);
+ if (!D.partialDemangle(attrs.mangled_name)) {
+ name_buf = D.getFunctionBaseName(nullptr, nullptr);
+ name = name_buf;
+ }
}
// We just have a function that isn't part of a class
@@ -1243,6 +1245,7 @@
: containing_decl_ctx,
GetOwningClangModule(die), name, clang_type, attrs.storage,
attrs.is_inline);
+ std::free(name_buf);
if (has_template_params) {
TypeSystemClang::TemplateParameterInfos template_param_infos;
@@ -1266,13 +1269,10 @@
LinkDeclContextToDIE(function_decl, die);
if (!function_param_decls.empty()) {
- m_ast.SetFunctionParameters(function_decl,
- &function_param_decls.front(),
- function_param_decls.size());
+ m_ast.SetFunctionParameters(function_decl, function_param_decls);
if (template_function_decl)
m_ast.SetFunctionParameters(template_function_decl,
- &function_param_decls.front(),
- function_param_decls.size());
+ function_param_decls);
}
ClangASTMetadata metadata;
@@ -1357,7 +1357,7 @@
dwarf->ResolveTypeUID(attrs.containing_type.Reference(), true);
CompilerType pointee_clang_type = pointee_type->GetForwardCompilerType();
- CompilerType class_clang_type = class_type->GetLayoutCompilerType();
+ CompilerType class_clang_type = class_type->GetForwardCompilerType();
CompilerType clang_type = TypeSystemClang::CreateMemberPointerType(
class_clang_type, pointee_clang_type);
@@ -1684,14 +1684,18 @@
die.GetOffset(), attrs.name.GetCString());
}
- if (tag == DW_TAG_structure_type) // this only applies in C
- {
+ // If the byte size of the record is specified then overwrite the size
+ // that would be computed by Clang. This is only needed as LLDB's
+ // TypeSystemClang is always in C++ mode, but some compilers such as
+ // GCC and Clang give empty structs a size of 0 in C mode (in contrast to
+ // the size of 1 for empty structs that would be computed in C++ mode).
+ if (attrs.byte_size) {
clang::RecordDecl *record_decl =
TypeSystemClang::GetAsRecordDecl(clang_type);
-
if (record_decl) {
- GetClangASTImporter().SetRecordLayout(
- record_decl, ClangASTImporter::LayoutInfo());
+ ClangASTImporter::LayoutInfo layout;
+ layout.bit_size = *attrs.byte_size * 8;
+ GetClangASTImporter().SetRecordLayout(record_decl, layout);
}
}
} else if (clang_type_was_created) {
@@ -1822,8 +1826,7 @@
case DW_TAG_GNU_template_parameter_pack: {
template_param_infos.packed_args =
std::make_unique<TypeSystemClang::TemplateParameterInfos>();
- for (DWARFDIE child_die = die.GetFirstChild(); child_die.IsValid();
- child_die = child_die.GetSibling()) {
+ for (DWARFDIE child_die : die.children()) {
if (!ParseTemplateDIE(child_die, *template_param_infos.packed_args))
return false;
}
@@ -1928,8 +1931,7 @@
if (!parent_die)
return false;
- for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
- die = die.GetSibling()) {
+ for (DWARFDIE die : parent_die.children()) {
const dw_tag_t tag = die.Tag();
switch (tag) {
@@ -1978,15 +1980,12 @@
}
std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases;
- std::vector<int> member_accessibilities;
- bool is_a_class = false;
// Parse members and base classes first
std::vector<DWARFDIE> member_function_dies;
DelayedPropertyList delayed_properties;
- ParseChildMembers(die, clang_type, bases, member_accessibilities,
- member_function_dies, delayed_properties,
- default_accessibility, is_a_class, layout_info);
+ ParseChildMembers(die, clang_type, bases, member_function_dies,
+ delayed_properties, default_accessibility, layout_info);
// Now parse any methods if there were any...
for (const DWARFDIE &die : member_function_dies)
@@ -2007,31 +2006,6 @@
}
}
- // If we have a DW_TAG_structure_type instead of a DW_TAG_class_type we
- // need to tell the clang type it is actually a class.
- if (!type_is_objc_object_or_interface) {
- if (is_a_class && tag_decl_kind != clang::TTK_Class)
- m_ast.SetTagTypeKind(ClangUtil::GetQualType(clang_type),
- clang::TTK_Class);
- }
-
- // Since DW_TAG_structure_type gets used for both classes and
- // structures, we may need to set any DW_TAG_member fields to have a
- // "private" access if none was specified. When we parsed the child
- // members we tracked that actual accessibility value for each
- // DW_TAG_member in the "member_accessibilities" array. If the value
- // for the member is zero, then it was set to the
- // "default_accessibility" which for structs was "public". Below we
- // correct this by setting any fields to "private" that weren't
- // correctly set.
- if (is_a_class && !member_accessibilities.empty()) {
- // This is a class and all members that didn't have their access
- // specified are private.
- m_ast.SetDefaultAccessForRecordFields(
- m_ast.GetAsRecordDecl(clang_type), eAccessPrivate,
- &member_accessibilities.front(), member_accessibilities.size());
- }
-
if (!bases.empty()) {
// Make sure all base classes refer to complete types and not forward
// declarations. If we don't do this, clang will crash with an
@@ -2131,8 +2105,7 @@
for (auto it = m_decl_ctx_to_die.find(opaque_decl_ctx);
it != m_decl_ctx_to_die.end() && it->first == opaque_decl_ctx;
it = m_decl_ctx_to_die.erase(it))
- for (DWARFDIE decl = it->second.GetFirstChild(); decl;
- decl = decl.GetSibling())
+ for (DWARFDIE decl : it->second.children())
GetClangDeclForDIE(decl);
}
@@ -2168,8 +2141,7 @@
size_t enumerators_added = 0;
- for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
- die = die.GetSibling()) {
+ for (DWARFDIE die : parent_die.children()) {
const dw_tag_t tag = die.Tag();
if (tag == DW_TAG_enumerator) {
DWARFAttributes attributes;
@@ -2201,7 +2173,8 @@
case DW_AT_description:
default:
case DW_AT_decl_file:
- decl.SetFile(die.GetCU()->GetFile(form_value.Unsigned()));
+ decl.SetFile(attributes.CompileUnitAtIndex(i)->GetFile(
+ form_value.Unsigned()));
break;
case DW_AT_decl_line:
decl.SetLine(form_value.Unsigned());
@@ -2343,7 +2316,6 @@
void DWARFASTParserClang::ParseSingleMember(
const DWARFDIE &die, const DWARFDIE &parent_die,
const lldb_private::CompilerType &class_clang_type,
- std::vector<int> &member_accessibilities,
lldb::AccessType default_accessibility,
DelayedPropertyList &delayed_properties,
lldb_private::ClangASTImporter::LayoutInfo &layout_info,
@@ -2533,7 +2505,7 @@
if (accessibility == eAccessNone)
accessibility = eAccessPublic;
TypeSystemClang::AddVariableToRecordType(
- class_clang_type, name, var_type->GetLayoutCompilerType(),
+ class_clang_type, name, var_type->GetForwardCompilerType(),
accessibility);
}
return;
@@ -2551,7 +2523,6 @@
if (accessibility == eAccessNone)
accessibility = default_accessibility;
- member_accessibilities.push_back(accessibility);
uint64_t field_bit_offset =
(member_byte_offset == UINT32_MAX ? 0 : (member_byte_offset * 8));
@@ -2666,7 +2637,7 @@
last_field_info.bit_offset = field_bit_offset;
if (llvm::Optional<uint64_t> clang_type_size =
- member_clang_type.GetByteSize(nullptr)) {
+ member_type->GetByteSize(nullptr)) {
last_field_info.bit_size = *clang_type_size * character_width;
}
@@ -2761,10 +2732,9 @@
bool DWARFASTParserClang::ParseChildMembers(
const DWARFDIE &parent_die, CompilerType &class_clang_type,
std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes,
- std::vector<int> &member_accessibilities,
std::vector<DWARFDIE> &member_function_dies,
DelayedPropertyList &delayed_properties, AccessType &default_accessibility,
- bool &is_a_class, ClangASTImporter::LayoutInfo &layout_info) {
+ ClangASTImporter::LayoutInfo &layout_info) {
if (!parent_die)
return false;
@@ -2776,16 +2746,15 @@
if (ast == nullptr)
return false;
- for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
- die = die.GetSibling()) {
+ for (DWARFDIE die : parent_die.children()) {
dw_tag_t tag = die.Tag();
switch (tag) {
case DW_TAG_member:
case DW_TAG_APPLE_property:
ParseSingleMember(die, parent_die, class_clang_type,
- member_accessibilities, default_accessibility,
- delayed_properties, layout_info, last_field_info);
+ default_accessibility, delayed_properties, layout_info,
+ last_field_info);
break;
case DW_TAG_subprogram:
@@ -2794,9 +2763,6 @@
break;
case DW_TAG_inheritance: {
- is_a_class = true;
- if (default_accessibility == eAccessNone)
- default_accessibility = eAccessPrivate;
// TODO: implement DW_TAG_inheritance type parsing
DWARFAttributes attributes;
const size_t num_attributes = die.GetAttributes(attributes);
@@ -2926,8 +2892,7 @@
return 0;
size_t arg_idx = 0;
- for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
- die = die.GetSibling()) {
+ for (DWARFDIE die : parent_die.children()) {
const dw_tag_t tag = die.Tag();
switch (tag) {
case DW_TAG_formal_parameter: {
@@ -3046,8 +3011,7 @@
if (!parent_die)
return llvm::None;
- for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
- die = die.GetSibling()) {
+ for (DWARFDIE die : parent_die.children()) {
const dw_tag_t tag = die.Tag();
if (tag != DW_TAG_subrange_type)
continue;
@@ -3349,8 +3313,7 @@
}
static DWARFDIE FindAnyChildWithAbstractOrigin(const DWARFDIE &context) {
- for (DWARFDIE candidate = context.GetFirstChild(); candidate.IsValid();
- candidate = candidate.GetSibling()) {
+ for (DWARFDIE candidate : context.children()) {
if (candidate.GetReferencedDIE(DW_AT_abstract_origin)) {
return candidate;
}
@@ -3514,8 +3477,7 @@
UniqueCStringMap<DWARFDIE> dst_name_to_die;
UniqueCStringMap<DWARFDIE> src_name_to_die_artificial;
UniqueCStringMap<DWARFDIE> dst_name_to_die_artificial;
- for (src_die = src_class_die.GetFirstChild(); src_die.IsValid();
- src_die = src_die.GetSibling()) {
+ for (DWARFDIE src_die : src_class_die.children()) {
if (src_die.Tag() == DW_TAG_subprogram) {
// Make sure this is a declaration and not a concrete instance by looking
// for DW_AT_declaration set to 1. Sometimes concrete function instances
@@ -3533,8 +3495,7 @@
}
}
}
- for (dst_die = dst_class_die.GetFirstChild(); dst_die.IsValid();
- dst_die = dst_die.GetSibling()) {
+ for (DWARFDIE dst_die : dst_class_die.children()) {
if (dst_die.Tag() == DW_TAG_subprogram) {
// Make sure this is a declaration and not a concrete instance by looking
// for DW_AT_declaration set to 1. Sometimes concrete function instances
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
index e13716b..9bf6240 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
@@ -111,10 +111,9 @@
bool ParseChildMembers(
const DWARFDIE &die, lldb_private::CompilerType &class_compiler_type,
std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes,
- std::vector<int> &member_accessibilities,
std::vector<DWARFDIE> &member_function_dies,
DelayedPropertyList &delayed_properties,
- lldb::AccessType &default_accessibility, bool &is_a_class,
+ lldb::AccessType &default_accessibility,
lldb_private::ClangASTImporter::LayoutInfo &layout_info);
size_t
@@ -194,7 +193,6 @@
void
ParseSingleMember(const DWARFDIE &die, const DWARFDIE &parent_die,
const lldb_private::CompilerType &class_clang_type,
- std::vector<int> &member_accessibilities,
lldb::AccessType default_accessibility,
DelayedPropertyList &delayed_properties,
lldb_private::ClangASTImporter::LayoutInfo &layout_info,
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
index 0e9370b..2f6b36c 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
@@ -17,9 +17,7 @@
using namespace lldb_private;
-DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration()
- : m_code(InvalidCode), m_tag(llvm::dwarf::DW_TAG_null), m_has_children(0),
- m_attributes() {}
+DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() : m_attributes() {}
DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration(dw_tag_t tag,
uint8_t has_children)
@@ -58,7 +56,7 @@
DWARFFormValue::ValueType val;
if (form == DW_FORM_implicit_const)
- val.value.sval = data.GetULEB128(offset_ptr);
+ val.value.sval = data.GetSLEB128(offset_ptr);
m_attributes.push_back(DWARFAttribute(attr, form, val));
}
@@ -82,9 +80,3 @@
}
return DW_INVALID_INDEX;
}
-
-bool DWARFAbbreviationDeclaration::
-operator==(const DWARFAbbreviationDeclaration &rhs) const {
- return Tag() == rhs.Tag() && HasChildren() == rhs.HasChildren() &&
- m_attributes == rhs.m_attributes;
-}
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
index f70aa71..378ba88 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
@@ -53,12 +53,11 @@
extract(const lldb_private::DWARFDataExtractor &data,
lldb::offset_t *offset_ptr);
bool IsValid();
- bool operator==(const DWARFAbbreviationDeclaration &rhs) const;
protected:
- dw_uleb128_t m_code;
- dw_tag_t m_tag;
- uint8_t m_has_children;
+ dw_uleb128_t m_code = InvalidCode;
+ dw_tag_t m_tag = llvm::dwarf::DW_TAG_null;
+ uint8_t m_has_children = 0;
DWARFAttribute::collection m_attributes;
};
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp
index ef98d7e..134f6b2 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp
@@ -12,7 +12,7 @@
DWARFAttributes::DWARFAttributes() : m_infos() {}
-DWARFAttributes::~DWARFAttributes() {}
+DWARFAttributes::~DWARFAttributes() = default;
uint32_t DWARFAttributes::FindAttributeIndex(dw_attr_t attr) const {
collection::const_iterator end = m_infos.end();
@@ -25,10 +25,11 @@
return UINT32_MAX;
}
-void DWARFAttributes::Append(DWARFUnit *cu, dw_offset_t attr_die_offset,
- dw_attr_t attr, dw_form_t form) {
- AttributeValue attr_value = {
- cu, attr_die_offset, {attr, form, DWARFFormValue::ValueType()}};
+void DWARFAttributes::Append(const DWARFFormValue &form_value,
+ dw_offset_t attr_die_offset, dw_attr_t attr) {
+ AttributeValue attr_value = {const_cast<DWARFUnit *>(form_value.GetUnit()),
+ attr_die_offset,
+ {attr, form_value.Form(), form_value.Value()}};
m_infos.push_back(attr_value);
}
@@ -37,6 +38,10 @@
const DWARFUnit *cu = CompileUnitAtIndex(i);
form_value.SetUnit(cu);
form_value.SetForm(FormAtIndex(i));
+ if (form_value.Form() == DW_FORM_implicit_const) {
+ form_value.SetValue(ValueAtIndex(i));
+ return true;
+ }
lldb::offset_t offset = DIEOffsetAtIndex(i);
return form_value.ExtractValue(cu->GetData(), &offset);
}
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
index 8c21404..a31ee86 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
@@ -22,21 +22,15 @@
DWARFFormValue::ValueType value)
: m_attr(attr), m_form(form), m_value(value) {}
- void set(dw_attr_t attr, dw_form_t form) {
- m_attr = attr;
- m_form = form;
- }
dw_attr_t get_attr() const { return m_attr; }
dw_form_t get_form() const { return m_form; }
+ DWARFFormValue::ValueType get_value() const { return m_value; }
void get(dw_attr_t &attr, dw_form_t &form,
DWARFFormValue::ValueType &val) const {
attr = m_attr;
form = m_form;
val = m_value;
}
- bool operator==(const DWARFAttribute &rhs) const {
- return m_attr == rhs.m_attr && m_form == rhs.m_form;
- }
typedef std::vector<DWARFAttribute> collection;
typedef collection::iterator iterator;
typedef collection::const_iterator const_iterator;
@@ -52,8 +46,8 @@
DWARFAttributes();
~DWARFAttributes();
- void Append(DWARFUnit *cu, dw_offset_t attr_die_offset, dw_attr_t attr,
- dw_form_t form);
+ void Append(const DWARFFormValue &form_value, dw_offset_t attr_die_offset,
+ dw_attr_t attr);
DWARFUnit *CompileUnitAtIndex(uint32_t i) const { return m_infos[i].cu; }
dw_offset_t DIEOffsetAtIndex(uint32_t i) const {
return m_infos[i].die_offset;
@@ -62,6 +56,9 @@
return m_infos[i].attr.get_attr();
}
dw_attr_t FormAtIndex(uint32_t i) const { return m_infos[i].attr.get_form(); }
+ DWARFFormValue::ValueType ValueAtIndex(uint32_t i) const {
+ return m_infos[i].attr.get_value();
+ }
bool ExtractFormValueAtIndex(uint32_t i, DWARFFormValue &form_value) const;
DWARFDIE FormValueAsReferenceAtIndex(uint32_t i) const;
DWARFDIE FormValueAsReference(dw_attr_t attr) const;
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h
index 059b8486..36df980 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h
@@ -24,7 +24,7 @@
class DWARFBaseDIE {
public:
- DWARFBaseDIE() : m_cu(nullptr), m_die(nullptr) {}
+ DWARFBaseDIE() = default;
DWARFBaseDIE(DWARFUnit *cu, DWARFDebugInfoEntry *die)
: m_cu(cu), m_die(die) {}
@@ -115,8 +115,8 @@
Recurse recurse = Recurse::yes) const;
protected:
- DWARFUnit *m_cu;
- DWARFDebugInfoEntry *m_die;
+ DWARFUnit *m_cu = nullptr;
+ DWARFDebugInfoEntry *m_die = nullptr;
};
bool operator==(const DWARFBaseDIE &lhs, const DWARFBaseDIE &rhs);
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
index 8e995e6..dda691e 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
@@ -54,7 +54,7 @@
explicit ElaboratingDIEIterator(DWARFDIE d) : m_worklist(1, d) {}
/// End marker
- ElaboratingDIEIterator() {}
+ ElaboratingDIEIterator() = default;
const DWARFDIE &operator*() const { return m_worklist.back(); }
ElaboratingDIEIterator &operator++() {
@@ -192,7 +192,7 @@
}
if (check_children) {
- for (DWARFDIE child = GetFirstChild(); child; child = child.GetSibling()) {
+ for (DWARFDIE child : children()) {
if (DWARFDIE child_result = child.LookupDeepestBlock(address))
return child_result;
}
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
index 1373728..5615405 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
@@ -11,9 +11,11 @@
#include "DWARFBaseDIE.h"
#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/iterator_range.h"
class DWARFDIE : public DWARFBaseDIE {
public:
+ class child_iterator;
using DWARFBaseDIE::DWARFBaseDIE;
// Tests
@@ -88,6 +90,47 @@
int &decl_line, int &decl_column, int &call_file,
int &call_line, int &call_column,
lldb_private::DWARFExpression *frame_base) const;
+ /// The range of all the children of this DIE.
+ ///
+ /// This is a template just because child_iterator is not completely defined
+ /// at this point.
+ template <typename T = child_iterator>
+ llvm::iterator_range<T> children() const {
+ return llvm::make_range(T(*this), T());
+ }
+};
+
+class DWARFDIE::child_iterator
+ : public llvm::iterator_facade_base<DWARFDIE::child_iterator,
+ std::forward_iterator_tag, DWARFDIE> {
+ /// The current child or an invalid DWARFDie.
+ DWARFDIE m_die;
+
+public:
+ child_iterator() = default;
+ child_iterator(const DWARFDIE &parent) : m_die(parent.GetFirstChild()) {}
+ bool operator==(const child_iterator &it) const {
+ // DWARFDIE's operator== differentiates between an invalid DWARFDIE that
+ // has a CU but no DIE and one that has neither CU nor DIE. The 'end'
+ // iterator could be default constructed, so explicitly allow
+ // (CU, (DIE)nullptr) == (nullptr, nullptr) -> true
+ if (!m_die.IsValid() && !it.m_die.IsValid())
+ return true;
+ return m_die == it.m_die;
+ }
+ const DWARFDIE &operator*() const {
+ assert(m_die.IsValid() && "Derefencing invalid iterator?");
+ return m_die;
+ }
+ DWARFDIE &operator*() {
+ assert(m_die.IsValid() && "Derefencing invalid iterator?");
+ return m_die;
+ }
+ child_iterator &operator++() {
+ assert(m_die.IsValid() && "Incrementing invalid iterator?");
+ m_die = m_die.GetSibling();
+ return *this;
+ }
};
#endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDIE_H
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h
index 555864f..ec6b93c 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h
@@ -26,8 +26,7 @@
class DWARFAbbreviationDeclarationSet {
public:
- DWARFAbbreviationDeclarationSet()
- : m_offset(DW_INVALID_OFFSET), m_idx_offset(0), m_decls() {}
+ DWARFAbbreviationDeclarationSet() : m_offset(DW_INVALID_OFFSET), m_decls() {}
DWARFAbbreviationDeclarationSet(dw_offset_t offset, uint32_t idx_offset)
: m_offset(offset), m_idx_offset(idx_offset), m_decls() {}
@@ -51,7 +50,7 @@
/// @}
private:
dw_offset_t m_offset;
- uint32_t m_idx_offset;
+ uint32_t m_idx_offset = 0;
std::vector<DWARFAbbreviationDeclaration> m_decls;
};
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp
index 728cefe..ce51438 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp
@@ -8,22 +8,18 @@
#include "DWARFDebugArangeSet.h"
#include "DWARFDataExtractor.h"
+#include "LogChannelDWARF.h"
#include "llvm/Object/Error.h"
#include <cassert>
using namespace lldb_private;
DWARFDebugArangeSet::DWARFDebugArangeSet()
- : m_offset(DW_INVALID_OFFSET), m_header(), m_arange_descriptors() {
- m_header.length = 0;
- m_header.version = 0;
- m_header.cu_offset = 0;
- m_header.addr_size = 0;
- m_header.seg_size = 0;
-}
+ : m_offset(DW_INVALID_OFFSET), m_next_offset(DW_INVALID_OFFSET) {}
void DWARFDebugArangeSet::Clear() {
m_offset = DW_INVALID_OFFSET;
+ m_next_offset = DW_INVALID_OFFSET;
m_header.length = 0;
m_header.version = 0;
m_header.cu_offset = 0;
@@ -54,6 +50,12 @@
// consists of an address and a length, each in the size appropriate for an
// address on the target architecture.
m_header.length = data.GetDWARFInitialLength(offset_ptr);
+ // The length could be 4 bytes or 12 bytes, so use the current offset to
+ // determine the next offset correctly.
+ if (m_header.length > 0)
+ m_next_offset = *offset_ptr + m_header.length;
+ else
+ m_next_offset = DW_INVALID_OFFSET;
m_header.version = data.GetU16(offset_ptr);
m_header.cu_offset = data.GetDWARFOffset(offset_ptr);
m_header.addr_size = data.GetU8(offset_ptr);
@@ -105,17 +107,45 @@
"DWARFDebugArangeSet::Descriptor.address and "
"DWARFDebugArangeSet::Descriptor.length must have same size");
- while (data.ValidOffset(*offset_ptr)) {
+ const lldb::offset_t next_offset = GetNextOffset();
+ assert(next_offset != DW_INVALID_OFFSET);
+ uint32_t num_terminators = 0;
+ bool last_was_terminator = false;
+ while (*offset_ptr < next_offset) {
arangeDescriptor.address = data.GetMaxU64(offset_ptr, m_header.addr_size);
arangeDescriptor.length = data.GetMaxU64(offset_ptr, m_header.addr_size);
// Each set of tuples is terminated by a 0 for the address and 0 for
- // the length.
- if (!arangeDescriptor.address && !arangeDescriptor.length)
- return llvm::ErrorSuccess();
-
- m_arange_descriptors.push_back(arangeDescriptor);
+ // the length. Some linkers can emit .debug_aranges with multiple
+ // terminator pair entries that are still withing the length of the
+ // DWARFDebugArangeSet. We want to be sure to parse all entries for
+ // this DWARFDebugArangeSet so that we don't stop parsing early and end up
+ // treating addresses as a header of the next DWARFDebugArangeSet. We also
+ // need to make sure we parse all valid address pairs so we don't omit them
+ // from the aranges result, so we can't stop at the first terminator entry
+ // we find.
+ if (arangeDescriptor.address == 0 && arangeDescriptor.length == 0) {
+ ++num_terminators;
+ last_was_terminator = true;
+ } else {
+ last_was_terminator = false;
+ // Only add .debug_aranges address entries that have a non zero size.
+ // Some linkers will zero out the length field for some .debug_aranges
+ // entries if they were stripped. We also could watch out for multiple
+ // entries at address zero and remove those as well.
+ if (arangeDescriptor.length > 0)
+ m_arange_descriptors.push_back(arangeDescriptor);
+ }
}
+ if (num_terminators > 1) {
+ Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);
+ LLDB_LOG(log,
+ "warning: DWARFDebugArangeSet at %#" PRIx64 " contains %u "
+ "terminator entries",
+ m_offset, num_terminators);
+ }
+ if (last_was_terminator)
+ return llvm::ErrorSuccess();
return llvm::make_error<llvm::object::GenericBinaryError>(
"arange descriptors not terminated by null entry");
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h
index 6b5b69a..3c8633e 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h
@@ -16,18 +16,21 @@
class DWARFDebugArangeSet {
public:
struct Header {
- uint32_t length; // The total length of the entries for that set, not
- // including the length field itself.
- uint16_t version; // The DWARF version number
- uint32_t cu_offset; // The offset from the beginning of the .debug_info
- // section of the compilation unit entry referenced by
- // the table.
- uint8_t addr_size; // The size in bytes of an address on the target
- // architecture. For segmented addressing, this is the
- // size of the offset portion of the address
- uint8_t seg_size; // The size in bytes of a segment descriptor on the target
- // architecture. If the target system uses a flat address
- // space, this value is 0.
+ /// The total length of the entries for that set, not including the length
+ /// field itself.
+ uint32_t length = 0;
+ /// The DWARF version number.
+ uint16_t version = 0;
+ /// The offset from the beginning of the .debug_info section of the
+ /// compilation unit entry referenced by the table.
+ uint32_t cu_offset = 0;
+ /// The size in bytes of an address on the target architecture. For
+ /// segmented addressing, this is the size of the offset portion of the
+ /// address.
+ uint8_t addr_size = 0;
+ /// The size in bytes of a segment descriptor on the target architecture.
+ /// If the target system uses a flat address space, this value is 0.
+ uint8_t seg_size = 0;
};
struct Descriptor {
@@ -44,7 +47,7 @@
dw_offset_t FindAddress(dw_addr_t address) const;
size_t NumDescriptors() const { return m_arange_descriptors.size(); }
const Header &GetHeader() const { return m_header; }
-
+ dw_offset_t GetNextOffset() const { return m_next_offset; }
const Descriptor &GetDescriptorRef(uint32_t i) const {
return m_arange_descriptors[i];
}
@@ -54,7 +57,8 @@
typedef DescriptorColl::iterator DescriptorIter;
typedef DescriptorColl::const_iterator DescriptorConstIter;
- uint32_t m_offset;
+ dw_offset_t m_offset;
+ dw_offset_t m_next_offset;
Header m_header;
DescriptorColl m_arange_descriptors;
};
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
index 9f190fb..65923cb 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
@@ -9,6 +9,7 @@
#include "DWARFDebugAranges.h"
#include "DWARFDebugArangeSet.h"
#include "DWARFUnit.h"
+#include "LogChannelDWARF.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Timer.h"
@@ -31,31 +32,40 @@
};
// Extract
-llvm::Error
-DWARFDebugAranges::extract(const DWARFDataExtractor &debug_aranges_data) {
+void DWARFDebugAranges::extract(const DWARFDataExtractor &debug_aranges_data) {
lldb::offset_t offset = 0;
DWARFDebugArangeSet set;
Range range;
while (debug_aranges_data.ValidOffset(offset)) {
- llvm::Error error = set.extract(debug_aranges_data, &offset);
- if (error)
- return error;
+ const lldb::offset_t set_offset = offset;
+ if (llvm::Error error = set.extract(debug_aranges_data, &offset)) {
+ Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);
+ LLDB_LOG_ERROR(log, std::move(error),
+ "DWARFDebugAranges::extract failed to extract "
+ ".debug_aranges set at offset %#" PRIx64,
+ set_offset);
+ } else {
+ const uint32_t num_descriptors = set.NumDescriptors();
+ if (num_descriptors > 0) {
+ const dw_offset_t cu_offset = set.GetHeader().cu_offset;
- const uint32_t num_descriptors = set.NumDescriptors();
- if (num_descriptors > 0) {
- const dw_offset_t cu_offset = set.GetHeader().cu_offset;
-
- for (uint32_t i = 0; i < num_descriptors; ++i) {
- const DWARFDebugArangeSet::Descriptor &descriptor =
- set.GetDescriptorRef(i);
- m_aranges.Append(RangeToDIE::Entry(descriptor.address,
- descriptor.length, cu_offset));
+ for (uint32_t i = 0; i < num_descriptors; ++i) {
+ const DWARFDebugArangeSet::Descriptor &descriptor =
+ set.GetDescriptorRef(i);
+ m_aranges.Append(RangeToDIE::Entry(descriptor.address,
+ descriptor.length, cu_offset));
+ }
}
}
+ // Always use the previous DWARFDebugArangeSet's information to calculate
+ // the offset of the next DWARFDebugArangeSet in case we entouncter an
+ // error in the current DWARFDebugArangeSet and our offset position is
+ // still in the middle of the data. If we do this, we can parse all valid
+ // DWARFDebugArangeSet objects without returning invalid errors.
+ offset = set.GetNextOffset();
set.Clear();
}
- return llvm::ErrorSuccess();
}
void DWARFDebugAranges::Dump(Log *log) const {
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h
index 96e8261..5ff37e4 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h
@@ -26,8 +26,7 @@
void Clear() { m_aranges.Clear(); }
- llvm::Error
- extract(const lldb_private::DWARFDataExtractor &debug_aranges_data);
+ void extract(const lldb_private::DWARFDataExtractor &debug_aranges_data);
// Use append range multiple times and then call sort
void AppendRange(dw_offset_t cu_offset, dw_addr_t low_pc, dw_addr_t high_pc);
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
index 8d393b2..e43afa1 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
@@ -34,17 +34,18 @@
lldb_private::DWARFContext &context)
: m_dwarf(dwarf), m_context(context), m_units(), m_cu_aranges_up() {}
-llvm::Expected<DWARFDebugAranges &> DWARFDebugInfo::GetCompileUnitAranges() {
+const DWARFDebugAranges &DWARFDebugInfo::GetCompileUnitAranges() {
if (m_cu_aranges_up)
return *m_cu_aranges_up;
m_cu_aranges_up = std::make_unique<DWARFDebugAranges>();
const DWARFDataExtractor &debug_aranges_data =
m_context.getOrLoadArangesData();
- if (llvm::Error error = m_cu_aranges_up->extract(debug_aranges_data))
- return std::move(error);
- // Make a list of all CUs represented by the arange data in the file.
+ // Extract what we can from the .debug_aranges first.
+ m_cu_aranges_up->extract(debug_aranges_data);
+
+ // Make a list of all CUs represented by the .debug_aranges data.
std::set<dw_offset_t> cus_with_data;
for (size_t n = 0; n < m_cu_aranges_up->GetNumRanges(); n++) {
dw_offset_t offset = m_cu_aranges_up->OffsetAtIndex(n);
@@ -52,8 +53,7 @@
cus_with_data.insert(offset);
}
- // Manually build arange data for everything that wasn't in the
- // .debug_aranges table.
+ // Manually build arange data for everything that wasn't in .debug_aranges.
const size_t num_units = GetNumUnits();
for (size_t idx = 0; idx < num_units; ++idx) {
DWARFUnit *cu = GetUnitAtIndex(idx);
@@ -72,16 +72,10 @@
DWARFDataExtractor data = section == DIERef::Section::DebugTypes
? m_context.getOrLoadDebugTypesData()
: m_context.getOrLoadDebugInfoData();
- const llvm::DWARFUnitIndex *index = nullptr;
- if (m_context.isDwo())
- index = &llvm::getDWARFUnitIndex(m_context.GetAsLLVM(),
- section == DIERef::Section::DebugTypes
- ? llvm::DW_SECT_EXT_TYPES
- : llvm::DW_SECT_INFO);
lldb::offset_t offset = 0;
while (data.ValidOffset(offset)) {
llvm::Expected<DWARFUnitSP> unit_sp = DWARFUnit::extract(
- m_dwarf, m_units.size(), data, section, &offset, index);
+ m_dwarf, m_units.size(), data, section, &offset);
if (!unit_sp) {
// FIXME: Propagate this error up.
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
index bdc718a..46c04d7 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
@@ -54,7 +54,7 @@
(1 << 2) // Show all parent DIEs when dumping single DIEs
};
- llvm::Expected<DWARFDebugAranges &> GetCompileUnitAranges();
+ const DWARFDebugAranges &GetCompileUnitAranges();
protected:
typedef std::vector<DWARFUnitSP> UnitColl;
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
index 4212988..39915aa 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
@@ -8,7 +8,7 @@
#include "DWARFDebugInfoEntry.h"
-#include <assert.h>
+#include <cassert>
#include <algorithm>
@@ -49,156 +49,159 @@
// assert (fixed_form_sizes); // For best performance this should be
// specified!
- if (m_abbr_idx) {
- lldb::offset_t offset = *offset_ptr;
- const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu);
- if (abbrevDecl == nullptr) {
- cu->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
- "{0x%8.8x}: invalid abbreviation code %u, please file a bug and "
- "attach the file at the start of this error message",
- m_offset, (unsigned)abbr_idx);
- // WE can't parse anymore if the DWARF is borked...
- *offset_ptr = UINT32_MAX;
- return false;
- }
- m_tag = abbrevDecl->Tag();
- m_has_children = abbrevDecl->HasChildren();
- // Skip all data in the .debug_info or .debug_types for the attributes
- const uint32_t numAttributes = abbrevDecl->NumAttributes();
- uint32_t i;
- dw_form_t form;
- for (i = 0; i < numAttributes; ++i) {
- form = abbrevDecl->GetFormByIndexUnchecked(i);
- llvm::Optional<uint8_t> fixed_skip_size =
- DWARFFormValue::GetFixedSize(form, cu);
- if (fixed_skip_size)
- offset += *fixed_skip_size;
- else {
- bool form_is_indirect = false;
- do {
- form_is_indirect = false;
- uint32_t form_size = 0;
- switch (form) {
- // Blocks if inlined data that have a length field and the data bytes
- // inlined in the .debug_info/.debug_types
- case DW_FORM_exprloc:
- case DW_FORM_block:
- form_size = data.GetULEB128(&offset);
- break;
- case DW_FORM_block1:
- form_size = data.GetU8_unchecked(&offset);
- break;
- case DW_FORM_block2:
- form_size = data.GetU16_unchecked(&offset);
- break;
- case DW_FORM_block4:
- form_size = data.GetU32_unchecked(&offset);
- break;
-
- // Inlined NULL terminated C-strings
- case DW_FORM_string:
- data.GetCStr(&offset);
- break;
-
- // Compile unit address sized values
- case DW_FORM_addr:
- form_size = cu->GetAddressByteSize();
- break;
- case DW_FORM_ref_addr:
- if (cu->GetVersion() <= 2)
- form_size = cu->GetAddressByteSize();
- else
- form_size = 4;
- break;
-
- // 0 sized form
- case DW_FORM_flag_present:
- form_size = 0;
- break;
-
- // 1 byte values
- case DW_FORM_addrx1:
- case DW_FORM_data1:
- case DW_FORM_flag:
- case DW_FORM_ref1:
- case DW_FORM_strx1:
- form_size = 1;
- break;
-
- // 2 byte values
- case DW_FORM_addrx2:
- case DW_FORM_data2:
- case DW_FORM_ref2:
- case DW_FORM_strx2:
- form_size = 2;
- break;
-
- // 3 byte values
- case DW_FORM_addrx3:
- case DW_FORM_strx3:
- form_size = 3;
- break;
-
- // 4 byte values
- case DW_FORM_addrx4:
- case DW_FORM_data4:
- case DW_FORM_ref4:
- case DW_FORM_strx4:
- form_size = 4;
- break;
-
- // 8 byte values
- case DW_FORM_data8:
- case DW_FORM_ref8:
- case DW_FORM_ref_sig8:
- form_size = 8;
- break;
-
- // signed or unsigned LEB 128 values
- case DW_FORM_addrx:
- case DW_FORM_loclistx:
- case DW_FORM_rnglistx:
- case DW_FORM_sdata:
- case DW_FORM_udata:
- case DW_FORM_ref_udata:
- case DW_FORM_GNU_addr_index:
- case DW_FORM_GNU_str_index:
- case DW_FORM_strx:
- data.Skip_LEB128(&offset);
- break;
-
- case DW_FORM_indirect:
- form_is_indirect = true;
- form = data.GetULEB128(&offset);
- break;
-
- case DW_FORM_strp:
- case DW_FORM_sec_offset:
- data.GetU32(&offset);
- break;
-
- case DW_FORM_implicit_const:
- form_size = 0;
- break;
-
- default:
- *offset_ptr = m_offset;
- return false;
- }
- offset += form_size;
-
- } while (form_is_indirect);
- }
- }
- *offset_ptr = offset;
- return true;
- } else {
+ if (m_abbr_idx == 0) {
m_tag = llvm::dwarf::DW_TAG_null;
m_has_children = false;
return true; // NULL debug tag entry
}
- return false;
+ lldb::offset_t offset = *offset_ptr;
+ const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu);
+ if (abbrevDecl == nullptr) {
+ cu->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
+ "{0x%8.8x}: invalid abbreviation code %u, please file a bug and "
+ "attach the file at the start of this error message",
+ m_offset, (unsigned)abbr_idx);
+ // WE can't parse anymore if the DWARF is borked...
+ *offset_ptr = UINT32_MAX;
+ return false;
+ }
+ m_tag = abbrevDecl->Tag();
+ m_has_children = abbrevDecl->HasChildren();
+ // Skip all data in the .debug_info or .debug_types for the attributes
+ const uint32_t numAttributes = abbrevDecl->NumAttributes();
+ uint32_t i;
+ dw_form_t form;
+ for (i = 0; i < numAttributes; ++i) {
+ form = abbrevDecl->GetFormByIndexUnchecked(i);
+ llvm::Optional<uint8_t> fixed_skip_size =
+ DWARFFormValue::GetFixedSize(form, cu);
+ if (fixed_skip_size)
+ offset += *fixed_skip_size;
+ else {
+ bool form_is_indirect = false;
+ do {
+ form_is_indirect = false;
+ uint32_t form_size = 0;
+ switch (form) {
+ // Blocks if inlined data that have a length field and the data bytes
+ // inlined in the .debug_info/.debug_types
+ case DW_FORM_exprloc:
+ case DW_FORM_block:
+ form_size = data.GetULEB128(&offset);
+ break;
+ case DW_FORM_block1:
+ form_size = data.GetU8_unchecked(&offset);
+ break;
+ case DW_FORM_block2:
+ form_size = data.GetU16_unchecked(&offset);
+ break;
+ case DW_FORM_block4:
+ form_size = data.GetU32_unchecked(&offset);
+ break;
+
+ // Inlined NULL terminated C-strings
+ case DW_FORM_string:
+ data.GetCStr(&offset);
+ break;
+
+ // Compile unit address sized values
+ case DW_FORM_addr:
+ form_size = cu->GetAddressByteSize();
+ break;
+ case DW_FORM_ref_addr:
+ if (cu->GetVersion() <= 2)
+ form_size = cu->GetAddressByteSize();
+ else
+ form_size = 4;
+ break;
+
+ // 0 sized form
+ case DW_FORM_flag_present:
+ form_size = 0;
+ break;
+
+ // 1 byte values
+ case DW_FORM_addrx1:
+ case DW_FORM_data1:
+ case DW_FORM_flag:
+ case DW_FORM_ref1:
+ case DW_FORM_strx1:
+ form_size = 1;
+ break;
+
+ // 2 byte values
+ case DW_FORM_addrx2:
+ case DW_FORM_data2:
+ case DW_FORM_ref2:
+ case DW_FORM_strx2:
+ form_size = 2;
+ break;
+
+ // 3 byte values
+ case DW_FORM_addrx3:
+ case DW_FORM_strx3:
+ form_size = 3;
+ break;
+
+ // 4 byte values
+ case DW_FORM_addrx4:
+ case DW_FORM_data4:
+ case DW_FORM_ref4:
+ case DW_FORM_strx4:
+ form_size = 4;
+ break;
+
+ // 8 byte values
+ case DW_FORM_data8:
+ case DW_FORM_ref8:
+ case DW_FORM_ref_sig8:
+ form_size = 8;
+ break;
+
+ // signed or unsigned LEB 128 values
+ case DW_FORM_addrx:
+ case DW_FORM_loclistx:
+ case DW_FORM_rnglistx:
+ case DW_FORM_sdata:
+ case DW_FORM_udata:
+ case DW_FORM_ref_udata:
+ case DW_FORM_GNU_addr_index:
+ case DW_FORM_GNU_str_index:
+ case DW_FORM_strx:
+ data.Skip_LEB128(&offset);
+ break;
+
+ case DW_FORM_indirect:
+ form_is_indirect = true;
+ form = data.GetULEB128(&offset);
+ break;
+
+ case DW_FORM_strp:
+ case DW_FORM_line_strp:
+ case DW_FORM_sec_offset:
+ data.GetU32(&offset);
+ break;
+
+ case DW_FORM_implicit_const:
+ form_size = 0;
+ break;
+
+ default:
+ cu->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
+ "{0x%8.8x}: Unsupported DW_FORM_0x%x, please file a bug and "
+ "attach the file at the start of this error message",
+ m_offset, (unsigned)form);
+ *offset_ptr = m_offset;
+ return false;
+ }
+ offset += form_size;
+
+ } while (form_is_indirect);
+ }
+ }
+ *offset_ptr = offset;
+ return true;
}
static DWARFRangeList GetRangesOrReportError(DWARFUnit &unit,
@@ -211,11 +214,12 @@
if (expected_ranges)
return std::move(*expected_ranges);
unit.GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
- "{0x%8.8x}: DIE has DW_AT_ranges(0x%" PRIx64 ") attribute, but "
+ "{0x%8.8x}: DIE has DW_AT_ranges(%s 0x%" PRIx64 ") attribute, but "
"range extraction failed (%s), please file a bug "
"and attach the file at the start of this error message",
- die.GetOffset(), value.Unsigned(),
- toString(expected_ranges.takeError()).c_str());
+ die.GetOffset(),
+ llvm::dwarf::FormEncodingString(value.Form()).str().c_str(),
+ value.Unsigned(), toString(expected_ranges.takeError()).c_str());
return DWARFRangeList();
}
@@ -429,7 +433,7 @@
}
LLVM_FALLTHROUGH;
default:
- attributes.Append(cu, offset, attr, form);
+ attributes.Append(form_value, offset, attr);
break;
}
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
index 0ba56a0..64e86c7 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
@@ -35,8 +35,7 @@
typedef collection::const_iterator const_iterator;
DWARFDebugInfoEntry()
- : m_offset(DW_INVALID_OFFSET), m_parent_idx(0), m_sibling_idx(0),
- m_has_children(false), m_abbr_idx(0), m_tag(llvm::dwarf::DW_TAG_null) {}
+ : m_offset(DW_INVALID_OFFSET), m_sibling_idx(0), m_has_children(false) {}
explicit operator bool() const { return m_offset != DW_INVALID_OFFSET; }
bool operator==(const DWARFDebugInfoEntry &rhs) const;
@@ -167,14 +166,14 @@
GetDWARFDeclContextStatic(const DWARFDebugInfoEntry *die, DWARFUnit *cu);
dw_offset_t m_offset; // Offset within the .debug_info/.debug_types
- uint32_t m_parent_idx; // How many to subtract from "this" to get the parent.
- // If zero this die has no parent
+ uint32_t m_parent_idx = 0; // How many to subtract from "this" to get the
+ // parent. If zero this die has no parent
uint32_t m_sibling_idx : 31, // How many to add to "this" to get the sibling.
// If it is zero, then the DIE doesn't have children, or the
// DWARF claimed it had children but the DIE only contained
// a single NULL terminating child.
m_has_children : 1;
- uint16_t m_abbr_idx;
+ uint16_t m_abbr_idx = 0;
/// A copy of the DW_TAG value so we don't have to go through the compile
/// unit abbrev table
dw_tag_t m_tag = llvm::dwarf::DW_TAG_null;
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
index 9072b2d..e466944 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
@@ -23,7 +23,7 @@
class DWARFDeclContext {
public:
struct Entry {
- Entry() : tag(llvm::dwarf::DW_TAG_null), name(nullptr) {}
+ Entry() = default;
Entry(dw_tag_t t, const char *n) : tag(t), name(n) {}
bool NameMatches(const Entry &rhs) const {
@@ -37,11 +37,11 @@
// Test operator
explicit operator bool() const { return tag != 0; }
- dw_tag_t tag;
- const char *name;
+ dw_tag_t tag = llvm::dwarf::DW_TAG_null;
+ const char *name = nullptr;
};
- DWARFDeclContext() : m_entries(), m_language(lldb::eLanguageTypeUnknown) {}
+ DWARFDeclContext() : m_entries() {}
void AppendDeclContext(dw_tag_t tag, const char *name) {
m_entries.push_back(Entry(tag, name));
@@ -83,7 +83,7 @@
typedef std::vector<Entry> collection;
collection m_entries;
mutable std::string m_qualified_name;
- lldb::LanguageType m_language;
+ lldb::LanguageType m_language = lldb::eLanguageTypeUnknown;
};
#endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDECLCONTEXT_H
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.h b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.h
index 1b7102c..2d0d5ca 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.h
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.h
@@ -10,7 +10,7 @@
#define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDEFINES_H
#include "lldb/Core/dwarf.h"
-#include <stdint.h>
+#include <cstdint>
namespace lldb_private {
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
index 305f1cb..4c49870 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include <assert.h>
+#include <cassert>
#include "lldb/Core/Module.h"
#include "lldb/Core/dwarf.h"
@@ -150,40 +150,40 @@
uint8_t valid:1, size:7;
};
static FormSize g_form_sizes[] = {
- {0,0}, // 0x00 unused
- {0,0}, // 0x01 DW_FORM_addr
- {0,0}, // 0x02 unused
- {0,0}, // 0x03 DW_FORM_block2
- {0,0}, // 0x04 DW_FORM_block4
- {1,2}, // 0x05 DW_FORM_data2
- {1,4}, // 0x06 DW_FORM_data4
- {1,8}, // 0x07 DW_FORM_data8
- {0,0}, // 0x08 DW_FORM_string
- {0,0}, // 0x09 DW_FORM_block
- {0,0}, // 0x0a DW_FORM_block1
- {1,1}, // 0x0b DW_FORM_data1
- {1,1}, // 0x0c DW_FORM_flag
- {0,0}, // 0x0d DW_FORM_sdata
- {1,4}, // 0x0e DW_FORM_strp
- {0,0}, // 0x0f DW_FORM_udata
- {0,0}, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes for
- // DWARF32, 8 bytes for DWARF32 in DWARF 3 and later
- {1,1}, // 0x11 DW_FORM_ref1
- {1,2}, // 0x12 DW_FORM_ref2
- {1,4}, // 0x13 DW_FORM_ref4
- {1,8}, // 0x14 DW_FORM_ref8
- {0,0}, // 0x15 DW_FORM_ref_udata
- {0,0}, // 0x16 DW_FORM_indirect
- {1,4}, // 0x17 DW_FORM_sec_offset
- {0,0}, // 0x18 DW_FORM_exprloc
- {1,0}, // 0x19 DW_FORM_flag_present
- {0,0}, // 0x1a
- {0,0}, // 0x1b
- {0,0}, // 0x1c
- {0,0}, // 0x1d
- {0,0}, // 0x1e
- {0,0}, // 0x1f
- {1,8}, // 0x20 DW_FORM_ref_sig8
+ {0, 0}, // 0x00 unused
+ {0, 0}, // 0x01 DW_FORM_addr
+ {0, 0}, // 0x02 unused
+ {0, 0}, // 0x03 DW_FORM_block2
+ {0, 0}, // 0x04 DW_FORM_block4
+ {1, 2}, // 0x05 DW_FORM_data2
+ {1, 4}, // 0x06 DW_FORM_data4
+ {1, 8}, // 0x07 DW_FORM_data8
+ {0, 0}, // 0x08 DW_FORM_string
+ {0, 0}, // 0x09 DW_FORM_block
+ {0, 0}, // 0x0a DW_FORM_block1
+ {1, 1}, // 0x0b DW_FORM_data1
+ {1, 1}, // 0x0c DW_FORM_flag
+ {0, 0}, // 0x0d DW_FORM_sdata
+ {1, 4}, // 0x0e DW_FORM_strp
+ {0, 0}, // 0x0f DW_FORM_udata
+ {0, 0}, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes
+ // for DWARF32, 8 bytes for DWARF32 in DWARF 3 and later
+ {1, 1}, // 0x11 DW_FORM_ref1
+ {1, 2}, // 0x12 DW_FORM_ref2
+ {1, 4}, // 0x13 DW_FORM_ref4
+ {1, 8}, // 0x14 DW_FORM_ref8
+ {0, 0}, // 0x15 DW_FORM_ref_udata
+ {0, 0}, // 0x16 DW_FORM_indirect
+ {1, 4}, // 0x17 DW_FORM_sec_offset
+ {0, 0}, // 0x18 DW_FORM_exprloc
+ {1, 0}, // 0x19 DW_FORM_flag_present
+ {0, 0}, // 0x1a DW_FORM_strx (ULEB128)
+ {0, 0}, // 0x1b DW_FORM_addrx (ULEB128)
+ {1, 4}, // 0x1c DW_FORM_ref_sup4
+ {0, 0}, // 0x1d DW_FORM_strp_sup (4 bytes for DWARF32, 8 bytes for DWARF64)
+ {1, 16}, // 0x1e DW_FORM_data16
+ {1, 4}, // 0x1f DW_FORM_line_strp
+ {1, 8}, // 0x20 DW_FORM_ref_sig8
};
llvm::Optional<uint8_t>
@@ -286,6 +286,7 @@
// 32 bit for DWARF 32, 64 for DWARF 64
case DW_FORM_sec_offset:
case DW_FORM_strp:
+ case DW_FORM_line_strp:
*offset_ptr += 4;
return true;
@@ -398,7 +399,8 @@
case DW_FORM_udata:
s.PutULEB128(uvalue);
break;
- case DW_FORM_strp: {
+ case DW_FORM_strp:
+ case DW_FORM_line_strp: {
const char *dbg_str = AsCString();
if (dbg_str) {
s.QuotedCString(dbg_str);
@@ -606,6 +608,7 @@
case DW_FORM_flag:
case DW_FORM_sdata:
case DW_FORM_strp:
+ case DW_FORM_line_strp:
case DW_FORM_strx:
case DW_FORM_strx1:
case DW_FORM_strx2:
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
index fe6a555..9406bcf 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
@@ -10,8 +10,8 @@
#define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFFORMVALUE_H
#include "DWARFDataExtractor.h"
-#include <stddef.h>
#include "llvm/ADT/Optional.h"
+#include <cstddef>
class DWARFUnit;
class SymbolFileDWARF;
@@ -20,14 +20,14 @@
class DWARFFormValue {
public:
typedef struct ValueTypeTag {
- ValueTypeTag() : value(), data(nullptr) { value.uval = 0; }
+ ValueTypeTag() : value() { value.uval = 0; }
union {
uint64_t uval;
int64_t sval;
const char *cstr;
} value;
- const uint8_t *data;
+ const uint8_t *data = nullptr;
} ValueType;
enum {
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
index a761dd3..824e438 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -236,6 +236,11 @@
}
if (!m_die_array.empty()) {
+ // The last die cannot have children (if it did, it wouldn't be the last one).
+ // This only makes a difference for malformed dwarf that does not have a
+ // terminating null die.
+ m_die_array.back().SetHasChildren(false);
+
if (m_first_die) {
// Only needed for the assertion.
m_first_die.SetHasChildren(m_die_array.front().HasChildren());
@@ -292,8 +297,7 @@
// m_die_array_mutex must be already held as read/write.
void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
- llvm::Optional<uint64_t> addr_base, gnu_addr_base, ranges_base,
- gnu_ranges_base;
+ llvm::Optional<uint64_t> addr_base, gnu_addr_base, gnu_ranges_base;
DWARFAttributes attributes;
size_t num_attributes = cu_die.GetAttributes(this, attributes);
@@ -320,8 +324,7 @@
SetLoclistsBase(form_value.Unsigned());
break;
case DW_AT_rnglists_base:
- ranges_base = form_value.Unsigned();
- SetRangesBase(*ranges_base);
+ SetRangesBase(form_value.Unsigned());
break;
case DW_AT_str_offsets_base:
SetStrOffsetsBase(form_value.Unsigned());
@@ -482,19 +485,46 @@
}
void DWARFUnit::SetRangesBase(dw_addr_t ranges_base) {
+ lldbassert(!m_rnglist_table_done);
+
m_ranges_base = ranges_base;
+}
- if (GetVersion() < 5)
- return;
+const llvm::Optional<llvm::DWARFDebugRnglistTable> &
+DWARFUnit::GetRnglistTable() {
+ if (GetVersion() >= 5 && !m_rnglist_table_done) {
+ m_rnglist_table_done = true;
+ if (auto table_or_error =
+ ParseListTableHeader<llvm::DWARFDebugRnglistTable>(
+ m_dwarf.GetDWARFContext().getOrLoadRngListsData().GetAsLLVM(),
+ m_ranges_base, DWARF32))
+ m_rnglist_table = std::move(table_or_error.get());
+ else
+ GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
+ "Failed to extract range list table at offset 0x%" PRIx64 ": %s",
+ m_ranges_base, toString(table_or_error.takeError()).c_str());
+ }
+ return m_rnglist_table;
+}
- if (auto table_or_error = ParseListTableHeader<llvm::DWARFDebugRnglistTable>(
- m_dwarf.GetDWARFContext().getOrLoadRngListsData().GetAsLLVM(),
- ranges_base, DWARF32))
- m_rnglist_table = std::move(table_or_error.get());
- else
- GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
- "Failed to extract range list table at offset 0x%" PRIx64 ": %s",
- ranges_base, toString(table_or_error.takeError()).c_str());
+// This function is called only for DW_FORM_rnglistx.
+llvm::Expected<uint64_t> DWARFUnit::GetRnglistOffset(uint32_t Index) {
+ if (!GetRnglistTable())
+ return llvm::createStringError(errc::invalid_argument,
+ "missing or invalid range list table");
+ if (!m_ranges_base)
+ return llvm::createStringError(errc::invalid_argument,
+ "DW_FORM_rnglistx cannot be used without "
+ "DW_AT_rnglists_base for CU at 0x%8.8x",
+ GetOffset());
+ if (llvm::Optional<uint64_t> off = GetRnglistTable()->getOffsetEntry(
+ m_dwarf.GetDWARFContext().getOrLoadRngListsData().GetAsLLVM(), Index))
+ return *off + m_ranges_base;
+ return llvm::createStringError(
+ errc::invalid_argument,
+ "invalid range list table index %u; OffsetEntryCount is %u, "
+ "DW_AT_rnglists_base is %" PRIu64,
+ Index, GetRnglistTable()->getOffsetEntryCount(), m_ranges_base);
}
void DWARFUnit::SetStrOffsetsBase(dw_offset_t str_offsets_base) {
@@ -784,12 +814,11 @@
llvm::Expected<DWARFUnitHeader>
DWARFUnitHeader::extract(const DWARFDataExtractor &data,
- DIERef::Section section, lldb::offset_t *offset_ptr,
- const llvm::DWARFUnitIndex *index) {
+ DIERef::Section section,
+ lldb_private::DWARFContext &context,
+ lldb::offset_t *offset_ptr) {
DWARFUnitHeader header;
header.m_offset = *offset_ptr;
- if (index)
- header.m_index_entry = index->getFromOffset(*offset_ptr);
header.m_length = data.GetDWARFInitialLength(offset_ptr);
header.m_version = data.GetU16(offset_ptr);
if (header.m_version == 5) {
@@ -806,6 +835,16 @@
section == DIERef::Section::DebugTypes ? DW_UT_type : DW_UT_compile;
}
+ if (context.isDwo()) {
+ if (header.IsTypeUnit()) {
+ header.m_index_entry =
+ context.GetAsLLVM().getTUIndex().getFromOffset(header.m_offset);
+ } else {
+ header.m_index_entry =
+ context.GetAsLLVM().getCUIndex().getFromOffset(header.m_offset);
+ }
+ }
+
if (header.m_index_entry) {
if (header.m_abbr_offset) {
return llvm::createStringError(
@@ -856,12 +895,11 @@
llvm::Expected<DWARFUnitSP>
DWARFUnit::extract(SymbolFileDWARF &dwarf, user_id_t uid,
const DWARFDataExtractor &debug_info,
- DIERef::Section section, lldb::offset_t *offset_ptr,
- const llvm::DWARFUnitIndex *index) {
+ DIERef::Section section, lldb::offset_t *offset_ptr) {
assert(debug_info.ValidOffset(*offset_ptr));
- auto expected_header =
- DWARFUnitHeader::extract(debug_info, section, offset_ptr, index);
+ auto expected_header = DWARFUnitHeader::extract(
+ debug_info, section, dwarf.GetDWARFContext(), offset_ptr);
if (!expected_header)
return expected_header.takeError();
@@ -930,11 +968,11 @@
return ranges;
}
- if (!m_rnglist_table)
+ if (!GetRnglistTable())
return llvm::createStringError(errc::invalid_argument,
"missing or invalid range list table");
- auto range_list_or_error = m_rnglist_table->findList(
+ auto range_list_or_error = GetRnglistTable()->findList(
m_dwarf.GetDWARFContext().getOrLoadRngListsData().GetAsLLVM(), offset);
if (!range_list_or_error)
return range_list_or_error.takeError();
@@ -963,12 +1001,8 @@
llvm::Expected<DWARFRangeList>
DWARFUnit::FindRnglistFromIndex(uint32_t index) {
- if (llvm::Optional<uint64_t> offset = GetRnglistOffset(index))
- return FindRnglistFromOffset(*offset);
- if (m_rnglist_table)
- return llvm::createStringError(errc::invalid_argument,
- "invalid range list table index %d", index);
-
- return llvm::createStringError(errc::invalid_argument,
- "missing or invalid range list table");
+ llvm::Expected<uint64_t> maybe_offset = GetRnglistOffset(index);
+ if (!maybe_offset)
+ return maybe_offset.takeError();
+ return FindRnglistFromOffset(*maybe_offset);
}
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
index 5739c36..da79a6a 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
@@ -73,7 +73,8 @@
static llvm::Expected<DWARFUnitHeader>
extract(const lldb_private::DWARFDataExtractor &data, DIERef::Section section,
- lldb::offset_t *offset_ptr, const llvm::DWARFUnitIndex *index);
+ lldb_private::DWARFContext &dwarf_context,
+ lldb::offset_t *offset_ptr);
};
class DWARFUnit : public lldb_private::UserID {
@@ -84,8 +85,7 @@
static llvm::Expected<DWARFUnitSP>
extract(SymbolFileDWARF &dwarf2Data, lldb::user_id_t uid,
const lldb_private::DWARFDataExtractor &debug_info,
- DIERef::Section section, lldb::offset_t *offset_ptr,
- const llvm::DWARFUnitIndex *index);
+ DIERef::Section section, lldb::offset_t *offset_ptr);
virtual ~DWARFUnit();
bool IsDWOUnit() { return m_is_dwo; }
@@ -235,15 +235,7 @@
/// Return a rangelist's offset based on an index. The index designates
/// an entry in the rangelist table's offset array and is supplied by
/// DW_FORM_rnglistx.
- llvm::Optional<uint64_t> GetRnglistOffset(uint32_t Index) const {
- if (!m_rnglist_table)
- return llvm::None;
- if (llvm::Optional<uint64_t> off = m_rnglist_table->getOffsetEntry(
- m_dwarf.GetDWARFContext().getOrLoadRngListsData().GetAsLLVM(),
- Index))
- return *off + m_ranges_base;
- return llvm::None;
- }
+ llvm::Expected<uint64_t> GetRnglistOffset(uint32_t Index);
llvm::Optional<uint64_t> GetLoclistOffset(uint32_t Index) {
if (!m_loclist_table_header)
@@ -291,6 +283,8 @@
return &m_die_array[0];
}
+ const llvm::Optional<llvm::DWARFDebugRnglistTable> &GetRnglistTable();
+
SymbolFileDWARF &m_dwarf;
std::shared_ptr<DWARFUnit> m_dwo;
DWARFUnitHeader m_header;
@@ -331,6 +325,7 @@
dw_offset_t m_str_offsets_base = 0; // Value of DW_AT_str_offsets_base.
llvm::Optional<llvm::DWARFDebugRnglistTable> m_rnglist_table;
+ bool m_rnglist_table_done = false;
llvm::Optional<llvm::DWARFListTableHeader> m_loclist_table_header;
const DIERef::Section m_section;
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp
index d36f2a8..ce71281 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp
@@ -130,8 +130,7 @@
: die_offset(o), tag(t), type_flags(f), qualified_name_hash(h) {}
DWARFMappedHash::Prologue::Prologue(dw_offset_t _die_base_offset)
- : die_base_offset(_die_base_offset), atoms(), atom_mask(0),
- min_hash_data_byte_size(0), hash_data_has_fixed_byte_size(true) {
+ : die_base_offset(_die_base_offset), atoms() {
// Define an array of DIE offsets by first defining an array, and then define
// the atom type for the array, in this case we have an array of DIE offsets.
AppendAtom(eAtomTypeDIEOffset, DW_FORM_data4);
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
index ad178fc..efc08e4 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
@@ -101,9 +101,9 @@
/// DIE offset base so die offsets in hash_data can be CU relative.
dw_offset_t die_base_offset;
AtomArray atoms;
- uint32_t atom_mask;
- size_t min_hash_data_byte_size;
- bool hash_data_has_fixed_byte_size;
+ uint32_t atom_mask = 0;
+ size_t min_hash_data_byte_size = 0;
+ bool hash_data_has_fixed_byte_size = true;
};
class Header : public MappedHash::Header<Prologue> {
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
index dda599b..1f40d88 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
@@ -13,9 +13,11 @@
#include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h"
#include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h"
#include "lldb/Core/Module.h"
+#include "lldb/Core/Progress.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/Timer.h"
+#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/ThreadPool.h"
using namespace lldb_private;
@@ -56,6 +58,17 @@
if (units_to_index.empty())
return;
+ StreamString module_desc;
+ m_module.GetDescription(module_desc.AsRawOstream(),
+ lldb::eDescriptionLevelBrief);
+
+ // Include 2 passes per unit to index for extracting DIEs from the unit and
+ // indexing the unit, and then 8 extra entries for finalizing each index set.
+ const uint64_t total_progress = units_to_index.size() * 2 + 8;
+ Progress progress(
+ llvm::formatv("Manually indexing DWARF for {0}", module_desc.GetData()),
+ total_progress);
+
std::vector<IndexSet> sets(units_to_index.size());
// Keep memory down by clearing DIEs for any units if indexing
@@ -64,10 +77,12 @@
units_to_index.size());
auto parser_fn = [&](size_t cu_idx) {
IndexUnit(*units_to_index[cu_idx], dwp_dwarf, sets[cu_idx]);
+ progress.Increment();
};
- auto extract_fn = [&units_to_index, &clear_cu_dies](size_t cu_idx) {
+ auto extract_fn = [&](size_t cu_idx) {
clear_cu_dies[cu_idx] = units_to_index[cu_idx]->ExtractDIEsScoped();
+ progress.Increment();
};
// Share one thread pool across operations to avoid the overhead of
@@ -92,11 +107,12 @@
pool.async(parser_fn, i);
pool.wait();
- auto finalize_fn = [this, &sets](NameToDIE(IndexSet::*index)) {
+ auto finalize_fn = [this, &sets, &progress](NameToDIE(IndexSet::*index)) {
NameToDIE &result = m_set.*index;
for (auto &set : sets)
result.Append(set.*index);
result.Finalize();
+ progress.Increment();
};
pool.async(finalize_fn, &IndexSet::function_basenames);
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h
index 5aa841c..a6863f6 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h
@@ -22,7 +22,7 @@
public:
NameToDIE() : m_map() {}
- ~NameToDIE() {}
+ ~NameToDIE() = default;
void Dump(lldb_private::Stream *s);
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 3656c73..ccaf313 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -16,6 +16,7 @@
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Progress.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/Value.h"
@@ -74,18 +75,19 @@
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/FormatVariadic.h"
#include <algorithm>
#include <map>
#include <memory>
-#include <ctype.h>
-#include <string.h>
+#include <cctype>
+#include <cstring>
//#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN
#ifdef ENABLE_DEBUG_PRINTF
-#include <stdio.h>
+#include <cstdio>
#define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
#else
#define DEBUG_PRINTF(fmt, ...)
@@ -238,9 +240,12 @@
const size_t number_of_files = prologue.FileNames.size();
for (size_t idx = first_file; idx <= number_of_files; ++idx) {
std::string remapped_file;
- if (auto file_path = GetFileByIndex(prologue, idx, compile_dir, style))
- if (!module->RemapSourceFile(llvm::StringRef(*file_path), remapped_file))
+ if (auto file_path = GetFileByIndex(prologue, idx, compile_dir, style)) {
+ if (auto remapped = module->RemapSourceFile(llvm::StringRef(*file_path)))
+ remapped_file = *remapped;
+ else
remapped_file = std::move(*file_path);
+ }
// Unconditionally add an entry, so the indices match up.
support_files.EmplaceBack(remapped_file, style);
@@ -358,8 +363,7 @@
}
}
- for (DWARFDIE child_die = die.GetFirstChild(); child_die.IsValid();
- child_die = child_die.GetSibling()) {
+ for (DWARFDIE child_die : die.children()) {
GetTypes(child_die, min_die_offset, max_die_offset, type_mask, type_set);
}
}
@@ -435,7 +439,7 @@
m_fetched_external_modules(false),
m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate) {}
-SymbolFileDWARF::~SymbolFileDWARF() {}
+SymbolFileDWARF::~SymbolFileDWARF() = default;
static ConstString GetDWARFMachOSegmentName() {
static ConstString g_dwarf_section_name("__DWARF");
@@ -467,22 +471,32 @@
Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);
if (!GetGlobalPluginProperties()->IgnoreFileIndexes()) {
+ StreamString module_desc;
+ GetObjectFile()->GetModule()->GetDescription(module_desc.AsRawOstream(),
+ lldb::eDescriptionLevelBrief);
DWARFDataExtractor apple_names, apple_namespaces, apple_types, apple_objc;
LoadSectionData(eSectionTypeDWARFAppleNames, apple_names);
LoadSectionData(eSectionTypeDWARFAppleNamespaces, apple_namespaces);
LoadSectionData(eSectionTypeDWARFAppleTypes, apple_types);
LoadSectionData(eSectionTypeDWARFAppleObjC, apple_objc);
- m_index = AppleDWARFIndex::Create(
- *GetObjectFile()->GetModule(), apple_names, apple_namespaces,
- apple_types, apple_objc, m_context.getOrLoadStrData());
+ if (apple_names.GetByteSize() > 0 || apple_namespaces.GetByteSize() > 0 ||
+ apple_types.GetByteSize() > 0 || apple_objc.GetByteSize() > 0) {
+ Progress progress(llvm::formatv("Loading Apple DWARF index for {0}",
+ module_desc.GetData()));
+ m_index = AppleDWARFIndex::Create(
+ *GetObjectFile()->GetModule(), apple_names, apple_namespaces,
+ apple_types, apple_objc, m_context.getOrLoadStrData());
- if (m_index)
- return;
+ if (m_index)
+ return;
+ }
DWARFDataExtractor debug_names;
LoadSectionData(eSectionTypeDWARFDebugNames, debug_names);
if (debug_names.GetByteSize() > 0) {
+ Progress progress(
+ llvm::formatv("Loading DWARF5 index for {0}", module_desc.GetData()));
llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>> index_or =
DebugNamesDWARFIndex::Create(*GetObjectFile()->GetModule(),
debug_names,
@@ -669,9 +683,8 @@
// files are NFS mounted.
file_spec.MakeAbsolute(dwarf_cu.GetCompilationDirectory());
- std::string remapped_file;
- if (module_sp->RemapSourceFile(file_spec.GetPath(), remapped_file))
- file_spec.SetFile(remapped_file, FileSpec::Style::native);
+ if (auto remapped_file = module_sp->RemapSourceFile(file_spec.GetPath()))
+ file_spec.SetFile(*remapped_file, FileSpec::Style::native);
}
lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
@@ -973,8 +986,7 @@
if (!die)
return false;
- for (DWARFDIE child_die = die.GetFirstChild(); child_die;
- child_die = child_die.GetSibling()) {
+ for (DWARFDIE child_die : die.children()) {
if (child_die.Tag() != DW_TAG_imported_declaration)
continue;
@@ -1233,8 +1245,7 @@
bool SymbolFileDWARF::ClassOrStructIsVirtual(const DWARFDIE &parent_die) {
if (parent_die) {
- for (DWARFDIE die = parent_die.GetFirstChild(); die;
- die = die.GetSibling()) {
+ for (DWARFDIE die : parent_die.children()) {
dw_tag_t tag = die.Tag();
bool check_virtuality = false;
switch (tag) {
@@ -1639,6 +1650,13 @@
return nullptr;
dwo_file.SetFile(comp_dir, FileSpec::Style::native);
+ if (dwo_file.IsRelative()) {
+ // if DW_AT_comp_dir is relative, it should be relative to the location
+ // of the executable, not to the location from which the debugger was
+ // launched.
+ dwo_file.PrependPathComponent(
+ m_objfile_sp->GetFileSpec().GetDirectory().GetStringRef());
+ }
FileSystem::Instance().Resolve(dwo_file);
dwo_file.AppendPathComponent(dwo_name);
}
@@ -1784,7 +1802,7 @@
if (location.Evaluate(nullptr, LLDB_INVALID_ADDRESS, nullptr,
nullptr, location_result, &error)) {
if (location_result.GetValueType() ==
- Value::eValueTypeFileAddress) {
+ Value::ValueType::FileAddress) {
lldb::addr_t file_addr =
location_result.GetScalar().ULongLong();
lldb::addr_t byte_size = 1;
@@ -1850,17 +1868,8 @@
lldb::addr_t file_vm_addr = so_addr.GetFileAddress();
DWARFDebugInfo &debug_info = DebugInfo();
- llvm::Expected<DWARFDebugAranges &> aranges =
- debug_info.GetCompileUnitAranges();
- if (!aranges) {
- Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);
- LLDB_LOG_ERROR(log, aranges.takeError(),
- "SymbolFileDWARF::ResolveSymbolContext failed to get cu "
- "aranges. {0}");
- return 0;
- }
-
- const dw_offset_t cu_offset = aranges->FindAddress(file_vm_addr);
+ const DWARFDebugAranges &aranges = debug_info.GetCompileUnitAranges();
+ const dw_offset_t cu_offset = aranges.FindAddress(file_vm_addr);
if (cu_offset == DW_INVALID_OFFSET) {
// Global variables are not in the compile unit address ranges. The only
// way to currently find global variables is to iterate over the
@@ -1949,12 +1958,11 @@
return resolved;
}
-uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec,
- uint32_t line,
- bool check_inlines,
- SymbolContextItem resolve_scope,
- SymbolContextList &sc_list) {
+uint32_t SymbolFileDWARF::ResolveSymbolContext(
+ const SourceLocationSpec &src_location_spec,
+ SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
+ const bool check_inlines = src_location_spec.GetCheckInlines();
const uint32_t prev_size = sc_list.GetSize();
if (resolve_scope & eSymbolContextCompUnit) {
for (uint32_t cu_idx = 0, num_cus = GetNumCompileUnits(); cu_idx < num_cus;
@@ -1963,69 +1971,10 @@
if (!dc_cu)
continue;
- bool file_spec_matches_cu_file_spec =
- FileSpec::Match(file_spec, dc_cu->GetPrimaryFile());
+ bool file_spec_matches_cu_file_spec = FileSpec::Match(
+ src_location_spec.GetFileSpec(), dc_cu->GetPrimaryFile());
if (check_inlines || file_spec_matches_cu_file_spec) {
- SymbolContext sc(m_objfile_sp->GetModule());
- sc.comp_unit = dc_cu;
- uint32_t file_idx = UINT32_MAX;
-
- // If we are looking for inline functions only and we don't find it
- // in the support files, we are done.
- if (check_inlines) {
- file_idx =
- sc.comp_unit->GetSupportFiles().FindFileIndex(1, file_spec, true);
- if (file_idx == UINT32_MAX)
- continue;
- }
-
- if (line != 0) {
- LineTable *line_table = sc.comp_unit->GetLineTable();
-
- if (line_table != nullptr && line != 0) {
- // We will have already looked up the file index if we are
- // searching for inline entries.
- if (!check_inlines)
- file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex(
- 1, file_spec, true);
-
- if (file_idx != UINT32_MAX) {
- uint32_t found_line;
- uint32_t line_idx = line_table->FindLineEntryIndexByFileIndex(
- 0, file_idx, line, false, &sc.line_entry);
- found_line = sc.line_entry.line;
-
- while (line_idx != UINT32_MAX) {
- sc.function = nullptr;
- sc.block = nullptr;
- if (resolve_scope &
- (eSymbolContextFunction | eSymbolContextBlock)) {
- const lldb::addr_t file_vm_addr =
- sc.line_entry.range.GetBaseAddress().GetFileAddress();
- if (file_vm_addr != LLDB_INVALID_ADDRESS) {
- ResolveFunctionAndBlock(
- file_vm_addr, resolve_scope & eSymbolContextBlock, sc);
- }
- }
-
- sc_list.Append(sc);
- line_idx = line_table->FindLineEntryIndexByFileIndex(
- line_idx + 1, file_idx, found_line, true, &sc.line_entry);
- }
- }
- } else if (file_spec_matches_cu_file_spec && !check_inlines) {
- // only append the context if we aren't looking for inline call
- // sites by file and line and if the file spec matches that of
- // the compile unit
- sc_list.Append(sc);
- }
- } else if (file_spec_matches_cu_file_spec && !check_inlines) {
- // only append the context if we aren't looking for inline call
- // sites by file and line and if the file spec matches that of
- // the compile unit
- sc_list.Append(sc);
- }
-
+ dc_cu->ResolveSymbolContext(src_location_spec, resolve_scope, sc_list);
if (!check_inlines)
break;
}
@@ -2462,7 +2411,7 @@
return;
m_index->GetTypes(name, [&](DWARFDIE die) {
- if (!languages[GetLanguage(*die.GetCU())])
+ if (!languages[GetLanguageFamily(*die.GetCU())])
return true;
llvm::SmallVector<CompilerContext, 4> die_context;
@@ -3126,8 +3075,8 @@
continue;
switch (attr) {
case DW_AT_decl_file:
- decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(
- form_value.Unsigned()));
+ decl.SetFile(
+ attributes.CompileUnitAtIndex(i)->GetFile(form_value.Unsigned()));
break;
case DW_AT_decl_line:
decl.SetLine(form_value.Unsigned());
@@ -3469,8 +3418,7 @@
// Give the concrete function die specified by "func_die_offset", find the
// concrete block whose DW_AT_specification or DW_AT_abstract_origin points
// to "spec_block_die_offset"
- for (DWARFDIE child_die = die.GetFirstChild(); child_die;
- child_die = child_die.GetSibling()) {
+ for (DWARFDIE child_die : die.children()) {
DWARFDIE result_die =
FindBlockContainingSpecification(child_die, spec_block_die_offset);
if (result_die)
@@ -3599,8 +3547,7 @@
static CallSiteParameterArray
CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) {
CallSiteParameterArray parameters;
- for (DWARFDIE child = call_site_die.GetFirstChild(); child.IsValid();
- child = child.GetSibling()) {
+ for (DWARFDIE child : call_site_die.children()) {
if (child.Tag() != DW_TAG_call_site_parameter &&
child.Tag() != DW_TAG_GNU_call_site_parameter)
continue;
@@ -3665,8 +3612,7 @@
// For now, assume that all entries are nested directly under the subprogram
// (this is the kind of DWARF LLVM produces) and parse them eagerly.
std::vector<std::unique_ptr<CallEdge>> call_edges;
- for (DWARFDIE child = function_die.GetFirstChild(); child.IsValid();
- child = child.GetSibling()) {
+ for (DWARFDIE child : function_die.children()) {
if (child.Tag() != DW_TAG_call_site && child.Tag() != DW_TAG_GNU_call_site)
continue;
@@ -3842,7 +3788,7 @@
}
SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() {
- if (m_debug_map_symfile == nullptr && !m_debug_map_module_wp.expired()) {
+ if (m_debug_map_symfile == nullptr) {
lldb::ModuleSP module_sp(m_debug_map_module_wp.lock());
if (module_sp) {
m_debug_map_symfile =
@@ -3936,3 +3882,10 @@
LanguageType SymbolFileDWARF::GetLanguage(DWARFUnit &unit) {
return LanguageTypeFromDWARF(unit.GetDWARFLanguageType());
}
+
+LanguageType SymbolFileDWARF::GetLanguageFamily(DWARFUnit &unit) {
+ auto lang = (llvm::dwarf::SourceLanguage)unit.GetDWARFLanguageType();
+ if (llvm::dwarf::isCPlusPlus(lang))
+ lang = DW_LANG_C_plus_plus;
+ return LanguageTypeFromDWARF(lang);
+}
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 019f76c..d9feeef 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -161,11 +161,10 @@
lldb::SymbolContextItem resolve_scope,
lldb_private::SymbolContext &sc) override;
- uint32_t
- ResolveSymbolContext(const lldb_private::FileSpec &file_spec, uint32_t line,
- bool check_inlines,
- lldb::SymbolContextItem resolve_scope,
- lldb_private::SymbolContextList &sc_list) override;
+ uint32_t ResolveSymbolContext(
+ const lldb_private::SourceLocationSpec &src_location_spec,
+ lldb::SymbolContextItem resolve_scope,
+ lldb_private::SymbolContextList &sc_list) override;
void
FindGlobalVariables(lldb_private::ConstString name,
@@ -318,6 +317,8 @@
static lldb::LanguageType LanguageTypeFromDWARF(uint64_t val);
static lldb::LanguageType GetLanguage(DWARFUnit &unit);
+ /// Same as GetLanguage() but reports all C++ versions as C++ (no version).
+ static lldb::LanguageType GetLanguageFamily(DWARFUnit &unit);
protected:
typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *>
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
index fa24f97..4e2e5e1 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
@@ -16,7 +16,6 @@
#include "lldb/Host/FileSystem.h"
#include "lldb/Utility/RangeMap.h"
#include "lldb/Utility/RegularExpression.h"
-#include "lldb/Utility/Timer.h"
//#define DEBUG_OSO_DMAP // DO NOT CHECKIN WITH THIS NOT COMMENTED OUT
#if defined(DEBUG_OSO_DMAP)
@@ -34,6 +33,9 @@
#include "LogChannelDWARF.h"
#include "SymbolFileDWARF.h"
+// Work around the fact that Timer.h pulls in the system Mach-O headers.
+#include "lldb/Utility/Timer.h"
+
#include <memory>
using namespace lldb;
@@ -246,7 +248,7 @@
m_func_indexes(), m_glob_indexes(),
m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate) {}
-SymbolFileDWARFDebugMap::~SymbolFileDWARFDebugMap() {}
+SymbolFileDWARFDebugMap::~SymbolFileDWARFDebugMap() = default;
void SymbolFileDWARFDebugMap::InitializeObject() {}
@@ -806,7 +808,7 @@
}
uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext(
- const FileSpec &file_spec, uint32_t line, bool check_inlines,
+ const SourceLocationSpec &src_location_spec,
SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
const uint32_t initial = sc_list.GetSize();
@@ -815,18 +817,19 @@
for (uint32_t i = 0; i < cu_count; ++i) {
// If we are checking for inlines, then we need to look through all compile
// units no matter if "file_spec" matches.
- bool resolve = check_inlines;
+ bool resolve = src_location_spec.GetCheckInlines();
if (!resolve) {
FileSpec so_file_spec;
if (GetFileSpecForSO(i, so_file_spec))
- resolve = FileSpec::Match(file_spec, so_file_spec);
+ resolve =
+ FileSpec::Match(src_location_spec.GetFileSpec(), so_file_spec);
}
if (resolve) {
SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(i);
if (oso_dwarf)
- oso_dwarf->ResolveSymbolContext(file_spec, line, check_inlines,
- resolve_scope, sc_list);
+ oso_dwarf->ResolveSymbolContext(src_location_spec, resolve_scope,
+ sc_list);
}
}
return sc_list.GetSize() - initial;
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
index 06f0d48..8b6624e 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
@@ -97,11 +97,10 @@
uint32_t ResolveSymbolContext(const lldb_private::Address &so_addr,
lldb::SymbolContextItem resolve_scope,
lldb_private::SymbolContext &sc) override;
- uint32_t
- ResolveSymbolContext(const lldb_private::FileSpec &file_spec, uint32_t line,
- bool check_inlines,
- lldb::SymbolContextItem resolve_scope,
- lldb_private::SymbolContextList &sc_list) override;
+ uint32_t ResolveSymbolContext(
+ const lldb_private::SourceLocationSpec &src_location_spec,
+ lldb::SymbolContextItem resolve_scope,
+ lldb_private::SymbolContextList &sc_list) override;
void
FindGlobalVariables(lldb_private::ConstString name,
const lldb_private::CompilerDeclContext &parent_decl_ctx,
@@ -171,18 +170,17 @@
llvm::sys::TimePoint<> oso_mod_time;
OSOInfoSP oso_sp;
lldb::CompUnitSP compile_unit_sp;
- uint32_t first_symbol_index;
- uint32_t last_symbol_index;
- uint32_t first_symbol_id;
- uint32_t last_symbol_id;
+ uint32_t first_symbol_index = UINT32_MAX;
+ uint32_t last_symbol_index = UINT32_MAX;
+ uint32_t first_symbol_id = UINT32_MAX;
+ uint32_t last_symbol_id = UINT32_MAX;
FileRangeMap file_range_map;
- bool file_range_map_valid;
+ bool file_range_map_valid = false;
CompileUnitInfo()
: so_file(), oso_path(), oso_mod_time(), oso_sp(), compile_unit_sp(),
- first_symbol_index(UINT32_MAX), last_symbol_index(UINT32_MAX),
- first_symbol_id(UINT32_MAX), last_symbol_id(UINT32_MAX),
- file_range_map(), file_range_map_valid(false) {}
+
+ file_range_map() {}
const FileRangeMap &GetFileRangeMap(SymbolFileDWARFDebugMap *exe_symfile);
};
@@ -280,8 +278,7 @@
// OSOEntry
class OSOEntry {
public:
- OSOEntry()
- : m_exe_sym_idx(UINT32_MAX), m_oso_file_addr(LLDB_INVALID_ADDRESS) {}
+ OSOEntry() = default;
OSOEntry(uint32_t exe_sym_idx, lldb::addr_t oso_file_addr)
: m_exe_sym_idx(exe_sym_idx), m_oso_file_addr(oso_file_addr) {}
@@ -299,8 +296,8 @@
}
protected:
- uint32_t m_exe_sym_idx;
- lldb::addr_t m_oso_file_addr;
+ uint32_t m_exe_sym_idx = UINT32_MAX;
+ lldb::addr_t m_oso_file_addr = LLDB_INVALID_ADDRESS;
};
typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, OSOEntry>
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
index 2181989..34ff236 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
@@ -8,7 +8,7 @@
#include "UniqueDWARFASTType.h"
-#include "lldb/Symbol/Declaration.h"
+#include "lldb/Core/Declaration.h"
bool UniqueDWARFASTTypeList::Find(const DWARFDIE &die,
const lldb_private::Declaration &decl,
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h
index a1b1a30..0947d1e 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h
@@ -14,16 +14,12 @@
#include "llvm/ADT/DenseMap.h"
#include "DWARFDIE.h"
-#include "lldb/Symbol/Declaration.h"
+#include "lldb/Core/Declaration.h"
class UniqueDWARFASTType {
public:
// Constructors and Destructors
- UniqueDWARFASTType()
- : m_type_sp(), m_die(), m_declaration(),
- m_byte_size(
- -1) // Set to negative value to make sure we have a valid value
- {}
+ UniqueDWARFASTType() : m_type_sp(), m_die(), m_declaration() {}
UniqueDWARFASTType(lldb::TypeSP &type_sp, const DWARFDIE &die,
const lldb_private::Declaration &decl, int32_t byte_size)
@@ -34,7 +30,7 @@
: m_type_sp(rhs.m_type_sp), m_die(rhs.m_die),
m_declaration(rhs.m_declaration), m_byte_size(rhs.m_byte_size) {}
- ~UniqueDWARFASTType() {}
+ ~UniqueDWARFASTType() = default;
UniqueDWARFASTType &operator=(const UniqueDWARFASTType &rhs) {
if (this != &rhs) {
@@ -49,14 +45,14 @@
lldb::TypeSP m_type_sp;
DWARFDIE m_die;
lldb_private::Declaration m_declaration;
- int32_t m_byte_size;
+ int32_t m_byte_size = -1;
};
class UniqueDWARFASTTypeList {
public:
UniqueDWARFASTTypeList() : m_collection() {}
- ~UniqueDWARFASTTypeList() {}
+ ~UniqueDWARFASTTypeList() = default;
uint32_t GetSize() { return (uint32_t)m_collection.size(); }
@@ -76,7 +72,7 @@
public:
UniqueDWARFASTTypeMap() : m_collection() {}
- ~UniqueDWARFASTTypeMap() {}
+ ~UniqueDWARFASTTypeMap() = default;
void Insert(lldb_private::ConstString name,
const UniqueDWARFASTType &entry) {
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp b/src/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp
index f25dc84..9f09c0a 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp
@@ -43,7 +43,7 @@
llvm::SmallString<64> normalized(other);
llvm::sys::path::native(normalized);
- return main.equals_lower(normalized);
+ return main.equals_insensitive(normalized);
}
static void ParseCompile3(const CVSymbol &sym, CompilandIndexItem &cci) {
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/src/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
index 5b4ab78..43cf262 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
@@ -1093,7 +1093,7 @@
}
if (!params.empty())
- m_clang.SetFunctionParameters(&function_decl, params.data(), params.size());
+ m_clang.SetFunctionParameters(&function_decl, params);
}
clang::QualType PdbAstBuilder::CreateEnumType(PdbTypeSymId id,
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp b/src/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp
index ecae767..4f570d5e 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp
@@ -41,7 +41,7 @@
auto it = llvm::find_if(
register_names,
[®_name](const llvm::EnumEntry<uint16_t> ®ister_entry) {
- return reg_name.compare_lower(register_entry.Name) == 0;
+ return reg_name.compare_insensitive(register_entry.Name) == 0;
});
if (it == register_names.end())
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/src/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
index 24b4c64..b9b075d 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -256,7 +256,7 @@
SymbolFileNativePDB::SymbolFileNativePDB(ObjectFileSP objfile_sp)
: SymbolFile(std::move(objfile_sp)) {}
-SymbolFileNativePDB::~SymbolFileNativePDB() {}
+SymbolFileNativePDB::~SymbolFileNativePDB() = default;
uint32_t SymbolFileNativePDB::CalculateAbilities() {
uint32_t abilities = 0;
@@ -1001,7 +1001,7 @@
}
uint32_t SymbolFileNativePDB::ResolveSymbolContext(
- const FileSpec &file_spec, uint32_t line, bool check_inlines,
+ const SourceLocationSpec &src_location_spec,
lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
return 0;
}
@@ -1039,7 +1039,7 @@
table.AppendLineEntryToSequence(seq.get(), base_addr + block.CodeSize,
last_line, 0, file_number, false, false,
false, false, true);
- table.InsertSequence(seq.release());
+ table.InsertSequence(seq.get());
}
bool SymbolFileNativePDB::ParseLineTable(CompileUnit &comp_unit) {
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/src/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
index 61c1d77..def0995 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
@@ -120,8 +120,7 @@
uint32_t ResolveSymbolContext(const Address &so_addr,
lldb::SymbolContextItem resolve_scope,
SymbolContext &sc) override;
- uint32_t ResolveSymbolContext(const FileSpec &file_spec, uint32_t line,
- bool check_inlines,
+ uint32_t ResolveSymbolContext(const SourceLocationSpec &src_location_spec,
lldb::SymbolContextItem resolve_scope,
SymbolContextList &sc_list) override;
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp b/src/llvm-project/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
index f9c12e6..78a0d09 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
@@ -17,8 +17,8 @@
#include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h"
#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
+#include "lldb/Core/Declaration.h"
#include "lldb/Core/Module.h"
-#include "lldb/Symbol/Declaration.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/TypeMap.h"
#include "lldb/Symbol/TypeSystem.h"
@@ -326,7 +326,7 @@
if (result.empty())
return nullptr;
- return result[0];
+ return *result.begin();
}
static bool IsAnonymousNamespaceName(llvm::StringRef name) {
@@ -355,7 +355,7 @@
PDBASTParser::PDBASTParser(lldb_private::TypeSystemClang &ast) : m_ast(ast) {}
-PDBASTParser::~PDBASTParser() {}
+PDBASTParser::~PDBASTParser() = default;
// DebugInfoASTParser interface
@@ -534,8 +534,12 @@
auto type_def = llvm::dyn_cast<PDBSymbolTypeTypedef>(&type);
assert(type_def);
+ SymbolFile *symbol_file = m_ast.GetSymbolFile();
+ if (!symbol_file)
+ return nullptr;
+
lldb_private::Type *target_type =
- m_ast.GetSymbolFile()->ResolveTypeUID(type_def->getTypeId());
+ symbol_file->ResolveTypeUID(type_def->getTypeId());
if (!target_type)
return nullptr;
@@ -609,8 +613,13 @@
auto arg = arg_enum->getChildAtIndex(arg_idx);
if (!arg)
break;
+
+ SymbolFile *symbol_file = m_ast.GetSymbolFile();
+ if (!symbol_file)
+ return nullptr;
+
lldb_private::Type *arg_type =
- m_ast.GetSymbolFile()->ResolveTypeUID(arg->getSymIndexId());
+ symbol_file->ResolveTypeUID(arg->getSymIndexId());
// If there's some error looking up one of the dependent types of this
// function signature, bail.
if (!arg_type)
@@ -621,8 +630,12 @@
lldbassert(arg_list.size() <= num_args);
auto pdb_return_type = func_sig->getReturnType();
+ SymbolFile *symbol_file = m_ast.GetSymbolFile();
+ if (!symbol_file)
+ return nullptr;
+
lldb_private::Type *return_type =
- m_ast.GetSymbolFile()->ResolveTypeUID(pdb_return_type->getSymIndexId());
+ symbol_file->ResolveTypeUID(pdb_return_type->getSymIndexId());
// If there's some error looking up one of the dependent types of this
// function signature, bail.
if (!return_type)
@@ -654,10 +667,13 @@
if (uint64_t size = array_type->getLength())
bytes = size;
+ SymbolFile *symbol_file = m_ast.GetSymbolFile();
+ if (!symbol_file)
+ return nullptr;
+
// If array rank > 0, PDB gives the element type at N=0. So element type
// will parsed in the order N=0, N=1,..., N=rank sequentially.
- lldb_private::Type *element_type =
- m_ast.GetSymbolFile()->ResolveTypeUID(element_uid);
+ lldb_private::Type *element_type = symbol_file->ResolveTypeUID(element_uid);
if (!element_type)
return nullptr;
@@ -711,7 +727,12 @@
case PDB_SymType::PointerType: {
auto *pointer_type = llvm::dyn_cast<PDBSymbolTypePointer>(&type);
assert(pointer_type);
- Type *pointee_type = m_ast.GetSymbolFile()->ResolveTypeUID(
+
+ SymbolFile *symbol_file = m_ast.GetSymbolFile();
+ if (!symbol_file)
+ return nullptr;
+
+ Type *pointee_type = symbol_file->ResolveTypeUID(
pointer_type->getPointeeType()->getSymIndexId());
if (!pointee_type)
return nullptr;
@@ -719,8 +740,7 @@
if (pointer_type->isPointerToDataMember() ||
pointer_type->isPointerToMemberFunction()) {
auto class_parent_uid = pointer_type->getRawSymbol().getClassParentId();
- auto class_parent_type =
- m_ast.GetSymbolFile()->ResolveTypeUID(class_parent_uid);
+ auto class_parent_type = symbol_file->ResolveTypeUID(class_parent_uid);
assert(class_parent_type);
CompilerType pointer_ast_type;
@@ -950,7 +970,7 @@
}
}
if (params.size())
- m_ast.SetFunctionParameters(decl, params.data(), params.size());
+ m_ast.SetFunctionParameters(decl, params);
m_uid_to_decl[sym_id] = decl;
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/src/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
index befc081..6b30ad2 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
@@ -84,8 +84,10 @@
static bool ShouldUseNativeReader() {
#if defined(_WIN32)
llvm::StringRef use_native = ::getenv("LLDB_USE_NATIVE_PDB_READER");
- return use_native.equals_lower("on") || use_native.equals_lower("yes") ||
- use_native.equals_lower("1") || use_native.equals_lower("true");
+ return use_native.equals_insensitive("on") ||
+ use_native.equals_insensitive("yes") ||
+ use_native.equals_insensitive("1") ||
+ use_native.equals_insensitive("true");
#else
return true;
#endif
@@ -128,7 +130,7 @@
SymbolFilePDB::SymbolFilePDB(lldb::ObjectFileSP objfile_sp)
: SymbolFile(std::move(objfile_sp)), m_session_up(), m_global_scope_up() {}
-SymbolFilePDB::~SymbolFilePDB() {}
+SymbolFilePDB::~SymbolFilePDB() = default;
uint32_t SymbolFilePDB::CalculateAbilities() {
uint32_t abilities = 0;
@@ -784,10 +786,12 @@
}
uint32_t SymbolFilePDB::ResolveSymbolContext(
- const lldb_private::FileSpec &file_spec, uint32_t line, bool check_inlines,
+ const lldb_private::SourceLocationSpec &src_location_spec,
SymbolContextItem resolve_scope, lldb_private::SymbolContextList &sc_list) {
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
const size_t old_size = sc_list.GetSize();
+ const FileSpec &file_spec = src_location_spec.GetFileSpec();
+ const uint32_t line = src_location_spec.GetLine().getValueOr(0);
if (resolve_scope & lldb::eSymbolContextCompUnit) {
// Locate all compilation units with line numbers referencing the specified
// file. For example, if `file_spec` is <vector>, then this should return
@@ -806,7 +810,7 @@
// this file unless the FileSpec matches. For inline functions, we don't
// have to match the FileSpec since they could be defined in headers
// other than file specified in FileSpec.
- if (!check_inlines) {
+ if (!src_location_spec.GetCheckInlines()) {
std::string source_file = compiland->getSourceFileFullPath();
if (source_file.empty())
continue;
@@ -1813,7 +1817,7 @@
sequence.get(), prev_addr + prev_length, prev_line, 0,
prev_source_idx, false, false, false, false, true);
- line_table->InsertSequence(sequence.release());
+ line_table->InsertSequence(sequence.get());
sequence = line_table->CreateLineSequenceContainer();
}
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h b/src/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
index 928cbff..2171b7f 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
+++ b/src/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
@@ -104,11 +104,10 @@
lldb::SymbolContextItem resolve_scope,
lldb_private::SymbolContext &sc) override;
- uint32_t
- ResolveSymbolContext(const lldb_private::FileSpec &file_spec, uint32_t line,
- bool check_inlines,
- lldb::SymbolContextItem resolve_scope,
- lldb_private::SymbolContextList &sc_list) override;
+ uint32_t ResolveSymbolContext(
+ const lldb_private::SourceLocationSpec &src_location_spec,
+ lldb::SymbolContextItem resolve_scope,
+ lldb_private::SymbolContextList &sc_list) override;
void
FindGlobalVariables(lldb_private::ConstString name,
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp b/src/llvm-project/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
index 4df5140..9130eed 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
@@ -8,7 +8,7 @@
#include "SymbolVendorELF.h"
-#include <string.h>
+#include <cstring>
#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
#include "lldb/Core/Module.h"
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp b/src/llvm-project/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
index 605a35d..cd1aceb 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
@@ -8,7 +8,7 @@
#include "SymbolVendorMacOSX.h"
-#include <string.h>
+#include <cstring>
#include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
#include "lldb/Core/Module.h"
diff --git a/src/llvm-project/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp b/src/llvm-project/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp
index 67a1ef5..2b28407 100644
--- a/src/llvm-project/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp
@@ -8,7 +8,7 @@
#include "SymbolVendorWasm.h"
-#include <string.h>
+#include <cstring>
#include "Plugins/ObjectFile/wasm/ObjectFileWasm.h"
#include "lldb/Core/Module.h"
diff --git a/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp b/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp
index 989247b..7ece7f5 100644
--- a/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp
@@ -98,7 +98,7 @@
m_get_item_info_return_buffer_addr(LLDB_INVALID_ADDRESS),
m_get_item_info_retbuffer_mutex() {}
-AppleGetItemInfoHandler::~AppleGetItemInfoHandler() {}
+AppleGetItemInfoHandler::~AppleGetItemInfoHandler() = default;
void AppleGetItemInfoHandler::Detach() {
@@ -258,26 +258,26 @@
CompilerType clang_void_ptr_type =
clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
Value return_buffer_ptr_value;
- return_buffer_ptr_value.SetValueType(Value::eValueTypeScalar);
+ return_buffer_ptr_value.SetValueType(Value::ValueType::Scalar);
return_buffer_ptr_value.SetCompilerType(clang_void_ptr_type);
CompilerType clang_int_type = clang_ast_context->GetBasicType(eBasicTypeInt);
Value debug_value;
- debug_value.SetValueType(Value::eValueTypeScalar);
+ debug_value.SetValueType(Value::ValueType::Scalar);
debug_value.SetCompilerType(clang_int_type);
CompilerType clang_uint64_type =
clang_ast_context->GetBasicType(eBasicTypeUnsignedLongLong);
Value item_value;
- item_value.SetValueType(Value::eValueTypeScalar);
+ item_value.SetValueType(Value::ValueType::Scalar);
item_value.SetCompilerType(clang_uint64_type);
Value page_to_free_value;
- page_to_free_value.SetValueType(Value::eValueTypeScalar);
+ page_to_free_value.SetValueType(Value::ValueType::Scalar);
page_to_free_value.SetCompilerType(clang_void_ptr_type);
Value page_to_free_size_value;
- page_to_free_size_value.SetValueType(Value::eValueTypeScalar);
+ page_to_free_size_value.SetValueType(Value::ValueType::Scalar);
page_to_free_size_value.SetCompilerType(clang_uint64_type);
std::lock_guard<std::mutex> guard(m_get_item_info_retbuffer_mutex);
diff --git a/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.h b/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.h
index f1119a9..04cfbae 100644
--- a/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.h
+++ b/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.h
@@ -46,13 +46,12 @@
~AppleGetItemInfoHandler();
struct GetItemInfoReturnInfo {
- lldb::addr_t item_buffer_ptr; /* the address of the item buffer from
- libBacktraceRecording */
- lldb::addr_t item_buffer_size; /* the size of the item buffer from
+ lldb::addr_t item_buffer_ptr = LLDB_INVALID_ADDRESS; /* the address of the
+ item buffer from libBacktraceRecording */
+ lldb::addr_t item_buffer_size = 0; /* the size of the item buffer from
libBacktraceRecording */
- GetItemInfoReturnInfo()
- : item_buffer_ptr(LLDB_INVALID_ADDRESS), item_buffer_size(0) {}
+ GetItemInfoReturnInfo() = default;
};
/// Get the information about a work item by calling
diff --git a/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp b/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp
index 7bf158e..82b71b8 100644
--- a/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp
@@ -102,7 +102,7 @@
m_get_pending_items_return_buffer_addr(LLDB_INVALID_ADDRESS),
m_get_pending_items_retbuffer_mutex() {}
-AppleGetPendingItemsHandler::~AppleGetPendingItemsHandler() {}
+AppleGetPendingItemsHandler::~AppleGetPendingItemsHandler() = default;
void AppleGetPendingItemsHandler::Detach() {
if (m_process && m_process->IsAlive() &&
@@ -261,26 +261,26 @@
CompilerType clang_void_ptr_type =
clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
Value return_buffer_ptr_value;
- return_buffer_ptr_value.SetValueType(Value::eValueTypeScalar);
+ return_buffer_ptr_value.SetValueType(Value::ValueType::Scalar);
return_buffer_ptr_value.SetCompilerType(clang_void_ptr_type);
CompilerType clang_int_type = clang_ast_context->GetBasicType(eBasicTypeInt);
Value debug_value;
- debug_value.SetValueType(Value::eValueTypeScalar);
+ debug_value.SetValueType(Value::ValueType::Scalar);
debug_value.SetCompilerType(clang_int_type);
CompilerType clang_uint64_type =
clang_ast_context->GetBasicType(eBasicTypeUnsignedLongLong);
Value queue_value;
- queue_value.SetValueType(Value::eValueTypeScalar);
+ queue_value.SetValueType(Value::ValueType::Scalar);
queue_value.SetCompilerType(clang_uint64_type);
Value page_to_free_value;
- page_to_free_value.SetValueType(Value::eValueTypeScalar);
+ page_to_free_value.SetValueType(Value::ValueType::Scalar);
page_to_free_value.SetCompilerType(clang_void_ptr_type);
Value page_to_free_size_value;
- page_to_free_size_value.SetValueType(Value::eValueTypeScalar);
+ page_to_free_size_value.SetValueType(Value::ValueType::Scalar);
page_to_free_size_value.SetCompilerType(clang_uint64_type);
std::lock_guard<std::mutex> guard(m_get_pending_items_retbuffer_mutex);
diff --git a/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.h b/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.h
index 20895ca..fe02526 100644
--- a/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.h
+++ b/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.h
@@ -48,16 +48,14 @@
~AppleGetPendingItemsHandler();
struct GetPendingItemsReturnInfo {
- lldb::addr_t items_buffer_ptr; /* the address of the pending items buffer
- from libBacktraceRecording */
- lldb::addr_t
- items_buffer_size; /* the size of the pending items buffer from
- libBacktraceRecording */
- uint64_t count; /* the number of pending items included in the buffer */
+ lldb::addr_t items_buffer_ptr =
+ LLDB_INVALID_ADDRESS; /* the address of the pending items buffer
+ from libBacktraceRecording */
+ lldb::addr_t items_buffer_size = 0; /* the size of the pending items buffer
+ from libBacktraceRecording */
+ uint64_t count = 0; /* the number of pending items included in the buffer */
- GetPendingItemsReturnInfo()
- : items_buffer_ptr(LLDB_INVALID_ADDRESS), items_buffer_size(0),
- count(0) {}
+ GetPendingItemsReturnInfo() = default;
};
/// Get the list of pending items for a given queue via a call to
diff --git a/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp b/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp
index 6e65211..f471871 100644
--- a/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp
@@ -99,7 +99,7 @@
m_get_queues_return_buffer_addr(LLDB_INVALID_ADDRESS),
m_get_queues_retbuffer_mutex() {}
-AppleGetQueuesHandler::~AppleGetQueuesHandler() {}
+AppleGetQueuesHandler::~AppleGetQueuesHandler() = default;
void AppleGetQueuesHandler::Detach() {
@@ -264,22 +264,22 @@
CompilerType clang_void_ptr_type =
clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
Value return_buffer_ptr_value;
- return_buffer_ptr_value.SetValueType(Value::eValueTypeScalar);
+ return_buffer_ptr_value.SetValueType(Value::ValueType::Scalar);
return_buffer_ptr_value.SetCompilerType(clang_void_ptr_type);
CompilerType clang_int_type = clang_ast_context->GetBasicType(eBasicTypeInt);
Value debug_value;
- debug_value.SetValueType(Value::eValueTypeScalar);
+ debug_value.SetValueType(Value::ValueType::Scalar);
debug_value.SetCompilerType(clang_int_type);
Value page_to_free_value;
- page_to_free_value.SetValueType(Value::eValueTypeScalar);
+ page_to_free_value.SetValueType(Value::ValueType::Scalar);
page_to_free_value.SetCompilerType(clang_void_ptr_type);
CompilerType clang_uint64_type =
clang_ast_context->GetBasicType(eBasicTypeUnsignedLongLong);
Value page_to_free_size_value;
- page_to_free_size_value.SetValueType(Value::eValueTypeScalar);
+ page_to_free_size_value.SetValueType(Value::ValueType::Scalar);
page_to_free_size_value.SetCompilerType(clang_uint64_type);
std::lock_guard<std::mutex> guard(m_get_queues_retbuffer_mutex);
diff --git a/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.h b/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.h
index 0c828d7..b33e6186 100644
--- a/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.h
+++ b/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.h
@@ -45,15 +45,14 @@
~AppleGetQueuesHandler();
struct GetQueuesReturnInfo {
- lldb::addr_t queues_buffer_ptr; /* the address of the queues buffer from
+ lldb::addr_t queues_buffer_ptr =
+ LLDB_INVALID_ADDRESS; /* the address of the queues buffer from
+ libBacktraceRecording */
+ lldb::addr_t queues_buffer_size = 0; /* the size of the queues buffer from
libBacktraceRecording */
- lldb::addr_t queues_buffer_size; /* the size of the queues buffer from
- libBacktraceRecording */
- uint64_t count; /* the number of queues included in the queues buffer */
+ uint64_t count = 0; /* the number of queues included in the queues buffer */
- GetQueuesReturnInfo()
- : queues_buffer_ptr(LLDB_INVALID_ADDRESS), queues_buffer_size(0),
- count(0) {}
+ GetQueuesReturnInfo() = default;
};
/// Get the list of queues that exist (with any active or pending items) via
diff --git a/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp b/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp
index 77fb0be..7837dca 100644
--- a/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp
+++ b/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp
@@ -107,7 +107,7 @@
m_get_thread_item_info_return_buffer_addr(LLDB_INVALID_ADDRESS),
m_get_thread_item_info_retbuffer_mutex() {}
-AppleGetThreadItemInfoHandler::~AppleGetThreadItemInfoHandler() {}
+AppleGetThreadItemInfoHandler::~AppleGetThreadItemInfoHandler() = default;
void AppleGetThreadItemInfoHandler::Detach() {
@@ -262,26 +262,26 @@
CompilerType clang_void_ptr_type =
clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
Value return_buffer_ptr_value;
- return_buffer_ptr_value.SetValueType(Value::eValueTypeScalar);
+ return_buffer_ptr_value.SetValueType(Value::ValueType::Scalar);
return_buffer_ptr_value.SetCompilerType(clang_void_ptr_type);
CompilerType clang_int_type = clang_ast_context->GetBasicType(eBasicTypeInt);
Value debug_value;
- debug_value.SetValueType(Value::eValueTypeScalar);
+ debug_value.SetValueType(Value::ValueType::Scalar);
debug_value.SetCompilerType(clang_int_type);
CompilerType clang_uint64_type =
clang_ast_context->GetBasicType(eBasicTypeUnsignedLongLong);
Value thread_id_value;
- thread_id_value.SetValueType(Value::eValueTypeScalar);
+ thread_id_value.SetValueType(Value::ValueType::Scalar);
thread_id_value.SetCompilerType(clang_uint64_type);
Value page_to_free_value;
- page_to_free_value.SetValueType(Value::eValueTypeScalar);
+ page_to_free_value.SetValueType(Value::ValueType::Scalar);
page_to_free_value.SetCompilerType(clang_void_ptr_type);
Value page_to_free_size_value;
- page_to_free_size_value.SetValueType(Value::eValueTypeScalar);
+ page_to_free_size_value.SetValueType(Value::ValueType::Scalar);
page_to_free_size_value.SetCompilerType(clang_uint64_type);
std::lock_guard<std::mutex> guard(m_get_thread_item_info_retbuffer_mutex);
diff --git a/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.h b/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.h
index 0f7201a..9b2005f 100644
--- a/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.h
+++ b/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.h
@@ -47,13 +47,12 @@
~AppleGetThreadItemInfoHandler();
struct GetThreadItemInfoReturnInfo {
- lldb::addr_t item_buffer_ptr; /* the address of the item buffer from
- libBacktraceRecording */
- lldb::addr_t item_buffer_size; /* the size of the item buffer from
+ lldb::addr_t item_buffer_ptr = LLDB_INVALID_ADDRESS; /* the address of the
+ item buffer from libBacktraceRecording */
+ lldb::addr_t item_buffer_size = 0; /* the size of the item buffer from
libBacktraceRecording */
- GetThreadItemInfoReturnInfo()
- : item_buffer_ptr(LLDB_INVALID_ADDRESS), item_buffer_size(0) {}
+ GetThreadItemInfoReturnInfo() = default;
};
/// Get the information about a work item by calling
diff --git a/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h b/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h
index 844682e..877a2ad 100644
--- a/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h
+++ b/src/llvm-project/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h
@@ -108,14 +108,12 @@
private:
struct libBacktraceRecording_info {
- uint16_t queue_info_version;
- uint16_t queue_info_data_offset;
- uint16_t item_info_version;
- uint16_t item_info_data_offset;
+ uint16_t queue_info_version = 0;
+ uint16_t queue_info_data_offset = 0;
+ uint16_t item_info_version = 0;
+ uint16_t item_info_data_offset = 0;
- libBacktraceRecording_info()
- : queue_info_version(0), queue_info_data_offset(0),
- item_info_version(0), item_info_data_offset(0) {}
+ libBacktraceRecording_info() = default;
};
// A structure which reflects the data recorded in the
@@ -186,44 +184,35 @@
};
struct LibdispatchVoucherOffsets {
- uint16_t vo_version;
- uint16_t vo_activity_ids_count;
- uint16_t vo_activity_ids_count_size;
- uint16_t vo_activity_ids_array;
- uint16_t vo_activity_ids_array_entry_size;
+ uint16_t vo_version = UINT16_MAX;
+ uint16_t vo_activity_ids_count = UINT16_MAX;
+ uint16_t vo_activity_ids_count_size = UINT16_MAX;
+ uint16_t vo_activity_ids_array = UINT16_MAX;
+ uint16_t vo_activity_ids_array_entry_size = UINT16_MAX;
- LibdispatchVoucherOffsets()
- : vo_version(UINT16_MAX), vo_activity_ids_count(UINT16_MAX),
- vo_activity_ids_count_size(UINT16_MAX),
- vo_activity_ids_array(UINT16_MAX),
- vo_activity_ids_array_entry_size(UINT16_MAX) {}
+ LibdispatchVoucherOffsets() = default;
bool IsValid() { return vo_version != UINT16_MAX; }
};
struct LibdispatchTSDIndexes {
- uint16_t dti_version;
- uint64_t dti_queue_index;
- uint64_t dti_voucher_index;
- uint64_t dti_qos_class_index;
+ uint16_t dti_version = UINT16_MAX;
+ uint64_t dti_queue_index = UINT64_MAX;
+ uint64_t dti_voucher_index = UINT64_MAX;
+ uint64_t dti_qos_class_index = UINT64_MAX;
- LibdispatchTSDIndexes()
- : dti_version(UINT16_MAX), dti_queue_index(UINT64_MAX),
- dti_voucher_index(UINT64_MAX), dti_qos_class_index(UINT64_MAX) {}
+ LibdispatchTSDIndexes() = default;
bool IsValid() { return dti_version != UINT16_MAX; }
};
struct LibpthreadOffsets {
- uint16_t plo_version;
- uint16_t plo_pthread_tsd_base_offset;
- uint16_t plo_pthread_tsd_base_address_offset;
- uint16_t plo_pthread_tsd_entry_size;
+ uint16_t plo_version = UINT16_MAX;
+ uint16_t plo_pthread_tsd_base_offset = UINT16_MAX;
+ uint16_t plo_pthread_tsd_base_address_offset = UINT16_MAX;
+ uint16_t plo_pthread_tsd_entry_size = UINT16_MAX;
- LibpthreadOffsets()
- : plo_version(UINT16_MAX), plo_pthread_tsd_base_offset(UINT16_MAX),
- plo_pthread_tsd_base_address_offset(UINT16_MAX),
- plo_pthread_tsd_entry_size(UINT16_MAX) {}
+ LibpthreadOffsets() = default;
bool IsValid() { return plo_version != UINT16_MAX; }
};
diff --git a/src/llvm-project/lldb/source/Plugins/Trace/CMakeLists.txt b/src/llvm-project/lldb/source/Plugins/Trace/CMakeLists.txt
index edbb5f1..955f88c 100644
--- a/src/llvm-project/lldb/source/Plugins/Trace/CMakeLists.txt
+++ b/src/llvm-project/lldb/source/Plugins/Trace/CMakeLists.txt
@@ -1,5 +1,7 @@
option(LLDB_BUILD_INTEL_PT "Enable Building of Intel(R) Processor Trace Tool" OFF)
+add_subdirectory(common)
+
if (LLDB_BUILD_INTEL_PT)
add_subdirectory(intel-pt)
endif()
diff --git a/src/llvm-project/lldb/source/Plugins/Trace/common/CMakeLists.txt b/src/llvm-project/lldb/source/Plugins/Trace/common/CMakeLists.txt
new file mode 100644
index 0000000..604ddb6
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Trace/common/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_lldb_library(lldbPluginTraceCommon
+ ThreadPostMortemTrace.cpp
+ TraceSessionFileParser.cpp
+
+ LINK_LIBS
+ lldbCore
+ lldbTarget
+ )
diff --git a/src/llvm-project/lldb/source/Plugins/Trace/common/ThreadPostMortemTrace.cpp b/src/llvm-project/lldb/source/Plugins/Trace/common/ThreadPostMortemTrace.cpp
new file mode 100644
index 0000000..45d6f3b
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Trace/common/ThreadPostMortemTrace.cpp
@@ -0,0 +1,41 @@
+//===-- ThreadPostMortemTrace.cpp -----------------------------------------===//
+//
+// 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 "ThreadPostMortemTrace.h"
+
+#include <memory>
+
+#include "Plugins/Process/Utility/RegisterContextHistory.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void ThreadPostMortemTrace::RefreshStateAfterStop() {}
+
+RegisterContextSP ThreadPostMortemTrace::GetRegisterContext() {
+ if (!m_reg_context_sp)
+ m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
+
+ return m_reg_context_sp;
+}
+
+RegisterContextSP
+ThreadPostMortemTrace::CreateRegisterContextForFrame(StackFrame *frame) {
+ // Eventually this will calculate the register context based on the current
+ // trace position.
+ return std::make_shared<RegisterContextHistory>(
+ *this, 0, GetProcess()->GetAddressByteSize(), LLDB_INVALID_ADDRESS);
+}
+
+bool ThreadPostMortemTrace::CalculateStopInfo() { return false; }
+
+const FileSpec &ThreadPostMortemTrace::GetTraceFile() const {
+ return m_trace_file;
+}
diff --git a/src/llvm-project/lldb/source/Plugins/Trace/common/ThreadPostMortemTrace.h b/src/llvm-project/lldb/source/Plugins/Trace/common/ThreadPostMortemTrace.h
new file mode 100644
index 0000000..9cfe754
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Trace/common/ThreadPostMortemTrace.h
@@ -0,0 +1,60 @@
+//===-- ThreadPostMortemTrace.h ---------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_TARGET_THREADPOSTMORTEMTRACE_H
+#define LLDB_TARGET_THREADPOSTMORTEMTRACE_H
+
+#include "lldb/Target/Thread.h"
+
+namespace lldb_private {
+
+/// \class ThreadPostMortemTrace ThreadPostMortemTrace.h
+///
+/// Thread implementation used for representing threads gotten from trace
+/// session files, which are similar to threads from core files.
+///
+/// See \a TraceSessionFileParser for more information regarding trace session
+/// files.
+class ThreadPostMortemTrace : public Thread {
+public:
+ /// \param[in] process
+ /// The process who owns this thread.
+ ///
+ /// \param[in] tid
+ /// The tid of this thread.
+ ///
+ /// \param[in] trace_file
+ /// The file that contains the list of instructions that were traced when
+ /// this thread was being executed.
+ ThreadPostMortemTrace(Process &process, lldb::tid_t tid,
+ const FileSpec &trace_file)
+ : Thread(process, tid), m_trace_file(trace_file) {}
+
+ void RefreshStateAfterStop() override;
+
+ lldb::RegisterContextSP GetRegisterContext() override;
+
+ lldb::RegisterContextSP
+ CreateRegisterContextForFrame(StackFrame *frame) override;
+
+ /// \return
+ /// The trace file of this thread.
+ const FileSpec &GetTraceFile() const;
+
+protected:
+ bool CalculateStopInfo() override;
+
+ lldb::RegisterContextSP m_thread_reg_ctx_sp;
+
+private:
+ FileSpec m_trace_file;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_TARGET_THREADPOSTMORTEMTRACE_H
diff --git a/src/llvm-project/lldb/source/Plugins/Trace/common/TraceSessionFileParser.cpp b/src/llvm-project/lldb/source/Plugins/Trace/common/TraceSessionFileParser.cpp
new file mode 100644
index 0000000..c88ad9d
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Trace/common/TraceSessionFileParser.cpp
@@ -0,0 +1,224 @@
+//===-- TraceSessionFileParser.cpp ---------------------------------------===//
+//
+// 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 "TraceSessionFileParser.h"
+#include "ThreadPostMortemTrace.h"
+
+#include <sstream>
+
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace llvm;
+
+void TraceSessionFileParser::NormalizePath(lldb_private::FileSpec &file_spec) {
+ if (file_spec.IsRelative())
+ file_spec.PrependPathComponent(m_session_file_dir);
+}
+
+Error TraceSessionFileParser::ParseModule(lldb::TargetSP &target_sp,
+ const JSONModule &module) {
+ FileSpec system_file_spec(module.system_path);
+ NormalizePath(system_file_spec);
+
+ FileSpec local_file_spec(module.file.hasValue() ? *module.file
+ : module.system_path);
+ NormalizePath(local_file_spec);
+
+ ModuleSpec module_spec;
+ module_spec.GetFileSpec() = local_file_spec;
+ module_spec.GetPlatformFileSpec() = system_file_spec;
+
+ if (module.uuid.hasValue())
+ module_spec.GetUUID().SetFromStringRef(*module.uuid);
+
+ Status error;
+ ModuleSP module_sp =
+ target_sp->GetOrCreateModule(module_spec, /*notify*/ false, &error);
+
+ if (error.Fail())
+ return error.ToError();
+
+ bool load_addr_changed = false;
+ module_sp->SetLoadAddress(*target_sp, module.load_address.value, false,
+ load_addr_changed);
+ return llvm::Error::success();
+}
+
+Error TraceSessionFileParser::CreateJSONError(json::Path::Root &root,
+ const json::Value &value) {
+ std::string err;
+ raw_string_ostream os(err);
+ root.printErrorContext(value, os);
+ return createStringError(
+ std::errc::invalid_argument, "%s\n\nContext:\n%s\n\nSchema:\n%s",
+ toString(root.getError()).c_str(), os.str().c_str(), m_schema.data());
+}
+
+std::string TraceSessionFileParser::BuildSchema(StringRef plugin_schema) {
+ std::ostringstream schema_builder;
+ schema_builder << "{\n \"trace\": ";
+ schema_builder << plugin_schema.data() << ",";
+ schema_builder << R"(
+ "processes": [
+ {
+ "pid": integer,
+ "triple": string, // llvm-triple
+ "threads": [
+ {
+ "tid": integer,
+ "traceFile": string
+ }
+ ],
+ "modules": [
+ {
+ "systemPath": string, // original path of the module at runtime
+ "file"?: string, // copy of the file if not available at "systemPath"
+ "loadAddress": string, // string address in hex or decimal form
+ "uuid"?: string,
+ }
+ ]
+ }
+ ]
+ // Notes:
+ // All paths are either absolute or relative to the session file.
+}
+)";
+ return schema_builder.str();
+}
+
+ThreadPostMortemTraceSP
+TraceSessionFileParser::ParseThread(ProcessSP &process_sp,
+ const JSONThread &thread) {
+ lldb::tid_t tid = static_cast<lldb::tid_t>(thread.tid);
+
+ FileSpec trace_file(thread.trace_file);
+ NormalizePath(trace_file);
+
+ ThreadPostMortemTraceSP thread_sp =
+ std::make_shared<ThreadPostMortemTrace>(*process_sp, tid, trace_file);
+ process_sp->GetThreadList().AddThread(thread_sp);
+ return thread_sp;
+}
+
+Expected<TraceSessionFileParser::ParsedProcess>
+TraceSessionFileParser::ParseProcess(const JSONProcess &process) {
+ TargetSP target_sp;
+ Status error = m_debugger.GetTargetList().CreateTarget(
+ m_debugger, /*user_exe_path*/ StringRef(), process.triple,
+ eLoadDependentsNo,
+ /*platform_options*/ nullptr, target_sp);
+
+ if (!target_sp)
+ return error.ToError();
+
+ ParsedProcess parsed_process;
+ parsed_process.target_sp = target_sp;
+
+ ProcessSP process_sp = target_sp->CreateProcess(
+ /*listener*/ nullptr, "trace",
+ /*crash_file*/ nullptr,
+ /*can_connect*/ false);
+
+ process_sp->SetID(static_cast<lldb::pid_t>(process.pid));
+
+ for (const JSONThread &thread : process.threads)
+ parsed_process.threads.push_back(ParseThread(process_sp, thread));
+
+ for (const JSONModule &module : process.modules)
+ if (Error err = ParseModule(target_sp, module))
+ return std::move(err);
+
+ if (!process.threads.empty())
+ process_sp->GetThreadList().SetSelectedThreadByIndexID(0);
+
+ // We invoke DidAttach to create a correct stopped state for the process and
+ // its threads.
+ ArchSpec process_arch;
+ process_sp->DidAttach(process_arch);
+
+ return parsed_process;
+}
+
+Expected<std::vector<TraceSessionFileParser::ParsedProcess>>
+TraceSessionFileParser::ParseCommonSessionFile(
+ const JSONTraceSessionBase &session) {
+ std::vector<ParsedProcess> parsed_processes;
+
+ auto onError = [&]() {
+ // Delete all targets that were created so far in case of failures
+ for (ParsedProcess &parsed_process : parsed_processes)
+ m_debugger.GetTargetList().DeleteTarget(parsed_process.target_sp);
+ };
+
+ for (const JSONProcess &process : session.processes) {
+ if (Expected<ParsedProcess> parsed_process = ParseProcess(process))
+ parsed_processes.push_back(std::move(*parsed_process));
+ else {
+ onError();
+ return parsed_process.takeError();
+ }
+ }
+ return parsed_processes;
+}
+
+namespace llvm {
+namespace json {
+
+bool fromJSON(const Value &value, TraceSessionFileParser::JSONAddress &address,
+ Path path) {
+ Optional<StringRef> s = value.getAsString();
+ if (s.hasValue() && !s->getAsInteger(0, address.value))
+ return true;
+
+ path.report("expected numeric string");
+ return false;
+}
+
+bool fromJSON(const Value &value, TraceSessionFileParser::JSONModule &module,
+ Path path) {
+ ObjectMapper o(value, path);
+ return o && o.map("systemPath", module.system_path) &&
+ o.map("file", module.file) &&
+ o.map("loadAddress", module.load_address) &&
+ o.map("uuid", module.uuid);
+}
+
+bool fromJSON(const Value &value, TraceSessionFileParser::JSONThread &thread,
+ Path path) {
+ ObjectMapper o(value, path);
+ return o && o.map("tid", thread.tid) && o.map("traceFile", thread.trace_file);
+}
+
+bool fromJSON(const Value &value, TraceSessionFileParser::JSONProcess &process,
+ Path path) {
+ ObjectMapper o(value, path);
+ return o && o.map("pid", process.pid) && o.map("triple", process.triple) &&
+ o.map("threads", process.threads) && o.map("modules", process.modules);
+}
+
+bool fromJSON(const Value &value,
+ TraceSessionFileParser::JSONTracePluginSettings &plugin_settings,
+ Path path) {
+ ObjectMapper o(value, path);
+ return o && o.map("type", plugin_settings.type);
+}
+
+bool fromJSON(const Value &value,
+ TraceSessionFileParser::JSONTraceSessionBase &session,
+ Path path) {
+ ObjectMapper o(value, path);
+ return o && o.map("processes", session.processes);
+}
+
+} // namespace json
+} // namespace llvm
diff --git a/src/llvm-project/lldb/source/Plugins/Trace/common/TraceSessionFileParser.h b/src/llvm-project/lldb/source/Plugins/Trace/common/TraceSessionFileParser.h
new file mode 100644
index 0000000..6abaffc
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Trace/common/TraceSessionFileParser.h
@@ -0,0 +1,179 @@
+//===-- TraceSessionFileParser.h --------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_TARGET_TRACESESSIONPARSER_H
+#define LLDB_TARGET_TRACESESSIONPARSER_H
+
+#include "llvm/Support/JSON.h"
+
+#include "ThreadPostMortemTrace.h"
+
+namespace lldb_private {
+
+/// \class TraceSessionFileParser TraceSessionFileParser.h
+///
+/// Base class for parsing the common information of JSON trace session files.
+/// Contains the basic C++ structs that represent the JSON data, which include
+/// \a JSONTraceSession as the root object.
+///
+/// See \a Trace::FindPlugin for more information regarding these JSON files.
+class TraceSessionFileParser {
+public:
+ /// C++ structs representing the JSON trace session.
+ /// \{
+ struct JSONAddress {
+ lldb::addr_t value;
+ };
+
+ struct JSONModule {
+ std::string system_path;
+ llvm::Optional<std::string> file;
+ JSONAddress load_address;
+ llvm::Optional<std::string> uuid;
+ };
+
+ struct JSONThread {
+ int64_t tid;
+ std::string trace_file;
+ };
+
+ struct JSONProcess {
+ int64_t pid;
+ std::string triple;
+ std::vector<JSONThread> threads;
+ std::vector<JSONModule> modules;
+ };
+
+ struct JSONTracePluginSettings {
+ std::string type;
+ };
+
+ struct JSONTraceSessionBase {
+ std::vector<JSONProcess> processes;
+ };
+
+ /// The trace plug-in implementation should provide its own TPluginSettings,
+ /// which corresponds to the "trace" section of the schema.
+ template <class TPluginSettings>
+ struct JSONTraceSession : JSONTraceSessionBase {
+ TPluginSettings trace;
+ };
+ /// \}
+
+ /// Helper struct holding the objects created when parsing a process
+ struct ParsedProcess {
+ lldb::TargetSP target_sp;
+ std::vector<lldb::ThreadPostMortemTraceSP> threads;
+ };
+
+ TraceSessionFileParser(Debugger &debugger, llvm::StringRef session_file_dir,
+ llvm::StringRef schema)
+ : m_debugger(debugger), m_session_file_dir(session_file_dir),
+ m_schema(schema) {}
+
+ /// Build the full schema for a Trace plug-in.
+ ///
+ /// \param[in] plugin_schema
+ /// The subschema that corresponds to the "trace" section of the schema.
+ ///
+ /// \return
+ /// The full schema containing the common attributes and the plug-in
+ /// specific attributes.
+ static std::string BuildSchema(llvm::StringRef plugin_schema);
+
+ /// Parse the fields common to all trace session schemas.
+ ///
+ /// \param[in] session
+ /// The session json objects already deserialized.
+ ///
+ /// \return
+ /// A list of \a ParsedProcess containing all threads and targets created
+ /// during the parsing, or an error in case of failures. In case of
+ /// errors, no side effects are produced.
+ llvm::Expected<std::vector<ParsedProcess>>
+ ParseCommonSessionFile(const JSONTraceSessionBase &session);
+
+protected:
+ /// Resolve non-absolute paths relative to the session file folder. It
+ /// modifies the given file_spec.
+ void NormalizePath(lldb_private::FileSpec &file_spec);
+
+ lldb::ThreadPostMortemTraceSP ParseThread(lldb::ProcessSP &process_sp,
+ const JSONThread &thread);
+
+ llvm::Expected<ParsedProcess> ParseProcess(const JSONProcess &process);
+
+ llvm::Error ParseModule(lldb::TargetSP &target_sp, const JSONModule &module);
+
+ /// Create a user-friendly error message upon a JSON-parsing failure using the
+ /// \a json::ObjectMapper functionality.
+ ///
+ /// \param[in] root
+ /// The \a llvm::json::Path::Root used to parse the JSON \a value.
+ ///
+ /// \param[in] value
+ /// The json value that failed to parse.
+ ///
+ /// \return
+ /// An \a llvm::Error containing the user-friendly error message.
+ llvm::Error CreateJSONError(llvm::json::Path::Root &root,
+ const llvm::json::Value &value);
+
+ Debugger &m_debugger;
+ std::string m_session_file_dir;
+ llvm::StringRef m_schema;
+};
+} // namespace lldb_private
+
+namespace llvm {
+namespace json {
+
+bool fromJSON(const Value &value,
+ lldb_private::TraceSessionFileParser::JSONAddress &address,
+ Path path);
+
+bool fromJSON(const Value &value,
+ lldb_private::TraceSessionFileParser::JSONModule &module,
+ Path path);
+
+bool fromJSON(const Value &value,
+ lldb_private::TraceSessionFileParser::JSONThread &thread,
+ Path path);
+
+bool fromJSON(const Value &value,
+ lldb_private::TraceSessionFileParser::JSONProcess &process,
+ Path path);
+
+bool fromJSON(const Value &value,
+ lldb_private::TraceSessionFileParser::JSONTracePluginSettings
+ &plugin_settings,
+ Path path);
+
+bool fromJSON(
+ const Value &value,
+ lldb_private::TraceSessionFileParser::JSONTraceSessionBase &session,
+ Path path);
+
+template <class TPluginSettings>
+bool fromJSON(
+ const Value &value,
+ lldb_private::TraceSessionFileParser::JSONTraceSession<TPluginSettings>
+ &session,
+ Path path) {
+ ObjectMapper o(value, path);
+ return o && o.map("trace", session.trace) &&
+ fromJSON(value,
+ (lldb_private::TraceSessionFileParser::JSONTraceSessionBase &)
+ session,
+ path);
+}
+
+} // namespace json
+} // namespace llvm
+
+#endif // LLDB_TARGET_TRACESESSIONPARSER_H
diff --git a/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/CMakeLists.txt b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/CMakeLists.txt
index a75d967..7ecc9b7 100644
--- a/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/CMakeLists.txt
+++ b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/CMakeLists.txt
@@ -17,6 +17,7 @@
CommandObjectTraceStartIntelPT.cpp
DecodedThread.cpp
IntelPTDecoder.cpp
+ TraceCursorIntelPT.cpp
TraceIntelPT.cpp
TraceIntelPTSessionFileParser.cpp
@@ -24,6 +25,7 @@
lldbCore
lldbSymbol
lldbTarget
+ lldbPluginTraceCommon
${LIBIPT_LIBRARY}
LINK_COMPONENTS
Support
diff --git a/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp
index e1758df..5650af6 100644
--- a/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp
@@ -8,7 +8,10 @@
#include "CommandObjectTraceStartIntelPT.h"
+#include "TraceIntelPT.h"
+#include "TraceIntelPTConstants.h"
#include "lldb/Host/OptionParser.h"
+#include "lldb/Target/Process.h"
#include "lldb/Target/Trace.h"
using namespace lldb;
@@ -16,10 +19,12 @@
using namespace lldb_private::trace_intel_pt;
using namespace llvm;
+// CommandObjectThreadTraceStartIntelPT
+
#define LLDB_OPTIONS_thread_trace_start_intel_pt
#include "TraceIntelPTCommandOptions.inc"
-Status CommandObjectTraceStartIntelPT::CommandOptions::SetOptionValue(
+Status CommandObjectThreadTraceStartIntelPT::CommandOptions::SetOptionValue(
uint32_t option_idx, llvm::StringRef option_arg,
ExecutionContext *execution_context) {
Status error;
@@ -27,23 +32,27 @@
switch (short_option) {
case 's': {
- int32_t size_in_kb;
- if (option_arg.empty() || option_arg.getAsInteger(0, size_in_kb) ||
- size_in_kb < 0)
+ int64_t thread_buffer_size;
+ if (option_arg.empty() || option_arg.getAsInteger(0, thread_buffer_size) ||
+ thread_buffer_size < 0)
error.SetErrorStringWithFormat("invalid integer value for option '%s'",
option_arg.str().c_str());
else
- m_size_in_kb = size_in_kb;
+ m_thread_buffer_size = thread_buffer_size;
break;
}
- case 'c': {
- int32_t custom_config;
- if (option_arg.empty() || option_arg.getAsInteger(0, custom_config) ||
- custom_config < 0)
+ case 't': {
+ m_enable_tsc = true;
+ break;
+ }
+ case 'p': {
+ int64_t psb_period;
+ if (option_arg.empty() || option_arg.getAsInteger(0, psb_period) ||
+ psb_period < 0)
error.SetErrorStringWithFormat("invalid integer value for option '%s'",
option_arg.str().c_str());
else
- m_custom_config = custom_config;
+ m_psb_period = psb_period;
break;
}
default:
@@ -52,22 +61,104 @@
return error;
}
-void CommandObjectTraceStartIntelPT::CommandOptions::OptionParsingStarting(
- ExecutionContext *execution_context) {
- m_size_in_kb = 4;
- m_custom_config = 0;
+void CommandObjectThreadTraceStartIntelPT::CommandOptions::
+ OptionParsingStarting(ExecutionContext *execution_context) {
+ m_thread_buffer_size = kDefaultThreadBufferSize;
+ m_enable_tsc = kDefaultEnableTscValue;
+ m_psb_period = kDefaultPsbPeriod;
}
llvm::ArrayRef<OptionDefinition>
-CommandObjectTraceStartIntelPT::CommandOptions::GetDefinitions() {
+CommandObjectThreadTraceStartIntelPT::CommandOptions::GetDefinitions() {
return llvm::makeArrayRef(g_thread_trace_start_intel_pt_options);
}
-bool CommandObjectTraceStartIntelPT::HandleOneThread(
- lldb::tid_t tid, CommandReturnObject &result) {
- result.AppendMessageWithFormat(
- "would trace tid %" PRIu64 " with size_in_kb %zu and custom_config %d\n",
- tid, m_options.m_size_in_kb, m_options.m_custom_config);
- result.SetStatus(eReturnStatusSuccessFinishResult);
+bool CommandObjectThreadTraceStartIntelPT::DoExecuteOnThreads(
+ Args &command, CommandReturnObject &result,
+ llvm::ArrayRef<lldb::tid_t> tids) {
+ if (Error err = m_trace.Start(tids, m_options.m_thread_buffer_size,
+ m_options.m_enable_tsc, m_options.m_psb_period))
+ result.SetError(Status(std::move(err)));
+ else
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+
+ return result.Succeeded();
+}
+
+/// CommandObjectProcessTraceStartIntelPT
+
+#define LLDB_OPTIONS_process_trace_start_intel_pt
+#include "TraceIntelPTCommandOptions.inc"
+
+Status CommandObjectProcessTraceStartIntelPT::CommandOptions::SetOptionValue(
+ uint32_t option_idx, llvm::StringRef option_arg,
+ ExecutionContext *execution_context) {
+ Status error;
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option) {
+ case 's': {
+ int64_t thread_buffer_size;
+ if (option_arg.empty() || option_arg.getAsInteger(0, thread_buffer_size) ||
+ thread_buffer_size < 0)
+ error.SetErrorStringWithFormat("invalid integer value for option '%s'",
+ option_arg.str().c_str());
+ else
+ m_thread_buffer_size = thread_buffer_size;
+ break;
+ }
+ case 'l': {
+ int64_t process_buffer_size_limit;
+ if (option_arg.empty() ||
+ option_arg.getAsInteger(0, process_buffer_size_limit) ||
+ process_buffer_size_limit < 0)
+ error.SetErrorStringWithFormat("invalid integer value for option '%s'",
+ option_arg.str().c_str());
+ else
+ m_process_buffer_size_limit = process_buffer_size_limit;
+ break;
+ }
+ case 't': {
+ m_enable_tsc = true;
+ break;
+ }
+ case 'p': {
+ int64_t psb_period;
+ if (option_arg.empty() || option_arg.getAsInteger(0, psb_period) ||
+ psb_period < 0)
+ error.SetErrorStringWithFormat("invalid integer value for option '%s'",
+ option_arg.str().c_str());
+ else
+ m_psb_period = psb_period;
+ break;
+ }
+ default:
+ llvm_unreachable("Unimplemented option");
+ }
+ return error;
+}
+
+void CommandObjectProcessTraceStartIntelPT::CommandOptions::
+ OptionParsingStarting(ExecutionContext *execution_context) {
+ m_thread_buffer_size = kDefaultThreadBufferSize;
+ m_process_buffer_size_limit = kDefaultProcessBufferSizeLimit;
+ m_enable_tsc = kDefaultEnableTscValue;
+ m_psb_period = kDefaultPsbPeriod;
+}
+
+llvm::ArrayRef<OptionDefinition>
+CommandObjectProcessTraceStartIntelPT::CommandOptions::GetDefinitions() {
+ return llvm::makeArrayRef(g_process_trace_start_intel_pt_options);
+}
+
+bool CommandObjectProcessTraceStartIntelPT::DoExecute(
+ Args &command, CommandReturnObject &result) {
+ if (Error err = m_trace.Start(m_options.m_thread_buffer_size,
+ m_options.m_process_buffer_size_limit,
+ m_options.m_enable_tsc, m_options.m_psb_period))
+ result.SetError(Status(std::move(err)));
+ else
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+
return result.Succeeded();
}
diff --git a/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h
index 265569c5..2f3d53a8 100644
--- a/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h
+++ b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h
@@ -9,21 +9,21 @@
#ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_COMMANDOBJECTTRACESTARTINTELPT_H
#define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_COMMANDOBJECTTRACESTARTINTELPT_H
-#include "../../../../source/Commands/CommandObjectThreadUtil.h"
+#include "../../../../source/Commands/CommandObjectTrace.h"
+#include "TraceIntelPT.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
namespace lldb_private {
namespace trace_intel_pt {
-class CommandObjectTraceStartIntelPT : public CommandObjectIterateOverThreads {
+class CommandObjectThreadTraceStartIntelPT
+ : public CommandObjectMultipleThreads {
public:
class CommandOptions : public Options {
public:
CommandOptions() : Options() { OptionParsingStarting(nullptr); }
- ~CommandOptions() override = default;
-
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
ExecutionContext *execution_context) override;
@@ -31,31 +31,76 @@
llvm::ArrayRef<OptionDefinition> GetDefinitions() override;
- size_t m_size_in_kb;
- uint32_t m_custom_config;
+ size_t m_thread_buffer_size;
+ bool m_enable_tsc;
+ llvm::Optional<size_t> m_psb_period;
};
- CommandObjectTraceStartIntelPT(CommandInterpreter &interpreter)
- : CommandObjectIterateOverThreads(
+ CommandObjectThreadTraceStartIntelPT(TraceIntelPT &trace,
+ CommandInterpreter &interpreter)
+ : CommandObjectMultipleThreads(
interpreter, "thread trace start",
"Start tracing one or more threads with intel-pt. "
"Defaults to the current thread. Thread indices can be "
"specified as arguments.\n Use the thread-index \"all\" to trace "
- "all threads.",
+ "all threads including future threads.",
"thread trace start [<thread-index> <thread-index> ...] "
"[<intel-pt-options>]",
lldb::eCommandRequiresProcess | lldb::eCommandTryTargetAPILock |
lldb::eCommandProcessMustBeLaunched |
lldb::eCommandProcessMustBePaused),
- m_options() {}
-
- ~CommandObjectTraceStartIntelPT() override = default;
+ m_trace(trace), m_options() {}
Options *GetOptions() override { return &m_options; }
protected:
- bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override;
+ bool DoExecuteOnThreads(Args &command, CommandReturnObject &result,
+ llvm::ArrayRef<lldb::tid_t> tids) override;
+ TraceIntelPT &m_trace;
+ CommandOptions m_options;
+};
+
+class CommandObjectProcessTraceStartIntelPT : public CommandObjectParsed {
+public:
+ class CommandOptions : public Options {
+ public:
+ CommandOptions() : Options() { OptionParsingStarting(nullptr); }
+
+ Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
+ ExecutionContext *execution_context) override;
+
+ void OptionParsingStarting(ExecutionContext *execution_context) override;
+
+ llvm::ArrayRef<OptionDefinition> GetDefinitions() override;
+
+ size_t m_thread_buffer_size;
+ size_t m_process_buffer_size_limit;
+ bool m_enable_tsc;
+ llvm::Optional<size_t> m_psb_period;
+ };
+
+ CommandObjectProcessTraceStartIntelPT(TraceIntelPT &trace,
+ CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "process trace start",
+ "Start tracing this process with intel-pt, including future "
+ "threads. "
+ "This is implemented by tracing each thread independently. "
+ "Threads traced with the \"thread trace start\" command are left "
+ "unaffected ant not retraced.",
+ "process trace start [<intel-pt-options>]",
+ lldb::eCommandRequiresProcess | lldb::eCommandTryTargetAPILock |
+ lldb::eCommandProcessMustBeLaunched |
+ lldb::eCommandProcessMustBePaused),
+ m_trace(trace), m_options() {}
+
+ Options *GetOptions() override { return &m_options; }
+
+protected:
+ bool DoExecute(Args &command, CommandReturnObject &result) override;
+
+ TraceIntelPT &m_trace;
CommandOptions m_options;
};
diff --git a/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp
index 6b8b065..4822a78 100644
--- a/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp
@@ -8,8 +8,13 @@
#include "DecodedThread.h"
+#include <intel-pt.h>
+#include <memory>
+
+#include "TraceCursorIntelPT.h"
#include "lldb/Utility/StreamString.h"
+using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::trace_intel_pt;
using namespace llvm;
@@ -30,12 +35,21 @@
OS << "error: " << libipt_error_message;
}
+IntelPTInstruction::IntelPTInstruction(llvm::Error err) {
+ llvm::handleAllErrors(std::move(err),
+ [&](std::unique_ptr<llvm::ErrorInfoBase> info) {
+ m_error = std::move(info);
+ });
+ m_pt_insn.ip = LLDB_INVALID_ADDRESS;
+ m_pt_insn.iclass = ptic_error;
+}
+
bool IntelPTInstruction::IsError() const { return (bool)m_error; }
-Expected<lldb::addr_t> IntelPTInstruction::GetLoadAddress() const {
- if (IsError())
- return ToError();
- return m_pt_insn.ip;
+lldb::addr_t IntelPTInstruction::GetLoadAddress() const { return m_pt_insn.ip; }
+
+Optional<uint64_t> IntelPTInstruction::GetTimestampCounter() const {
+ return m_timestamp;
}
Error IntelPTInstruction::ToError() const {
@@ -47,18 +61,58 @@
return make_error<StringError>(m_error->message(),
m_error->convertToErrorCode());
}
+size_t DecodedThread::GetRawTraceSize() const { return m_raw_trace_size; }
-size_t DecodedThread::GetLastPosition() const {
- return m_instructions.empty() ? 0 : m_instructions.size() - 1;
+TraceInstructionControlFlowType
+IntelPTInstruction::GetControlFlowType(lldb::addr_t next_load_address) const {
+ if (IsError())
+ return (TraceInstructionControlFlowType)0;
+
+ TraceInstructionControlFlowType mask =
+ eTraceInstructionControlFlowTypeInstruction;
+
+ switch (m_pt_insn.iclass) {
+ case ptic_cond_jump:
+ case ptic_jump:
+ case ptic_far_jump:
+ mask |= eTraceInstructionControlFlowTypeBranch;
+ if (m_pt_insn.ip + m_pt_insn.size != next_load_address)
+ mask |= eTraceInstructionControlFlowTypeTakenBranch;
+ break;
+ case ptic_return:
+ case ptic_far_return:
+ mask |= eTraceInstructionControlFlowTypeReturn;
+ break;
+ case ptic_call:
+ case ptic_far_call:
+ mask |= eTraceInstructionControlFlowTypeCall;
+ break;
+ default:
+ break;
+ }
+
+ return mask;
}
ArrayRef<IntelPTInstruction> DecodedThread::GetInstructions() const {
return makeArrayRef(m_instructions);
}
-size_t DecodedThread::GetCursorPosition() const { return m_position; }
+DecodedThread::DecodedThread(ThreadSP thread_sp, Error error)
+ : m_thread_sp(thread_sp) {
+ m_instructions.emplace_back(std::move(error));
+}
-size_t DecodedThread::SetCursorPosition(size_t new_position) {
- m_position = std::min(new_position, GetLastPosition());
- return m_position;
+DecodedThread::DecodedThread(ThreadSP thread_sp,
+ std::vector<IntelPTInstruction> &&instructions,
+ size_t raw_trace_size)
+ : m_thread_sp(thread_sp), m_instructions(std::move(instructions)),
+ m_raw_trace_size(raw_trace_size) {
+ if (m_instructions.empty())
+ m_instructions.emplace_back(
+ createStringError(inconvertibleErrorCode(), "empty trace"));
+}
+
+lldb::TraceCursorUP DecodedThread::GetCursor() {
+ return std::make_unique<TraceCursorIntelPT>(m_thread_sp, shared_from_this());
}
diff --git a/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h
index 3c7e030..592c402 100644
--- a/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h
+++ b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h
@@ -15,6 +15,7 @@
#include "llvm/Support/Error.h"
#include "lldb/Target/Trace.h"
+#include "lldb/Utility/TraceIntelPTGDBRemotePackets.h"
#include "intel-pt.h"
@@ -60,17 +61,15 @@
/// As mentioned, any gap is represented as an error in this class.
class IntelPTInstruction {
public:
+ IntelPTInstruction(const pt_insn &pt_insn, uint64_t timestamp)
+ : m_pt_insn(pt_insn), m_timestamp(timestamp) {}
+
IntelPTInstruction(const pt_insn &pt_insn) : m_pt_insn(pt_insn) {}
/// Error constructor
///
/// libipt errors should use the underlying \a IntelPTError class.
- IntelPTInstruction(llvm::Error err) {
- llvm::handleAllErrors(std::move(err),
- [&](std::unique_ptr<llvm::ErrorInfoBase> info) {
- m_error = std::move(info);
- });
- }
+ IntelPTInstruction(llvm::Error err);
/// Check if this object represents an error (i.e. a gap).
///
@@ -79,15 +78,34 @@
bool IsError() const;
/// \return
- /// The instruction pointer address, or an \a llvm::Error if it is an
- /// error.
- llvm::Expected<lldb::addr_t> GetLoadAddress() const;
+ /// The instruction pointer address, or \a LLDB_INVALID_ADDRESS if it is
+ /// an error.
+ lldb::addr_t GetLoadAddress() const;
/// \return
/// An \a llvm::Error object if this class corresponds to an Error, or an
/// \a llvm::Error::success otherwise.
llvm::Error ToError() const;
+ /// Get the timestamp associated with the current instruction. The timestamp
+ /// is similar to what a rdtsc instruction would return.
+ ///
+ /// \return
+ /// The timestamp or \b llvm::None if not available.
+ llvm::Optional<uint64_t> GetTimestampCounter() const;
+
+ /// Get the \a lldb::TraceInstructionControlFlowType categories of the
+ /// instruction.
+ ///
+ /// \param[in] next_load_address
+ /// The address of the next instruction in the trace or \b
+ /// LLDB_INVALID_ADDRESS if not available.
+ ///
+ /// \return
+ /// The control flow categories, or \b 0 if the instruction is an error.
+ lldb::TraceInstructionControlFlowType
+ GetControlFlowType(lldb::addr_t next_load_address) const;
+
IntelPTInstruction(IntelPTInstruction &&other) = default;
private:
@@ -95,6 +113,7 @@
const IntelPTInstruction &operator=(const IntelPTInstruction &other) = delete;
pt_insn m_pt_insn;
+ llvm::Optional<uint64_t> m_timestamp;
std::unique_ptr<llvm::ErrorInfoBase> m_error;
};
@@ -105,11 +124,15 @@
///
/// Each decoded thread contains a cursor to the current position the user is
/// stopped at. See \a Trace::GetCursorPosition for more information.
-class DecodedThread {
+class DecodedThread : public std::enable_shared_from_this<DecodedThread> {
public:
- DecodedThread(std::vector<IntelPTInstruction> &&instructions)
- : m_instructions(std::move(instructions)), m_position(GetLastPosition()) {
- }
+ DecodedThread(lldb::ThreadSP thread_sp,
+ std::vector<IntelPTInstruction> &&instructions,
+ size_t raw_trace_size);
+
+ /// Constructor with a single error signaling a complete failure of the
+ /// decoding process.
+ DecodedThread(lldb::ThreadSP thread_sp, llvm::Error error);
/// Get the instructions from the decoded trace. Some of them might indicate
/// errors (i.e. gaps) in the trace.
@@ -118,28 +141,23 @@
/// The instructions of the trace.
llvm::ArrayRef<IntelPTInstruction> GetInstructions() const;
- /// \return
- /// The current position of the cursor of this trace, or 0 if there are no
- /// instructions.
- size_t GetCursorPosition() const;
+ /// Get a new cursor for the decoded thread.
+ lldb::TraceCursorUP GetCursor();
- /// Change the position of the cursor of this trace. If this value is to high,
- /// the new position will be set as the last instruction of the trace.
+ /// Get the size in bytes of the corresponding Intel PT raw trace
///
/// \return
- /// The effective new position.
- size_t SetCursorPosition(size_t new_position);
- /// \}
+ /// The size of the trace.
+ size_t GetRawTraceSize() const;
private:
- /// \return
- /// The index of the last element of the trace, or 0 if empty.
- size_t GetLastPosition() const;
-
+ lldb::ThreadSP m_thread_sp;
std::vector<IntelPTInstruction> m_instructions;
- size_t m_position;
+ size_t m_raw_trace_size;
};
+using DecodedThreadSP = std::shared_ptr<DecodedThread>;
+
} // namespace trace_intel_pt
} // namespace lldb_private
diff --git a/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp
index b6e8ae8..3827881 100644
--- a/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp
@@ -1,5 +1,4 @@
-//===-- IntelPTDecoder.cpp --------------------------------------*- C++ -*-===//
-//
+//===-- IntelPTDecoder.cpp --======----------------------------------------===//
// 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
@@ -10,10 +9,13 @@
#include "llvm/Support/MemoryBuffer.h"
+#include "../common/ThreadPostMortemTrace.h"
+#include "DecodedThread.h"
+#include "TraceIntelPT.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Target/Target.h"
-#include "lldb/Target/ThreadTrace.h"
+#include "lldb/Utility/StringExtractor.h"
using namespace lldb;
using namespace lldb_private;
@@ -85,7 +87,7 @@
return errcode;
}
return 0;
-};
+}
/// Decode all the instructions from a configured decoder.
/// The decoding flow is based on
@@ -135,7 +137,23 @@
break;
}
- instructions.emplace_back(insn);
+ uint64_t time;
+ int time_error = pt_insn_time(&decoder, &time, nullptr, nullptr);
+ if (time_error == -pte_invalid) {
+ // This happens if we invoke the pt_insn_time method incorrectly,
+ // but the instruction is good though.
+ instructions.emplace_back(
+ make_error<IntelPTError>(time_error, insn.ip));
+ instructions.emplace_back(insn);
+ break;
+ }
+ if (time_error == -pte_no_time) {
+ // We simply don't have time information, i.e. None of TSC, MTC or CYC
+ // was enabled.
+ instructions.emplace_back(insn);
+ } else {
+ instructions.emplace_back(insn, time);
+ }
}
}
@@ -158,39 +176,26 @@
return bytes_read;
}
-static std::vector<IntelPTInstruction> makeInstructionListFromError(Error err) {
- std::vector<IntelPTInstruction> instructions;
- instructions.emplace_back(std::move(err));
- return instructions;
-}
-
-static std::vector<IntelPTInstruction>
-CreateDecoderAndDecode(Process &process, const pt_cpu &pt_cpu,
- const FileSpec &trace_file) {
- ErrorOr<std::unique_ptr<MemoryBuffer>> trace_or_error =
- MemoryBuffer::getFile(trace_file.GetPath());
- if (std::error_code err = trace_or_error.getError())
- return makeInstructionListFromError(errorCodeToError(err));
-
- MemoryBuffer &trace = **trace_or_error;
+static Expected<std::vector<IntelPTInstruction>>
+DecodeInMemoryTrace(Process &process, TraceIntelPT &trace_intel_pt,
+ MutableArrayRef<uint8_t> buffer) {
+ Expected<pt_cpu> cpu_info = trace_intel_pt.GetCPUInfo();
+ if (!cpu_info)
+ return cpu_info.takeError();
pt_config config;
pt_config_init(&config);
- config.cpu = pt_cpu;
+ config.cpu = *cpu_info;
if (int errcode = pt_cpu_errata(&config.errata, &config.cpu))
- return makeInstructionListFromError(make_error<IntelPTError>(errcode));
+ return make_error<IntelPTError>(errcode);
- // The libipt library does not modify the trace buffer, hence the following
- // cast is safe.
- config.begin =
- reinterpret_cast<uint8_t *>(const_cast<char *>(trace.getBufferStart()));
- config.end =
- reinterpret_cast<uint8_t *>(const_cast<char *>(trace.getBufferEnd()));
+ config.begin = buffer.data();
+ config.end = buffer.data() + buffer.size();
pt_insn_decoder *decoder = pt_insn_alloc_decoder(&config);
if (!decoder)
- return makeInstructionListFromError(make_error<IntelPTError>(-pte_nomem));
+ return make_error<IntelPTError>(-pte_nomem);
pt_image *image = pt_insn_get_image(decoder);
@@ -204,12 +209,71 @@
return instructions;
}
-const DecodedThread &ThreadTraceDecoder::Decode() {
- if (!m_decoded_thread.hasValue()) {
- m_decoded_thread = DecodedThread(
- CreateDecoderAndDecode(*m_trace_thread->GetProcess(), m_pt_cpu,
- m_trace_thread->GetTraceFile()));
- }
+static Expected<std::vector<IntelPTInstruction>>
+DecodeTraceFile(Process &process, TraceIntelPT &trace_intel_pt,
+ const FileSpec &trace_file, size_t &raw_trace_size) {
+ ErrorOr<std::unique_ptr<MemoryBuffer>> trace_or_error =
+ MemoryBuffer::getFile(trace_file.GetPath());
+ if (std::error_code err = trace_or_error.getError())
+ return errorCodeToError(err);
+ MemoryBuffer &trace = **trace_or_error;
+ MutableArrayRef<uint8_t> trace_data(
+ // The libipt library does not modify the trace buffer, hence the
+ // following cast is safe.
+ reinterpret_cast<uint8_t *>(const_cast<char *>(trace.getBufferStart())),
+ trace.getBufferSize());
+ raw_trace_size = trace_data.size();
+ return DecodeInMemoryTrace(process, trace_intel_pt, trace_data);
+}
+
+static Expected<std::vector<IntelPTInstruction>>
+DecodeLiveThread(Thread &thread, TraceIntelPT &trace, size_t &raw_trace_size) {
+ Expected<std::vector<uint8_t>> buffer =
+ trace.GetLiveThreadBuffer(thread.GetID());
+ if (!buffer)
+ return buffer.takeError();
+ raw_trace_size = buffer->size();
+ if (Expected<pt_cpu> cpu_info = trace.GetCPUInfo())
+ return DecodeInMemoryTrace(*thread.GetProcess(), trace,
+ MutableArrayRef<uint8_t>(*buffer));
+ else
+ return cpu_info.takeError();
+}
+
+DecodedThreadSP ThreadDecoder::Decode() {
+ if (!m_decoded_thread.hasValue())
+ m_decoded_thread = DoDecode();
return *m_decoded_thread;
}
+
+PostMortemThreadDecoder::PostMortemThreadDecoder(
+ const lldb::ThreadPostMortemTraceSP &trace_thread, TraceIntelPT &trace)
+ : m_trace_thread(trace_thread), m_trace(trace) {}
+
+DecodedThreadSP PostMortemThreadDecoder::DoDecode() {
+ size_t raw_trace_size = 0;
+ if (Expected<std::vector<IntelPTInstruction>> instructions =
+ DecodeTraceFile(*m_trace_thread->GetProcess(), m_trace,
+ m_trace_thread->GetTraceFile(), raw_trace_size))
+ return std::make_shared<DecodedThread>(m_trace_thread->shared_from_this(),
+ std::move(*instructions),
+ raw_trace_size);
+ else
+ return std::make_shared<DecodedThread>(m_trace_thread->shared_from_this(),
+ instructions.takeError());
+}
+
+LiveThreadDecoder::LiveThreadDecoder(Thread &thread, TraceIntelPT &trace)
+ : m_thread_sp(thread.shared_from_this()), m_trace(trace) {}
+
+DecodedThreadSP LiveThreadDecoder::DoDecode() {
+ size_t raw_trace_size = 0;
+ if (Expected<std::vector<IntelPTInstruction>> instructions =
+ DecodeLiveThread(*m_thread_sp, m_trace, raw_trace_size))
+ return std::make_shared<DecodedThread>(
+ m_thread_sp, std::move(*instructions), raw_trace_size);
+ else
+ return std::make_shared<DecodedThread>(m_thread_sp,
+ instructions.takeError());
+}
diff --git a/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.h b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.h
index 2e67f9b..e969db5 100644
--- a/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.h
+++ b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.h
@@ -12,38 +12,73 @@
#include "intel-pt.h"
#include "DecodedThread.h"
+#include "forward-declarations.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/FileSpec.h"
namespace lldb_private {
namespace trace_intel_pt {
-/// \a lldb_private::ThreadTrace decoder that stores the output from decoding,
-/// avoiding recomputations, as decoding is expensive.
-class ThreadTraceDecoder {
+/// Base class that handles the decoding of a thread and caches the result.
+class ThreadDecoder {
+public:
+ virtual ~ThreadDecoder() = default;
+
+ ThreadDecoder() = default;
+
+ /// Decode the thread and store the result internally, to avoid
+ /// recomputations.
+ ///
+ /// \return
+ /// A \a DecodedThread instance.
+ DecodedThreadSP Decode();
+
+ ThreadDecoder(const ThreadDecoder &other) = delete;
+ ThreadDecoder &operator=(const ThreadDecoder &other) = delete;
+
+protected:
+ /// Decode the thread.
+ ///
+ /// \return
+ /// A \a DecodedThread instance.
+ virtual DecodedThreadSP DoDecode() = 0;
+
+ llvm::Optional<DecodedThreadSP> m_decoded_thread;
+};
+
+/// Decoder implementation for \a lldb_private::ThreadPostMortemTrace, which are
+/// non-live processes that come trace session files.
+class PostMortemThreadDecoder : public ThreadDecoder {
public:
/// \param[in] trace_thread
/// The thread whose trace file will be decoded.
///
- /// \param[in] pt_cpu
- /// The libipt cpu used when recording the trace.
- ThreadTraceDecoder(const std::shared_ptr<ThreadTrace> &trace_thread,
- const pt_cpu &pt_cpu)
- : m_trace_thread(trace_thread), m_pt_cpu(pt_cpu), m_decoded_thread() {}
-
- /// Decode the thread and store the result internally.
- ///
- /// \return
- /// A \a DecodedThread instance.
- const DecodedThread &Decode();
+ /// \param[in] trace
+ /// The main Trace object who owns this decoder and its data.
+ PostMortemThreadDecoder(const lldb::ThreadPostMortemTraceSP &trace_thread,
+ TraceIntelPT &trace);
private:
- ThreadTraceDecoder(const ThreadTraceDecoder &other) = delete;
- ThreadTraceDecoder &operator=(const ThreadTraceDecoder &other) = delete;
+ DecodedThreadSP DoDecode() override;
- std::shared_ptr<ThreadTrace> m_trace_thread;
- pt_cpu m_pt_cpu;
- llvm::Optional<DecodedThread> m_decoded_thread;
+ lldb::ThreadPostMortemTraceSP m_trace_thread;
+ TraceIntelPT &m_trace;
+};
+
+class LiveThreadDecoder : public ThreadDecoder {
+public:
+ /// \param[in] thread
+ /// The thread whose traces will be decoded.
+ ///
+ /// \param[in] trace
+ /// The main Trace object who owns this decoder and its data.
+ LiveThreadDecoder(Thread &thread, TraceIntelPT &trace);
+
+private:
+ DecodedThreadSP DoDecode() override;
+
+ lldb::ThreadSP m_thread_sp;
+ TraceIntelPT &m_trace;
};
} // namespace trace_intel_pt
diff --git a/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp
new file mode 100644
index 0000000..edefdd0
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp
@@ -0,0 +1,100 @@
+//===-- TraceCursorIntelPT.cpp --------------------------------------------===//
+//
+// 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 "TraceCursorIntelPT.h"
+#include "DecodedThread.h"
+#include "TraceIntelPT.h"
+
+#include <cstdlib>
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::trace_intel_pt;
+using namespace llvm;
+
+TraceCursorIntelPT::TraceCursorIntelPT(ThreadSP thread_sp,
+ DecodedThreadSP decoded_thread_sp)
+ : TraceCursor(thread_sp), m_decoded_thread_sp(decoded_thread_sp) {
+ assert(!m_decoded_thread_sp->GetInstructions().empty() &&
+ "a trace should have at least one instruction or error");
+ m_pos = m_decoded_thread_sp->GetInstructions().size() - 1;
+}
+
+size_t TraceCursorIntelPT::GetInternalInstructionSize() {
+ return m_decoded_thread_sp->GetInstructions().size();
+}
+
+bool TraceCursorIntelPT::Next() {
+ auto canMoveOne = [&]() {
+ if (IsForwards())
+ return m_pos + 1 < GetInternalInstructionSize();
+ return m_pos > 0;
+ };
+
+ size_t initial_pos = m_pos;
+
+ while (canMoveOne()) {
+ m_pos += IsForwards() ? 1 : -1;
+ if (!m_ignore_errors && IsError())
+ return true;
+ if (GetInstructionControlFlowType() & m_granularity)
+ return true;
+ }
+
+ // Didn't find any matching instructions
+ m_pos = initial_pos;
+ return false;
+}
+
+size_t TraceCursorIntelPT::Seek(int64_t offset, SeekType origin) {
+ int64_t last_index = GetInternalInstructionSize() - 1;
+
+ auto fitPosToBounds = [&](int64_t raw_pos) -> int64_t {
+ return std::min(std::max((int64_t)0, raw_pos), last_index);
+ };
+
+ switch (origin) {
+ case TraceCursor::SeekType::Set:
+ m_pos = fitPosToBounds(offset);
+ return m_pos;
+ case TraceCursor::SeekType::End:
+ m_pos = fitPosToBounds(offset + last_index);
+ return last_index - m_pos;
+ case TraceCursor::SeekType::Current:
+ int64_t new_pos = fitPosToBounds(offset + m_pos);
+ int64_t dist = m_pos - new_pos;
+ m_pos = new_pos;
+ return std::abs(dist);
+ }
+}
+
+bool TraceCursorIntelPT::IsError() {
+ return m_decoded_thread_sp->GetInstructions()[m_pos].IsError();
+}
+
+Error TraceCursorIntelPT::GetError() {
+ return m_decoded_thread_sp->GetInstructions()[m_pos].ToError();
+}
+
+lldb::addr_t TraceCursorIntelPT::GetLoadAddress() {
+ return m_decoded_thread_sp->GetInstructions()[m_pos].GetLoadAddress();
+}
+
+Optional<uint64_t> TraceCursorIntelPT::GetTimestampCounter() {
+ return m_decoded_thread_sp->GetInstructions()[m_pos].GetTimestampCounter();
+}
+
+TraceInstructionControlFlowType
+TraceCursorIntelPT::GetInstructionControlFlowType() {
+ lldb::addr_t next_load_address =
+ m_pos + 1 < GetInternalInstructionSize()
+ ? m_decoded_thread_sp->GetInstructions()[m_pos + 1].GetLoadAddress()
+ : LLDB_INVALID_ADDRESS;
+ return m_decoded_thread_sp->GetInstructions()[m_pos].GetControlFlowType(
+ next_load_address);
+}
diff --git a/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h
new file mode 100644
index 0000000..29d3792
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h
@@ -0,0 +1,50 @@
+//===-- TraceCursorIntelPT.h ------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACECURSORINTELPT_H
+#define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACECURSORINTELPT_H
+
+#include "IntelPTDecoder.h"
+#include "TraceIntelPTSessionFileParser.h"
+
+namespace lldb_private {
+namespace trace_intel_pt {
+
+class TraceCursorIntelPT : public TraceCursor {
+public:
+ TraceCursorIntelPT(lldb::ThreadSP thread_sp,
+ DecodedThreadSP decoded_thread_sp);
+
+ size_t Seek(int64_t offset, SeekType origin) override;
+
+ virtual bool Next() override;
+
+ llvm::Error GetError() override;
+
+ lldb::addr_t GetLoadAddress() override;
+
+ llvm::Optional<uint64_t> GetTimestampCounter() override;
+
+ lldb::TraceInstructionControlFlowType
+ GetInstructionControlFlowType() override;
+
+ bool IsError() override;
+
+private:
+ size_t GetInternalInstructionSize();
+
+ /// Storage of the actual instructions
+ DecodedThreadSP m_decoded_thread_sp;
+ /// Internal instruction index currently pointing at.
+ size_t m_pos;
+};
+
+} // namespace trace_intel_pt
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACECURSORINTELPT_H
diff --git a/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
index 63a8b2d..c12bcd3 100644
--- a/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
@@ -8,12 +8,14 @@
#include "TraceIntelPT.h"
+#include "../common/ThreadPostMortemTrace.h"
#include "CommandObjectTraceStartIntelPT.h"
+#include "DecodedThread.h"
+#include "TraceIntelPTConstants.h"
#include "TraceIntelPTSessionFileParser.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
-#include "lldb/Target/ThreadTrace.h"
using namespace lldb;
using namespace lldb_private;
@@ -22,18 +24,27 @@
LLDB_PLUGIN_DEFINE(TraceIntelPT)
-CommandObjectSP GetStartCommand(CommandInterpreter &interpreter) {
- return CommandObjectSP(new CommandObjectTraceStartIntelPT(interpreter));
+lldb::CommandObjectSP
+TraceIntelPT::GetProcessTraceStartCommand(CommandInterpreter &interpreter) {
+ return CommandObjectSP(
+ new CommandObjectProcessTraceStartIntelPT(*this, interpreter));
+}
+
+lldb::CommandObjectSP
+TraceIntelPT::GetThreadTraceStartCommand(CommandInterpreter &interpreter) {
+ return CommandObjectSP(
+ new CommandObjectThreadTraceStartIntelPT(*this, interpreter));
}
void TraceIntelPT::Initialize() {
- PluginManager::RegisterPlugin(
- GetPluginNameStatic(), "Intel Processor Trace", CreateInstance,
- TraceIntelPTSessionFileParser::GetSchema(), GetStartCommand);
+ PluginManager::RegisterPlugin(GetPluginNameStatic(), "Intel Processor Trace",
+ CreateInstanceForSessionFile,
+ CreateInstanceForLiveProcess,
+ TraceIntelPTSessionFileParser::GetSchema());
}
void TraceIntelPT::Terminate() {
- PluginManager::UnregisterPlugin(CreateInstance);
+ PluginManager::UnregisterPlugin(CreateInstanceForSessionFile);
}
ConstString TraceIntelPT::GetPluginNameStatic() {
@@ -55,60 +66,278 @@
void TraceIntelPT::Dump(Stream *s) const {}
-Expected<TraceSP>
-TraceIntelPT::CreateInstance(const json::Value &trace_session_file,
- StringRef session_file_dir, Debugger &debugger) {
+Expected<TraceSP> TraceIntelPT::CreateInstanceForSessionFile(
+ const json::Value &trace_session_file, StringRef session_file_dir,
+ Debugger &debugger) {
return TraceIntelPTSessionFileParser(debugger, trace_session_file,
session_file_dir)
.Parse();
}
+Expected<TraceSP> TraceIntelPT::CreateInstanceForLiveProcess(Process &process) {
+ TraceSP instance(new TraceIntelPT(process));
+ process.GetTarget().SetTrace(instance);
+ return instance;
+}
+
TraceIntelPT::TraceIntelPT(
- const pt_cpu &pt_cpu,
- const std::vector<std::shared_ptr<ThreadTrace>> &traced_threads)
- : m_pt_cpu(pt_cpu) {
- for (const std::shared_ptr<ThreadTrace> &thread : traced_threads)
- m_trace_threads.emplace(
- std::piecewise_construct,
- std::forward_as_tuple(thread->GetProcess()->GetID(), thread->GetID()),
- std::forward_as_tuple(thread, pt_cpu));
+ const pt_cpu &cpu_info,
+ const std::vector<ThreadPostMortemTraceSP> &traced_threads)
+ : m_cpu_info(cpu_info) {
+ for (const ThreadPostMortemTraceSP &thread : traced_threads)
+ m_thread_decoders.emplace(
+ thread.get(), std::make_unique<PostMortemThreadDecoder>(thread, *this));
}
-const DecodedThread *TraceIntelPT::Decode(const Thread &thread) {
- auto it = m_trace_threads.find(
- std::make_pair(thread.GetProcess()->GetID(), thread.GetID()));
- if (it == m_trace_threads.end())
- return nullptr;
- return &it->second.Decode();
+DecodedThreadSP TraceIntelPT::Decode(Thread &thread) {
+ RefreshLiveProcessState();
+ if (m_live_refresh_error.hasValue())
+ return std::make_shared<DecodedThread>(
+ thread.shared_from_this(),
+ createStringError(inconvertibleErrorCode(), *m_live_refresh_error));
+
+ auto it = m_thread_decoders.find(&thread);
+ if (it == m_thread_decoders.end())
+ return std::make_shared<DecodedThread>(
+ thread.shared_from_this(),
+ createStringError(inconvertibleErrorCode(), "thread not traced"));
+ return it->second->Decode();
}
-size_t TraceIntelPT::GetCursorPosition(const Thread &thread) {
- const DecodedThread *decoded_thread = Decode(thread);
- if (!decoded_thread)
- return 0;
- return decoded_thread->GetCursorPosition();
+lldb::TraceCursorUP TraceIntelPT::GetCursor(Thread &thread) {
+ return Decode(thread)->GetCursor();
}
-void TraceIntelPT::TraverseInstructions(
- const Thread &thread, size_t position, TraceDirection direction,
- std::function<bool(size_t index, Expected<lldb::addr_t> load_addr)>
- callback) {
- const DecodedThread *decoded_thread = Decode(thread);
- if (!decoded_thread)
+void TraceIntelPT::DumpTraceInfo(Thread &thread, Stream &s, bool verbose) {
+ Optional<size_t> raw_size = GetRawTraceSize(thread);
+ s.Printf("\nthread #%u: tid = %" PRIu64, thread.GetIndexID(), thread.GetID());
+ if (!raw_size) {
+ s.Printf(", not traced\n");
return;
-
- ArrayRef<IntelPTInstruction> instructions = decoded_thread->GetInstructions();
-
- ssize_t delta = direction == TraceDirection::Forwards ? 1 : -1;
- for (ssize_t i = position; i < (ssize_t)instructions.size() && i >= 0;
- i += delta)
- if (!callback(i, instructions[i].GetLoadAddress()))
- break;
+ }
+ s.Printf("\n Raw trace size: %zu bytes\n", *raw_size);
+ return;
}
-size_t TraceIntelPT::GetInstructionCount(const Thread &thread) {
- if (const DecodedThread *decoded_thread = Decode(thread))
- return decoded_thread->GetInstructions().size();
+Optional<size_t> TraceIntelPT::GetRawTraceSize(Thread &thread) {
+ if (IsTraced(thread))
+ return Decode(thread)->GetRawTraceSize();
else
- return 0;
+ return None;
+}
+
+Expected<pt_cpu> TraceIntelPT::GetCPUInfoForLiveProcess() {
+ Expected<std::vector<uint8_t>> cpu_info = GetLiveProcessBinaryData("cpuInfo");
+ if (!cpu_info)
+ return cpu_info.takeError();
+
+ int64_t cpu_family = -1;
+ int64_t model = -1;
+ int64_t stepping = -1;
+ std::string vendor_id;
+
+ StringRef rest(reinterpret_cast<const char *>(cpu_info->data()),
+ cpu_info->size());
+ while (!rest.empty()) {
+ StringRef line;
+ std::tie(line, rest) = rest.split('\n');
+
+ SmallVector<StringRef, 2> columns;
+ line.split(columns, StringRef(":"), -1, false);
+
+ if (columns.size() < 2)
+ continue; // continue searching
+
+ columns[1] = columns[1].trim(" ");
+ if (columns[0].contains("cpu family") &&
+ columns[1].getAsInteger(10, cpu_family))
+ continue;
+
+ else if (columns[0].contains("model") && columns[1].getAsInteger(10, model))
+ continue;
+
+ else if (columns[0].contains("stepping") &&
+ columns[1].getAsInteger(10, stepping))
+ continue;
+
+ else if (columns[0].contains("vendor_id")) {
+ vendor_id = columns[1].str();
+ if (!vendor_id.empty())
+ continue;
+ }
+
+ if ((cpu_family != -1) && (model != -1) && (stepping != -1) &&
+ (!vendor_id.empty())) {
+ return pt_cpu{vendor_id == "GenuineIntel" ? pcv_intel : pcv_unknown,
+ static_cast<uint16_t>(cpu_family),
+ static_cast<uint8_t>(model),
+ static_cast<uint8_t>(stepping)};
+ }
+ }
+ return createStringError(inconvertibleErrorCode(),
+ "Failed parsing the target's /proc/cpuinfo file");
+}
+
+Expected<pt_cpu> TraceIntelPT::GetCPUInfo() {
+ if (!m_cpu_info) {
+ if (llvm::Expected<pt_cpu> cpu_info = GetCPUInfoForLiveProcess())
+ m_cpu_info = *cpu_info;
+ else
+ return cpu_info.takeError();
+ }
+ return *m_cpu_info;
+}
+
+void TraceIntelPT::DoRefreshLiveProcessState(
+ Expected<TraceGetStateResponse> state) {
+ m_thread_decoders.clear();
+
+ if (!state) {
+ m_live_refresh_error = toString(state.takeError());
+ return;
+ }
+
+ for (const TraceThreadState &thread_state : state->tracedThreads) {
+ Thread &thread =
+ *m_live_process->GetThreadList().FindThreadByID(thread_state.tid);
+ m_thread_decoders.emplace(
+ &thread, std::make_unique<LiveThreadDecoder>(thread, *this));
+ }
+}
+
+bool TraceIntelPT::IsTraced(const Thread &thread) {
+ RefreshLiveProcessState();
+ return m_thread_decoders.count(&thread);
+}
+
+// The information here should match the description of the intel-pt section
+// of the jLLDBTraceStart packet in the lldb/docs/lldb-gdb-remote.txt
+// documentation file. Similarly, it should match the CLI help messages of the
+// TraceIntelPTOptions.td file.
+const char *TraceIntelPT::GetStartConfigurationHelp() {
+ return R"(Parameters:
+
+ Note: If a parameter is not specified, a default value will be used.
+
+ - int threadBufferSize (defaults to 4096 bytes):
+ [process and thread tracing]
+ Trace size in bytes per thread. It must be a power of 2 greater
+ than or equal to 4096 (2^12). The trace is circular keeping the
+ the most recent data.
+
+ - boolean enableTsc (default to false):
+ [process and thread tracing]
+ Whether to use enable TSC timestamps or not. This is supported on
+ all devices that support intel-pt.
+
+ - psbPeriod (defaults to null):
+ [process and thread tracing]
+ This value defines the period in which PSB packets will be generated.
+ A PSB packet is a synchronization packet that contains a TSC
+ timestamp and the current absolute instruction pointer.
+
+ This parameter can only be used if
+
+ /sys/bus/event_source/devices/intel_pt/caps/psb_cyc
+
+ is 1. Otherwise, the PSB period will be defined by the processor.
+
+ If supported, valid values for this period can be found in
+
+ /sys/bus/event_source/devices/intel_pt/caps/psb_periods
+
+ which contains a hexadecimal number, whose bits represent
+ valid values e.g. if bit 2 is set, then value 2 is valid.
+
+ The psb_period value is converted to the approximate number of
+ raw trace bytes between PSB packets as:
+
+ 2 ^ (value + 11)
+
+ e.g. value 3 means 16KiB between PSB packets. Defaults to 0 if
+ supported.
+
+ - int processBufferSizeLimit (defaults to 500 MB):
+ [process tracing only]
+ Maximum total trace size per process in bytes. This limit applies
+ to the sum of the sizes of all thread traces of this process,
+ excluding the ones created explicitly with "thread tracing".
+ Whenever a thread is attempted to be traced due to this command
+ and the limit would be reached, the process is stopped with a
+ "processor trace" reason, so that the user can retrace the process
+ if needed.)";
+}
+
+Error TraceIntelPT::Start(size_t thread_buffer_size,
+ size_t total_buffer_size_limit, bool enable_tsc,
+ Optional<size_t> psb_period) {
+ TraceIntelPTStartRequest request;
+ request.threadBufferSize = thread_buffer_size;
+ request.processBufferSizeLimit = total_buffer_size_limit;
+ request.enableTsc = enable_tsc;
+ request.psbPeriod = psb_period.map([](size_t val) { return (int64_t)val; });
+ request.type = GetPluginName().AsCString();
+ return Trace::Start(toJSON(request));
+}
+
+Error TraceIntelPT::Start(StructuredData::ObjectSP configuration) {
+ size_t thread_buffer_size = kDefaultThreadBufferSize;
+ size_t process_buffer_size_limit = kDefaultProcessBufferSizeLimit;
+ bool enable_tsc = kDefaultEnableTscValue;
+ Optional<size_t> psb_period = kDefaultPsbPeriod;
+
+ if (configuration) {
+ if (StructuredData::Dictionary *dict = configuration->GetAsDictionary()) {
+ dict->GetValueForKeyAsInteger("threadBufferSize", thread_buffer_size);
+ dict->GetValueForKeyAsInteger("processBufferSizeLimit",
+ process_buffer_size_limit);
+ dict->GetValueForKeyAsBoolean("enableTsc", enable_tsc);
+ dict->GetValueForKeyAsInteger("psbPeriod", psb_period);
+ } else {
+ return createStringError(inconvertibleErrorCode(),
+ "configuration object is not a dictionary");
+ }
+ }
+
+ return Start(thread_buffer_size, process_buffer_size_limit, enable_tsc,
+ psb_period);
+}
+
+llvm::Error TraceIntelPT::Start(llvm::ArrayRef<lldb::tid_t> tids,
+ size_t thread_buffer_size, bool enable_tsc,
+ Optional<size_t> psb_period) {
+ TraceIntelPTStartRequest request;
+ request.threadBufferSize = thread_buffer_size;
+ request.enableTsc = enable_tsc;
+ request.psbPeriod = psb_period.map([](size_t val) { return (int64_t)val; });
+ request.type = GetPluginName().AsCString();
+ request.tids.emplace();
+ for (lldb::tid_t tid : tids)
+ request.tids->push_back(tid);
+ return Trace::Start(toJSON(request));
+}
+
+Error TraceIntelPT::Start(llvm::ArrayRef<lldb::tid_t> tids,
+ StructuredData::ObjectSP configuration) {
+ size_t thread_buffer_size = kDefaultThreadBufferSize;
+ bool enable_tsc = kDefaultEnableTscValue;
+ Optional<size_t> psb_period = kDefaultPsbPeriod;
+
+ if (configuration) {
+ if (StructuredData::Dictionary *dict = configuration->GetAsDictionary()) {
+ dict->GetValueForKeyAsInteger("threadBufferSize", thread_buffer_size);
+ dict->GetValueForKeyAsBoolean("enableTsc", enable_tsc);
+ dict->GetValueForKeyAsInteger("psbPeriod", psb_period);
+ } else {
+ return createStringError(inconvertibleErrorCode(),
+ "configuration object is not a dictionary");
+ }
+ }
+
+ return Start(tids, thread_buffer_size, enable_tsc, psb_period);
+}
+
+Expected<std::vector<uint8_t>>
+TraceIntelPT::GetLiveThreadBuffer(lldb::tid_t tid) {
+ return Trace::GetLiveThreadBinaryData(tid, "threadTraceBuffer");
}
diff --git a/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
index 5058e6f..e3b2471 100644
--- a/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
+++ b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
@@ -45,49 +45,134 @@
/// \return
/// A trace instance or an error in case of failures.
static llvm::Expected<lldb::TraceSP>
- CreateInstance(const llvm::json::Value &trace_session_file,
- llvm::StringRef session_file_dir, Debugger &debugger);
+ CreateInstanceForSessionFile(const llvm::json::Value &trace_session_file,
+ llvm::StringRef session_file_dir,
+ Debugger &debugger);
+
+ static llvm::Expected<lldb::TraceSP>
+ CreateInstanceForLiveProcess(Process &process);
static ConstString GetPluginNameStatic();
uint32_t GetPluginVersion() override;
/// \}
+ lldb::CommandObjectSP
+ GetProcessTraceStartCommand(CommandInterpreter &interpreter) override;
+
+ lldb::CommandObjectSP
+ GetThreadTraceStartCommand(CommandInterpreter &interpreter) override;
+
llvm::StringRef GetSchema() override;
- void TraverseInstructions(
- const Thread &thread, size_t position, TraceDirection direction,
- std::function<bool(size_t index, llvm::Expected<lldb::addr_t> load_addr)>
- callback) override;
+ lldb::TraceCursorUP GetCursor(Thread &thread) override;
- size_t GetInstructionCount(const Thread &thread) override;
+ void DumpTraceInfo(Thread &thread, Stream &s, bool verbose) override;
- size_t GetCursorPosition(const Thread &thread) override;
+ llvm::Optional<size_t> GetRawTraceSize(Thread &thread);
+
+ void DoRefreshLiveProcessState(
+ llvm::Expected<TraceGetStateResponse> state) override;
+
+ bool IsTraced(const Thread &thread) override;
+
+ const char *GetStartConfigurationHelp() override;
+
+ /// Start tracing a live process.
+ ///
+ /// \param[in] thread_buffer_size
+ /// Trace size per thread in bytes.
+ ///
+ /// \param[in] total_buffer_size_limit
+ /// Maximum total trace size per process in bytes.
+ /// More information in TraceIntelPT::GetStartConfigurationHelp().
+ ///
+ /// \param[in] enable_tsc
+ /// Whether to use enable TSC timestamps or not.
+ /// More information in TraceIntelPT::GetStartConfigurationHelp().
+ ///
+ /// \param[in] psb_period
+ ///
+ /// This value defines the period in which PSB packets will be generated.
+ /// More information in TraceIntelPT::GetStartConfigurationHelp();
+ ///
+ /// \return
+ /// \a llvm::Error::success if the operation was successful, or
+ /// \a llvm::Error otherwise.
+ llvm::Error Start(size_t thread_buffer_size, size_t total_buffer_size_limit,
+ bool enable_tsc, llvm::Optional<size_t> psb_period);
+
+ /// \copydoc Trace::Start
+ llvm::Error Start(StructuredData::ObjectSP configuration =
+ StructuredData::ObjectSP()) override;
+
+ /// Start tracing live threads.
+ ///
+ /// \param[in] tids
+ /// Threads to trace.
+ ///
+ /// \param[in] thread_buffer_size
+ /// Trace size per thread in bytes.
+ ///
+ /// \param[in] enable_tsc
+ /// Whether to use enable TSC timestamps or not.
+ /// More information in TraceIntelPT::GetStartConfigurationHelp().
+ ///
+ /// \param[in] psb_period
+ ///
+ /// This value defines the period in which PSB packets will be generated.
+ /// More information in TraceIntelPT::GetStartConfigurationHelp().
+ ///
+ /// \return
+ /// \a llvm::Error::success if the operation was successful, or
+ /// \a llvm::Error otherwise.
+ llvm::Error Start(llvm::ArrayRef<lldb::tid_t> tids, size_t thread_buffer_size,
+ bool enable_tsc, llvm::Optional<size_t> psb_period);
+
+ /// \copydoc Trace::Start
+ llvm::Error Start(llvm::ArrayRef<lldb::tid_t> tids,
+ StructuredData::ObjectSP configuration =
+ StructuredData::ObjectSP()) override;
+
+ /// Get the thread buffer content for a live thread
+ llvm::Expected<std::vector<uint8_t>> GetLiveThreadBuffer(lldb::tid_t tid);
+
+ llvm::Expected<pt_cpu> GetCPUInfo();
private:
friend class TraceIntelPTSessionFileParser;
+ llvm::Expected<pt_cpu> GetCPUInfoForLiveProcess();
+
/// \param[in] trace_threads
/// ThreadTrace instances, which are not live-processes and whose trace
/// files are fixed.
- TraceIntelPT(const pt_cpu &pt_cpu,
- const std::vector<std::shared_ptr<ThreadTrace>> &traced_threads);
+ TraceIntelPT(
+ const pt_cpu &cpu_info,
+ const std::vector<lldb::ThreadPostMortemTraceSP> &traced_threads);
+
+ /// Constructor for live processes
+ TraceIntelPT(Process &live_process)
+ : Trace(live_process), m_thread_decoders(){};
/// Decode the trace of the given thread that, i.e. recontruct the traced
- /// instructions. That trace must be managed by this class.
+ /// instructions.
///
/// \param[in] thread
/// If \a thread is a \a ThreadTrace, then its internal trace file will be
/// decoded. Live threads are not currently supported.
///
/// \return
- /// A \a DecodedThread instance if decoding was successful, or a \b
- /// nullptr if the thread's trace is not managed by this class.
- const DecodedThread *Decode(const Thread &thread);
+ /// A \a DecodedThread shared pointer with the decoded instructions. Any
+ /// errors are embedded in the instruction list.
+ DecodedThreadSP Decode(Thread &thread);
- pt_cpu m_pt_cpu;
- std::map<std::pair<lldb::pid_t, lldb::tid_t>, ThreadTraceDecoder>
- m_trace_threads;
+ /// It is provided by either a session file or a live process' "cpuInfo"
+ /// binary data.
+ llvm::Optional<pt_cpu> m_cpu_info;
+ std::map<const Thread *, std::unique_ptr<ThreadDecoder>> m_thread_decoders;
+ /// Error gotten after a failed live process update, if any.
+ llvm::Optional<std::string> m_live_refresh_error;
};
} // namespace trace_intel_pt
diff --git a/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTConstants.h b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTConstants.h
new file mode 100644
index 0000000..c2bc1b5
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTConstants.h
@@ -0,0 +1,27 @@
+//===-- TraceIntelPTConstants.h ---------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_CONSTANTS_H
+#define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_CONSTANTS_H
+
+#include <cstddef>
+
+#include <llvm/ADT/Optional.h>
+
+namespace lldb_private {
+namespace trace_intel_pt {
+
+const size_t kDefaultThreadBufferSize = 4 * 1024; // 4KB
+const size_t kDefaultProcessBufferSizeLimit = 5 * 1024 * 1024; // 500MB
+const bool kDefaultEnableTscValue = false;
+const llvm::Optional<size_t> kDefaultPsbPeriod = llvm::None;
+
+} // namespace trace_intel_pt
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_CONSTANTS_H
diff --git a/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td
index 6ffe949..9e8cab1 100644
--- a/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td
+++ b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td
@@ -1,16 +1,74 @@
include "../../../../source/Commands/OptionsBase.td"
+// The information of the start commands here should match the description of
+// the intel-pt section of the jLLDBTraceStart packet in the
+// lldb/docs/lldb-gdb-remote.txt documentation file. Similarly, it should match
+// the API help message of TraceIntelPT::GetStartConfigurationHelp().
+
let Command = "thread trace start intel pt" in {
def thread_trace_start_intel_pt_size: Option<"size", "s">,
Group<1>,
Arg<"Value">,
- Desc<"The size of the trace in KB. The kernel rounds it down to the nearest"
- " multiple of 4. Defaults to 4.">;
- def thread_trace_start_intel_pt_custom_config: Option<"custom-config", "c">,
+ Desc<"Trace size in bytes per thread. It must be a power of 2 greater "
+ "than or equal to 4096 (2^12). The trace is circular keeping "
+ "the most recent data. Defaults to 4096 bytes.">;
+ def thread_trace_start_intel_pt_tsc: Option<"tsc", "t">,
+ Group<1>,
+ Desc<"Enable the use of TSC timestamps. This is supported on all devices "
+ "that support intel-pt.">;
+ def thread_trace_start_intel_pt_psb_period: Option<"psb-period", "p">,
Group<1>,
Arg<"Value">,
- Desc<"Low level bitmask configuration for the kernel based on the values "
- "in `grep -H /sys/bus/event_source/devices/intel_pt/format/*`. "
- "See https://github.com/torvalds/linux/blob/master/tools/perf/Documentation/perf-intel-pt.txt"
- " for more information. Defaults to 0.">;
+ Desc<"This value defines the period in which PSB packets will be "
+ "generated. A PSB packet is a synchronization packet that contains a "
+ "TSC timestamp and the current absolute instruction pointer. "
+ "This parameter can only be used if "
+ "/sys/bus/event_source/devices/intel_pt/caps/psb_cyc is 1. Otherwise, "
+ "the PSB period will be defined by the processor. If supported, valid "
+ "values for this period can be found in "
+ "/sys/bus/event_source/devices/intel_pt/caps/psb_periods which "
+ "contains a hexadecimal number, whose bits represent valid values "
+ "e.g. if bit 2 is set, then value 2 is valid. The psb_period value is "
+ "converted to the approximate number of raw trace bytes between PSB "
+ "packets as: 2 ^ (value + 11), e.g. value 3 means 16KiB between PSB "
+ "packets. Defaults to 0 if supported.">;
+}
+
+let Command = "process trace start intel pt" in {
+ def process_trace_start_intel_pt_thread_size: Option<"thread-size", "s">,
+ Group<1>,
+ Arg<"Value">,
+ Desc<"Trace size in bytes per thread. It must be a power of 2 greater "
+ "than or equal to 4096 (2^12). The trace is circular keeping "
+ "the most recent data. Defaults to 4096 bytes.">;
+ def process_trace_start_intel_pt_process_size_limit: Option<"total-size-limit", "l">,
+ Group<1>,
+ Arg<"Value">,
+ Desc<"Maximum total trace size per process in bytes. This limit applies to "
+ "the sum of the sizes of all thread traces of this process, excluding "
+ "the ones created with the \"thread trace start\" command. "
+ "Whenever a thread is attempted to be traced due to this command and "
+ "the limit would be reached, the process is stopped with a "
+ "\"processor trace\" reason, so that the user can retrace the process "
+ "if needed. Defaults to 500MB.">;
+ def process_trace_start_intel_pt_tsc: Option<"tsc", "t">,
+ Group<1>,
+ Desc<"Enable the use of TSC timestamps. This is supported on all devices "
+ "that support intel-pt.">;
+ def process_trace_start_intel_pt_psb_period: Option<"psb-period", "p">,
+ Group<1>,
+ Arg<"Value">,
+ Desc<"This value defines the period in which PSB packets will be "
+ "generated. A PSB packet is a synchronization packet that contains a "
+ "TSC timestamp and the current absolute instruction pointer. "
+ "This parameter can only be used if "
+ "/sys/bus/event_source/devices/intel_pt/caps/psb_cyc is 1. Otherwise, "
+ "the PSB period will be defined by the processor. If supported, valid "
+ "values for this period can be found in "
+ "/sys/bus/event_source/devices/intel_pt/caps/psb_periods which "
+ "contains a hexadecimal number, whose bits represent valid values "
+ "e.g. if bit 2 is set, then value 2 is valid. The psb_period value is "
+ "converted to the approximate number of raw trace bytes between PSB "
+ "packets as: 2 ^ (value + 11), e.g. value 3 means 16KiB between PSB "
+ "packets. Defaults to 0 if supported.">;
}
diff --git a/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp
index beef5c3..5af7c26 100644
--- a/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp
+++ b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp
@@ -8,11 +8,11 @@
#include "TraceIntelPTSessionFileParser.h"
+#include "../common/ThreadPostMortemTrace.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadList.h"
-#include "lldb/Target/ThreadTrace.h"
using namespace lldb;
using namespace lldb_private;
@@ -24,7 +24,7 @@
if (schema.empty()) {
schema = TraceSessionFileParser::BuildSchema(R"({
"type": "intel-pt",
- "pt_cpu": {
+ "cpuInfo": {
"vendor": "intel" | "unknown",
"family": integer,
"model": integer,
@@ -35,21 +35,22 @@
return schema;
}
-pt_cpu TraceIntelPTSessionFileParser::ParsePTCPU(const JSONPTCPU &pt_cpu) {
- return {pt_cpu.vendor.compare("intel") == 0 ? pcv_intel : pcv_unknown,
- static_cast<uint16_t>(pt_cpu.family),
- static_cast<uint8_t>(pt_cpu.model),
- static_cast<uint8_t>(pt_cpu.stepping)};
+pt_cpu TraceIntelPTSessionFileParser::ParsePTCPU(
+ const JSONTraceIntelPTCPUInfo &cpu_info) {
+ return {cpu_info.vendor.compare("intel") == 0 ? pcv_intel : pcv_unknown,
+ static_cast<uint16_t>(cpu_info.family),
+ static_cast<uint8_t>(cpu_info.model),
+ static_cast<uint8_t>(cpu_info.stepping)};
}
TraceSP TraceIntelPTSessionFileParser::CreateTraceIntelPTInstance(
- const pt_cpu &pt_cpu, std::vector<ParsedProcess> &parsed_processes) {
- std::vector<ThreadTraceSP> threads;
+ const pt_cpu &cpu_info, std::vector<ParsedProcess> &parsed_processes) {
+ std::vector<ThreadPostMortemTraceSP> threads;
for (const ParsedProcess &parsed_process : parsed_processes)
threads.insert(threads.end(), parsed_process.threads.begin(),
parsed_process.threads.end());
- TraceSP trace_instance(new TraceIntelPT(pt_cpu, threads));
+ TraceSP trace_instance(new TraceIntelPT(cpu_info, threads));
for (const ParsedProcess &parsed_process : parsed_processes)
parsed_process.target_sp->SetTrace(trace_instance);
@@ -64,7 +65,7 @@
if (Expected<std::vector<ParsedProcess>> parsed_processes =
ParseCommonSessionFile(session))
- return CreateTraceIntelPTInstance(ParsePTCPU(session.trace.pt_cpu),
+ return CreateTraceIntelPTInstance(ParsePTCPU(session.trace.cpuInfo),
*parsed_processes);
else
return parsed_processes.takeError();
@@ -73,25 +74,34 @@
namespace llvm {
namespace json {
-bool fromJSON(const Value &value,
- TraceIntelPTSessionFileParser::JSONPTCPU &pt_cpu, Path path) {
- ObjectMapper o(value, path);
- return o && o.map("vendor", pt_cpu.vendor) &&
- o.map("family", pt_cpu.family) && o.map("model", pt_cpu.model) &&
- o.map("stepping", pt_cpu.stepping);
-}
-
bool fromJSON(
const Value &value,
TraceIntelPTSessionFileParser::JSONTraceIntelPTSettings &plugin_settings,
Path path) {
ObjectMapper o(value, path);
- return o && o.map("pt_cpu", plugin_settings.pt_cpu) &&
+ return o && o.map("cpuInfo", plugin_settings.cpuInfo) &&
fromJSON(
value,
(TraceSessionFileParser::JSONTracePluginSettings &)plugin_settings,
path);
}
+bool fromJSON(const json::Value &value,
+ TraceIntelPTSessionFileParser::JSONTraceIntelPTCPUInfo &cpu_info,
+ Path path) {
+ ObjectMapper o(value, path);
+ return o && o.map("vendor", cpu_info.vendor) &&
+ o.map("family", cpu_info.family) && o.map("model", cpu_info.model) &&
+ o.map("stepping", cpu_info.stepping);
+}
+
+Value toJSON(
+ const TraceIntelPTSessionFileParser::JSONTraceIntelPTCPUInfo &cpu_info) {
+ return Value(Object{{"family", cpu_info.family},
+ {"model", cpu_info.model},
+ {"stepping", cpu_info.stepping},
+ {"vendor", cpu_info.vendor}});
+}
+
} // namespace json
} // namespace llvm
diff --git a/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.h b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.h
index 6a896de..b2667a8 100644
--- a/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.h
+++ b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.h
@@ -10,7 +10,8 @@
#define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPTSESSIONFILEPARSER_H
#include "TraceIntelPT.h"
-#include "lldb/Target/TraceSessionFileParser.h"
+
+#include "../common/TraceSessionFileParser.h"
namespace lldb_private {
namespace trace_intel_pt {
@@ -19,16 +20,16 @@
class TraceIntelPTSessionFileParser : public TraceSessionFileParser {
public:
- struct JSONPTCPU {
- std::string vendor;
+ struct JSONTraceIntelPTCPUInfo {
int64_t family;
int64_t model;
int64_t stepping;
+ std::string vendor;
};
struct JSONTraceIntelPTSettings
: TraceSessionFileParser::JSONTracePluginSettings {
- JSONPTCPU pt_cpu;
+ JSONTraceIntelPTCPUInfo cpuInfo;
};
/// See \a TraceSessionFileParser::TraceSessionFileParser for the description
@@ -52,11 +53,11 @@
llvm::Expected<lldb::TraceSP> Parse();
lldb::TraceSP
- CreateTraceIntelPTInstance(const pt_cpu &pt_cpu,
+ CreateTraceIntelPTInstance(const pt_cpu &cpu_info,
std::vector<ParsedProcess> &parsed_processes);
private:
- pt_cpu ParsePTCPU(const JSONPTCPU &pt_cpu);
+ static pt_cpu ParsePTCPU(const JSONTraceIntelPTCPUInfo &cpu_info);
const llvm::json::Value &m_trace_session_file;
};
@@ -67,17 +68,20 @@
namespace llvm {
namespace json {
-bool fromJSON(
- const Value &value,
- lldb_private::trace_intel_pt::TraceIntelPTSessionFileParser::JSONPTCPU
- &pt_cpu,
- Path path);
-
bool fromJSON(const Value &value,
lldb_private::trace_intel_pt::TraceIntelPTSessionFileParser::
JSONTraceIntelPTSettings &plugin_settings,
Path path);
+bool fromJSON(const llvm::json::Value &value,
+ lldb_private::trace_intel_pt::TraceIntelPTSessionFileParser::
+ JSONTraceIntelPTCPUInfo &packet,
+ llvm::json::Path path);
+
+llvm::json::Value
+toJSON(const lldb_private::trace_intel_pt::TraceIntelPTSessionFileParser::
+ JSONTraceIntelPTCPUInfo &packet);
+
} // namespace json
} // namespace llvm
diff --git a/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/forward-declarations.h b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/forward-declarations.h
new file mode 100644
index 0000000..3c5f811
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/Trace/intel-pt/forward-declarations.h
@@ -0,0 +1,20 @@
+//===-- forward-declarations.h ----------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_FORWARD_DECLARATIONS_H
+#define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_FORWARD_DECLARATIONS_H
+
+namespace lldb_private {
+namespace trace_intel_pt {
+
+class TraceIntelPT;
+class ThreadDecoder;
+
+} // namespace trace_intel_pt
+} // namespace lldb_private
+#endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_FORWARD_DECLARATIONS_H
diff --git a/src/llvm-project/lldb/source/Plugins/TraceExporter/CMakeLists.txt b/src/llvm-project/lldb/source/Plugins/TraceExporter/CMakeLists.txt
new file mode 100644
index 0000000..7c40191
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/TraceExporter/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(ctf)
diff --git a/src/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CMakeLists.txt b/src/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CMakeLists.txt
new file mode 100644
index 0000000..766cc18
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CMakeLists.txt
@@ -0,0 +1,17 @@
+lldb_tablegen(TraceExporterCTFCommandOptions.inc -gen-lldb-option-defs
+ SOURCE TraceExporterCTFOptions.td
+ TARGET TraceExporterCTFOptionsGen)
+
+add_lldb_library(lldbPluginTraceExporterCTF PLUGIN
+CommandObjectThreadTraceExportCTF.cpp
+ TraceExporterCTF.cpp
+
+ LINK_LIBS
+ lldbCore
+ lldbSymbol
+ lldbTarget
+ LINK_COMPONENTS
+ Support
+ )
+
+add_dependencies(lldbPluginTraceExporterCTF TraceExporterCTFOptionsGen)
diff --git a/src/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.cpp b/src/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.cpp
new file mode 100644
index 0000000..3dd4c89
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.cpp
@@ -0,0 +1,66 @@
+//===-- CommandObjectThreadTraceExportCTF.cpp -----------------------------===//
+//
+// 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 "CommandObjectThreadTraceExportCTF.h"
+
+#include "lldb/Host/OptionParser.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::ctf;
+using namespace llvm;
+
+// CommandObjectThreadTraceExportCTF
+
+#define LLDB_OPTIONS_thread_trace_export_ctf
+#include "TraceExporterCTFCommandOptions.inc"
+
+Status CommandObjectThreadTraceExportCTF::CommandOptions::SetOptionValue(
+ uint32_t option_idx, llvm::StringRef option_arg,
+ ExecutionContext *execution_context) {
+ Status error;
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option) {
+ case 't': {
+ int64_t thread_index;
+ if (option_arg.empty() || option_arg.getAsInteger(0, thread_index) ||
+ thread_index < 0)
+ error.SetErrorStringWithFormat("invalid integer value for option '%s'",
+ option_arg.str().c_str());
+ else
+ m_thread_index = thread_index;
+ break;
+ }
+ default:
+ llvm_unreachable("Unimplemented option");
+ }
+ return error;
+}
+
+void CommandObjectThreadTraceExportCTF::CommandOptions::OptionParsingStarting(
+ ExecutionContext *execution_context) {
+ m_thread_index = None;
+}
+
+llvm::ArrayRef<OptionDefinition>
+CommandObjectThreadTraceExportCTF::CommandOptions::GetDefinitions() {
+ return llvm::makeArrayRef(g_thread_trace_export_ctf_options);
+}
+
+bool CommandObjectThreadTraceExportCTF::DoExecute(Args &command,
+ CommandReturnObject &result) {
+ Stream &s = result.GetOutputStream();
+ // TODO: create an actual instance of the exporter and invoke it
+ if (m_options.m_thread_index)
+ s.Printf("got thread index %d\n", (int)m_options.m_thread_index.getValue());
+ else
+ s.Printf("didn't get a thread index\n");
+
+ return result.Succeeded();
+}
diff --git a/src/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.h b/src/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.h
new file mode 100644
index 0000000..26b068a
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.h
@@ -0,0 +1,56 @@
+//===-- CommandObjectThreadTraceExportCTF.h -------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_COMMANDOBJECTTHREADTRACEEXPORTCTF_H
+#define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_COMMANDOBJECTTHREADTRACEEXPORTCTF_H
+
+#include "TraceExporterCTF.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+namespace lldb_private {
+namespace ctf {
+
+class CommandObjectThreadTraceExportCTF : public CommandObjectParsed {
+public:
+ class CommandOptions : public Options {
+ public:
+ CommandOptions() : Options() { OptionParsingStarting(nullptr); }
+
+ Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
+ ExecutionContext *execution_context) override;
+
+ void OptionParsingStarting(ExecutionContext *execution_context) override;
+
+ llvm::ArrayRef<OptionDefinition> GetDefinitions() override;
+
+ llvm::Optional<size_t> m_thread_index;
+ };
+
+ CommandObjectThreadTraceExportCTF(CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "thread trace export ctf",
+ "Export a given thread's trace to Chrome Trace Format",
+ "thread trace export ctf [<ctf-options>]",
+ lldb::eCommandRequiresProcess | lldb::eCommandTryTargetAPILock |
+ lldb::eCommandProcessMustBeLaunched |
+ lldb::eCommandProcessMustBePaused),
+ m_options() {}
+
+ Options *GetOptions() override { return &m_options; }
+
+protected:
+ bool DoExecute(Args &command, CommandReturnObject &result) override;
+
+ CommandOptions m_options;
+};
+
+} // namespace ctf
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_COMMANDOBJECTTHREADTRACEEXPORTCTF_H
diff --git a/src/llvm-project/lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTF.cpp b/src/llvm-project/lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTF.cpp
new file mode 100644
index 0000000..08bc03d
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTF.cpp
@@ -0,0 +1,53 @@
+//===-- TraceExporterCTF.cpp ----------------------------------------------===//
+//
+// 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 "TraceExporterCTF.h"
+
+#include <memory>
+
+#include "CommandObjectThreadTraceExportCTF.h"
+#include "lldb/Core/PluginManager.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::ctf;
+using namespace llvm;
+
+LLDB_PLUGIN_DEFINE(TraceExporterCTF)
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+
+static CommandObjectSP
+GetThreadTraceExportCommand(CommandInterpreter &interpreter) {
+ return std::make_shared<CommandObjectThreadTraceExportCTF>(interpreter);
+}
+
+void TraceExporterCTF::Initialize() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ "Chrome Trace Format Exporter", CreateInstance,
+ GetThreadTraceExportCommand);
+}
+
+void TraceExporterCTF::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+ConstString TraceExporterCTF::GetPluginNameStatic() {
+ static ConstString g_name("ctf");
+ return g_name;
+}
+
+ConstString TraceExporterCTF::GetPluginName() { return GetPluginNameStatic(); }
+
+uint32_t TraceExporterCTF::GetPluginVersion() { return 1; }
+
+Expected<TraceExporterUP> TraceExporterCTF::CreateInstance() {
+ return std::make_unique<TraceExporterCTF>();
+}
diff --git a/src/llvm-project/lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTF.h b/src/llvm-project/lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTF.h
new file mode 100644
index 0000000..8f9e354
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTF.h
@@ -0,0 +1,42 @@
+//===-- TraceExporterCTF.h --------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_TRACE_EXPORTER_CTF_H
+#define LLDB_SOURCE_PLUGINS_TRACE_EXPORTER_CTF_H
+
+#include "lldb/Target/TraceExporter.h"
+
+namespace lldb_private {
+namespace ctf {
+
+/// Trace Exporter Plugin that can produce traces in Chrome Trace Format.
+/// Still in development.
+class TraceExporterCTF : public TraceExporter {
+public:
+ ~TraceExporterCTF() override = default;
+
+ /// PluginInterface protocol
+ /// \{
+ static llvm::Expected<lldb::TraceExporterUP> CreateInstance();
+
+ ConstString GetPluginName() override;
+
+ static void Initialize();
+
+ static void Terminate();
+
+ static ConstString GetPluginNameStatic();
+
+ uint32_t GetPluginVersion() override;
+ /// \}
+};
+
+} // namespace ctf
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_TRACE_EXPORTER_CTF_H
diff --git a/src/llvm-project/lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTFOptions.td b/src/llvm-project/lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTFOptions.td
new file mode 100644
index 0000000..ce751f1
--- /dev/null
+++ b/src/llvm-project/lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTFOptions.td
@@ -0,0 +1,9 @@
+include "../../../../source/Commands/OptionsBase.td"
+
+let Command = "thread trace export ctf" in {
+ def thread_trace_export_ctf: Option<"tid", "t">,
+ Group<1>,
+ Arg<"ThreadIndex">,
+ Desc<"Export the trace for the specified thread index. Otherwise, the "
+ "currently selected thread will be used.">;
+}
diff --git a/src/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/src/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index c15b15e..7150fdc 100644
--- a/src/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/src/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -75,7 +75,7 @@
#include "Plugins/SymbolFile/DWARF/DWARFASTParserClang.h"
#include "Plugins/SymbolFile/PDB/PDBASTParser.h"
-#include <stdio.h>
+#include <cstdio>
#include <mutex>
@@ -163,7 +163,6 @@
if (name.getNameKind() == clang::DeclarationName::CXXDestructorName)
if (auto *baseDtorDecl = base_record->getDestructor()) {
if (baseDtorDecl->isVirtual()) {
- path.Decls = baseDtorDecl;
decls.push_back(baseDtorDecl);
return true;
} else
@@ -171,12 +170,11 @@
}
// Otherwise, search for name in the base class.
- for (path.Decls = base_record->lookup(name); !path.Decls.empty();
- path.Decls = path.Decls.slice(1)) {
+ for (path.Decls = base_record->lookup(name).begin();
+ path.Decls != path.Decls.end(); ++path.Decls) {
if (auto *method_decl =
- llvm::dyn_cast<clang::CXXMethodDecl>(path.Decls.front()))
+ llvm::dyn_cast<clang::CXXMethodDecl>(*path.Decls))
if (method_decl->isVirtual() && !isOverload(decl, method_decl)) {
- path.Decls = method_decl;
decls.push_back(method_decl);
return true;
}
@@ -479,6 +477,9 @@
case clang::Language::OpenCL:
LangStd = LangStandard::lang_opencl10;
break;
+ case clang::Language::OpenCLCXX:
+ LangStd = LangStandard::lang_openclcpp;
+ break;
case clang::Language::CUDA:
LangStd = LangStandard::lang_cuda;
break;
@@ -686,8 +687,8 @@
void TypeSystemClang::SetExternalSource(
llvm::IntrusiveRefCntPtr<ExternalASTSource> &ast_source_up) {
ASTContext &ast = getASTContext();
- ast.setExternalSource(ast_source_up);
ast.getTranslationUnitDecl()->setHasExternalLexicalStorage(true);
+ ast.setExternalSource(ast_source_up);
}
ASTContext &TypeSystemClang::getASTContext() {
@@ -745,7 +746,7 @@
*m_diagnostics_engine_up, *m_file_manager_up);
m_ast_up = std::make_unique<ASTContext>(
*m_language_options_up, *m_source_manager_up, *m_identifier_table_up,
- *m_selector_table_up, *m_builtins_up);
+ *m_selector_table_up, *m_builtins_up, TU_Complete);
m_diagnostic_consumer_up = std::make_unique<NullDiagnosticConsumer>();
m_ast_up->getDiagnostics().setClient(m_diagnostic_consumer_up.get(), false);
@@ -1356,9 +1357,11 @@
}
namespace {
- bool IsValueParam(const clang::TemplateArgument &argument) {
- return argument.getKind() == TemplateArgument::Integral;
- }
+/// Returns true iff the given TemplateArgument should be represented as an
+/// NonTypeTemplateParmDecl in the AST.
+bool IsValueParam(const clang::TemplateArgument &argument) {
+ return argument.getKind() == TemplateArgument::Integral;
+}
}
static TemplateParameterList *CreateTemplateParameterList(
@@ -1462,6 +1465,99 @@
template_args_ptr, nullptr);
}
+/// Returns true if the given template parameter can represent the given value.
+/// For example, `typename T` can represent `int` but not integral values such
+/// as `int I = 3`.
+static bool TemplateParameterAllowsValue(NamedDecl *param,
+ const TemplateArgument &value) {
+ if (auto *type_param = llvm::dyn_cast<TemplateTypeParmDecl>(param)) {
+ // Compare the argument kind, i.e. ensure that <typename> != <int>.
+ if (value.getKind() != TemplateArgument::Type)
+ return false;
+ } else if (auto *type_param =
+ llvm::dyn_cast<NonTypeTemplateParmDecl>(param)) {
+ // Compare the argument kind, i.e. ensure that <typename> != <int>.
+ if (!IsValueParam(value))
+ return false;
+ // Compare the integral type, i.e. ensure that <int> != <char>.
+ if (type_param->getType() != value.getIntegralType())
+ return false;
+ } else {
+ // There is no way to create other parameter decls at the moment, so we
+ // can't reach this case during normal LLDB usage. Log that this happened
+ // and assert.
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
+ LLDB_LOG(log,
+ "Don't know how to compare template parameter to passed"
+ " value. Decl kind of parameter is: {0}",
+ param->getDeclKindName());
+ lldbassert(false && "Can't compare this TemplateParmDecl subclass");
+ // In release builds just fall back to marking the parameter as not
+ // accepting the value so that we don't try to fit an instantiation to a
+ // template that doesn't fit. E.g., avoid that `S<1>` is being connected to
+ // `template<typename T> struct S;`.
+ return false;
+ }
+ return true;
+}
+
+/// Returns true if the given class template declaration could produce an
+/// instantiation with the specified values.
+/// For example, `<typename T>` allows the arguments `float`, but not for
+/// example `bool, float` or `3` (as an integer parameter value).
+static bool ClassTemplateAllowsToInstantiationArgs(
+ ClassTemplateDecl *class_template_decl,
+ const TypeSystemClang::TemplateParameterInfos &instantiation_values) {
+
+ TemplateParameterList ¶ms = *class_template_decl->getTemplateParameters();
+
+ // Save some work by iterating only once over the found parameters and
+ // calculate the information related to parameter packs.
+
+ // Contains the first pack parameter (or non if there are none).
+ llvm::Optional<NamedDecl *> pack_parameter;
+ // Contains the number of non-pack parameters.
+ size_t non_pack_params = params.size();
+ for (size_t i = 0; i < params.size(); ++i) {
+ NamedDecl *param = params.getParam(i);
+ if (param->isParameterPack()) {
+ pack_parameter = param;
+ non_pack_params = i;
+ break;
+ }
+ }
+
+ // The found template needs to have compatible non-pack template arguments.
+ // E.g., ensure that <typename, typename> != <typename>.
+ // The pack parameters are compared later.
+ if (non_pack_params != instantiation_values.args.size())
+ return false;
+
+ // Ensure that <typename...> != <typename>.
+ if (pack_parameter.hasValue() != instantiation_values.hasParameterPack())
+ return false;
+
+ // Compare the first pack parameter that was found with the first pack
+ // parameter value. The special case of having an empty parameter pack value
+ // always fits to a pack parameter.
+ // E.g., ensure that <int...> != <typename...>.
+ if (pack_parameter && !instantiation_values.packed_args->args.empty() &&
+ !TemplateParameterAllowsValue(
+ *pack_parameter, instantiation_values.packed_args->args.front()))
+ return false;
+
+ // Compare all the non-pack parameters now.
+ // E.g., ensure that <int> != <long>.
+ for (const auto pair : llvm::zip_first(instantiation_values.args, params)) {
+ const TemplateArgument &passed_arg = std::get<0>(pair);
+ NamedDecl *found_param = std::get<1>(pair);
+ if (!TemplateParameterAllowsValue(found_param, passed_arg))
+ return false;
+ }
+
+ return class_template_decl;
+}
+
ClassTemplateDecl *TypeSystemClang::CreateClassTemplateDecl(
DeclContext *decl_ctx, OptionalClangModuleID owning_module,
lldb::AccessType access_type, const char *class_name, int kind,
@@ -1475,12 +1571,22 @@
IdentifierInfo &identifier_info = ast.Idents.get(class_name);
DeclarationName decl_name(&identifier_info);
+ // Search the AST for an existing ClassTemplateDecl that could be reused.
clang::DeclContext::lookup_result result = decl_ctx->lookup(decl_name);
-
for (NamedDecl *decl : result) {
class_template_decl = dyn_cast<clang::ClassTemplateDecl>(decl);
- if (class_template_decl)
- return class_template_decl;
+ if (!class_template_decl)
+ continue;
+ // The class template has to be able to represents the instantiation
+ // values we received. Without this we might end up putting an instantiation
+ // with arguments such as <int, int> to a template such as:
+ // template<typename T> struct S;
+ // Connecting the instantiation to an incompatible template could cause
+ // problems later on.
+ if (!ClassTemplateAllowsToInstantiationArgs(class_template_decl,
+ template_param_infos))
+ continue;
+ return class_template_decl;
}
llvm::SmallVector<NamedDecl *, 8> template_param_decls;
@@ -1866,8 +1972,8 @@
clang::NestedNameSpecifierLoc(), clang::DeclarationNameInfo(), false);
SetOwningModule(using_decl, owning_module);
clang::UsingShadowDecl *shadow_decl = clang::UsingShadowDecl::Create(
- getASTContext(), current_decl_ctx, clang::SourceLocation(), using_decl,
- target);
+ getASTContext(), current_decl_ctx, clang::SourceLocation(),
+ target->getDeclName(), using_decl, target);
SetOwningModule(shadow_decl, owning_module);
using_decl->addShadowDecl(shadow_decl);
current_decl_ctx->addDecl(using_decl);
@@ -2114,11 +2220,10 @@
return decl;
}
-void TypeSystemClang::SetFunctionParameters(FunctionDecl *function_decl,
- ParmVarDecl **params,
- unsigned num_params) {
+void TypeSystemClang::SetFunctionParameters(
+ FunctionDecl *function_decl, llvm::ArrayRef<ParmVarDecl *> params) {
if (function_decl)
- function_decl->setParams(ArrayRef<ParmVarDecl *>(params, num_params));
+ function_decl->setParams(params);
}
CompilerType
@@ -2470,42 +2575,6 @@
return nullptr;
}
-bool TypeSystemClang::SetTagTypeKind(clang::QualType tag_qual_type,
- int kind) const {
- const clang::Type *clang_type = tag_qual_type.getTypePtr();
- if (clang_type) {
- const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(clang_type);
- if (tag_type) {
- clang::TagDecl *tag_decl =
- llvm::dyn_cast<clang::TagDecl>(tag_type->getDecl());
- if (tag_decl) {
- tag_decl->setTagKind((clang::TagDecl::TagKind)kind);
- return true;
- }
- }
- }
- return false;
-}
-
-bool TypeSystemClang::SetDefaultAccessForRecordFields(
- clang::RecordDecl *record_decl, int default_accessibility,
- int *assigned_accessibilities, size_t num_assigned_accessibilities) {
- if (record_decl) {
- uint32_t field_idx;
- clang::RecordDecl::field_iterator field, field_end;
- for (field = record_decl->field_begin(),
- field_end = record_decl->field_end(), field_idx = 0;
- field != field_end; ++field, ++field_idx) {
- // If no accessibility was assigned, assign the correct one
- if (field_idx < num_assigned_accessibilities &&
- assigned_accessibilities[field_idx] == clang::AS_none)
- field->setAccess((clang::AccessSpecifier)default_accessibility);
- }
- return true;
- }
- return false;
-}
-
clang::DeclContext *
TypeSystemClang::GetDeclContextForType(const CompilerType &type) {
return GetDeclContextForType(ClangUtil::GetQualType(type));
@@ -4697,7 +4766,6 @@
case clang::BuiltinType::Void:
break;
- case clang::BuiltinType::Bool:
case clang::BuiltinType::Char_S:
case clang::BuiltinType::SChar:
case clang::BuiltinType::WChar_S:
@@ -4708,6 +4776,7 @@
case clang::BuiltinType::Int128:
return lldb::eEncodingSint;
+ case clang::BuiltinType::Bool:
case clang::BuiltinType::Char_U:
case clang::BuiltinType::UChar:
case clang::BuiltinType::WChar_U:
@@ -4889,6 +4958,75 @@
case clang::BuiltinType::SveFloat64x4:
break;
+ // RISC-V V builtin types.
+ case clang::BuiltinType::RvvInt8mf8:
+ case clang::BuiltinType::RvvInt8mf4:
+ case clang::BuiltinType::RvvInt8mf2:
+ case clang::BuiltinType::RvvInt8m1:
+ case clang::BuiltinType::RvvInt8m2:
+ case clang::BuiltinType::RvvInt8m4:
+ case clang::BuiltinType::RvvInt8m8:
+ case clang::BuiltinType::RvvUint8mf8:
+ case clang::BuiltinType::RvvUint8mf4:
+ case clang::BuiltinType::RvvUint8mf2:
+ case clang::BuiltinType::RvvUint8m1:
+ case clang::BuiltinType::RvvUint8m2:
+ case clang::BuiltinType::RvvUint8m4:
+ case clang::BuiltinType::RvvUint8m8:
+ case clang::BuiltinType::RvvInt16mf4:
+ case clang::BuiltinType::RvvInt16mf2:
+ case clang::BuiltinType::RvvInt16m1:
+ case clang::BuiltinType::RvvInt16m2:
+ case clang::BuiltinType::RvvInt16m4:
+ case clang::BuiltinType::RvvInt16m8:
+ case clang::BuiltinType::RvvUint16mf4:
+ case clang::BuiltinType::RvvUint16mf2:
+ case clang::BuiltinType::RvvUint16m1:
+ case clang::BuiltinType::RvvUint16m2:
+ case clang::BuiltinType::RvvUint16m4:
+ case clang::BuiltinType::RvvUint16m8:
+ case clang::BuiltinType::RvvInt32mf2:
+ case clang::BuiltinType::RvvInt32m1:
+ case clang::BuiltinType::RvvInt32m2:
+ case clang::BuiltinType::RvvInt32m4:
+ case clang::BuiltinType::RvvInt32m8:
+ case clang::BuiltinType::RvvUint32mf2:
+ case clang::BuiltinType::RvvUint32m1:
+ case clang::BuiltinType::RvvUint32m2:
+ case clang::BuiltinType::RvvUint32m4:
+ case clang::BuiltinType::RvvUint32m8:
+ case clang::BuiltinType::RvvInt64m1:
+ case clang::BuiltinType::RvvInt64m2:
+ case clang::BuiltinType::RvvInt64m4:
+ case clang::BuiltinType::RvvInt64m8:
+ case clang::BuiltinType::RvvUint64m1:
+ case clang::BuiltinType::RvvUint64m2:
+ case clang::BuiltinType::RvvUint64m4:
+ case clang::BuiltinType::RvvUint64m8:
+ case clang::BuiltinType::RvvFloat16mf4:
+ case clang::BuiltinType::RvvFloat16mf2:
+ case clang::BuiltinType::RvvFloat16m1:
+ case clang::BuiltinType::RvvFloat16m2:
+ case clang::BuiltinType::RvvFloat16m4:
+ case clang::BuiltinType::RvvFloat16m8:
+ case clang::BuiltinType::RvvFloat32mf2:
+ case clang::BuiltinType::RvvFloat32m1:
+ case clang::BuiltinType::RvvFloat32m2:
+ case clang::BuiltinType::RvvFloat32m4:
+ case clang::BuiltinType::RvvFloat32m8:
+ case clang::BuiltinType::RvvFloat64m1:
+ case clang::BuiltinType::RvvFloat64m2:
+ case clang::BuiltinType::RvvFloat64m4:
+ case clang::BuiltinType::RvvFloat64m8:
+ case clang::BuiltinType::RvvBool1:
+ case clang::BuiltinType::RvvBool2:
+ case clang::BuiltinType::RvvBool4:
+ case clang::BuiltinType::RvvBool8:
+ case clang::BuiltinType::RvvBool16:
+ case clang::BuiltinType::RvvBool32:
+ case clang::BuiltinType::RvvBool64:
+ break;
+
case clang::BuiltinType::IncompleteMatrixIdx:
break;
}
@@ -6365,7 +6503,7 @@
case clang::Type::RValueReference:
if (idx_is_valid) {
const clang::ReferenceType *reference_type =
- llvm::cast<clang::ReferenceType>(parent_qual_type.getTypePtr());
+ llvm::cast<clang::ReferenceType>(GetQualType(type).getTypePtr());
CompilerType pointee_clang_type =
GetType(reference_type->getPointeeType());
if (transparent_pointers && pointee_clang_type.IsAggregateType()) {
@@ -6536,10 +6674,11 @@
if (cxx_record_decl->lookupInBases(
[decl_name](const clang::CXXBaseSpecifier *specifier,
clang::CXXBasePath &path) {
- path.Decls =
- specifier->getType()->getAsCXXRecordDecl()->lookup(
- decl_name);
- return !path.Decls.empty();
+ CXXRecordDecl *record =
+ specifier->getType()->getAsCXXRecordDecl();
+ auto r = record->lookup(decl_name);
+ path.Decls = r.begin();
+ return !r.empty();
},
paths)) {
clang::CXXBasePaths::const_paths_iterator path,
@@ -6562,9 +6701,10 @@
->getDecl());
}
}
- for (clang::NamedDecl *path_decl : path->Decls) {
+ for (clang::DeclContext::lookup_iterator I = path->Decls, E;
+ I != E; ++I) {
child_idx = GetIndexForRecordChild(
- parent_record_decl, path_decl, omit_empty_base_classes);
+ parent_record_decl, *I, omit_empty_base_classes);
if (child_idx == UINT32_MAX) {
child_indexes.clear();
return 0;
@@ -9234,11 +9374,11 @@
std::vector<CompilerDecl> TypeSystemClang::DeclContextFindDeclByName(
void *opaque_decl_ctx, ConstString name, const bool ignore_using_decls) {
std::vector<CompilerDecl> found_decls;
- if (opaque_decl_ctx) {
+ SymbolFile *symbol_file = GetSymbolFile();
+ if (opaque_decl_ctx && symbol_file) {
DeclContext *root_decl_ctx = (DeclContext *)opaque_decl_ctx;
std::set<DeclContext *> searched;
std::multimap<DeclContext *, DeclContext *> search_queue;
- SymbolFile *symbol_file = GetSymbolFile();
for (clang::DeclContext *decl_context = root_decl_ctx;
decl_context != nullptr && found_decls.empty();
@@ -9332,10 +9472,10 @@
clang::DeclContext *child_decl_ctx,
ConstString *child_name,
CompilerType *child_type) {
- if (frame_decl_ctx) {
+ SymbolFile *symbol_file = GetSymbolFile();
+ if (frame_decl_ctx && symbol_file) {
std::set<DeclContext *> searched;
std::multimap<DeclContext *, DeclContext *> search_queue;
- SymbolFile *symbol_file = GetSymbolFile();
// Get the lookup scope for the decl we're trying to find.
clang::DeclContext *parent_decl_ctx = child_decl_ctx->getParent();
@@ -9581,7 +9721,8 @@
llvm::Triple triple)
: TypeSystemClang("scratch ASTContext", triple), m_triple(triple),
m_target_wp(target.shared_from_this()),
- m_persistent_variables(new ClangPersistentVariables) {
+ m_persistent_variables(
+ new ClangPersistentVariables(target.shared_from_this())) {
m_scratch_ast_source_up = CreateASTSource();
m_scratch_ast_source_up->InstallASTContext(*this);
llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> proxy_ast_source(
@@ -9649,7 +9790,8 @@
return {};
return std::make_unique<ClangUtilityFunction>(
- *target_sp.get(), std::move(text), std::move(name));
+ *target_sp.get(), std::move(text), std::move(name),
+ target_sp->GetDebugUtilityExpression());
}
PersistentExpressionState *
diff --git a/src/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/src/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
index f37652f..701e4ca 100644
--- a/src/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
+++ b/src/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
@@ -9,7 +9,7 @@
#ifndef LLDB_SOURCE_PLUGINS_TYPESYSTEM_CLANG_TYPESYSTEMCLANG_H
#define LLDB_SOURCE_PLUGINS_TYPESYSTEM_CLANG_TYPESYSTEMCLANG_H
-#include <stdint.h>
+#include <cstdint>
#include <functional>
#include <initializer_list>
@@ -265,7 +265,7 @@
clang::DeclContext::lookup_result result = decl_context->lookup(myName);
if (!result.empty()) {
- clang::NamedDecl *named_decl = result[0];
+ clang::NamedDecl *named_decl = *result.begin();
if (const RecordDeclType *record_decl =
llvm::dyn_cast<RecordDeclType>(named_decl))
compiler_type.SetCompilerType(
@@ -328,6 +328,8 @@
(!packed_args || !packed_args->packed_args);
}
+ bool hasParameterPack() const { return static_cast<bool>(packed_args); }
+
llvm::SmallVector<const char *, 2> names;
llvm::SmallVector<clang::TemplateArgument, 2> args;
@@ -378,13 +380,6 @@
bool isForwardDecl, bool isInternal,
ClangASTMetadata *metadata = nullptr);
- bool SetTagTypeKind(clang::QualType type, int kind) const;
-
- bool SetDefaultAccessForRecordFields(clang::RecordDecl *record_decl,
- int default_accessibility,
- int *assigned_accessibilities,
- size_t num_assigned_accessibilities);
-
// Returns a mask containing bits from the TypeSystemClang::eTypeXXX
// enumerations
@@ -421,7 +416,7 @@
int storage, bool add_decl = false);
void SetFunctionParameters(clang::FunctionDecl *function_decl,
- clang::ParmVarDecl **params, unsigned num_params);
+ llvm::ArrayRef<clang::ParmVarDecl *> params);
CompilerType CreateBlockPointerType(const CompilerType &function_type);
diff --git a/src/llvm-project/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/src/llvm-project/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
index 1bc071c..65947c5 100644
--- a/src/llvm-project/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
+++ b/src/llvm-project/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
@@ -38,10 +38,10 @@
ProcessSP process_sp(thread.GetProcess());
if (process_sp) {
Status error;
- const bool prefer_file_cache = true;
+ const bool force_live_memory = true;
if (process_sp->GetTarget().ReadMemory(
- range.GetBaseAddress(), prefer_file_cache, function_text.data(),
- range.GetByteSize(), error) != range.GetByteSize()) {
+ range.GetBaseAddress(), function_text.data(), range.GetByteSize(),
+ error, force_live_memory) != range.GetByteSize()) {
return false;
}
}
diff --git a/src/llvm-project/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp b/src/llvm-project/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
index fe1275d..402a70c 100644
--- a/src/llvm-project/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
+++ b/src/llvm-project/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
@@ -51,12 +51,11 @@
ProcessSP process_sp(thread.GetProcess());
if (process_sp.get() == nullptr)
return false;
- const bool prefer_file_cache = true;
std::vector<uint8_t> function_text(func.GetByteSize());
Status error;
if (process_sp->GetTarget().ReadMemory(
- func.GetBaseAddress(), prefer_file_cache, function_text.data(),
- func.GetByteSize(), error) == func.GetByteSize()) {
+ func.GetBaseAddress(), function_text.data(), func.GetByteSize(),
+ error) == func.GetByteSize()) {
RegisterContextSP reg_ctx(thread.GetRegisterContext());
m_assembly_inspection_engine->Initialize(reg_ctx);
return m_assembly_inspection_engine->GetNonCallSiteUnwindPlanFromAssembly(
@@ -153,12 +152,11 @@
return false;
if (m_assembly_inspection_engine == nullptr)
return false;
- const bool prefer_file_cache = true;
std::vector<uint8_t> function_text(func.GetByteSize());
Status error;
if (process_sp->GetTarget().ReadMemory(
- func.GetBaseAddress(), prefer_file_cache, function_text.data(),
- func.GetByteSize(), error) == func.GetByteSize()) {
+ func.GetBaseAddress(), function_text.data(), func.GetByteSize(),
+ error) == func.GetByteSize()) {
RegisterContextSP reg_ctx(thread.GetRegisterContext());
m_assembly_inspection_engine->Initialize(reg_ctx);
return m_assembly_inspection_engine->AugmentUnwindPlanFromCallSite(
@@ -185,10 +183,9 @@
ProcessSP process_sp = thread.GetProcess();
if (process_sp) {
Target &target(process_sp->GetTarget());
- const bool prefer_file_cache = true;
Status error;
- if (target.ReadMemory(func.GetBaseAddress(), prefer_file_cache,
- opcode_data.data(), 4, error) == 4) {
+ if (target.ReadMemory(func.GetBaseAddress(), opcode_data.data(), 4,
+ error) == 4) {
uint8_t i386_push_mov[] = {0x55, 0x89, 0xe5};
uint8_t x86_64_push_mov[] = {0x55, 0x48, 0x89, 0xe5};
@@ -220,12 +217,10 @@
if (m_assembly_inspection_engine == nullptr)
return false;
- const bool prefer_file_cache = true;
std::vector<uint8_t> function_text(func.GetByteSize());
Status error;
- if (target->ReadMemory(func.GetBaseAddress(), prefer_file_cache,
- function_text.data(), func.GetByteSize(),
- error) == func.GetByteSize()) {
+ if (target->ReadMemory(func.GetBaseAddress(), function_text.data(),
+ func.GetByteSize(), error) == func.GetByteSize()) {
size_t offset;
if (m_assembly_inspection_engine->FindFirstNonPrologueInstruction(
function_text.data(), func.GetByteSize(), offset)) {
diff --git a/src/llvm-project/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h b/src/llvm-project/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h
index f39dce1..4877488 100644
--- a/src/llvm-project/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h
+++ b/src/llvm-project/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h
@@ -45,9 +45,9 @@
/// are called. This one takes a vector of register name and lldb
/// register numbers.
struct lldb_reg_info {
- const char *name;
- uint32_t lldb_regnum;
- lldb_reg_info() : name(nullptr), lldb_regnum(LLDB_INVALID_REGNUM) {}
+ const char *name = nullptr;
+ uint32_t lldb_regnum = LLDB_INVALID_REGNUM;
+ lldb_reg_info() = default;
};
void Initialize(std::vector<lldb_reg_info> ®_info);