Skip to content

Commit 0211c2e

Browse files
github-actions[bot]Mike McLaughlin
andauthored
[release/7.0] Fix dump creation on MacOS Ventura (#79360)
* Fix dump creation on MacOS Ventura Use the task_info(TASK_DYLD_INFO) API to get the dylinker info instead of enumerating all the memory regions. This works on Ventura and simplifies the module enumeration quite a bit. * Need to ensure the symbol table and symbol string table for the dylinker module is part of the core dump for the dump readers. They still need to look up the "dyld_all_image_infos" symbol. Co-authored-by: Mike McLaughlin <[email protected]>
1 parent ff4cab3 commit 0211c2e

File tree

4 files changed

+54
-96
lines changed

4 files changed

+54
-96
lines changed

src/coreclr/debug/createdump/crashinfo.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,6 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback, public ICLRDataLoggi
142142
#ifdef __APPLE__
143143
bool EnumerateMemoryRegions();
144144
void InitializeOtherMappings();
145-
bool TryFindDyLinker(mach_vm_address_t address, mach_vm_size_t size, bool* found);
146145
void VisitModule(MachOModule& module);
147146
void VisitSegment(MachOModule& module, const segment_command_64& segment);
148147
void VisitSection(MachOModule& module, const section_64& section);

src/coreclr/debug/createdump/crashinfomac.cpp

Lines changed: 15 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -148,18 +148,23 @@ CrashInfo::EnumerateMemoryRegions()
148148
}
149149
}
150150

151-
// Now find all the modules and add them to the module list
152-
for (const MemoryRegion& region : m_allMemoryRegions)
151+
// Get the dylinker info and enumerate all the modules
152+
struct task_dyld_info dyld_info;
153+
mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
154+
kern_return_t result = ::task_info(Task(), TASK_DYLD_INFO, (task_info_t)&dyld_info, &count);
155+
if (result != KERN_SUCCESS)
153156
{
154-
bool found;
155-
if (!TryFindDyLinker(region.StartAddress(), region.Size(), &found)) {
156-
return false;
157-
}
158-
if (found) {
159-
break;
160-
}
157+
TRACE("EnumerateMemoryRegions: task_info(TASK_DYLD_INFO) FAILED %x %s\n", result, mach_error_string(result));
158+
return false;
159+
}
160+
161+
// Enumerate all the modules in dyld's image cache. VisitModule is called for every module found.
162+
if (!EnumerateModules(dyld_info.all_image_info_addr))
163+
{
164+
return false;
161165
}
162-
TRACE("AllMemoryRegions %06llx native ModuleMappings %06llx\n", cbAllMemoryRegions / PAGE_SIZE, m_cbModuleMappings / PAGE_SIZE);
166+
167+
TRACE("EnumerateMemoryRegions: cbAllMemoryRegions %06llx native cbModuleMappings %06llx\n", cbAllMemoryRegions / PAGE_SIZE, m_cbModuleMappings / PAGE_SIZE);
163168
return true;
164169
}
165170

@@ -216,46 +221,6 @@ CrashInfo::InitializeOtherMappings()
216221
TRACE("OtherMappings: %06llx\n", cbOtherMappings / PAGE_SIZE);
217222
}
218223

