mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-27 15:41:46 +00:00
Change the dyld notification function that lldb puts a breakpoint in
On Darwin systems, the dynamic linker dyld has an empty function it calls when binaries are added/removed from the process. lldb puts a breakpoint on this dyld function to catch the notifications. The function arguments are used by lldb to tell what is happening. The linker has a natural representation when the addresses of binaries being added/removed are in the pointer size of the process. There is then a second function where the addresses of the binaries are in a uint64_t array, which the debugger has been using before - dyld allocates memory for the array, copies the values in to it, and calls it for lldb's benefit. This changes to using the native notifier function, with pointer-sized addresses. This is the second time landing this change; this time correct the size of the image_count argument, and add a fallback if the notification function "lldb_image_notifier" can't be found. Differential Revision: https://reviews.llvm.org/D139453
This commit is contained in:
parent
93ff2110e5
commit
c3192196ae
@ -233,12 +233,13 @@ bool DynamicLoaderMacOS::NotifyBreakpointHit(void *baton,
|
||||
StoppointCallbackContext *context,
|
||||
lldb::user_id_t break_id,
|
||||
lldb::user_id_t break_loc_id) {
|
||||
// Let the event know that the images have changed
|
||||
// DYLD passes three arguments to the notification breakpoint.
|
||||
// Arg1: enum dyld_notify_mode mode - 0 = adding, 1 = removing, 2 = remove
|
||||
// all Arg2: unsigned long icount - Number of shared libraries
|
||||
// added/removed Arg3: uint64_t mach_headers[] - Array of load addresses
|
||||
// of binaries added/removed
|
||||
//
|
||||
// Our breakpoint on
|
||||
//
|
||||
// void lldb_image_notifier(enum dyld_image_mode mode, uint32_t infoCount,
|
||||
// const dyld_image_info info[])
|
||||
//
|
||||
// has been hit. We need to read the arguments.
|
||||
|
||||
DynamicLoaderMacOS *dyld_instance = (DynamicLoaderMacOS *)baton;
|
||||
|
||||
@ -268,9 +269,10 @@ bool DynamicLoaderMacOS::NotifyBreakpointHit(void *baton,
|
||||
ValueList argument_values;
|
||||
|
||||
Value mode_value; // enum dyld_notify_mode { dyld_notify_adding=0,
|
||||
// dyld_notify_removing=1, dyld_notify_remove_all=2 };
|
||||
Value count_value; // unsigned long count
|
||||
Value headers_value; // uint64_t machHeaders[] (aka void*)
|
||||
// dyld_notify_removing=1, dyld_notify_remove_all=2,
|
||||
// dyld_notify_dyld_moved=3 };
|
||||
Value count_value; // uint32_t
|
||||
Value headers_value; // struct dyld_image_info machHeaders[]
|
||||
|
||||
CompilerType clang_void_ptr_type =
|
||||
scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType();
|
||||
@ -284,13 +286,8 @@ bool DynamicLoaderMacOS::NotifyBreakpointHit(void *baton,
|
||||
mode_value.SetValueType(Value::ValueType::Scalar);
|
||||
mode_value.SetCompilerType(clang_uint32_type);
|
||||
|
||||
if (process->GetTarget().GetArchitecture().GetAddressByteSize() == 4) {
|
||||
count_value.SetValueType(Value::ValueType::Scalar);
|
||||
count_value.SetCompilerType(clang_uint32_type);
|
||||
} else {
|
||||
count_value.SetValueType(Value::ValueType::Scalar);
|
||||
count_value.SetCompilerType(clang_uint64_type);
|
||||
}
|
||||
count_value.SetValueType(Value::ValueType::Scalar);
|
||||
count_value.SetCompilerType(clang_uint32_type);
|
||||
|
||||
headers_value.SetValueType(Value::ValueType::Scalar);
|
||||
headers_value.SetCompilerType(clang_void_ptr_type);
|
||||
@ -312,12 +309,30 @@ bool DynamicLoaderMacOS::NotifyBreakpointHit(void *baton,
|
||||
argument_values.GetValueAtIndex(2)->GetScalar().ULongLong(-1);
|
||||
if (header_array != static_cast<uint64_t>(-1)) {
|
||||
std::vector<addr_t> image_load_addresses;
|
||||
// header_array points to an array of image_infos_count elements,
|
||||
// each is
|
||||
// struct dyld_image_info {
|
||||
// const struct mach_header* imageLoadAddress;
|
||||
// const char* imageFilePath;
|
||||
// uintptr_t imageFileModDate;
|
||||
// };
|
||||
//
|
||||
// and we only need the imageLoadAddress fields.
|
||||
|
||||
const int addrsize =
|
||||
process->GetTarget().GetArchitecture().GetAddressByteSize();
|
||||
for (uint64_t i = 0; i < image_infos_count; i++) {
|
||||
Status error;
|
||||
addr_t addr = process->ReadUnsignedIntegerFromMemory(
|
||||
header_array + (8 * i), 8, LLDB_INVALID_ADDRESS, error);
|
||||
if (addr != LLDB_INVALID_ADDRESS) {
|
||||
addr_t dyld_image_info = header_array + (addrsize * 3 * i);
|
||||
addr_t addr =
|
||||
process->ReadPointerFromMemory(dyld_image_info, error);
|
||||
if (error.Success()) {
|
||||
image_load_addresses.push_back(addr);
|
||||
} else {
|
||||
Debugger::ReportWarning(
|
||||
"DynamicLoaderMacOS::NotifyBreakpointHit unable "
|
||||
"to read binary mach-o load address at 0x%" PRIx64,
|
||||
addr);
|
||||
}
|
||||
}
|
||||
if (dyld_mode == 0) {
|
||||
@ -362,10 +377,16 @@ bool DynamicLoaderMacOS::NotifyBreakpointHit(void *baton,
|
||||
Status error;
|
||||
addr_t notification_addr =
|
||||
process->ReadPointerFromMemory(notification_location, error);
|
||||
if (ABISP abi_sp = process->GetABI())
|
||||
notification_addr = abi_sp->FixCodeAddress(notification_addr);
|
||||
|
||||
dyld_instance->SetDYLDHandoverBreakpoint(notification_addr);
|
||||
if (!error.Success()) {
|
||||
Debugger::ReportWarning(
|
||||
"DynamicLoaderMacOS::NotifyBreakpointHit unable "
|
||||
"to read address of dyld-handover notification function at "
|
||||
"0x%" PRIx64,
|
||||
notification_location);
|
||||
} else {
|
||||
notification_addr = process->FixCodeAddress(notification_addr);
|
||||
dyld_instance->SetDYLDHandoverBreakpoint(notification_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -417,7 +438,16 @@ void DynamicLoaderMacOS::PutToLog(Log *log) const {
|
||||
return;
|
||||
}
|
||||
|
||||
// We want to put a breakpoint on dyld's lldb_image_notifier()
|
||||
// but we may have attached to the process during the
|
||||
// transition from on-disk-dyld to shared-cache-dyld, so there's
|
||||
// officially no dyld binary loaded in the process (libdyld will
|
||||
// report none when asked), but the kernel can find the dyld_all_image_infos
|
||||
// struct and the function pointer for lldb_image_notifier is in
|
||||
// that struct.
|
||||
bool DynamicLoaderMacOS::SetNotificationBreakpoint() {
|
||||
|
||||
// First try to find the notification breakpoint function by name
|
||||
if (m_break_id == LLDB_INVALID_BREAK_ID) {
|
||||
ModuleSP dyld_sp(GetDYLDModule());
|
||||
if (dyld_sp) {
|
||||
@ -431,9 +461,9 @@ bool DynamicLoaderMacOS::SetNotificationBreakpoint() {
|
||||
Breakpoint *breakpoint =
|
||||
m_process->GetTarget()
|
||||
.CreateBreakpoint(&dyld_filelist, source_files,
|
||||
"_dyld_debugger_notification",
|
||||
eFunctionNameTypeFull, eLanguageTypeC, 0,
|
||||
skip_prologue, internal, hardware)
|
||||
"lldb_image_notifier", eFunctionNameTypeFull,
|
||||
eLanguageTypeC, 0, skip_prologue, internal,
|
||||
hardware)
|
||||
.get();
|
||||
breakpoint->SetCallback(DynamicLoaderMacOS::NotifyBreakpointHit, this,
|
||||
true);
|
||||
@ -441,6 +471,35 @@ bool DynamicLoaderMacOS::SetNotificationBreakpoint() {
|
||||
m_break_id = breakpoint->GetID();
|
||||
}
|
||||
}
|
||||
|
||||
// Failing that, find dyld_all_image_infos struct in memory,
|
||||
// read the notification function pointer at the offset.
|
||||
if (m_break_id == LLDB_INVALID_BREAK_ID && m_process) {
|
||||
addr_t all_image_infos_addr = m_process->GetImageInfoAddress();
|
||||
if (all_image_infos_addr != LLDB_INVALID_ADDRESS) {
|
||||
const uint32_t addr_size =
|
||||
m_process->GetTarget().GetArchitecture().GetAddressByteSize();
|
||||
offset_t notification_fptr_offset = sizeof(uint32_t) + // version
|
||||
sizeof(uint32_t) + // infoArrayCount
|
||||
addr_size; // infoArray
|
||||
// notification
|
||||
Status error;
|
||||
addr_t notification_fptr = m_process->ReadPointerFromMemory(
|
||||
all_image_infos_addr + notification_fptr_offset, error);
|
||||
notification_fptr = m_process->FixCodeAddress(notification_fptr);
|
||||
Address so_addr;
|
||||
// We may not have a dyld binary mapped to this address yet;
|
||||
// don't try to express the Address object as section+offset,
|
||||
// only as a raw load address.
|
||||
so_addr.SetRawAddress(notification_fptr);
|
||||
Breakpoint *dyld_break =
|
||||
m_process->GetTarget().CreateBreakpoint(so_addr, true, false).get();
|
||||
dyld_break->SetCallback(DynamicLoaderMacOS::NotifyBreakpointHit, this,
|
||||
true);
|
||||
dyld_break->SetBreakpointKind("shared-library-event");
|
||||
m_break_id = dyld_break->GetID();
|
||||
}
|
||||
}
|
||||
return m_break_id != LLDB_INVALID_BREAK_ID;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user