Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add crash report to createdump for Linux Watson #55438

Merged
merged 6 commits into from
Jul 12, 2021
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
1 change: 1 addition & 0 deletions src/coreclr/debug/createdump/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ endif(CLR_CMAKE_HOST_OSX)
dbgutil
# share the PAL in the dac module
mscordaccore
dl
)

add_dependencies(createdump mscordaccore)
Expand Down
87 changes: 68 additions & 19 deletions src/coreclr/debug/createdump/crashinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@
// This is for the PAL_VirtualUnwindOutOfProc read memory adapter.
CrashInfo* g_crashInfo;

static bool ModuleInfoCompare(const ModuleInfo* lhs, const ModuleInfo* rhs) { return lhs->BaseAddress() < rhs->BaseAddress(); }

CrashInfo::CrashInfo(pid_t pid, bool gatherFrames, pid_t crashThread, uint32_t signal) :
m_ref(1),
m_pid(pid),
m_ppid(-1),
m_hdac(nullptr),
m_gatherFrames(gatherFrames),
m_crashThread(crashThread),
m_signal(signal)
m_signal(signal),
m_moduleInfos(&ModuleInfoCompare)
{
g_crashInfo = this;
#ifdef __APPLE__
Expand All @@ -31,6 +35,20 @@ CrashInfo::~CrashInfo()
delete thread;
}
m_threads.clear();

// Clean up the modules
for (ModuleInfo* module : m_moduleInfos)
{
delete module;
}
m_moduleInfos.clear();