219-
bool
220-
CrashInfo::TryFindDyLinker(mach_vm_address_t address, mach_vm_size_t size, bool* found)
221-
{
222-
bool result = true;
223-
*found = false;
224-
225-
if (size > sizeof(mach_header_64))
226-
{
227-
mach_header_64 header;
228-
size_t read = 0;
229-
if (ReadProcessMemory((void*)address, &header, sizeof(mach_header_64), &read))
230-
{
231-
if (header.magic == MH_MAGIC_64)
232-
{
233-
TRACE("TryFindDyLinker: found module header at %016llx %08llx ncmds %d sizeofcmds %08x type %02x\n",
234-
address,
235-
size,
236-
header.ncmds,
237-
header.sizeofcmds,
238-
header.filetype);
239-
240-
if (header.filetype == MH_DYLINKER)
241-
{
242-
TRACE("TryFindDyLinker: found dylinker\n");
243-
*found = true;
244-
245-
// Enumerate all the modules in dyld's image cache. VisitModule is called for every module found.
246-
result = EnumerateModules(address, &header);
247-
}
248-
}
249-
}
250-
else
251-
{
252-
TRACE("TryFindDyLinker: ReadProcessMemory header at %p %d FAILED\n", address, read);
253-
}
254-
}
255-
256-
return result;
257-
}
258-
259224
void CrashInfo::VisitModule(MachOModule& module)
260225
{
261226
AddModuleInfo(false, module.BaseAddress(), nullptr, module.Name());

src/coreclr/debug/dbgutil/machoreader.cpp

Lines changed: 36 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ TryGetSymbol(ICorDebugDataTarget* dataTarget, uint64_t baseAddress, const char*
7575
// MachO module
7676
//--------------------------------------------------------------------
7777

78-
MachOModule::MachOModule(MachOReader& reader, mach_vm_address_t baseAddress, mach_header_64* header, std::string* name) :
78+
MachOModule::MachOModule(MachOReader& reader, mach_vm_address_t baseAddress, std::string* name) :
7979
m_reader(reader),
8080
m_baseAddress(baseAddress),
8181
m_loadBias(0),
@@ -84,9 +84,6 @@ MachOModule::MachOModule(MachOReader& reader, mach_vm_address_t baseAddress, mac
8484
m_nlists(nullptr),
8585
m_strtabAddress(0)
8686
{
87-
if (header != nullptr) {
88-
m_header = *header;
89-
}
9087
if (name != nullptr) {
9188
m_name = *name;
9289
}
@@ -363,43 +360,25 @@ MachOReader::MachOReader()
363360
}
364361

365362
bool
366-
MachOReader::EnumerateModules(mach_vm_address_t address, mach_header_64* header)
363+
MachOReader::EnumerateModules(mach_vm_address_t dyldInfoAddress)
367364
{
368-
_ASSERTE(header->magic == MH_MAGIC_64);
369-
_ASSERTE(header->filetype == MH_DYLINKER);
370-
371-
MachOModule dylinker(*this, address, header);
372-
373-
// Search for symbol for the dyld image info cache
374-
uint64_t dyldInfoAddress = 0;
375-
if (!dylinker.TryLookupSymbol("dyld_all_image_infos", &dyldInfoAddress))
376-
{
377-
Trace("ERROR: Can not find the _dyld_all_image_infos symbol\n");
378-
return false;
379-
}
380-
381365
// Read the all image info from the dylinker image
382366
dyld_all_image_infos dyldInfo;
383-
384367
if (!ReadMemory((void*)dyldInfoAddress, &dyldInfo, sizeof(dyld_all_image_infos)))
385368
{
386369
Trace("ERROR: Failed to read dyld_all_image_infos at %p\n", (void*)dyldInfoAddress);
387370
return false;
388371
}
389-
std::string dylinkerPath;
390-
if (!ReadString(dyldInfo.dyldPath, dylinkerPath))
372+
Trace("MOD: infoArray %p infoArrayCount %d\n", dyldInfo.infoArray, dyldInfo.infoArrayCount);
373+
374+
// Create the dyld module info
375+
if (!TryRegisterModule(dyldInfo.dyldImageLoadAddress, dyldInfo.dyldPath, true))
391376
{
392-
Trace("ERROR: Failed to read name at %p\n", dyldInfo.dyldPath);
377+
Trace("ERROR: Failed to read dyld header at %p\n", dyldInfo.dyldImageLoadAddress);
393378
return false;
394379
}
395-
dylinker.SetName(dylinkerPath);
396-
Trace("MOD: %016llx %08x %s\n", dylinker.BaseAddress(), dylinker.Header().flags, dylinker.Name().c_str());
397-
VisitModule(dylinker);
398-
399380
void* imageInfosAddress = (void*)dyldInfo.infoArray;
400381
size_t imageInfosSize = dyldInfo.infoArrayCount * sizeof(dyld_image_info);
401-
Trace("MOD: infoArray %p infoArrayCount %d\n", dyldInfo.infoArray, dyldInfo.infoArrayCount);
402-
403382
ArrayHolder<dyld_image_info> imageInfos = new (std::nothrow) dyld_image_info[dyldInfo.infoArrayCount];
404383
if (imageInfos == nullptr)
405384
{
@@ -413,22 +392,38 @@ MachOReader::EnumerateModules(mach_vm_address_t address, mach_header_64* header)
413392
}
414393
for (int i = 0; i < dyldInfo.infoArrayCount; i++)
415394
{
416-
mach_vm_address_t imageAddress = (mach_vm_address_t)imageInfos[i].imageLoadAddress;
417-
const char* imageFilePathAddress = imageInfos[i].imageFilePath;
395+
// Ignore any errors and continue to next module
396+
TryRegisterModule(imageInfos[i].imageLoadAddress, imageInfos[i].imageFilePath, false);
397+
}
398+
return true;
399+
}
418400

419-
std::string imagePath;
420-
if (!ReadString(imageFilePathAddress, imagePath))
421-
{
422-
Trace("ERROR: Failed to read image name at %p\n", imageFilePathAddress);
423-
continue;
424-
}
425-
MachOModule module(*this, imageAddress, nullptr, &imagePath);
426-
if (!module.ReadHeader())
401+
bool
402+
MachOReader::TryRegisterModule(const struct mach_header* imageAddress, const char* imageFilePathAddress, bool dylinker)
403+
{
404+
std::string imagePath;
405+
if (!ReadString(imageFilePathAddress, imagePath))
406+
{
407+
return false;
408+
}
409+
MachOModule module(*this, (mach_vm_address_t)imageAddress, &imagePath);
410+
if (!module.ReadHeader())
411+
{
412+
return false;
413+
}
414+
Trace("MOD: %016llx %08x %s\n", imageAddress, module.Header().flags, imagePath.c_str());
415+
VisitModule(module);
416+
if (dylinker)
417+
{
418+
// Make sure the memory for the symbol and string tables are in the core dump for our
419+
// dump readers which still use this symbol to enumerate modules.
420+
uint64_t dyldInfoAddress = 0;
421+
if (!module.TryLookupSymbol("dyld_all_image_infos", &dyldInfoAddress))
427422
{
428-
continue;
423+
Trace("ERROR: Can not find the _dyld_all_image_infos symbol\n");
424+
return false;
429425
}
430-
Trace("MOD: %016llx %08x %s\n", imageAddress, module.Header().flags, imagePath.c_str());
431-
VisitModule(module);
426+
Trace("MOD: dyldInfoAddress %016llx\n", dyldInfoAddress);
432427
}
433428
return true;
434429
}

src/coreclr/debug/dbgutil/machoreader.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class MachOModule
2727
uint64_t m_strtabAddress;
2828

2929
public:
30-
MachOModule(MachOReader& reader, mach_vm_address_t baseAddress, mach_header_64* header = nullptr, std::string* name = nullptr);
30+
MachOModule(MachOReader& reader, mach_vm_address_t baseAddress, std::string* name = nullptr);
3131
~MachOModule();
3232

3333
inline mach_vm_address_t BaseAddress() const { return m_baseAddress; }
@@ -41,8 +41,6 @@ class MachOModule
4141
bool EnumerateSegments();
4242

4343
private:
44-
inline void SetName(std::string& name) { m_name = name; }
45-
4644
bool ReadLoadCommands();
4745
bool ReadSymbolTable();
4846
uint64_t GetAddressFromFileOffset(uint32_t offset);
@@ -54,9 +52,10 @@ class MachOReader
5452
friend MachOModule;
5553
public:
5654
MachOReader();
57-
bool EnumerateModules(mach_vm_address_t address, mach_header_64* header);
55+
bool EnumerateModules(mach_vm_address_t dyldInfoAddress);
5856

5957
private:
58+
bool TryRegisterModule(const struct mach_header* imageAddress, const char* imageFilePathAddress, bool dylinker);
6059
bool ReadString(const char* address, std::string& str);
6160
virtual void VisitModule(MachOModule& module) { };
6261
virtual void VisitSegment(MachOModule& module, const segment_command_64& segment) { };

0 commit comments

Comments
 (0)