hr = GetTargetCLRMetrics(clrInfo.RuntimeModulePath, NULL, &clrInfo, NULL);
if (FAILED(hr))
{
+ // Runtime module not found (return false). This isn't an error that needs to be reported via the callback.
return false;
}
// Invoke the callback on error
m_callback(NULL, m_parameter, hr);
}
-
+ // Runtime module found (return true)
return true;
}
{
if (IsCoreClr(wszModulePath))
{
- // Get the runtime index info (build id) for Linux/MacOS
- if (!TryGetBuildIdFromFile(wszModulePath, pClrInfoOut->RuntimeBuildId, MAX_BUILDID_SIZE, &pClrInfoOut->RuntimeBuildIdSize))
+ // Get the runtime index info (build id) for Linux/MacOS. If getting the build id fails for any reason, return success
+ // but with an invalid ClrInfo (unknown index type, no build id) so ProvideLibraries fails in InvokeStartupCallback and
+ // invokes the callback with an error.
+ if (TryGetBuildIdFromFile(wszModulePath, pClrInfoOut->RuntimeBuildId, MAX_BUILDID_SIZE, &pClrInfoOut->RuntimeBuildIdSize))
{
- return E_FAIL;
+ pClrInfoOut->IndexType = LIBRARY_PROVIDER_INDEX_TYPE::Runtime;
}
- pClrInfoOut->IndexType = LIBRARY_PROVIDER_INDEX_TYPE::Runtime;
}
else
{
{
if (reader.EnumerateProgramHeaders(0, nullptr, nullptr))
{
- return reader.GetBuildId(buffer, bufferSize, pBuildSize);
+ if (reader.GetBuildId(buffer, bufferSize, pBuildSize))
+ {
+ return true;
+ }
+ }
+ if (reader.GetBuildIdFromSectionHeader(0, buffer, bufferSize, pBuildSize))
+ {
+ return true;
}
}
return false;
#ifdef HOST_UNIX
+bool
+ElfReader::GetBuildIdFromSectionHeader(uint64_t baseAddress, BYTE* buffer, ULONG bufferSize, PULONG pBuildSize)
+{
+ Elf_Ehdr ehdr;
+ if (!ReadHeader(baseAddress, ehdr)) {
+ return false;
+ }
+ if (ehdr.e_shoff == 0 || ehdr.e_shnum <= 0) {
+ return false;
+ }
+ Elf_Shdr* shdrAddr = reinterpret_cast<Elf_Shdr*>(baseAddress + ehdr.e_shoff);
+ for (int sectionIndex = 0; sectionIndex < ehdr.e_shnum; sectionIndex++, shdrAddr++)
+ {
+ Elf_Shdr sh;
+ if (!ReadMemory(shdrAddr, &sh, sizeof(sh))) {
+ Trace("GetBuildIdFromSectionHeader: %2d shdr %p ReadMemory FAILED\n", sectionIndex, shdrAddr);
+ return false;
+ }
+ Trace("GetBuildIdFromSectionHeader: %2d shdr %p type %2d (%x) addr %016lx offset %016lx size %016lx link %08x info %08x name %4d\n",
+ sectionIndex, shdrAddr, sh.sh_type, sh.sh_type, sh.sh_addr, sh.sh_offset, sh.sh_size, sh.sh_link, sh.sh_info, sh.sh_name);
+
+ if (sh.sh_type == SHT_NOTE)
+ {
+ m_noteStart = baseAddress + sh.sh_offset;
+ m_noteEnd = baseAddress + sh.sh_offset + sh.sh_size;
+ if (GetBuildId(buffer, bufferSize, pBuildSize))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
//
// Enumerate all the ELF info starting from the root program header. This
// function doesn't cache any state in the ElfReader class.
}
// Read the module's name and make sure the memory is added to the core dump
std::string moduleName;
- int i = 0;
- if (map.l_name != nullptr)
+ if (map.l_name != 0)
{
- for (; i < PATH_MAX; i++)
+ for (int i = 0; i < PATH_MAX; i++)
{
char ch;
- char* l_name = const_cast<char*>(map.l_name);
- if (!ReadMemory(l_name + i, &ch, sizeof(ch))) {
+ if (!ReadMemory(map.l_name + i, &ch, sizeof(ch))) {
Trace("DSO: ReadMemory link_map name %p + %d FAILED\n", map.l_name, i);
break;
}
moduleName.append(1, ch);
}
}
- Trace("\nDSO: link_map entry %p l_ld %p l_addr (Ehdr) %" PRIx " %s\n", linkMapAddr, map.l_ld, map.l_addr, moduleName.c_str());
+ Trace("\nDSO: link_map entry %p l_ld %p l_addr (Ehdr) %p l_name %p %s\n", linkMapAddr, map.l_ld, map.l_addr, map.l_name, moduleName.c_str());
// Call the derived class for each module
VisitModule(map.l_addr, moduleName);
#endif // HOST_UNIX
bool
-ElfReader::EnumerateProgramHeaders(uint64_t baseAddress, uint64_t* ploadbias, Elf_Dyn** pdynamicAddr)
+ElfReader::ReadHeader(uint64_t baseAddress, Elf_Ehdr& ehdr)
{
- Elf_Ehdr ehdr;
- if (!ReadMemory((void*)baseAddress, &ehdr, sizeof(ehdr))) {
- Trace("ERROR: EnumerateProgramHeaders ReadMemory(%p, %" PRIx ") ehdr FAILED\n", (void*)baseAddress, sizeof(ehdr));
+ if (!ReadMemory((void*)baseAddress, &ehdr, sizeof(Elf_Ehdr))) {
+ Trace("ERROR: EnumerateProgramHeaders ReadMemory(%p, %" PRIx ") ehdr FAILED\n", (void*)baseAddress, sizeof(Elf_Ehdr));
return false;
}
if (memcmp(ehdr.e_ident, ElfMagic, strlen(ElfMagic)) != 0) {
}
Trace("ELF: type %d mach 0x%x ver %d flags 0x%x phnum %d phoff %" PRIxA " phentsize 0x%02x shnum %d shoff %" PRIxA " shentsize 0x%02x shstrndx %d\n",
ehdr.e_type, ehdr.e_machine, ehdr.e_version, ehdr.e_flags, phnum, ehdr.e_phoff, ehdr.e_phentsize, ehdr.e_shnum, ehdr.e_shoff, ehdr.e_shentsize, ehdr.e_shstrndx);
+ return true;
+}
+bool
+ElfReader::EnumerateProgramHeaders(uint64_t baseAddress, uint64_t* ploadbias, Elf_Dyn** pdynamicAddr)
+{
+ Elf_Ehdr ehdr;
+ if (!ReadHeader(baseAddress, ehdr)) {
+ return false;
+ }
Elf_Phdr* phdrAddr = reinterpret_cast<Elf_Phdr*>(baseAddress + ehdr.e_phoff);
- return EnumerateProgramHeaders(phdrAddr, phnum, baseAddress, ploadbias, pdynamicAddr);
+ return EnumerateProgramHeaders(phdrAddr, ehdr.e_phnum, baseAddress, ploadbias, pdynamicAddr);
}
//
e_machine = EM_X86_64;
#elif defined(TARGET_ARM64)
e_machine = EM_AARCH64;
+#elif defined(TARGET_LOONGARCH64)
+ e_machine = EM_LOONGARCH;
#endif
e_flags = 0;
e_version = 1;
public:
ElfReader(bool isFileLayout);
virtual ~ElfReader();
+ bool PopulateForSymbolLookup(uint64_t baseAddress);
+ bool TryLookupSymbol(std::string symbolName, uint64_t* symbolOffset);
+ bool GetBuildId(BYTE* buffer, ULONG bufferSize, PULONG pBuildSize);
#ifdef HOST_UNIX
bool EnumerateElfInfo(ElfW(Phdr)* phdrAddr, int phnum);
+ bool GetBuildIdFromSectionHeader(uint64_t baseAddress, BYTE* buffer, ULONG bufferSize, PULONG pBuildSize);
#endif
- bool PopulateForSymbolLookup(uint64_t baseAddress);
- bool TryLookupSymbol(std::string symbolName, uint64_t* symbolOffset);
bool EnumerateProgramHeaders(uint64_t baseAddress, uint64_t* ploadbias = nullptr, ElfW(Dyn)** pdynamicAddr = nullptr);
- bool GetBuildId(BYTE* buffer, ULONG bufferSize, PULONG pBuildSize);
private:
bool GetSymbol(int32_t index, ElfW(Sym)* symbol);
uint32_t Hash(const std::string& symbolName);
bool GetChain(int index, int32_t* chain);
bool GetStringAtIndex(int index, std::string& result);
+ bool ReadHeader(uint64_t baseAddress, ElfW(Ehdr)& ehdr);
+ bool EnumerateProgramHeaders(ElfW(Phdr)* phdrAddr, int phnum, uint64_t baseAddress, uint64_t* ploadbias, ElfW(Dyn)** pdynamicAddr);
#ifdef HOST_UNIX
bool EnumerateLinkMapEntries(ElfW(Dyn)* dynamicAddr);
#endif
- bool EnumerateProgramHeaders(ElfW(Phdr)* phdrAddr, int phnum, uint64_t baseAddress, uint64_t* ploadbias, ElfW(Dyn)** pdynamicAddr);
#ifdef __FreeBSD__
virtual void VisitModule(caddr_t baseAddress, std::string& moduleName) { };
#else
<BuildProjectFrameworkLatest Condition="StartsWith('$(RuntimeVersionLatest)', '6')">net6.0</BuildProjectFrameworkLatest>
<TestProduct>ProjectK</TestProduct>
- <DebuggeeSourceRoot>$(RepoRootDir)\src\tests\DbgShim.UnitTests\Debuggees</DebuggeeSourceRoot>
- <DebuggeeMsbuildAuxRoot>$(RepoRootDir)\eng\AuxMsbuildFiles</DebuggeeMsbuildAuxRoot>
+ <DebuggeeSourceRoot>$(RepoRootDir)/src/tests/DbgShim.UnitTests/Debuggees</DebuggeeSourceRoot>
+ <DebuggeeMsbuildAuxRoot>$(RepoRootDir)/eng/AuxMsbuildFiles</DebuggeeMsbuildAuxRoot>
<DebuggeeBuildProcess>cli</DebuggeeBuildProcess>
<DebuggeeName>SimpleDebuggee</DebuggeeName>
!-- Use the global.json SDK to build and the test SDK/runtime to run -->
- <!--
- <CliPath>$(RepoRootDir)/.dotnet/dotnet</CliPath>
- -->
<CliPath>$(DotNetRoot)/dotnet</CliPath>
<NuGetPackageFeeds>
<RuntimeFrameworkVersion>$(RuntimeVersionLatest)</RuntimeFrameworkVersion>
</Option>
<Option Condition="'$(RuntimeVersion60)' != ''">
- <DebuggeeBuildRoot>$(RootBinDir)\Debuggees</DebuggeeBuildRoot>
+ <DebuggeeBuildRoot>$(RootBinDir)/Debuggees</DebuggeeBuildRoot>
<BuildProjectFramework>net6.0</BuildProjectFramework>
<RuntimeFrameworkVersion>$(RuntimeVersion60)</RuntimeFrameworkVersion>
</Option>