Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit d685894

Browse files
author
Mike McLaughlin
authored
Fix a few of createdump bugs. (#15079)
1) Fix createdump p_vaddr bias/base problem. 2) createdump was loading the DAC from the directory where createdump was executed from and not from the libcoreclr.so path. Fixed this. 3) Don't use the dac if the libcoreclr.so module is not found. 4) Remove the QI of ICoreDebugDataTarget4 in datatarget.cpp. Forgot to do this when the VirtualUnwind function was removed. Caused crash.
1 parent 0254bd8 commit d685894

File tree

6 files changed

+160
-137
lines changed

6 files changed

+160
-137
lines changed

src/debug/createdump/crashinfo.cpp

Lines changed: 119 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ CrashInfo::EnumerateAndSuspendThreads()
146146
// Gather all the necessary crash dump info.
147147
//
148148
bool
149-
CrashInfo::GatherCrashInfo(const char* programPath, MINIDUMP_TYPE minidumpType)
149+
CrashInfo::GatherCrashInfo(MINIDUMP_TYPE minidumpType)
150150
{
151151
// Get the process info
152152
if (!GetStatus(m_pid, &m_ppid, &m_tgid, &m_name))
@@ -206,7 +206,7 @@ CrashInfo::GatherCrashInfo(const char* programPath, MINIDUMP_TYPE minidumpType)
206206
}
207207
}
208208
// Gather all the useful memory regions from the DAC
209-
if (!EnumerateMemoryRegionsWithDAC(programPath, minidumpType))
209+
if (!EnumerateMemoryRegionsWithDAC(minidumpType))
210210
{
211211
return false;
212212
}
@@ -363,10 +363,21 @@ CrashInfo::EnumerateModuleMappings()
363363
}
364364
MemoryRegion memoryRegion(regionFlags, start, end, offset, moduleName);
365365

