[LLDB][Minidump] Support minidumps where there are multiple exception… · llvm/llvm-project@4926835 (original) (raw)

`@@ -157,8 +157,7 @@ ProcessMinidump::ProcessMinidump(lldb::TargetSP target_sp,

`

157

157

`const FileSpec &core_file,

`

158

158

` DataBufferSP core_data)

`

159

159

` : PostMortemProcess(target_sp, listener_sp, core_file),

`

160

``

`-

m_core_data(std::move(core_data)), m_active_exception(nullptr),

`

161

``

`-

m_is_wow64(false) {}

`

``

160

`+

m_core_data(std::move(core_data)), m_is_wow64(false) {}

`

162

161

``

163

162

`ProcessMinidump::~ProcessMinidump() {

`

164

163

`Clear();

`

`@@ -209,7 +208,20 @@ Status ProcessMinidump::DoLoadCore() {

`

209

208

`GetTarget().SetArchitecture(arch, true /set_platform/);

`

210

209

``

211

210

` m_thread_list = m_minidump_parser->GetThreads();

`

212

``

`-

m_active_exception = m_minidump_parser->GetExceptionStream();

`

``

211

`+

auto exception_stream_it = m_minidump_parser->GetExceptionStreams();

`

``

212

`+

for (auto exception_stream : exception_stream_it) {

`

``

213

`+

// If we can't read an exception stream skip it

`

``

214

`+

// We should probably serve a warning

`

``

215

`+

if (!exception_stream)

`

``

216

`+

continue;

`

``

217

+

``

218

`+

if (!m_exceptions_by_tid

`

``

219

`+

.try_emplace(exception_stream->ThreadId, exception_stream.get())

`

``

220

`+

.second) {

`

``

221

`+

return Status::FromErrorStringWithFormatv(

`

``

222

`+

"Duplicate exception stream for tid {0}", exception_stream->ThreadId);

`

``

223

`+

}

`

``

224

`+

}

`

213

225

``

214

226

`SetUnixSignals(UnixSignals::Create(GetArchitecture()));

`

215

227

``

`@@ -232,60 +244,57 @@ Status ProcessMinidump::DoDestroy() { return Status(); }

`

232

244

``

233

245

`void ProcessMinidump::RefreshStateAfterStop() {

`

234

246

``

235

``

`-

if (!m_active_exception)

`

236

``

`-

return;

`

237

``

-

238

``

`-

constexpr uint32_t BreakpadDumpRequested = 0xFFFFFFFF;

`

239

``

`-

if (m_active_exception->ExceptionRecord.ExceptionCode ==

`

240

``

`-

BreakpadDumpRequested) {

`

241

``

`-

// This "ExceptionCode" value is a sentinel that is sometimes used

`

242

``

`-

// when generating a dump for a process that hasn't crashed.

`

243

``

-

244

``

`-

// TODO: The definition and use of this "dump requested" constant

`

245

``

`-

// in Breakpad are actually Linux-specific, and for similar use

`

246

``

`-

// cases on Mac/Windows it defines different constants, referring

`

247

``

`-

// to them as "simulated" exceptions; consider moving this check

`

248

``

`-

// down to the OS-specific paths and checking each OS for its own

`

249

``

`-

// constant.

`

250

``

`-

return;

`

251

``

`-

}

`

``

247

`+

for (const auto &[_, exception_stream] : m_exceptions_by_tid) {

`

``

248

`+

constexpr uint32_t BreakpadDumpRequested = 0xFFFFFFFF;

`

``

249

`+

if (exception_stream.ExceptionRecord.ExceptionCode ==

`

``

250

`+

BreakpadDumpRequested) {

`

``

251

`+

// This "ExceptionCode" value is a sentinel that is sometimes used

`

``

252

`+

// when generating a dump for a process that hasn't crashed.

`

``

253

+

``

254

`+

// TODO: The definition and use of this "dump requested" constant

`

``

255

`+

// in Breakpad are actually Linux-specific, and for similar use

`

``

256

`+

// cases on Mac/Windows it defines different constants, referring

`

``

257

`+

// to them as "simulated" exceptions; consider moving this check

`

``

258

`+

// down to the OS-specific paths and checking each OS for its own

`

``

259

`+

// constant.

`

``

260

`+

return;

`

``

261

`+

}

`

252

262

``

253

``

`-

lldb::StopInfoSP stop_info;

`

254

``

`-

lldb::ThreadSP stop_thread;

`

``

263

`+

lldb::StopInfoSP stop_info;

`

``

264

`+

lldb::ThreadSP stop_thread;

`

255

265

``

256

``

`-

Process::m_thread_list.SetSelectedThreadByID(m_active_exception->ThreadId);

`

257

``

`-

stop_thread = Process::m_thread_list.GetSelectedThread();

`

258

``

`-

ArchSpec arch = GetArchitecture();

`

