Skip to content

Commit fc9938b

Browse files
committed
Use lldb_image_notifier if _dyld_debugger_notification is not available
1 parent 4d8e6ee commit fc9938b

3 files changed

Lines changed: 64 additions & 28 deletions

File tree

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
build
1+
build
2+
.DS_Store
3+

macOS/debugger.cpp

Lines changed: 59 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ limitations under the License.
4747
#define BREAKPOINT_TARGET 0x02
4848
#define BREAKPOINT_NOTIFICATION 0x04
4949
#define BREAKPOINT_TARGET_END 0x08
50+
#define BREAKPOINT_LLDB_NOTIFICATION 0x10
5051

5152
#define PERSIST_END_EXCEPTION 0x0F22
5253

@@ -409,7 +410,7 @@ size_t Debugger::GetReturnAddress() {
409410
#ifdef ARM64
410411
return GetRegister(LR);
411412
#else
412-
void *ra;
413+
void *ra = NULL;
413414
RemoteRead((void*)GetRegister(RSP), &ra, child_ptr_size);
414415
return (size_t)ra;
415416
#endif
@@ -713,7 +714,10 @@ void Debugger::AddBreakpoint(void *address, int type) {
713714
for (auto it = breakpoints.rbegin(); it != breakpoints.rend(); ++it) {
714715
if ((*it)->address == address) {
715716
(*it)->type |= type;
716-
if (((*it)->type & BREAKPOINT_NOTIFICATION) && ((*it)->type & BREAKPOINT_TARGET)) {
717+
if ((((*it)->type & BREAKPOINT_NOTIFICATION) ||
718+
((*it)->type & BREAKPOINT_LLDB_NOTIFICATION))
719+
&& ((*it)->type & BREAKPOINT_TARGET))
720+
{
717721
FATAL("Target method must not be the same as _dyld_debugger_notification");
718722
}
719723

@@ -1278,26 +1282,20 @@ void Debugger::OnModuleLoaded(void *module, char *module_name) {
12781282
void Debugger::HandleDyld(void *module) {
12791283
dyld_address = module;
12801284

1281-
m_dyld_debugger_notification = GetSymbolAddress(module, (char*)"__dyld_debugger_notification");
1282-
AddBreakpoint(m_dyld_debugger_notification, BREAKPOINT_NOTIFICATION);
1283-
1284-
#ifdef ARM64
1285-
// For arm we just mov pc, lr on BREAKPOINT_NOTIFICATION
1286-
#else
1287-
// This save us the recurring TRAP FLAG breakpoint on BREAKPOINT_NOTIFICATION.
1288-
unsigned char ret = 0xC3;
1289-
RemoteWrite((void*)((uint64_t)m_dyld_debugger_notification+1), (void*)&ret, 1);
1290-
#endif
1285+
void *dyld_debugger_notification = GetSymbolAddress(module, (char*)"__dyld_debugger_notification");
1286+
if(dyld_debugger_notification) {
1287+
AddBreakpoint(dyld_debugger_notification, BREAKPOINT_NOTIFICATION);
1288+
} else {
1289+
dyld_debugger_notification = GetSymbolAddress(module, (char*)"_lldb_image_notifier");
1290+
if(!dyld_debugger_notification) FATAL("Couldn't find __dyld_debugger_notification or _lldb_image_notifier");
1291+
AddBreakpoint(dyld_debugger_notification, BREAKPOINT_LLDB_NOTIFICATION);
1292+
}
12911293
}
12921294

1293-
void Debugger::OnDyldImageNotifier(size_t mode, unsigned long infoCount, uint64_t machHeaders[]) {
1294-
uint64_t *image_info_array = new uint64_t[infoCount];
1295-
size_t image_info_array_size = sizeof(uint64_t) * infoCount;
1296-
RemoteRead(machHeaders, (void*)image_info_array, image_info_array_size);
1297-
1295+
void Debugger::OnImageNotifier(size_t mode, unsigned long infoCount, uint64_t* headers) {
12981296
if (mode == 1) { /* dyld_image_removing */
12991297
for (unsigned long i = 0; i < infoCount; ++i) {
1300-
OnModuleUnloaded((void*)image_info_array[i]);
1298+
OnModuleUnloaded((void*)headers[i]);
13011299
}
13021300
} else {
13031301
dyld_all_image_infos all_image_infos = mach_target->GetAllImageInfos();
@@ -1319,8 +1317,8 @@ void Debugger::OnDyldImageNotifier(size_t mode, unsigned long infoCount, uint64_
13191317
void *mach_header_addr = (void*)all_image_info_array[i].imageLoadAddress;
13201318
if (mode == 2) { /* dyld_notify_remove_all */
13211319
OnModuleUnloaded(mach_header_addr);
1322-
} else if (std::find(image_info_array, image_info_array + infoCount, (uint64_t)mach_header_addr)
1323-
!= image_info_array + infoCount) {
1320+
} else if (std::find(headers, headers + infoCount, (uint64_t)mach_header_addr)
1321+
!= headers + infoCount) {
13241322
/* dyld_image_adding */
13251323
mach_target->ReadCString((uint64_t)all_image_info_array[i].imageFilePath, PATH_MAX, path);
13261324
char *base_name = strrchr((char*)path, '/');
@@ -1331,10 +1329,35 @@ void Debugger::OnDyldImageNotifier(size_t mode, unsigned long infoCount, uint64_
13311329

13321330
delete [] all_image_info_array;
13331331
}
1332+
}
1333+
1334+
void Debugger::OnDyldImageNotifier(size_t mode, unsigned long infoCount, uint64_t machHeaders[]) {
1335+
uint64_t *image_info_array = new uint64_t[infoCount];
1336+
size_t image_info_array_size = sizeof(uint64_t) * infoCount;
1337+
RemoteRead(machHeaders, (void*)image_info_array, image_info_array_size);
1338+
1339+
OnImageNotifier(mode, infoCount, image_info_array);
1340+
1341+
delete [] image_info_array;
1342+
}
1343+
1344+
void Debugger::OnLldbImageNotifier(size_t mode, unsigned long infoCount, size_t infos) {
1345+
uint64_t *header_array = new uint64_t[infoCount];
1346+
uint64_t *image_info_array = new uint64_t[infoCount * 3];
1347+
1348+
RemoteRead((void *)infos, (void *)image_info_array, 3 * sizeof(uint64_t) * infoCount);
1349+
1350+
for(size_t i = 0; i < infoCount; i++) {
1351+
header_array[i] = image_info_array[i * 3];
1352+
}
1353+
1354+
OnImageNotifier(mode, infoCount, header_array);
13341355

1356+
delete [] header_array;
13351357
delete [] image_info_array;
13361358
}
13371359

1360+
13381361
void Debugger::OnProcessCreated() {
13391362
if (trace_debug_events) {
13401363
SAY("Debugger: Process created or attached\n");
@@ -1374,8 +1397,12 @@ int Debugger::HandleDebuggerBreakpoint() {
13741397
OnDyldImageNotifier(GetRegister(ArgumentToRegister(0)),
13751398
(unsigned long)GetRegister(ArgumentToRegister(1)),
13761399
(uint64_t*)GetRegister(ArgumentToRegister(2)));
1377-
13781400
return BREAKPOINT_NOTIFICATION;
1401+
} else if (breakpoint->type & BREAKPOINT_LLDB_NOTIFICATION) {
1402+
OnLldbImageNotifier(GetRegister(ArgumentToRegister(0)),
1403+
(unsigned long)GetRegister(ArgumentToRegister(1)),
1404+
GetRegister(ArgumentToRegister(2)));
1405+
return BREAKPOINT_LLDB_NOTIFICATION;
13791406
}
13801407

13811408
breakpoints.erase(iter);
@@ -1438,12 +1465,19 @@ void Debugger::HandleExceptionInternal(MachException *raised_mach_exception) {
14381465
if (breakpoint_type & BREAKPOINT_TARGET_END) {
14391466
handle_exception_status = DEBUGGER_TARGET_END;
14401467
}
1468+
if ((breakpoint_type & BREAKPOINT_NOTIFICATION) ||
1469+
(breakpoint_type & BREAKPOINT_LLDB_NOTIFICATION))
1470+
{
1471+
// simulate return
14411472
#ifdef ARM64
1442-
if (breakpoint_type & BREAKPOINT_NOTIFICATION) {
1443-
SetRegister(ARCH_PC, GetRegister(LR));
1444-
return;
1445-
}
1473+
SetRegister(ARCH_PC, GetRegister(LR));
1474+
return;
1475+
#else
1476+
size_t ret_address = GetReturnAddress();
1477+
SetRegister(ARCH_SP, GetRegister(ARCH_SP) + child_ptr_size);
1478+
SetRegister(ARCH_PC, ret_address);
14461479
#endif
1480+
}
14471481

14481482
if (breakpoint_type != BREAKPOINT_UNKNOWN) {
14491483
return;

macOS/debugger.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,9 @@ friend kern_return_t catch_mach_exception_raise_state_identity(
369369
const char *segname,
370370
TCMD **ret_command);
371371

372+
void OnImageNotifier(size_t mode, unsigned long infoCount, uint64_t* headers);
372373
void OnDyldImageNotifier(size_t mode, unsigned long infoCount, uint64_t machHeaders[]);
374+
void OnLldbImageNotifier(size_t mode, unsigned long infoCount, size_t infos);
373375

374376
void AddBreakpoint(void *address, int type);
375377
void DeleteBreakpoints();
@@ -435,8 +437,6 @@ friend kern_return_t catch_mach_exception_raise_state_identity(
435437

436438
void (*m_dyld_process_info_release)(void *info);
437439

438-
void *m_dyld_debugger_notification;
439-
440440
void *dyld_address;
441441

442442
bool mute_child;

0 commit comments

Comments
 (0)