366-
if (moduleName != nullptr && *moduleName == '/') {
366+
if (moduleName != nullptr && *moduleName == '/')
367+
{
368+
if (m_coreclrPath.empty())
369+
{
370+
std::string coreclrPath;
371+
coreclrPath.append(moduleName);
372+
size_t last = coreclrPath.rfind(MAKEDLLNAME_A("coreclr"));
373+
if (last != -1) {
374+
m_coreclrPath = coreclrPath.substr(0, last);
375+
}
376+
}
367377
m_moduleMappings.insert(memoryRegion);
368378
}
369-
else {
379+
else
380+
{
370381
m_otherMappings.insert(memoryRegion);
371382
}
372383
if (linuxGateAddress != nullptr && reinterpret_cast<void*>(start) == linuxGateAddress)
@@ -412,40 +423,15 @@ CrashInfo::GetDSOInfo()
412423
return false;
413424
}
414425
uint64_t baseAddress = (uint64_t)phdrAddr - sizeof(Ehdr);
415-
TRACE("DSO: base %" PRIA PRIx64 " phdr %p phnum %d\n", baseAddress, phdrAddr, phnum);
416-
417-
// Search for the program PT_DYNAMIC header
418426
ElfW(Dyn)* dynamicAddr = nullptr;
419-
for (int i = 0; i < phnum; i++, phdrAddr++)
420-
{
421-
Phdr ph;
422-
if (!ReadMemory(phdrAddr, &ph, sizeof(ph))) {
423-
fprintf(stderr, "ReadMemory(%p, %" PRIx ") phdr FAILED\n", phdrAddr, sizeof(ph));
424-
return false;
425-
}
426-
TRACE("DSO: phdr %p type %d (%x) vaddr %" PRIxA " memsz %" PRIxA " offset %" PRIxA "\n",
427-
phdrAddr, ph.p_type, ph.p_type, ph.p_vaddr, ph.p_memsz, ph.p_offset);
428427

429-
switch (ph.p_type)
430-
{
431-
case PT_DYNAMIC:
432-
dynamicAddr = reinterpret_cast<ElfW(Dyn)*>(ph.p_vaddr);
433-
break;
434-
435-
case PT_NOTE:
436-
case PT_GNU_EH_FRAME:
437-
if (ph.p_vaddr != 0 && ph.p_memsz != 0) {
438-
InsertMemoryRegion(ph.p_vaddr, ph.p_memsz);
439-
}
440-
break;
428+
TRACE("DSO: base %" PRIA PRIx64 " phdr %p phnum %d\n", baseAddress, phdrAddr, phnum);
441429

442-
case PT_LOAD:
443-
MemoryRegion region(0, ph.p_vaddr, ph.p_vaddr + ph.p_memsz, baseAddress);
444-
m_moduleAddresses.insert(region);
445-
break;
446-
}
430+
// Enumerate program headers searching for the PT_DYNAMIC header, etc.
431+
if (!EnumerateProgramHeaders(phdrAddr, phnum, baseAddress, &dynamicAddr))
432+
{
433+
return false;
447434
}
448-
449435
if (dynamicAddr == nullptr) {
450436
return false;
451437
}
@@ -542,32 +528,70 @@ CrashInfo::GetELFInfo(uint64_t baseAddress)
542528
{
543529
Phdr* phdrAddr = reinterpret_cast<Phdr*>(baseAddress + ehdr.e_phoff);
544530

545-
// Add the program headers and search for the module's note and unwind info segments
546-
for (int i = 0; i < phnum; i++, phdrAddr++)
531+
if (!EnumerateProgramHeaders(phdrAddr, phnum, baseAddress, nullptr))
547532
{
548-
Phdr ph;
549-
if (!ReadMemory(phdrAddr, &ph, sizeof(ph))) {
550-
fprintf(stderr, "ReadMemory(%p, %" PRIx ") phdr FAILED\n", phdrAddr, sizeof(ph));
551-
return false;
552-
}
553-
TRACE("ELF: phdr %p type %d (%x) vaddr %" PRIxA " memsz %" PRIxA " paddr %" PRIxA " filesz %" PRIxA " offset %" PRIxA " align %" PRIxA "\n",
554-
phdrAddr, ph.p_type, ph.p_type, ph.p_vaddr, ph.p_memsz, ph.p_paddr, ph.p_filesz, ph.p_offset, ph.p_align);
533+
return false;
534+
}
535+
}
536+
537+
return true;
538+
}
539+
540+
//
541+
// Enumerate the program headers adding the build id note, unwind frame
542+
// region and module addresses to the crash info.
543+
//
544+
bool
545+
CrashInfo::EnumerateProgramHeaders(Phdr* phdrAddr, int phnum, uint64_t baseAddress, ElfW(Dyn)** pdynamicAddr)
546+
{
547+
uint64_t loadbias = baseAddress;
555548

556-
switch (ph.p_type)
549+
for (int i = 0; i < phnum; i++)
550+
{
551+
Phdr ph;
552+
if (!ReadMemory(phdrAddr + i, &ph, sizeof(ph))) {
553+
fprintf(stderr, "ReadMemory(%p, %" PRIx ") phdr FAILED\n", phdrAddr + i, sizeof(ph));
554+
return false;
555+
}
556+
if (ph.p_type == PT_LOAD && ph.p_offset == 0)
557+
{
558+
loadbias -= ph.p_vaddr;
559+
TRACE("PHDR: loadbias %" PRIA PRIx64 "\n", loadbias);
560+
break;
561+
}
562+
}
563+
564+
for (int i = 0; i < phnum; i++)
565+
{
566+
Phdr ph;
567+
if (!ReadMemory(phdrAddr + i, &ph, sizeof(ph))) {
568+
fprintf(stderr, "ReadMemory(%p, %" PRIx ") phdr FAILED\n", phdrAddr + i, sizeof(ph));
569+
return false;
570+
}
571+
TRACE("PHDR: %p type %d (%x) vaddr %" PRIxA " memsz %" PRIxA " paddr %" PRIxA " filesz %" PRIxA " offset %" PRIxA " align %" PRIxA "\n",
572+
phdrAddr + i, ph.p_type, ph.p_type, ph.p_vaddr, ph.p_memsz, ph.p_paddr, ph.p_filesz, ph.p_offset, ph.p_align);
573+
574+
switch (ph.p_type)
575+
{
576+
case PT_DYNAMIC:
577+
if (pdynamicAddr != nullptr)
557578
{
558-
case PT_DYNAMIC:
559-
case PT_NOTE:
560-
case PT_GNU_EH_FRAME:
561-
if (ph.p_vaddr != 0 && ph.p_memsz != 0) {
562-
InsertMemoryRegion(baseAddress + ph.p_vaddr, ph.p_memsz);
563-
}
579+
*pdynamicAddr = reinterpret_cast<ElfW(Dyn)*>(loadbias + ph.p_vaddr);
564580
break;
581+
}
582+
// fall into InsertMemoryRegion
565583

566-
case PT_LOAD:
567-
MemoryRegion region(0, baseAddress + ph.p_vaddr, baseAddress + ph.p_vaddr + ph.p_memsz, baseAddress);
568-
m_moduleAddresses.insert(region);
569-
break;
584+
case PT_NOTE:
585+
case PT_GNU_EH_FRAME:
586+
if (ph.p_vaddr != 0 && ph.p_memsz != 0) {
587+
InsertMemoryRegion(loadbias + ph.p_vaddr, ph.p_memsz);
570588
}
589+
break;
590+
591+
case PT_LOAD:
592+
MemoryRegion region(0, loadbias + ph.p_vaddr, loadbias + ph.p_vaddr + ph.p_memsz, baseAddress);
593+
m_moduleAddresses.insert(region);
594+
break;
571595
}
572596
}
573597

@@ -578,7 +602,7 @@ CrashInfo::GetELFInfo(uint64_t baseAddress)
578602
// Enumerate all the memory regions using the DAC memory region support given a minidump type
579603
//
580604
bool
581-
CrashInfo::EnumerateMemoryRegionsWithDAC(const char* programPath, MINIDUMP_TYPE minidumpType)
605+
CrashInfo::EnumerateMemoryRegionsWithDAC(MINIDUMP_TYPE minidumpType)
582606
{
583607
PFN_CLRDataCreateInstance pfnCLRDataCreateInstance = nullptr;
584608
ICLRDataEnumMemoryRegions* pClrDataEnumRegions = nullptr;
@@ -587,50 +611,55 @@ CrashInfo::EnumerateMemoryRegionsWithDAC(const char* programPath, MINIDUMP_TYPE
587611
HRESULT hr = S_OK;
588612
bool result = false;
589613

590-
// We assume that the DAC is in the same location as this createdump exe
591-
std::string dacPath;
592-
dacPath.append(programPath);
593-
dacPath.append("/");
594-
dacPath.append(MAKEDLLNAME_A("mscordaccore"));
595-
596-
// Load and initialize the DAC
597-
hdac = LoadLibraryA(dacPath.c_str());
598-
if (hdac == nullptr)
599-
{
600-
fprintf(stderr, "LoadLibraryA(%s) FAILED %d\n", dacPath.c_str(), GetLastError());
601-
goto exit;
602-
}
603-
pfnCLRDataCreateInstance = (PFN_CLRDataCreateInstance)GetProcAddress(hdac, "CLRDataCreateInstance");
604-
if (pfnCLRDataCreateInstance == nullptr)
605-
{
606-
fprintf(stderr, "GetProcAddress(CLRDataCreateInstance) FAILED %d\n", GetLastError());
607-
goto exit;
608-
}
609-
if ((minidumpType & MiniDumpWithFullMemory) == 0)
614+
if (!m_coreclrPath.empty())
610615
{
611-
hr = pfnCLRDataCreateInstance(__uuidof(ICLRDataEnumMemoryRegions), m_dataTarget, (void**)&pClrDataEnumRegions);
612-
if (FAILED(hr))
616+
// We assume that the DAC is in the same location as the libcoreclr.so module
617+
std::string dacPath;
618+
dacPath.append(m_coreclrPath);
619+
dacPath.append(MAKEDLLNAME_A("mscordaccore"));
620+
621+
// Load and initialize the DAC
622+
hdac = LoadLibraryA(dacPath.c_str());
623+
if (hdac == nullptr)
624+
{
625+
fprintf(stderr, "LoadLibraryA(%s) FAILED %d\n", dacPath.c_str(), GetLastError());
626+
goto exit;
627+
}
628+
pfnCLRDataCreateInstance = (PFN_CLRDataCreateInstance)GetProcAddress(hdac, "CLRDataCreateInstance");
629+
if (pfnCLRDataCreateInstance == nullptr)
613630
{
614-
fprintf(stderr, "CLRDataCreateInstance(ICLRDataEnumMemoryRegions) FAILED %08x\n", hr);
631+
fprintf(stderr, "GetProcAddress(CLRDataCreateInstance) FAILED %d\n", GetLastError());
615632
goto exit;
616633
}
617-
// Calls CrashInfo::EnumMemoryRegion for each memory region found by the DAC
618-
hr = pClrDataEnumRegions->EnumMemoryRegions(this, minidumpType, CLRDATA_ENUM_MEM_DEFAULT);
634+
if ((minidumpType & MiniDumpWithFullMemory) == 0)
635+
{
636+
hr = pfnCLRDataCreateInstance(__uuidof(ICLRDataEnumMemoryRegions), m_dataTarget, (void**)&pClrDataEnumRegions);
637+
if (FAILED(hr))
638+
{
639+
fprintf(stderr, "CLRDataCreateInstance(ICLRDataEnumMemoryRegions) FAILED %08x\n", hr);
640+
goto exit;
641+
}
642+
// Calls CrashInfo::EnumMemoryRegion for each memory region found by the DAC
643+
hr = pClrDataEnumRegions->EnumMemoryRegions(this, minidumpType, CLRDATA_ENUM_MEM_DEFAULT);
644+
if (FAILED(hr))
645+
{
646+
fprintf(stderr, "EnumMemoryRegions FAILED %08x\n", hr);
647+
goto exit;
648+
}
649+
}
650+
hr = pfnCLRDataCreateInstance(__uuidof(IXCLRDataProcess), m_dataTarget, (void**)&pClrDataProcess);
619651
if (FAILED(hr))
620652
{
621-
fprintf(stderr, "EnumMemoryRegions FAILED %08x\n", hr);
653+
fprintf(stderr, "CLRDataCreateInstance(IXCLRDataProcess) FAILED %08x\n", hr);
654+
goto exit;
655+
}
656+
if (!EnumerateManagedModules(pClrDataProcess))
657+
{
622658
goto exit;
623659
}
624660
}
625-
hr = pfnCLRDataCreateInstance(__uuidof(IXCLRDataProcess), m_dataTarget, (void**)&pClrDataProcess);
626-
if (FAILED(hr))
627-
{
628-
fprintf(stderr, "CLRDataCreateInstance(IXCLRDataProcess) FAILED %08x\n", hr);
629-
goto exit;
630-
}
631-
if (!EnumerateManagedModules(pClrDataProcess))
632-
{
633-
goto exit;
661+
else {
662+
TRACE("EnumerateMemoryRegionsWithDAC: coreclr not found; not using DAC\n");
634663
}
635664
if (!UnwindAllThreads(pClrDataProcess))
636665
{

src/debug/createdump/crashinfo.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback
3232
pid_t m_ppid; // parent pid
3333
pid_t m_tgid; // process group
3434
char* m_name; // exe name
35-
bool m_sos; // true if running under sos
35+
bool m_sos; // if true, running under sos
36+
std::string m_coreclrPath; // the path of the coreclr module or empty if none
3637
ICLRDataTarget* m_dataTarget; // read process memory, etc.
3738
std::array<elf_aux_val_t, AT_MAX> m_auxvValues; // auxv values
3839
std::vector<elf_aux_entry> m_auxvEntries; // full auxv entries
@@ -46,7 +47,7 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback
4647
CrashInfo(pid_t pid, ICLRDataTarget* dataTarget, bool sos);
4748
virtual ~CrashInfo();
4849
bool EnumerateAndSuspendThreads();
49-
bool GatherCrashInfo(const char* programPath, MINIDUMP_TYPE minidumpType);
50+
bool GatherCrashInfo(MINIDUMP_TYPE minidumpType);
5051
void ResumeThreads();
5152
bool ReadMemory(void* address, void* buffer, size_t size);
5253
uint64_t GetBaseAddress(uint64_t ip);
@@ -80,7 +81,8 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback
8081
bool EnumerateModuleMappings();
8182
bool GetDSOInfo();
8283
bool GetELFInfo(uint64_t baseAddress);
83-
bool EnumerateMemoryRegionsWithDAC(const char* programPath, MINIDUMP_TYPE minidumpType);
84+
bool EnumerateProgramHeaders(ElfW(Phdr)* phdrAddr, int phnum, uint64_t baseAddress, ElfW(Dyn)** pdynamicAddr);
85+
bool EnumerateMemoryRegionsWithDAC(MINIDUMP_TYPE minidumpType);
8486
bool EnumerateManagedModules(IXCLRDataProcess* pClrDataProcess);
8587
bool UnwindAllThreads(IXCLRDataProcess* pClrDataProcess);
8688
void ReplaceModuleMapping(CLRDATA_ADDRESS baseAddress, const char* pszName);

src/debug/createdump/createdump.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ bool g_diagnostics = false;
1010
// The common create dump code
1111
//
1212
bool
13-
CreateDumpCommon(const char* programPath, const char* dumpPathTemplate, MINIDUMP_TYPE minidumpType, CrashInfo* crashInfo)
13+
CreateDumpCommon(const char* dumpPathTemplate, MINIDUMP_TYPE minidumpType, CrashInfo* crashInfo)
1414
{
1515
ReleaseHolder<DumpWriter> dumpWriter = new DumpWriter(*crashInfo);
1616
bool result = false;
@@ -44,7 +44,7 @@ CreateDumpCommon(const char* programPath, const char* dumpPathTemplate, MINIDUMP
4444
goto exit;
4545
}
4646
// Gather all the info about the process, threads (registers, etc.) and memory regions
47-
if (!crashInfo->GatherCrashInfo(programPath, minidumpType))
47+
if (!crashInfo->GatherCrashInfo(minidumpType))
4848
{
4949
goto exit;
5050
}
@@ -69,5 +69,5 @@ bool
6969
CreateDumpForSOS(const char* programPath, const char* dumpPathTemplate, pid_t pid, MINIDUMP_TYPE minidumpType, ICLRDataTarget* dataTarget)
7070
{
7171
ReleaseHolder<CrashInfo> crashInfo = new CrashInfo(pid, dataTarget, true);
72-
return CreateDumpCommon(programPath, dumpPathTemplate, minidumpType, crashInfo);
73-
}
72+
return CreateDumpCommon(dumpPathTemplate, minidumpType, crashInfo);
73+
}

src/debug/createdump/datatarget.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,6 @@ DumpDataTarget::QueryInterface(
5252
AddRef();
5353
return S_OK;
5454
}
55-
else if (InterfaceId == IID_ICorDebugDataTarget4)
56-
{
57-
*Interface = (ICorDebugDataTarget4*)this;
58-
AddRef();
59-
return S_OK;
60-
}
6155
else
6256
{
6357
*Interface = NULL;

src/debug/createdump/main.cpp

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const char* g_help = "createdump [options] pid\n"
1212
"-u, --full - create full core dump.\n"
1313
"-d, --diag - enable diagnostic messages.\n";
1414

15-
bool CreateDumpCommon(const char* programPath, const char* dumpPathTemplate, MINIDUMP_TYPE minidumpType, CrashInfo* crashInfo);
15+
bool CreateDumpCommon(const char* dumpPathTemplate, MINIDUMP_TYPE minidumpType, CrashInfo* crashInfo);
1616

1717
//
1818
// Main entry point
@@ -34,13 +34,8 @@ int __cdecl main(const int argc, const char* argv[])
3434
return exitCode;
3535
}
3636

37-
// Parse off the program name leaving just the path. Used to locate/load the DAC module.
38-
std::string programPath;
39-
programPath.append(*argv++);
40-
size_t last = programPath.find_last_of('/');
41-
programPath = programPath.substr(0, last);
42-
4337
// Parse the command line options and target pid
38+
argv++;
4439
for (int i = 1; i < argc; i++)
4540
{
4641
if (*argv != nullptr)
@@ -83,7 +78,7 @@ int __cdecl main(const int argc, const char* argv[])
8378
// The initialize the data target's ReadVirtual support (opens /proc/$pid/mem)
8479
if (dataTarget->Initialize(crashInfo))
8580
{
86-
if (!CreateDumpCommon(programPath.c_str(), dumpPathTemplate, minidumpType, crashInfo))
81+
if (!CreateDumpCommon(dumpPathTemplate, minidumpType, crashInfo))
8782
{
8883
exitCode = -1;
8984
}

0 commit comments

Comments
 (0)