diff options
Diffstat (limited to 'lldb/tools/debugserver/source/MacOSX/MachDYLD.cpp')
| -rw-r--r-- | lldb/tools/debugserver/source/MacOSX/MachDYLD.cpp | 679 |
1 files changed, 0 insertions, 679 deletions
diff --git a/lldb/tools/debugserver/source/MacOSX/MachDYLD.cpp b/lldb/tools/debugserver/source/MacOSX/MachDYLD.cpp deleted file mode 100644 index 76288c55bf52..000000000000 --- a/lldb/tools/debugserver/source/MacOSX/MachDYLD.cpp +++ /dev/null @@ -1,679 +0,0 @@ -//===-- MachDYLD.cpp --------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Created by Greg Clayton on 6/29/07. -// -//===----------------------------------------------------------------------===// - -#include "MachDYLD.h" -#include "DNB.h" -#include "DNBDataRef.h" -#include <mach-o/loader.h> -#include "DNBLog.h" - -MachDYLD::MachDYLD() : - m_pid(INVALID_NUB_PROCESS), - m_addr_size(4), - m_dyld_addr(INVALID_NUB_ADDRESS), - m_dyld_all_image_infos_addr(INVALID_NUB_ADDRESS), - m_dylib_info_header(), - m_current_dylibs(), - m_changed_dylibs(), - m_notify_break_id(INVALID_NUB_BREAK_ID), - m_dyld_info_mutex(PTHREAD_MUTEX_RECURSIVE) -{ -} - -MachDYLD::~MachDYLD() -{ - Clear(); -} - - -void -MachDYLD::Clear() -{ - PThreadMutex::Locker locker(m_dyld_info_mutex); - - nub_process_t pid = m_pid; - if (pid != INVALID_NUB_PROCESS) - { - DNBProcessSetSharedLibraryInfoCallback ( pid, NULL, NULL); - DNBBreakpointClear(pid, m_notify_break_id); - } - - m_addr_size = 4; - m_dyld_addr = INVALID_NUB_ADDRESS; - m_dyld_all_image_infos_addr = INVALID_NUB_ADDRESS; - m_dylib_info_header.Clear(); - m_current_dylibs.clear(); - m_changed_dylibs.clear(); - m_notify_break_id = INVALID_NUB_BREAK_ID; -} - - -void -MachDYLD::Initialize(nub_process_t pid) -{ - //printf("MachDYLD::%s(0x%4.4x)\n", __FUNCTION__, pid); - Clear(); - m_pid = pid; -} - - -void -MachDYLD::ProcessStateChanged(nub_state_t state) -{ - //printf("MachDYLD::%s(%s)\n", __FUNCTION__, DNBStateAsString(state)); - - switch (state) - { - case eStateInvalid: - case eStateUnloaded: - case eStateExited: - case eStateDetached: - case eStateAttaching: - case eStateLaunching: - Clear(); - break; - - case eStateStopped: - // Keep trying find dyld each time we stop until we do - if (!FoundDYLD()) - { - assert(m_pid != INVALID_NUB_PROCESS); - DNBProcessSetSharedLibraryInfoCallback ( m_pid, CopySharedInfoCallback, this); - CheckForDYLDInMemory(); - } - break; - - case eStateRunning: - case eStateStepping: - case eStateCrashed: - case eStateSuspended: - break; - - default: - break; - } -} - -void -MachDYLD::SharedLibraryStateChanged(DNBExecutableImageInfo *image_infos, nub_size_t num_image_infos) -{ - //printf("MachDYLD::%s(%p, %u)\n", __FUNCTION__, image_infos, image_infos); - -} - -bool -MachDYLD::FoundDYLD() const -{ - return m_dyld_addr != INVALID_NUB_ADDRESS; -} - -bool -MachDYLD::CheckForDYLDInMemory() -{ -#if defined (__arm__) - return CheckForDYLDInMemory(0x2fe00000); -#else - return CheckForDYLDInMemory(0x8fe00000); -#endif -} - -bool -MachDYLD::CheckForDYLDInMemory(nub_addr_t addr) -{ - std::vector<uint8_t> dyld_header; - nub_size_t page_size = 0x1000; - dyld_header.resize(page_size); - nub_size_t bytes_read = DNBProcessMemoryRead(m_pid, addr, dyld_header.size(), &dyld_header[0]); - if (bytes_read > 0) - { - DNBDataRef::offset_t offset = 0; - DNBDataRef data(&dyld_header[0], bytes_read, false); - struct mach_header *header = (struct mach_header*)data.GetData(&offset, sizeof(struct mach_header)); - if (header) - { - switch (header->magic) - { - case MH_MAGIC: - case MH_CIGAM: - data.SetPointerSize(4); - m_addr_size = 4; - break; - - case MH_MAGIC_64: - case MH_CIGAM_64: - data.SetPointerSize(8); - m_addr_size = 8; - break; - - default: - return false; - } - - if (header->filetype == MH_DYLINKER) - { - // printf( "Found DYLD mach image at %8.8p", addr); - - m_dyld_all_image_infos_addr = DNBProcessLookupAddress(m_pid, "dyld_all_image_infos", "/usr/lib/dyld"); - -#if defined (__arm__) - m_dyld_all_image_infos_addr = 0x2fe3a004; -#endif - - if (m_dyld_all_image_infos_addr != INVALID_NUB_ADDRESS) - { - // printf( "Found DYLD data symbol 'dyld_all_image_infos' is %8.8p", m_dyld_all_image_infos_addr); - - if (ReadDYLIBInfo()) - { - if (m_dylib_info_header.notification != INVALID_NUB_ADDRESS) - { - m_notify_break_id = DNBBreakpointSet(m_pid, m_dylib_info_header.notification, 4, true); - if (NUB_BREAK_ID_IS_VALID(m_notify_break_id)) - { - DNBBreakpointSetCallback(m_pid, m_notify_break_id, MachDYLD::BreakpointHit, this); - m_dyld_addr = addr; - } - } - } - // if (DNBLogCheckLogBit(LOG_SHLIB)) - // Dump(DNBLogGetLogFile()); - } - return true; - } - } - } - return false; -} - -nub_bool_t -MachDYLD::BreakpointHit(nub_process_t pid, nub_thread_t tid, nub_break_t breakID, void *baton) -{ - MachDYLD *dyld = (MachDYLD*) baton; - //printf("MachDYLD::BreakpointHit called"); - dyld->ReadDYLIBInfo(); - DNBProcessSharedLibrariesUpdated(pid); - return false; // Don't stop the process, let it continue -} - -bool -MachDYLD::ReadDYLIBInfo() -{ - nub_addr_t addr = m_dyld_all_image_infos_addr; - if (addr != INVALID_NUB_ADDRESS) - { - PThreadMutex::Locker locker(m_dyld_info_mutex); - //printf("MachDYLD::ReadDYLIBInfo(addr =%8.8p)", addr); - bool swap = false; - uint32_t i = 0; - DYLIBInfo::collection previous_dylibs; - previous_dylibs.swap(m_current_dylibs); - uint8_t all_dylib_info_data[32]; - nub_size_t count = 8 + m_addr_size * 2; - nub_size_t bytes_read = DNBProcessMemoryRead(m_pid, addr, count, &all_dylib_info_data[0]); - if (bytes_read != count) - { - m_dylib_info_header.Clear(); - return false; - } - - DNBDataRef data(all_dylib_info_data, sizeof(all_dylib_info_data), swap); - data.SetPointerSize(m_addr_size); - DNBDataRef::offset_t offset = 0; - m_dylib_info_header.version = data.Get32(&offset); - m_dylib_info_header.dylib_info_count = data.Get32(&offset); - m_dylib_info_header.dylib_info_addr = data.GetPointer(&offset); - m_dylib_info_header.notification = data.GetPointer(&offset); - //printf( "%s: version=%d, count=%d, addr=%8.8p, notify=%8.8p", - // __PRETTY_FUNCTION__, - // m_dylib_info_header.version, - // m_dylib_info_header.dylib_info_count, - // m_dylib_info_header.dylib_info_addr, - // m_dylib_info_header.notification); - - switch (m_dylib_info_header.version) - { - case 1: // 10.4.x and prior - { - } - break; - - case 2: // 10.5 and later - { - } - break; - - default: - //printf( "Invalid dyld all_dylib_infos version number: %d", m_dylib_info_header.version); - return false; - break; - } - - // If we made it here, we are assuming that the all dylib info data should - // be valid, lets read the info array. - if (m_dylib_info_header.dylib_info_count > 0) - { - if (m_dylib_info_header.dylib_info_addr == 0) - { - //printf( "dyld is currently updating all_dylib_infos."); - } - else - { - m_current_dylibs.resize(m_dylib_info_header.dylib_info_count); - count = m_current_dylibs.size() * 3 * m_addr_size; - std::vector<uint8_t> info_data(count, 0); - bytes_read = DNBProcessMemoryRead(m_pid, m_dylib_info_header.dylib_info_addr, count, &info_data[0]); - if (bytes_read == count) - { - DNBDataRef::offset_t info_data_offset = 0; - DNBDataRef info_data_ref(&info_data[0], info_data.size(), swap); - info_data_ref.SetPointerSize(m_addr_size); - for (i = 0; info_data_ref.ValidOffset(info_data_offset); i++) - { - assert (i < m_current_dylibs.size()); - m_current_dylibs[i].address = info_data_ref.GetPointer(&info_data_offset); - nub_addr_t path_addr = info_data_ref.GetPointer(&info_data_offset); - m_current_dylibs[i].mod_date = info_data_ref.GetPointer(&info_data_offset); - - char raw_path[PATH_MAX]; - char resolved_path[PATH_MAX]; - bytes_read = DNBProcessMemoryRead(m_pid, path_addr, sizeof(raw_path), (char*)&raw_path[0]); - if (::realpath(raw_path, resolved_path)) - m_current_dylibs[i].path = resolved_path; - else - m_current_dylibs[i].path = raw_path; - } - assert(i == m_dylib_info_header.dylib_info_count); - - UpdateUUIDs(); - } - else - { - //printf( "unable to read all data for all_dylib_infos."); - m_current_dylibs.clear(); - return false; - } - } - } - // Read any UUID values that we can get - if (m_current_dylibs.empty()) - { - m_changed_dylibs = previous_dylibs; - const size_t num_changed_dylibs = m_changed_dylibs.size(); - for (i = 0; i < num_changed_dylibs; i++) - { - // Indicate the shared library was unloaded by giving it an invalid - // address... - m_changed_dylibs[i].address = INVALID_NUB_ADDRESS; - } - } - else - { - m_changed_dylibs.clear(); - - // Most of the time when we get shared library changes, they just - // get appended to the end of the list, so find out the min number - // of entries in the current and previous list that match and see - // how many are equal. - uint32_t curr_dylib_count = m_current_dylibs.size(); - uint32_t prev_dylib_count = previous_dylibs.size(); - uint32_t common_count = std::min<uint32_t>(prev_dylib_count, curr_dylib_count); - MachDYLD::DYLIBInfo::const_iterator curr_pos = m_current_dylibs.begin(); - MachDYLD::DYLIBInfo::const_iterator curr_end = m_current_dylibs.end(); - MachDYLD::DYLIBInfo::iterator prev_pos = previous_dylibs.begin(); - uint32_t idx; - for (idx = 0; idx < common_count; idx++) - { - if (*curr_pos == *prev_pos) - { - ++curr_pos; - ++prev_pos; - } - else - break; - } - - // Remove all the entries that were at the exact same index and that - // matched between the previous_dylibs and m_current_dylibs arrays. This will cover - // most of the cases as when shared libraries get loaded they get - // appended to the end of the list. - if (prev_pos != previous_dylibs.begin()) - { - previous_dylibs.erase(previous_dylibs.begin(), prev_pos); - } - - if (previous_dylibs.empty()) - { - // We only have new libraries to add, they are the only ones that - // have changed. - if (curr_pos != curr_end) - { - m_changed_dylibs.assign(curr_pos, curr_end); - } - } - else - { - // We still have items in our previous dylib list which means either - // one or more shared libraries got unloaded somewhere in the middle - // of the list, so we will manually search for each remaining item - // in our current list in the previous list - for (; curr_pos != curr_end; ++curr_pos) - { - MachDYLD::DYLIBInfo::iterator pos = std::find(previous_dylibs.begin(), previous_dylibs.end(), *curr_pos); - if (pos == previous_dylibs.end()) - { - // This dylib wasn't here before, add it to our change list - m_changed_dylibs.push_back(*curr_pos); - } - else - { - // This dylib was in our previous dylib list, it didn't - // change, so lets remove it from the previous list so we - // don't see it again. - previous_dylibs.erase(pos); - } - } - - // The only items left if our previous_dylibs array will be shared - // libraries that got unloaded (still in previous list, and not - // mentioned in the current list). - if (!previous_dylibs.empty()) - { - const size_t num_previous_dylibs = previous_dylibs.size(); - for (i = 0; i < num_previous_dylibs; i++) - { - // Indicate the shared library was unloaded by giving it - // an invalid address... - previous_dylibs[i].address = INVALID_NUB_ADDRESS; - } - // Add all remaining previous_dylibs to the changed list with - // invalidated addresses so we know they got unloaded. - m_changed_dylibs.insert(m_changed_dylibs.end(), previous_dylibs.begin(), previous_dylibs.end()); - } - } - } - return true; - } - return false; -} - - -void -MachDYLD::UpdateUUIDs() -{ - bool swap = false; - nub_size_t page_size = 0x1000; - uint32_t i; - // Read any UUID values that we can get - for (i = 0; i < m_dylib_info_header.dylib_info_count; i++) - { - if (!m_current_dylibs[i].UUIDValid()) - { - std::vector<uint8_t> bytes(page_size, 0); - nub_size_t bytes_read = DNBProcessMemoryRead(m_pid, m_current_dylibs[i].address, page_size, &bytes[0]); - if (bytes_read > 0) - { - DNBDataRef::offset_t offset = 0; - DNBDataRef data(&bytes[0], bytes_read, swap); - struct mach_header *header = (struct mach_header*)data.GetData(&offset, sizeof(struct mach_header)); - if (header) - { - switch (header->magic) - { - case MH_MAGIC: - case MH_CIGAM: - data.SetPointerSize(4); - m_addr_size = 4; - break; - - case MH_MAGIC_64: - case MH_CIGAM_64: - data.SetPointerSize(8); - m_addr_size = 8; - offset += 4; // Skip the extra reserved field in the 64 bit mach header - break; - - default: - continue; - } - - if (header->sizeofcmds > bytes_read) - { - bytes.resize(header->sizeofcmds); - nub_addr_t addr = m_current_dylibs[i].address + bytes_read; - bytes_read += DNBProcessMemoryRead(m_pid, addr , header->sizeofcmds - bytes_read, &bytes[bytes_read]); - } - assert(bytes_read >= header->sizeofcmds); - uint32_t cmd_idx; - DNBSegment segment; - - for (cmd_idx = 0; cmd_idx < header->ncmds; cmd_idx++) - { - if (data.ValidOffsetForDataOfSize(offset, sizeof(struct load_command))) - { - struct load_command load_cmd; - DNBDataRef::offset_t load_cmd_offset = offset; - load_cmd.cmd = data.Get32(&offset); - load_cmd.cmdsize = data.Get32(&offset); - switch (load_cmd.cmd) - { - case LC_SEGMENT: - { - strncpy(segment.name, data.GetCStr(&offset, 16), 16); - memset(&segment.name[16], 0, DNB_MAX_SEGMENT_NAME_LENGTH - 16); - segment.addr = data.Get32(&offset); - segment.size = data.Get32(&offset); - m_current_dylibs[i].segments.push_back(segment); - } - break; - - case LC_SEGMENT_64: - { - strncpy(segment.name, data.GetCStr(&offset, 16), 16); - memset(&segment.name[16], 0, DNB_MAX_SEGMENT_NAME_LENGTH - 16); - segment.addr = data.Get64(&offset); - segment.size = data.Get64(&offset); - m_current_dylibs[i].segments.push_back(segment); - } - break; - - case LC_UUID: - // We found our UUID, we can stop now... - memcpy(m_current_dylibs[i].uuid, data.GetData(&offset, 16), 16); - // if (DNBLogCheckLogBit(LOG_SHLIB)) - // { - // DNBLogThreaded("UUID found for aii[%d]:", i); - // m_current_dylibs[i].Dump(DNBLogGetLogFile()); - // } - break; - - default: - break; - } - // Set offset to be the beginning of the next load command. - offset = load_cmd_offset + load_cmd.cmdsize; - } - } - } - } - } - } -} - - -nub_addr_t -MachDYLD::GetSharedLibraryHeaderAddress(const char *shlib_path) const -{ - if (!m_current_dylibs.empty() && shlib_path && shlib_path[0]) - { - uint32_t i; - for (i = 0; i<m_current_dylibs.size(); i++) - { - if (m_current_dylibs[i].path == shlib_path) - return m_current_dylibs[i].address; - } - } - return INVALID_NUB_ADDRESS; -} - - -nub_size_t -MachDYLD::CopySharedLibraryInfo(DYLIBInfo::collection& dylib_coll, DNBExecutableImageInfo **image_infos) -{ - if (!dylib_coll.empty()) - { - size_t i; - size_t total_num_segments = 0; - size_t segment_index = 0; - for (i = 0; i<dylib_coll.size(); i++) - { - total_num_segments += dylib_coll[i].segments.size(); - } - size_t image_infos_byte_size = sizeof(DNBExecutableImageInfo) * dylib_coll.size(); - size_t all_segments_byte_size = sizeof(DNBSegment) * total_num_segments; - size_t total_byte_size = image_infos_byte_size + all_segments_byte_size; - - // Allocate enough space to fit all of the shared library information in - // a single buffer so consumers can free a single chunk of data when done - uint8_t *buf = (uint8_t*)malloc (total_byte_size); - - DNBExecutableImageInfo *info = (DNBExecutableImageInfo*)buf; - DNBSegment *all_segments = (DNBSegment*)(buf + image_infos_byte_size); - if (info) - { - for (i = 0; i<dylib_coll.size(); i++) - { - strncpy(info[i].name, dylib_coll[i].path.c_str(), PATH_MAX); - // NULL terminate paths that are too long (redundant for path - // that fit, but harmless - info[i].name[PATH_MAX-1] = '\0'; - info[i].header_addr = dylib_coll[i].address; - info[i].state = (dylib_coll[i].address == INVALID_NUB_ADDRESS ? eShlibStateUnloaded : eShlibStateLoaded); - memcpy(info[i].uuid, dylib_coll[i].uuid, sizeof(uuid_t)); - info[i].num_segments = dylib_coll[i].segments.size(); - if (info[i].num_segments == 0) - { - info[i].segments = NULL; - } - else - { - info[i].segments = &all_segments[segment_index]; - memcpy(info[i].segments, &(dylib_coll[i].segments[0]), sizeof(DNBSegment) * info[i].num_segments); - segment_index += info[i].num_segments; - } - - } - // Release ownership of the shared library array to the caller - *image_infos = info; - return dylib_coll.size(); - } - } - *image_infos = NULL; - return 0; -} - - - -nub_size_t -MachDYLD::CopySharedInfoCallback(nub_process_t pid, struct DNBExecutableImageInfo **image_infos, nub_bool_t only_changed, void *baton) -{ - MachDYLD *dyld = (MachDYLD*) baton; - - if (only_changed) - return dyld->CopyChangedShlibInfo(image_infos); - else - return dyld->CopyCurrentShlibInfo(image_infos); - - *image_infos = NULL; - return 0; -} - -nub_size_t -MachDYLD::CopyCurrentShlibInfo(DNBExecutableImageInfo **image_infos) -{ - PThreadMutex::Locker locker(m_dyld_info_mutex); - return CopySharedLibraryInfo(m_current_dylibs, image_infos); -} - - -nub_size_t -MachDYLD::CopyChangedShlibInfo(DNBExecutableImageInfo **image_infos) -{ - PThreadMutex::Locker locker(m_dyld_info_mutex); - return CopySharedLibraryInfo(m_changed_dylibs, image_infos); -} - - - -void -MachDYLD::DYLIBInfo::Dump(FILE *f) const -{ - if (f == NULL) - return; - if (address == INVALID_NUB_ADDRESS) - { - if (UUIDValid()) - { - fprintf(f, "UNLOADED %8.8llx %2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X %s", - (uint64_t)mod_date, - uuid[ 0], uuid[ 1], uuid[ 2], uuid[ 3], - uuid[ 4], uuid[ 5], uuid[ 6], uuid[ 7], - uuid[ 8], uuid[ 9], uuid[10], uuid[11], - uuid[12], uuid[13], uuid[14], uuid[15], - path.c_str()); - } - else - { - fprintf(f, "UNLOADED %8.8llx %s", (uint64_t)mod_date, path.c_str()); - } - } - else - { - if (UUIDValid()) - { - fprintf(f, "%8.8llx %8.8llx %2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X %s", - (uint64_t)address, - (uint64_t)mod_date, - uuid[ 0], uuid[ 1], uuid[ 2], uuid[ 3], - uuid[ 4], uuid[ 5], uuid[ 6], uuid[ 7], - uuid[ 8], uuid[ 9], uuid[10], uuid[11], - uuid[12], uuid[13], uuid[14], uuid[15], - path.c_str()); - } - else - { - fprintf(f, "%8.8llx %8.8llx %s", (uint64_t)address, (uint64_t)mod_date, path.c_str()); - } - } -} - -void -MachDYLD::Dump(FILE *f) const -{ - if (f == NULL) - return; - - PThreadMutex::Locker locker(m_dyld_info_mutex); - fprintf(f, "\n\tMachDYLD.m_dylib_info_header: version=%d, count=%d, addr=0x%llx, notify=0x%llx", - m_dylib_info_header.version, - m_dylib_info_header.dylib_info_count, - (uint64_t)m_dylib_info_header.dylib_info_addr, - (uint64_t)m_dylib_info_header.notification); - uint32_t i; - fprintf(f, "\n\tMachDYLD.m_current_dylibs"); - for (i = 0; i<m_current_dylibs.size(); i++) - m_current_dylibs[i].Dump(f); - fprintf(f, "\n\tMachDYLD.m_changed_dylibs"); - for (i = 0; i<m_changed_dylibs.size(); i++) - m_changed_dylibs[i].Dump(f); -} - |