// Unload DAC module
if (m_hdac != nullptr)
{
FreeLibrary(m_hdac);
m_hdac = nullptr;
}
#ifdef __APPLE__
if (m_task != 0)
{
Expand Down Expand Up @@ -191,7 +209,6 @@ CrashInfo::EnumerateMemoryRegionsWithDAC(MINIDUMP_TYPE minidumpType)
PFN_CLRDataCreateInstance pfnCLRDataCreateInstance = nullptr;
ICLRDataEnumMemoryRegions* pClrDataEnumRegions = nullptr;
IXCLRDataProcess* pClrDataProcess = nullptr;
HMODULE hdac = nullptr;
HRESULT hr = S_OK;
bool result = false;

Expand All @@ -205,13 +222,13 @@ CrashInfo::EnumerateMemoryRegionsWithDAC(MINIDUMP_TYPE minidumpType)
dacPath.append(MAKEDLLNAME_A("mscordaccore"));

// Load and initialize the DAC
hdac = LoadLibraryA(dacPath.c_str());
if (hdac == nullptr)
m_hdac = LoadLibraryA(dacPath.c_str());
if (m_hdac == nullptr)
{
fprintf(stderr, "LoadLibraryA(%s) FAILED %d\n", dacPath.c_str(), GetLastError());
goto exit;
}
pfnCLRDataCreateInstance = (PFN_CLRDataCreateInstance)GetProcAddress(hdac, "CLRDataCreateInstance");
pfnCLRDataCreateInstance = (PFN_CLRDataCreateInstance)GetProcAddress(m_hdac, "CLRDataCreateInstance");
if (pfnCLRDataCreateInstance == nullptr)
{
fprintf(stderr, "GetProcAddress(CLRDataCreateInstance) FAILED %d\n", GetLastError());
Expand Down Expand Up @@ -262,10 +279,6 @@ CrashInfo::EnumerateMemoryRegionsWithDAC(MINIDUMP_TYPE minidumpType)
{
pClrDataProcess->Release();
}
if (hdac != nullptr)
{
FreeLibrary(hdac);
}
return result;
}

Expand Down Expand Up @@ -347,10 +360,13 @@ CrashInfo::EnumerateManagedModules(IXCLRDataProcess* pClrDataProcess)
bool
CrashInfo::UnwindAllThreads(IXCLRDataProcess* pClrDataProcess)
{
ReleaseHolder<ISOSDacInterface> pSos = nullptr;
pClrDataProcess->QueryInterface(__uuidof(ISOSDacInterface), (void**)&pSos);

// For each native and managed thread
for (ThreadInfo* thread : m_threads)
{
if (!thread->UnwindThread(pClrDataProcess)) {
if (!thread->UnwindThread(pClrDataProcess, pSos)) {
return false;
}
}
Expand Down Expand Up @@ -426,17 +442,17 @@ CrashInfo::GetBaseAddressFromAddress(uint64_t address)
uint64_t
CrashInfo::GetBaseAddressFromName(const char* moduleName)
{
for (const ModuleInfo& moduleInfo : m_moduleInfos)
for (const ModuleInfo* moduleInfo : m_moduleInfos)
{
std::string name = GetFileName(moduleInfo.ModuleName());
std::string name = GetFileName(moduleInfo->ModuleName());
#ifdef __APPLE__
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only thing is this is configurable, but this is not the default. I don't know how common it is to request case sensitivity.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lee mentioned it in passing and then I confirmed on my local MacBook. Not sure what to do if it is configurable. I'm going to leave it this way for now.

// Module names are case insenstive on MacOS
if (strcasecmp(name.c_str(), moduleName) == 0)
#else
if (name.compare(moduleName) == 0)
#endif
{
return moduleInfo.BaseAddress();
return moduleInfo->BaseAddress();
}
}
return 0;
Expand All @@ -445,14 +461,14 @@ CrashInfo::GetBaseAddressFromName(const char* moduleName)
//
// Return the module info for the base address
//
const ModuleInfo*
ModuleInfo*
CrashInfo::GetModuleInfoFromBaseAddress(uint64_t baseAddress)
{
ModuleInfo search(baseAddress);
const auto& found = m_moduleInfos.find(search);
const auto& found = m_moduleInfos.find(&search);
if (found != m_moduleInfos.end())
{
return &*found;
return *found;
}
return nullptr;
}
Expand All @@ -475,11 +491,12 @@ void
CrashInfo::AddModuleInfo(bool isManaged, uint64_t baseAddress, IXCLRDataModule* pClrDataModule, const std::string& moduleName)
{
ModuleInfo moduleInfo(baseAddress);
const auto& found = m_moduleInfos.find(moduleInfo);
const auto& found = m_moduleInfos.find(&moduleInfo);
if (found == m_moduleInfos.end())
{
uint32_t timeStamp = 0;
uint32_t imageSize = 0;
bool isMainModule = false;
GUID mvid;
if (isManaged)
{
Expand Down Expand Up @@ -511,11 +528,18 @@ CrashInfo::AddModuleInfo(bool isManaged, uint64_t baseAddress, IXCLRDataModule*
}
if (pClrDataModule != nullptr)
{
ULONG32 flags = 0;
pClrDataModule->GetFlags(&flags);
isMainModule = (flags & CLRDATA_MODULE_IS_MAIN_MODULE) != 0;
pClrDataModule->GetVersionId(&mvid);
}
TRACE("MODULE: timestamp %08x size %08x %s %s\n", timeStamp, imageSize, FormatGuid(&mvid).c_str(), moduleName.c_str());
TRACE("MODULE: timestamp %08x size %08x %s %s%s\n", timeStamp, imageSize, FormatGuid(&mvid).c_str(), isMainModule ? "*" : "", moduleName.c_str());
}
ModuleInfo* moduleInfo = new ModuleInfo(isManaged, baseAddress, timeStamp, imageSize, &mvid, moduleName);
if (isMainModule) {
m_mainModule = moduleInfo;
}
m_moduleInfos.insert(ModuleInfo(isManaged, baseAddress, timeStamp, imageSize, &mvid, moduleName));
m_moduleInfos.insert(moduleInfo);
}
}

Expand Down Expand Up @@ -737,6 +761,31 @@ CrashInfo::TraceVerbose(const char* format, ...)
}
}

//
// Lookup a symbol in a module. The caller needs to call "free()" on symbol returned.
//
const char*
ModuleInfo::GetSymbolName(uint64_t address)
{
LoadModule();

if (m_localBaseAddress != 0)
{
uint64_t localAddress = m_localBaseAddress + (address - m_baseAddress);
Dl_info info;
if (dladdr((void*)localAddress, &info) != 0)
{
if (info.dli_sname != nullptr)
{
int status = -1;
char *demangled = abi::__cxa_demangle(info.dli_sname, nullptr, 0, &status);
return status == 0 ? demangled : strdup(info.dli_sname);
}
}
}
return nullptr;
}

//
// Returns just the file name portion of a file path
//
Expand Down
11 changes: 9 additions & 2 deletions src/coreclr/debug/createdump/crashinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback,
pid_t m_pid; // pid
pid_t m_ppid; // parent pid
pid_t m_tgid; // process group
HMODULE m_hdac; // dac module handle when loaded
bool m_gatherFrames; // if true, add the native and managed stack frames to the thread info
pid_t m_crashThread; // crashing thread id or 0 if none
uint32_t m_signal; // crash signal code or 0 if none
Expand All @@ -68,7 +69,12 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback,
std::set<MemoryRegion> m_otherMappings; // other memory mappings
std::set<MemoryRegion> m_memoryRegions; // memory regions from DAC, etc.
std::set<MemoryRegion> m_moduleAddresses; // memory region to module base address
std::set<ModuleInfo> m_moduleInfos; // module infos (base address and module name)
std::set<ModuleInfo*, bool (*)(const ModuleInfo* lhs, const ModuleInfo* rhs)> m_moduleInfos; // module infos (base address and module name)
ModuleInfo* m_mainModule; // the module containing "Main"

// no public copy constructor
CrashInfo(const CrashInfo&) = delete;
void operator=(const CrashInfo&) = delete;

public:
CrashInfo(pid_t pid, bool gatherFrames, pid_t crashThread, uint32_t signal);
Expand All @@ -82,7 +88,7 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback,
bool ReadProcessMemory(void* address, void* buffer, size_t size, size_t* read); // read raw memory
uint64_t GetBaseAddressFromAddress(uint64_t address);
uint64_t GetBaseAddressFromName(const char* moduleName);
const ModuleInfo* GetModuleInfoFromBaseAddress(uint64_t baseAddress);
ModuleInfo* GetModuleInfoFromBaseAddress(uint64_t baseAddress);
void AddModuleAddressRange(uint64_t startAddress, uint64_t endAddress, uint64_t baseAddress);
void AddModuleInfo(bool isManaged, uint64_t baseAddress, IXCLRDataModule* pClrDataModule, const std::string& moduleName);
void InsertMemoryRegion(uint64_t address, size_t size);
Expand All @@ -98,6 +104,7 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback,
inline const pid_t CrashThread() const { return m_crashThread; }
inline const uint32_t Signal() const { return m_signal; }
inline const std::string& Name() const { return m_name; }
inline const ModuleInfo* MainModule() const { return m_mainModule; }

inline const std::vector<ThreadInfo*> Threads() const { return m_threads; }
inline const std::set<MemoryRegion> ModuleMappings() const { return m_moduleMappings; }
Expand Down
36 changes: 36 additions & 0 deletions src/coreclr/debug/createdump/crashinfomac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -380,3 +380,39 @@ CrashInfo::ReadProcessMemory(void* address, void* buffer, size_t size, size_t* r
*read = numberOfBytesRead;
return size == 0 || numberOfBytesRead > 0;
}

const struct dyld_all_image_infos* g_image_infos = nullptr;

void
ModuleInfo::LoadModule()
{
if (m_module == nullptr)
{
m_module = dlopen(m_moduleName.c_str(), RTLD_LAZY);
if (m_module != nullptr)
{
if (g_image_infos == nullptr)
{
struct task_dyld_info dyld_info;
mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
kern_return_t result = task_info(mach_task_self_, TASK_DYLD_INFO, (task_info_t)&dyld_info, &count);
if (result == KERN_SUCCESS)
{
g_image_infos = (const struct dyld_all_image_infos*)dyld_info.all_image_info_addr;
}
}
if (g_image_infos != nullptr)
{
for (int i = 0; i < g_image_infos->infoArrayCount; ++i)
{
const struct dyld_image_info* image = g_image_infos->infoArray + i;
if (strcasecmp(image->imageFilePath, m_moduleName.c_str()) == 0)
{
m_localBaseAddress = (uint64_t)image->imageLoadAddress;
break;
}
}
}
}
}
}
10 changes: 10 additions & 0 deletions src/coreclr/debug/createdump/crashinfounix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -414,3 +414,13 @@ GetStatus(pid_t pid, pid_t* ppid, pid_t* tgid, std::string* name)
fclose(statusFile);
return true;
}

void
ModuleInfo::LoadModule()
{
if (m_module == nullptr)
{
m_module = dlopen(m_moduleName.c_str(), RTLD_LAZY);
mikem8361 marked this conversation as resolved.
Show resolved Hide resolved
m_localBaseAddress = ((struct link_map*)m_module)->l_addr;
}
}
Loading