Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 38 additions & 44 deletions lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,7 @@ Status MinidumpFileBuilder::AddHeaderAndCalculateDirectories() {
StopInfoSP stop_info_sp = thread_sp->GetStopInfo();
if (stop_info_sp) {
const StopReason &stop_reason = stop_info_sp->GetStopReason();
if (stop_reason == StopReason::eStopReasonException ||
stop_reason == StopReason::eStopReasonSignal)
if (stop_reason != lldb::eStopReasonInvalid)
m_expected_directories++;
}
}
Expand Down Expand Up @@ -685,50 +684,45 @@ Status MinidumpFileBuilder::AddExceptions() {
Status error;
for (const ThreadSP &thread_sp : thread_list) {
StopInfoSP stop_info_sp = thread_sp->GetStopInfo();
bool add_exception = false;
if (stop_info_sp) {
switch (stop_info_sp->GetStopReason()) {
case eStopReasonSignal:
case eStopReasonException:
add_exception = true;
break;
default:
break;
}
}
if (add_exception) {
constexpr size_t minidump_exception_size =
sizeof(llvm::minidump::ExceptionStream);
error = AddDirectory(StreamType::Exception, minidump_exception_size);
if (error.Fail())
return error;
// If we don't have a stop info, or if it's invalid, skip.
if (!stop_info_sp ||
stop_info_sp->GetStopReason() == lldb::eStopReasonInvalid)
continue;

StopInfoSP stop_info_sp = thread_sp->GetStopInfo();
RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext());
Exception exp_record = {};
exp_record.ExceptionCode =
static_cast<llvm::support::ulittle32_t>(stop_info_sp->GetValue());
exp_record.ExceptionFlags = static_cast<llvm::support::ulittle32_t>(0);
exp_record.ExceptionRecord = static_cast<llvm::support::ulittle64_t>(0);
exp_record.ExceptionAddress = reg_ctx_sp->GetPC();
exp_record.NumberParameters = static_cast<llvm::support::ulittle32_t>(0);
exp_record.UnusedAlignment = static_cast<llvm::support::ulittle32_t>(0);
// exp_record.ExceptionInformation;

ExceptionStream exp_stream;
exp_stream.ThreadId =
static_cast<llvm::support::ulittle32_t>(thread_sp->GetID());
exp_stream.UnusedAlignment = static_cast<llvm::support::ulittle32_t>(0);
exp_stream.ExceptionRecord = exp_record;
auto Iter = m_tid_to_reg_ctx.find(thread_sp->GetID());
if (Iter != m_tid_to_reg_ctx.end()) {
exp_stream.ThreadContext = Iter->second;
} else {
exp_stream.ThreadContext.DataSize = 0;
exp_stream.ThreadContext.RVA = 0;
}
m_data.AppendData(&exp_stream, minidump_exception_size);
constexpr size_t minidump_exception_size =
sizeof(llvm::minidump::ExceptionStream);
error = AddDirectory(StreamType::Exception, minidump_exception_size);
if (error.Fail())
return error;

RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext());
Exception exp_record = {};
exp_record.ExceptionCode =
static_cast<llvm::support::ulittle32_t>(stop_info_sp->GetValue());
exp_record.ExceptionFlags =
static_cast<llvm::support::ulittle32_t>(Exception::LLDB_FLAG);
exp_record.ExceptionRecord = static_cast<llvm::support::ulittle64_t>(0);
exp_record.ExceptionAddress = reg_ctx_sp->GetPC();
exp_record.NumberParameters = static_cast<llvm::support::ulittle32_t>(1);
std::string description = stop_info_sp->GetDescription();
// We have 120 bytes to work with and it's unlikely description will
// overflow, but we gotta check.
memcpy(&exp_record.ExceptionInformation, description.c_str(),
std::max(description.size(), Exception::MaxParameterBytes));
exp_record.UnusedAlignment = static_cast<llvm::support::ulittle32_t>(0);
ExceptionStream exp_stream;
exp_stream.ThreadId =
static_cast<llvm::support::ulittle32_t>(thread_sp->GetID());
exp_stream.UnusedAlignment = static_cast<llvm::support::ulittle32_t>(0);
exp_stream.ExceptionRecord = exp_record;
auto Iter = m_tid_to_reg_ctx.find(thread_sp->GetID());
if (Iter != m_tid_to_reg_ctx.end()) {
exp_stream.ThreadContext = Iter->second;
} else {
exp_stream.ThreadContext.DataSize = 0;
exp_stream.ThreadContext.RVA = 0;
}
m_data.AppendData(&exp_stream, minidump_exception_size);
}