``

266

`+

Process::m_thread_list.SetSelectedThreadByID(exception_stream.ThreadId);

`

``

267

`+

stop_thread = Process::m_thread_list.GetSelectedThread();

`

``

268

`+

ArchSpec arch = GetArchitecture();

`

259

269

``

260

``

`-

if (arch.GetTriple().getOS() == llvm::Triple::Linux) {

`

261

``

`-

uint32_t signo = m_active_exception->ExceptionRecord.ExceptionCode;

`

``

270

`+

if (arch.GetTriple().getOS() == llvm::Triple::Linux) {

`

``

271

`+

uint32_t signo = exception_stream.ExceptionRecord.ExceptionCode;

`

``

272

`+

if (signo == 0) {

`

``

273

`+

// No stop.

`

``

274

`+

return;

`

``

275

`+

}

`

262

276

``

263

``

`-

if (signo == 0) {

`

264

``

`-

// No stop.

`

265

``

`-

return;

`

``

277

`+

stop_info = StopInfo::CreateStopReasonWithSignal(*stop_thread, signo);

`

``

278

`+

} else if (arch.GetTriple().getVendor() == llvm::Triple::Apple) {

`

``

279

`+

stop_info = StopInfoMachException::CreateStopReasonWithMachException(

`

``

280

`+

*stop_thread, exception_stream.ExceptionRecord.ExceptionCode, 2,

`

``

281

`+

exception_stream.ExceptionRecord.ExceptionFlags,

`

``

282

`+

exception_stream.ExceptionRecord.ExceptionAddress, 0);

`

``

283

`+

} else {

`

``

284

`+

std::string desc;

`

``

285

`+

llvm::raw_string_ostream desc_stream(desc);

`

``

286

`+

desc_stream << "Exception "

`

``

287

`+

<< llvm::format_hex(

`

``

288

`+

exception_stream.ExceptionRecord.ExceptionCode, 8)

`

``

289

`+

<< " encountered at address "

`

``

290

`+

<< llvm::format_hex(

`

``

291

`+

exception_stream.ExceptionRecord.ExceptionAddress, 8);

`

``

292

`+

stop_info = StopInfo::CreateStopReasonWithException(

`

``

293

`+

*stop_thread, desc_stream.str().c_str());

`

266

294

` }

`

267

295

``

268

``

`-

stop_info = StopInfo::CreateStopReasonWithSignal(

`

269

``

`-

*stop_thread, signo);

`

270

``

`-

} else if (arch.GetTriple().getVendor() == llvm::Triple::Apple) {

`

271

``

`-

stop_info = StopInfoMachException::CreateStopReasonWithMachException(

`

272

``

`-

*stop_thread, m_active_exception->ExceptionRecord.ExceptionCode, 2,

`

273

``

`-

m_active_exception->ExceptionRecord.ExceptionFlags,

`

274

``

`-

m_active_exception->ExceptionRecord.ExceptionAddress, 0);

`

275

``

`-

} else {

`

276

``

`-

std::string desc;

`

277

``

`-

llvm::raw_string_ostream desc_stream(desc);

`

278

``

`-

desc_stream << "Exception "

`

279

``

`-

<< llvm::format_hex(

`

280

``

`-

m_active_exception->ExceptionRecord.ExceptionCode, 8)

`

281

``

`-

<< " encountered at address "

`

282

``

`-

<< llvm::format_hex(

`

283

``

`-

m_active_exception->ExceptionRecord.ExceptionAddress, 8);

`

284

``

`-

stop_info = StopInfo::CreateStopReasonWithException(

`

285

``

`-

*stop_thread, desc_stream.str().c_str());

`

286

``

`-

}

`

287

``

-

288

``

`-

stop_thread->SetStopInfo(stop_info);

`

``

296

`+

stop_thread->SetStopInfo(stop_info);

`

``

297

`+

}

`

289

298

`}

`

290

299

``

291

300

`bool ProcessMinidump::IsAlive() { return true; }

`

`@@ -387,10 +396,9 @@ bool ProcessMinidump::DoUpdateThreadList(ThreadList &old_thread_list,

`

387

396

` LocationDescriptor context_location = thread.Context;

`

388

397

``

389

398

`// If the minidump contains an exception context, use it

`

390

``

`-

if (m_active_exception != nullptr &&

`

391

``

`-

m_active_exception->ThreadId == thread.ThreadId) {

`

392

``

`-

context_location = m_active_exception->ThreadContext;

`

393

``

`-

}

`

``

399

`+

if (auto it = m_exceptions_by_tid.find(thread.ThreadId);

`

``

400

`+

it != m_exceptions_by_tid.end())

`

``

401

`+

context_location = it->second.ThreadContext;

`

394

402

``

395

403

` llvm::ArrayRef context;

`

396

404

`if (!m_is_wow64)

`