return error;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,5 +175,4 @@ class MinidumpFileBuilder {
lldb::FileUP m_core_file;
lldb_private::SaveCoreOptions m_save_core_options;
};

#endif // LLDB_SOURCE_PLUGINS_OBJECTFILE_MINIDUMP_MINIDUMPFILEBUILDER_H
12 changes: 10 additions & 2 deletions lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,8 +273,16 @@ void ProcessMinidump::RefreshStateAfterStop() {
// No stop.
return;
}

stop_info = StopInfo::CreateStopReasonWithSignal(*stop_thread, signo);
const char *description = nullptr;
if (exception_stream.ExceptionRecord.ExceptionFlags ==
llvm::minidump::Exception::LLDB_FLAG)
description = reinterpret_cast<const char *>(
exception_stream.ExceptionRecord.ExceptionInformation);

llvm::StringRef description_str(description,
Exception::MaxParameterBytes);
stop_info = StopInfo::CreateStopReasonWithSignal(
*stop_thread, signo, description_str.str().c_str());
} else if (arch.GetTriple().getVendor() == llvm::Triple::Apple) {
stop_info = StopInfoMachException::CreateStopReasonWithMachException(
*stop_thread, exception_stream.ExceptionRecord.ExceptionCode, 2,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -524,3 +524,23 @@ def test_multiple_exceptions_or_signals(self):
self.assertStopReason(thread.GetStopReason(), lldb.eStopReasonSignal)
stop_description = thread.GetStopDescription(256)
self.assertIn("SIGSEGV", stop_description)

def test_breakpoint_on_minidump(self):
"""
Test that LLDB breakpoints are recorded in Minidumps
"""
yaml = "linux-x86_64-exceptiondescription.yaml"
core = self.getBuildArtifact("breakpoint.core.dmp")
self.yaml2obj(yaml, core)
try:
# Create a target with the object file we just created from YAML
target = self.dbg.CreateTarget(None)
self.assertTrue(target, VALID_TARGET)
process = target.LoadCore(core)
self.assertTrue(process, VALID_PROCESS)
thread = process.GetThreadAtIndex(0)
stop_reason = thread.GetStopDescription(256)
self.assertIn("breakpoint 1.1", stop_reason)
finally:
if os.path.isfile(core):
os.unlink(core)
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
--- !minidump
Streams:
- Type: SystemInfo
Processor Arch: AMD64
Processor Level: 6
Processor Revision: 15876
Number of Processors: 40
Platform ID: Linux
CSD Version: 'Linux 3.13.0-91-generic'
CPU:
Vendor ID: GenuineIntel
Version Info: 0x00000000
Feature Info: 0x00000000
- Type: ThreadList
Threads:
- Thread Id: 0x31F222
Context: 00000000000000
Stack:
Start of Memory Range: 0x7FFFFFFFD660
Content: ''
- Type: Exception
Thread ID: 0x31F222
Exception Record:
Exception Code: 0x2
Exception Flags: 0x4C4C4442
Exception Address: 0x555555556671
Number of Parameters: 1
Parameter 0: 0x696F706B61657262
Parameter 1: 0x312E3120746E
Parameter 2: 0x1
Parameter 3: 0x8000000000000000
Parameter 4: 0x200000002
Parameter 5: 0x8000000000000002
Parameter 7: 0x555555556671
Parameter 8: 0x1
Thread Context: ''
...
2 changes: 2 additions & 0 deletions llvm/include/llvm/BinaryFormat/Minidump.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,8 @@ static_assert(sizeof(Thread) == 48);

struct Exception {
static constexpr size_t MaxParameters = 15;
static constexpr size_t MaxParameterBytes = MaxParameters * sizeof(uint64_t);
static const uint32_t LLDB_FLAG = 'LLDB';

support::ulittle32_t ExceptionCode;
support::ulittle32_t ExceptionFlags;
Expand Down