aboutsummaryrefslogtreecommitdiff
path: root/tools/debugserver/source
diff options
context:
space:
mode:
Diffstat (limited to 'tools/debugserver/source')
-rw-r--r--tools/debugserver/source/DNB.cpp56
-rw-r--r--tools/debugserver/source/DNB.h4
-rw-r--r--tools/debugserver/source/DNBDataRef.cpp5
-rw-r--r--tools/debugserver/source/MacOSX/CMakeLists.txt48
-rw-r--r--tools/debugserver/source/MacOSX/MachException.cpp1
-rw-r--r--tools/debugserver/source/MacOSX/MachProcess.h54
-rw-r--r--tools/debugserver/source/MacOSX/MachProcess.mm544
-rw-r--r--tools/debugserver/source/MacOSX/MachTask.h20
-rw-r--r--tools/debugserver/source/MacOSX/MachTask.mm85
-rw-r--r--tools/debugserver/source/MacOSX/Makefile54
-rw-r--r--tools/debugserver/source/MacOSX/i386/Makefile19
-rw-r--r--tools/debugserver/source/MacOSX/x86_64/Makefile19
-rw-r--r--tools/debugserver/source/Makefile46
-rw-r--r--tools/debugserver/source/RNBDefs.h21
-rw-r--r--tools/debugserver/source/RNBRemote.cpp251
-rw-r--r--tools/debugserver/source/RNBRemote.h2
-rw-r--r--tools/debugserver/source/debugserver.cpp11
17 files changed, 743 insertions, 497 deletions
diff --git a/tools/debugserver/source/DNB.cpp b/tools/debugserver/source/DNB.cpp
index 03c85df441de..bb3603649199 100644
--- a/tools/debugserver/source/DNB.cpp
+++ b/tools/debugserver/source/DNB.cpp
@@ -360,21 +360,13 @@ DNBProcessLaunch (const char *path,
char *err_str,
size_t err_len)
{
- DNBLogThreadedIf(LOG_PROCESS, "%s ( path='%s', argv = %p, envp = %p, working_dir=%s, stdin=%s, stdout=%s, stderr=%s, no-stdio=%i, launch_flavor = %u, disable_aslr = %d, err = %p, err_len = %llu) called...",
- __FUNCTION__,
- path,
- argv,
- envp,
- working_directory,
- stdin_path,
- stdout_path,
- stderr_path,
- no_stdio,
- launch_flavor,
- disable_aslr,
- err_str,
- (uint64_t)err_len);
-
+ DNBLogThreadedIf(LOG_PROCESS, "%s ( path='%s', argv = %p, envp = %p, working_dir=%s, stdin=%s, stdout=%s, "
+ "stderr=%s, no-stdio=%i, launch_flavor = %u, disable_aslr = %d, err = %p, err_len = "
+ "%llu) called...",
+ __FUNCTION__, path, static_cast<void *>(argv), static_cast<void *>(envp), working_directory,
+ stdin_path, stdout_path, stderr_path, no_stdio, launch_flavor, disable_aslr,
+ static_cast<void *>(err_str), static_cast<uint64_t>(err_len));
+
if (err_str && err_len > 0)
err_str[0] = '\0';
struct stat path_stat;
@@ -548,7 +540,6 @@ DNBProcessAttach (nub_process_t attach_pid, struct timespec *timeout, char *err_
switch (pid_state)
{
- default:
case eStateInvalid:
case eStateUnloaded:
case eStateAttaching:
@@ -1092,6 +1083,39 @@ DNBGetLoadedDynamicLibrariesInfos (nub_process_t pid, nub_addr_t image_list_addr
return JSONGenerator::ObjectSP();
}
+JSONGenerator::ObjectSP
+DNBGetAllLoadedLibrariesInfos (nub_process_t pid)
+{
+ MachProcessSP procSP;
+ if (GetProcessSP (pid, procSP))
+ {
+ return procSP->GetAllLoadedLibrariesInfos (pid);
+ }
+ return JSONGenerator::ObjectSP();
+}
+
+JSONGenerator::ObjectSP
+DNBGetLibrariesInfoForAddresses (nub_process_t pid, std::vector<uint64_t> &macho_addresses)
+{
+ MachProcessSP procSP;
+ if (GetProcessSP (pid, procSP))
+ {
+ return procSP->GetLibrariesInfoForAddresses (pid, macho_addresses);
+ }
+ return JSONGenerator::ObjectSP();
+}
+
+JSONGenerator::ObjectSP
+DNBGetSharedCacheInfo (nub_process_t pid)
+{
+ MachProcessSP procSP;
+ if (GetProcessSP (pid, procSP))
+ {
+ return procSP->GetSharedCacheInfo (pid);
+ }
+ return JSONGenerator::ObjectSP();
+}
+
const char *
diff --git a/tools/debugserver/source/DNB.h b/tools/debugserver/source/DNB.h
index 7b186d38b32a..fbaf5e348133 100644
--- a/tools/debugserver/source/DNB.h
+++ b/tools/debugserver/source/DNB.h
@@ -144,6 +144,10 @@ nub_addr_t DNBGetPThreadT (nub_process_t pid, nub_thread_t
nub_addr_t DNBGetDispatchQueueT (nub_process_t pid, nub_thread_t tid);
nub_addr_t DNBGetTSDAddressForThread (nub_process_t pid, nub_thread_t tid, uint64_t plo_pthread_tsd_base_address_offset, uint64_t plo_pthread_tsd_base_offset, uint64_t plo_pthread_tsd_entry_size);
JSONGenerator::ObjectSP DNBGetLoadedDynamicLibrariesInfos (nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count);
+JSONGenerator::ObjectSP DNBGetAllLoadedLibrariesInfos (nub_process_t pid);
+JSONGenerator::ObjectSP DNBGetLibrariesInfoForAddresses (nub_process_t pid, std::vector<uint64_t> &macho_addresses);
+JSONGenerator::ObjectSP DNBGetSharedCacheInfo (nub_process_t pid);
+
//
//----------------------------------------------------------------------
// Breakpoint functions
diff --git a/tools/debugserver/source/DNBDataRef.cpp b/tools/debugserver/source/DNBDataRef.cpp
index 53e9881dfb94..d52f28ee2fb9 100644
--- a/tools/debugserver/source/DNBDataRef.cpp
+++ b/tools/debugserver/source/DNBDataRef.cpp
@@ -250,7 +250,7 @@ DNBDataRef::Get_ULEB128 (offset_t *offset_ptr) const
{
bytecount++;
byte = *src++;
- result |= (byte & 0x7f) << shift;
+ result |= (uint64_t)(byte & 0x7f) << shift;
shift += 7;
if ((byte & 0x80) == 0)
break;
@@ -283,7 +283,7 @@ DNBDataRef::Get_SLEB128 (offset_t *offset_ptr) const
{
bytecount++;
byte = *src++;
- result |= (byte & 0x7f) << shift;
+ result |= (int64_t)(byte & 0x7f) << shift;
shift += 7;
if ((byte & 0x80) == 0)
break;
@@ -362,7 +362,6 @@ DNBDataRef::Dump
// the snprintf call each time through this loop
switch (type)
{
- default:
case TypeUInt8: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %2.2x", Get8(&offset)); break;
case TypeChar:
{
diff --git a/tools/debugserver/source/MacOSX/CMakeLists.txt b/tools/debugserver/source/MacOSX/CMakeLists.txt
index d319cb7b0bab..96cff0a22fc4 100644
--- a/tools/debugserver/source/MacOSX/CMakeLists.txt
+++ b/tools/debugserver/source/MacOSX/CMakeLists.txt
@@ -59,29 +59,31 @@ set_source_files_properties(
target_link_libraries(debugserver ${DEBUGSERVER_USED_LIBS})
-# Sign the debugserver binary
-set (CODESIGN_IDENTITY lldb_codesign)
-execute_process(
- COMMAND xcrun -f codesign_allocate
- OUTPUT_STRIP_TRAILING_WHITESPACE
- OUTPUT_VARIABLE CODESIGN_ALLOCATE
- )
-# Older cmake versions don't support "-E env".
-if (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} LESS 3.2)
- add_custom_command(TARGET debugserver
- POST_BUILD
- # Note: --entitlements option removed, as it causes errors when debugging.
- # was: COMMAND CODESIGN_ALLOCATE=${CODESIGN_ALLOCATE} codesign --entitlements ${CMAKE_CURRENT_SOURCE_DIR}/../debugserver-entitlements.plist --force --sign ${CODESIGN_IDENTITY} debugserver
- COMMAND CODESIGN_ALLOCATE=${CODESIGN_ALLOCATE} codesign --force --sign ${CODESIGN_IDENTITY} debugserver
- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/bin
- )
-else()
- add_custom_command(TARGET debugserver
- POST_BUILD
- # Note: --entitlements option removed (see comment above).
- COMMAND ${CMAKE_COMMAND} -E env CODESIGN_ALLOCATE=${CODESIGN_ALLOCATE} codesign --force --sign ${CODESIGN_IDENTITY} debugserver
- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/bin
- )
+set(LLDB_CODESIGN_IDENTITY "lldb_codesign"
+ CACHE STRING "Identity used for code signing. Set to empty string to skip the signing step.")
+if (NOT ("${LLDB_CODESIGN_IDENTITY}" STREQUAL ""))
+ execute_process(
+ COMMAND xcrun -f codesign_allocate
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ OUTPUT_VARIABLE CODESIGN_ALLOCATE
+ )
+ # Older cmake versions don't support "-E env".
+ if (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} LESS 3.2)
+ add_custom_command(TARGET debugserver
+ POST_BUILD
+ # Note: --entitlements option removed, as it causes errors when debugging.
+ # was: COMMAND CODESIGN_ALLOCATE=${CODESIGN_ALLOCATE} codesign --entitlements ${CMAKE_CURRENT_SOURCE_DIR}/../debugserver-entitlements.plist --force --sign ${LLDB_CODESIGN_IDENTITY} debugserver
+ COMMAND CODESIGN_ALLOCATE=${CODESIGN_ALLOCATE} codesign --force --sign ${LLDB_CODESIGN_IDENTITY} debugserver
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/bin
+ )
+ else()
+ add_custom_command(TARGET debugserver
+ POST_BUILD
+ # Note: --entitlements option removed (see comment above).
+ COMMAND ${CMAKE_COMMAND} -E env CODESIGN_ALLOCATE=${CODESIGN_ALLOCATE} codesign --force --sign ${LLDB_CODESIGN_IDENTITY} debugserver
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/bin
+ )
+ endif()
endif()
install(TARGETS debugserver
diff --git a/tools/debugserver/source/MacOSX/MachException.cpp b/tools/debugserver/source/MacOSX/MachException.cpp
index b7245796ae4c..0b5459e3a189 100644
--- a/tools/debugserver/source/MacOSX/MachException.cpp
+++ b/tools/debugserver/source/MacOSX/MachException.cpp
@@ -436,7 +436,6 @@ MachException::Message::Reply(MachProcess *process, int signal)
if (state.task_port == process->Task().TaskPort())
{
DNBLogThreaded("error: mach_msg() returned an error when replying to a mach exception: error = %u", err.Error());
- abort ();
}
else
{
diff --git a/tools/debugserver/source/MacOSX/MachProcess.h b/tools/debugserver/source/MacOSX/MachProcess.h
index 3be0b2dbabb3..094c13b8f0a8 100644
--- a/tools/debugserver/source/MacOSX/MachProcess.h
+++ b/tools/debugserver/source/MacOSX/MachProcess.h
@@ -15,8 +15,10 @@
#define __MachProcess_h__
#include <mach/mach.h>
+#include <mach-o/loader.h>
#include <sys/signal.h>
#include <pthread.h>
+#include <uuid/uuid.h>
#include <vector>
#include <CoreFoundation/CoreFoundation.h>
@@ -46,6 +48,45 @@ public:
MachProcess ();
~MachProcess ();
+ // A structure that can hold everything debugserver needs to know from
+ // a binary's Mach-O header / load commands.
+
+ struct mach_o_segment
+ {
+ std::string name;
+ uint64_t vmaddr;
+ uint64_t vmsize;
+ uint64_t fileoff;
+ uint64_t filesize;
+ uint64_t maxprot;
+ uint64_t initprot;
+ uint64_t nsects;
+ uint64_t flags;
+ };
+
+ struct mach_o_information
+ {
+ struct mach_header_64 mach_header;
+ std::vector<struct mach_o_segment> segments;
+ uuid_t uuid;
+ std::string min_version_os_name;
+ std::string min_version_os_version;
+ };
+
+ struct binary_image_information
+ {
+ std::string filename;
+ uint64_t load_address;
+ uint64_t mod_date; // may not be available - 0 if so
+ struct mach_o_information macho_info;
+
+ binary_image_information () :
+ filename (),
+ load_address (INVALID_NUB_ADDRESS),
+ mod_date (0)
+ { }
+ };
+
//----------------------------------------------------------------------
// Child process control
//----------------------------------------------------------------------
@@ -193,7 +234,15 @@ public:
nub_addr_t GetPThreadT (nub_thread_t tid);
nub_addr_t GetDispatchQueueT (nub_thread_t tid);
nub_addr_t GetTSDAddressForThread (nub_thread_t tid, uint64_t plo_pthread_tsd_base_address_offset, uint64_t plo_pthread_tsd_base_offset, uint64_t plo_pthread_tsd_entry_size);
+
+
+ bool GetMachOInformationFromMemory (nub_addr_t mach_o_header_addr, int wordsize, struct mach_o_information &inf);
+ JSONGenerator::ObjectSP FormatDynamicLibrariesIntoJSON (const std::vector<struct binary_image_information> &image_infos);
+ void GetAllLoadedBinariesViaDYLDSPI (std::vector<struct binary_image_information> &image_infos);
JSONGenerator::ObjectSP GetLoadedDynamicLibrariesInfos (nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count);
+ JSONGenerator::ObjectSP GetLibrariesInfoForAddresses (nub_process_t pid, std::vector<uint64_t> &macho_addresses);
+ JSONGenerator::ObjectSP GetAllLoadedLibrariesInfos (nub_process_t pid);
+ JSONGenerator::ObjectSP GetSharedCacheInfo (nub_process_t pid);
nub_size_t GetNumThreads () const;
nub_thread_t GetThreadAtIndex (nub_size_t thread_idx) const;
@@ -358,6 +407,11 @@ private:
// as the sole reason for the process being stopped, we can auto resume
// the process.
bool m_did_exec;
+
+ void * (*m_dyld_process_info_create) (task_t task, uint64_t timestamp, kern_return_t* kernelError);
+ void (*m_dyld_process_info_for_each_image) (void* info, void (^callback)(uint64_t machHeaderAddress, const uuid_t uuid, const char* path));
+ void (*m_dyld_process_info_release) (void* info);
+ void (*m_dyld_process_info_get_cache) (void* info, void* cacheInfo);
};
diff --git a/tools/debugserver/source/MacOSX/MachProcess.mm b/tools/debugserver/source/MacOSX/MachProcess.mm
index b9e06307a4aa..ab0039edd88f 100644
--- a/tools/debugserver/source/MacOSX/MachProcess.mm
+++ b/tools/debugserver/source/MacOSX/MachProcess.mm
@@ -12,8 +12,10 @@
//===----------------------------------------------------------------------===//
#include "DNB.h"
+#include <dlfcn.h>
#include <inttypes.h>
#include <mach/mach.h>
+#include <mach/task.h>
#include <signal.h>
#include <spawn.h>
#include <sys/fcntl.h>
@@ -417,8 +419,17 @@ MachProcess::MachProcess() :
m_image_infos_baton(NULL),
m_sent_interrupt_signo (0),
m_auto_resume_signo (0),
- m_did_exec (false)
+ m_did_exec (false),
+ m_dyld_process_info_create (nullptr),
+ m_dyld_process_info_for_each_image (nullptr),
+ m_dyld_process_info_release (nullptr),
+ m_dyld_process_info_get_cache (nullptr)
{
+ m_dyld_process_info_create = (void * (*) (task_t task, uint64_t timestamp, kern_return_t* kernelError)) dlsym (RTLD_DEFAULT, "_dyld_process_info_create");
+ m_dyld_process_info_for_each_image = (void (*)(void *info, void (^)(uint64_t machHeaderAddress, const uuid_t uuid, const char* path))) dlsym (RTLD_DEFAULT, "_dyld_process_info_for_each_image");
+ m_dyld_process_info_release = (void (*) (void* info)) dlsym (RTLD_DEFAULT, "_dyld_process_info_release");
+ m_dyld_process_info_get_cache = (void (*) (void* info, void* cacheInfo)) dlsym (RTLD_DEFAULT, "_dyld_process_info_get_cache");
+
DNBLogThreadedIf(LOG_PROCESS | LOG_VERBOSE, "%s", __PRETTY_FUNCTION__);
}
@@ -520,8 +531,232 @@ MachProcess::GetTSDAddressForThread (nub_thread_t tid, uint64_t plo_pthread_tsd_
return m_thread_list.GetTSDAddressForThread (tid, plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size);
}
+// Given an address, read the mach-o header and load commands out of memory to fill in
+// the mach_o_information "inf" object.
+//
+// Returns false if there was an error in reading this mach-o file header/load commands.
+
+bool
+MachProcess::GetMachOInformationFromMemory (nub_addr_t mach_o_header_addr, int wordsize, struct mach_o_information &inf)
+{
+ uint64_t load_cmds_p;
+ if (wordsize == 4)
+ {
+ struct mach_header header;
+ if (ReadMemory (mach_o_header_addr, sizeof (struct mach_header), &header) != sizeof (struct mach_header))
+ {
+ return false;
+ }
+ load_cmds_p = mach_o_header_addr + sizeof (struct mach_header);
+ inf.mach_header.magic = header.magic;
+ inf.mach_header.cputype = header.cputype;
+ // high byte of cpusubtype is used for "capability bits", v. CPU_SUBTYPE_MASK, CPU_SUBTYPE_LIB64 in machine.h
+ inf.mach_header.cpusubtype = header.cpusubtype & 0x00ffffff;
+ inf.mach_header.filetype = header.filetype;
+ inf.mach_header.ncmds = header.ncmds;
+ inf.mach_header.sizeofcmds = header.sizeofcmds;
+ inf.mach_header.flags = header.flags;
+ }
+ else
+ {
+ struct mach_header_64 header;
+ if (ReadMemory (mach_o_header_addr, sizeof (struct mach_header_64), &header) != sizeof (struct mach_header_64))
+ {
+ return false;
+ }
+ load_cmds_p = mach_o_header_addr + sizeof (struct mach_header_64);
+ inf.mach_header.magic = header.magic;
+ inf.mach_header.cputype = header.cputype;
+ // high byte of cpusubtype is used for "capability bits", v. CPU_SUBTYPE_MASK, CPU_SUBTYPE_LIB64 in machine.h
+ inf.mach_header.cpusubtype = header.cpusubtype & 0x00ffffff;
+ inf.mach_header.filetype = header.filetype;
+ inf.mach_header.ncmds = header.ncmds;
+ inf.mach_header.sizeofcmds = header.sizeofcmds;
+ inf.mach_header.flags = header.flags;
+ }
+ for (uint32_t j = 0; j < inf.mach_header.ncmds; j++)
+ {
+ struct load_command lc;
+ if (ReadMemory (load_cmds_p, sizeof (struct load_command), &lc) != sizeof (struct load_command))
+ {
+ return false;
+ }
+ if (lc.cmd == LC_SEGMENT)
+ {
+ struct segment_command seg;
+ if (ReadMemory (load_cmds_p, sizeof (struct segment_command), &seg) != sizeof (struct segment_command))
+ {
+ return false;
+ }
+ struct mach_o_segment this_seg;
+ char name[17];
+ ::memset (name, 0, sizeof (name));
+ memcpy (name, seg.segname, sizeof (seg.segname));
+ this_seg.name = name;
+ this_seg.vmaddr = seg.vmaddr;
+ this_seg.vmsize = seg.vmsize;
+ this_seg.fileoff = seg.fileoff;
+ this_seg.filesize = seg.filesize;
+ this_seg.maxprot = seg.maxprot;
+ this_seg.initprot = seg.initprot;
+ this_seg.nsects = seg.nsects;
+ this_seg.flags = seg.flags;
+ inf.segments.push_back(this_seg);
+ }
+ if (lc.cmd == LC_SEGMENT_64)
+ {
+ struct segment_command_64 seg;
+ if (ReadMemory (load_cmds_p, sizeof (struct segment_command_64), &seg) != sizeof (struct segment_command_64))
+ {
+ return false;
+ }
+ struct mach_o_segment this_seg;
+ char name[17];
+ ::memset (name, 0, sizeof (name));
+ memcpy (name, seg.segname, sizeof (seg.segname));
+ this_seg.name = name;
+ this_seg.vmaddr = seg.vmaddr;
+ this_seg.vmsize = seg.vmsize;
+ this_seg.fileoff = seg.fileoff;
+ this_seg.filesize = seg.filesize;
+ this_seg.maxprot = seg.maxprot;
+ this_seg.initprot = seg.initprot;
+ this_seg.nsects = seg.nsects;
+ this_seg.flags = seg.flags;
+ inf.segments.push_back(this_seg);
+ }
+ if (lc.cmd == LC_UUID)
+ {
+ struct uuid_command uuidcmd;
+ if (ReadMemory (load_cmds_p, sizeof (struct uuid_command), &uuidcmd) == sizeof (struct uuid_command))
+ uuid_copy (inf.uuid, uuidcmd.uuid);
+ }
+ bool lc_cmd_known = lc.cmd == LC_VERSION_MIN_IPHONEOS || lc.cmd == LC_VERSION_MIN_MACOSX;
+#if defined(LC_VERSION_MIN_TVOS)
+ lc_cmd_known |= lc.cmd == LC_VERSION_MIN_TVOS;
+#endif
+#if defined(LC_VERSION_MIN_WATCHOS)
+ lc_cmd_known |= lc.cmd == LC_VERSION_MIN_WATCHOS;
+#endif
+ if (lc_cmd_known)
+ {
+ struct version_min_command vers_cmd;
+ if (ReadMemory (load_cmds_p, sizeof (struct version_min_command), &vers_cmd) != sizeof (struct version_min_command))
+ {
+ return false;
+ }
+ switch (lc.cmd)
+ {
+ case LC_VERSION_MIN_IPHONEOS:
+ inf.min_version_os_name = "iphoneos";
+ break;
+ case LC_VERSION_MIN_MACOSX:
+ inf.min_version_os_name = "macosx";
+ break;
+#if defined(LC_VERSION_MIN_TVOS)
+ case LC_VERSION_MIN_TVOS:
+ inf.min_version_os_name = "tvos";
+ break;
+#endif
+#if defined(LC_VERSION_MIN_WATCHOS)
+ case LC_VERSION_MIN_WATCHOS:
+ inf.min_version_os_name = "watchos";
+ break;
+#endif
+ default:
+ return false;
+ }
+ uint32_t xxxx = vers_cmd.sdk >> 16;
+ uint32_t yy = (vers_cmd.sdk >> 8) & 0xffu;
+ uint32_t zz = vers_cmd.sdk & 0xffu;
+ inf.min_version_os_version = "";
+ inf.min_version_os_version += std::to_string(xxxx);
+ inf.min_version_os_version += ".";
+ inf.min_version_os_version += std::to_string(yy);
+ if (zz != 0)
+ {
+ inf.min_version_os_version += ".";
+ inf.min_version_os_version += std::to_string(zz);
+ }
+ }
+ load_cmds_p += lc.cmdsize;
+ }
+ return true;
+}
+
+// Given completely filled in array of binary_image_information structures, create a JSONGenerator object
+// with all the details we want to send to lldb.
+JSONGenerator::ObjectSP
+MachProcess::FormatDynamicLibrariesIntoJSON (const std::vector<struct binary_image_information> &image_infos)
+{
+
+ JSONGenerator::ArraySP image_infos_array_sp (new JSONGenerator::Array());
+
+ const size_t image_count = image_infos.size();
+
+ for (size_t i = 0; i < image_count; i++)
+ {
+ JSONGenerator::DictionarySP image_info_dict_sp (new JSONGenerator::Dictionary());
+ image_info_dict_sp->AddIntegerItem ("load_address", image_infos[i].load_address);
+ image_info_dict_sp->AddIntegerItem ("mod_date", image_infos[i].mod_date);
+ image_info_dict_sp->AddStringItem ("pathname", image_infos[i].filename);
+
+ uuid_string_t uuidstr;
+ uuid_unparse_upper (image_infos[i].macho_info.uuid, uuidstr);
+ image_info_dict_sp->AddStringItem ("uuid", uuidstr);
+
+ if (image_infos[i].macho_info.min_version_os_name.empty() == false
+ && image_infos[i].macho_info.min_version_os_version.empty() == false)
+ {
+ image_info_dict_sp->AddStringItem ("min_version_os_name", image_infos[i].macho_info.min_version_os_name);
+ image_info_dict_sp->AddStringItem ("min_version_os_sdk", image_infos[i].macho_info.min_version_os_version);
+ }
+
+ JSONGenerator::DictionarySP mach_header_dict_sp (new JSONGenerator::Dictionary());
+ mach_header_dict_sp->AddIntegerItem ("magic", image_infos[i].macho_info.mach_header.magic);
+ mach_header_dict_sp->AddIntegerItem ("cputype", (uint32_t) image_infos[i].macho_info.mach_header.cputype);
+ mach_header_dict_sp->AddIntegerItem ("cpusubtype", (uint32_t) image_infos[i].macho_info.mach_header.cpusubtype);
+ mach_header_dict_sp->AddIntegerItem ("filetype", image_infos[i].macho_info.mach_header.filetype);
+
+// DynamicLoaderMacOSX doesn't currently need these fields, so don't send them.
+// mach_header_dict_sp->AddIntegerItem ("ncmds", image_infos[i].macho_info.mach_header.ncmds);
+// mach_header_dict_sp->AddIntegerItem ("sizeofcmds", image_infos[i].macho_info.mach_header.sizeofcmds);
+// mach_header_dict_sp->AddIntegerItem ("flags", image_infos[i].macho_info.mach_header.flags);
+ image_info_dict_sp->AddItem ("mach_header", mach_header_dict_sp);
+
+ JSONGenerator::ArraySP segments_sp (new JSONGenerator::Array());
+ for (size_t j = 0; j < image_infos[i].macho_info.segments.size(); j++)
+ {
+ JSONGenerator::DictionarySP segment_sp (new JSONGenerator::Dictionary());
+ segment_sp->AddStringItem ("name", image_infos[i].macho_info.segments[j].name);
+ segment_sp->AddIntegerItem ("vmaddr", image_infos[i].macho_info.segments[j].vmaddr);
+ segment_sp->AddIntegerItem ("vmsize", image_infos[i].macho_info.segments[j].vmsize);
+ segment_sp->AddIntegerItem ("fileoff", image_infos[i].macho_info.segments[j].fileoff);
+ segment_sp->AddIntegerItem ("filesize", image_infos[i].macho_info.segments[j].filesize);
+ segment_sp->AddIntegerItem ("maxprot", image_infos[i].macho_info.segments[j].maxprot);
+
+// DynamicLoaderMacOSX doesn't currently need these fields, so don't send them.
+// segment_sp->AddIntegerItem ("initprot", image_infos[i].macho_info.segments[j].initprot);
+// segment_sp->AddIntegerItem ("nsects", image_infos[i].macho_info.segments[j].nsects);
+// segment_sp->AddIntegerItem ("flags", image_infos[i].macho_info.segments[j].flags);
+ segments_sp->AddItem (segment_sp);
+ }
+ image_info_dict_sp->AddItem ("segments", segments_sp);
+
+ image_infos_array_sp->AddItem (image_info_dict_sp);
+ }
+ JSONGenerator::DictionarySP reply_sp (new JSONGenerator::Dictionary());;
+ reply_sp->AddItem ("images", image_infos_array_sp);
+ return reply_sp;
+}
+
+// Get the shared library information using the old (pre-macOS 10.12, pre-iOS 10, pre-tvOS 10, pre-watchOS 3)
+// code path. We'll be given the address of an array of structures in the form
+// {void* load_addr, void* mod_date, void* pathname}
+//
+// In macOS 10.12 etc and newer, we'll use SPI calls into dyld to gather this information.
JSONGenerator::ObjectSP
MachProcess::GetLoadedDynamicLibrariesInfos (nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count)
{
@@ -536,29 +771,7 @@ MachProcess::GetLoadedDynamicLibrariesInfos (nub_process_t pid, nub_addr_t image
if (processInfo.kp_proc.p_flag & P_LP64)
pointer_size = 8;
- struct segment
- {
- std::string name;
- uint64_t vmaddr;
- uint64_t vmsize;
- uint64_t fileoff;
- uint64_t filesize;
- uint64_t maxprot;
- uint64_t initprot;
- uint64_t nsects;
- uint64_t flags;
- };
-
- struct image_info
- {
- uint64_t load_address;
- std::string pathname;
- uint64_t mod_date;
- struct mach_header_64 mach_header;
- std::vector<struct segment> segments;
- uuid_t uuid;
- };
- std::vector<image_info> image_infos;
+ std::vector<struct binary_image_information> image_infos;
size_t image_infos_size = image_count * 3 * pointer_size;
uint8_t *image_info_buf = (uint8_t *) malloc (image_infos_size);
@@ -577,7 +790,7 @@ MachProcess::GetLoadedDynamicLibrariesInfos (nub_process_t pid, nub_addr_t image
for (size_t i = 0; i < image_count; i++)
{
- struct image_info info;
+ struct binary_image_information info;
nub_addr_t pathname_address;
if (pointer_size == 4)
{
@@ -604,13 +817,13 @@ MachProcess::GetLoadedDynamicLibrariesInfos (nub_process_t pid, nub_addr_t image
pathname_address = pathname_address_64;
}
char strbuf[17];
- info.pathname = "";
+ info.filename = "";
uint64_t pathname_ptr = pathname_address;
bool still_reading = true;
while (still_reading && ReadMemory (pathname_ptr, sizeof (strbuf) - 1, strbuf) == sizeof (strbuf) - 1)
{
strbuf[sizeof(strbuf) - 1] = '\0';
- info.pathname += strbuf;
+ info.filename += strbuf;
pathname_ptr += sizeof (strbuf) - 1;
// Stop if we found nul byte indicating the end of the string
for (size_t i = 0; i < sizeof(strbuf) - 1; i++)
@@ -622,7 +835,7 @@ MachProcess::GetLoadedDynamicLibrariesInfos (nub_process_t pid, nub_addr_t image
}
}
}
- uuid_clear (info.uuid);
+ uuid_clear (info.macho_info.uuid);
image_infos.push_back (info);
}
if (image_infos.size() == 0)
@@ -630,157 +843,161 @@ MachProcess::GetLoadedDynamicLibrariesInfos (nub_process_t pid, nub_addr_t image
return reply_sp;
}
+ free (image_info_buf);
//// Second, read the mach header / load commands for all the dylibs
-
for (size_t i = 0; i < image_count; i++)
{
- uint64_t load_cmds_p;
- if (pointer_size == 4)
- {
- struct mach_header header;
- if (ReadMemory (image_infos[i].load_address, sizeof (struct mach_header), &header) != sizeof (struct mach_header))
- {
- return reply_sp;
- }
- load_cmds_p = image_infos[i].load_address + sizeof (struct mach_header);
- image_infos[i].mach_header.magic = header.magic;
- image_infos[i].mach_header.cputype = header.cputype;
- image_infos[i].mach_header.cpusubtype = header.cpusubtype;
- image_infos[i].mach_header.filetype = header.filetype;
- image_infos[i].mach_header.ncmds = header.ncmds;
- image_infos[i].mach_header.sizeofcmds = header.sizeofcmds;
- image_infos[i].mach_header.flags = header.flags;
- }
- else
- {
- struct mach_header_64 header;
- if (ReadMemory (image_infos[i].load_address, sizeof (struct mach_header_64), &header) != sizeof (struct mach_header_64))
- {
- return reply_sp;
- }
- load_cmds_p = image_infos[i].load_address + sizeof (struct mach_header_64);
- image_infos[i].mach_header.magic = header.magic;
- image_infos[i].mach_header.cputype = header.cputype;
- image_infos[i].mach_header.cpusubtype = header.cpusubtype;
- image_infos[i].mach_header.filetype = header.filetype;
- image_infos[i].mach_header.ncmds = header.ncmds;
- image_infos[i].mach_header.sizeofcmds = header.sizeofcmds;
- image_infos[i].mach_header.flags = header.flags;
- }
- for (uint32_t j = 0; j < image_infos[i].mach_header.ncmds; j++)
+ if (!GetMachOInformationFromMemory (image_infos[i].load_address, pointer_size, image_infos[i].macho_info))
{
- struct load_command lc;
- if (ReadMemory (load_cmds_p, sizeof (struct load_command), &lc) != sizeof (struct load_command))
- {
- return reply_sp;
- }
- if (lc.cmd == LC_SEGMENT)
- {
- struct segment_command seg;
- if (ReadMemory (load_cmds_p, sizeof (struct segment_command), &seg) != sizeof (struct segment_command))
- {
- return reply_sp;
- }
- struct segment this_seg;
- char name[17];
- ::memset (name, 0, sizeof (name));
- memcpy (name, seg.segname, sizeof (seg.segname));
- this_seg.name = name;
- this_seg.vmaddr = seg.vmaddr;
- this_seg.vmsize = seg.vmsize;
- this_seg.fileoff = seg.fileoff;
- this_seg.filesize = seg.filesize;
- this_seg.maxprot = seg.maxprot;
- this_seg.initprot = seg.initprot;
- this_seg.nsects = seg.nsects;
- this_seg.flags = seg.flags;
- image_infos[i].segments.push_back(this_seg);
- }
- if (lc.cmd == LC_SEGMENT_64)
- {
- struct segment_command_64 seg;
- if (ReadMemory (load_cmds_p, sizeof (struct segment_command_64), &seg) != sizeof (struct segment_command_64))
- {
- return reply_sp;
- }
- struct segment this_seg;
- char name[17];
- ::memset (name, 0, sizeof (name));
- memcpy (name, seg.segname, sizeof (seg.segname));
- this_seg.name = name;
- this_seg.vmaddr = seg.vmaddr;
- this_seg.vmsize = seg.vmsize;
- this_seg.fileoff = seg.fileoff;
- this_seg.filesize = seg.filesize;
- this_seg.maxprot = seg.maxprot;
- this_seg.initprot = seg.initprot;
- this_seg.nsects = seg.nsects;
- this_seg.flags = seg.flags;
- image_infos[i].segments.push_back(this_seg);
- }
- if (lc.cmd == LC_UUID)
- {
- struct uuid_command uuidcmd;
- if (ReadMemory (load_cmds_p, sizeof (struct uuid_command), &uuidcmd) == sizeof (struct uuid_command))
- uuid_copy (image_infos[i].uuid, uuidcmd.uuid);
- }
- load_cmds_p += lc.cmdsize;
+ return reply_sp;
}
}
- //// Thrid, format all of the above in the JSONGenerator object.
+ //// Third, format all of the above in the JSONGenerator object.
- JSONGenerator::ArraySP image_infos_array_sp (new JSONGenerator::Array());
+ return FormatDynamicLibrariesIntoJSON (image_infos);
+ }
+
+ return reply_sp;
+}
+
+// From dyld SPI header dyld_process_info.h
+typedef void* dyld_process_info;
+struct dyld_process_cache_info
+{
+ uuid_t cacheUUID; // UUID of cache used by process
+ uint64_t cacheBaseAddress; // load address of dyld shared cache
+ bool noCache; // process is running without a dyld cache
+ bool privateCache; // process is using a private copy of its dyld cache
+};
+
+
+// Use the dyld SPI present in macOS 10.12, iOS 10, tvOS 10, watchOS 3 and newer to get
+// the load address, uuid, and filenames of all the libraries.
+// This only fills in those three fields in the 'struct binary_image_information' - call
+// GetMachOInformationFromMemory to fill in the mach-o header/load command details.
+void
+MachProcess::GetAllLoadedBinariesViaDYLDSPI (std::vector<struct binary_image_information> &image_infos)
+{
+ kern_return_t kern_ret;
+ if (m_dyld_process_info_create)
+ {
+ dyld_process_info info = m_dyld_process_info_create (m_task.TaskPort(), 0, &kern_ret);
+ if (info)
+ {
+ m_dyld_process_info_for_each_image (info, ^(uint64_t mach_header_addr, const uuid_t uuid, const char *path) {
+ struct binary_image_information image;
+ image.filename = path;
+ uuid_copy (image.macho_info.uuid, uuid);
+ image.load_address = mach_header_addr;
+ image_infos.push_back (image);
+ });
+ m_dyld_process_info_release (info);
+ }
+ }
+}
+
+// Fetch information about all shared libraries using the dyld SPIs that exist in
+// macOS 10.12, iOS 10, tvOS 10, watchOS 3 and newer.
+JSONGenerator::ObjectSP
+MachProcess::GetAllLoadedLibrariesInfos (nub_process_t pid)
+{
+ JSONGenerator::DictionarySP reply_sp;
+
+ int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid };
+ struct kinfo_proc processInfo;
+ size_t bufsize = sizeof(processInfo);
+ if (sysctl(mib, (unsigned)(sizeof(mib)/sizeof(int)), &processInfo, &bufsize, NULL, 0) == 0 && bufsize > 0)
+ {
+ uint32_t pointer_size = 4;
+ if (processInfo.kp_proc.p_flag & P_LP64)
+ pointer_size = 8;
+
+ std::vector<struct binary_image_information> image_infos;
+ GetAllLoadedBinariesViaDYLDSPI (image_infos);
+ const size_t image_count = image_infos.size();
for (size_t i = 0; i < image_count; i++)
{
- JSONGenerator::DictionarySP image_info_dict_sp (new JSONGenerator::Dictionary());
- image_info_dict_sp->AddIntegerItem ("load_address", image_infos[i].load_address);
- image_info_dict_sp->AddIntegerItem ("mod_date", image_infos[i].mod_date);
- image_info_dict_sp->AddStringItem ("pathname", image_infos[i].pathname);
+ GetMachOInformationFromMemory (image_infos[i].load_address, pointer_size, image_infos[i].macho_info);
+ }
+ return FormatDynamicLibrariesIntoJSON (image_infos);
+ }
+ return reply_sp;
+}
- uuid_string_t uuidstr;
- uuid_unparse_upper (image_infos[i].uuid, uuidstr);
- image_info_dict_sp->AddStringItem ("uuid", uuidstr);
+// Fetch information about the shared libraries at the given load addresses using the
+// dyld SPIs that exist in macOS 10.12, iOS 10, tvOS 10, watchOS 3 and newer.
+JSONGenerator::ObjectSP
+MachProcess::GetLibrariesInfoForAddresses (nub_process_t pid, std::vector<uint64_t> &macho_addresses)
+{
+ JSONGenerator::DictionarySP reply_sp;
- JSONGenerator::DictionarySP mach_header_dict_sp (new JSONGenerator::Dictionary());
- mach_header_dict_sp->AddIntegerItem ("magic", image_infos[i].mach_header.magic);
- mach_header_dict_sp->AddIntegerItem ("cputype", image_infos[i].mach_header.cputype);
- mach_header_dict_sp->AddIntegerItem ("cpusubtype", image_infos[i].mach_header.cpusubtype);
- mach_header_dict_sp->AddIntegerItem ("filetype", image_infos[i].mach_header.filetype);
+ int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid };
+ struct kinfo_proc processInfo;
+ size_t bufsize = sizeof(processInfo);
+ if (sysctl(mib, (unsigned)(sizeof(mib)/sizeof(int)), &processInfo, &bufsize, NULL, 0) == 0 && bufsize > 0)
+ {
+ uint32_t pointer_size = 4;
+ if (processInfo.kp_proc.p_flag & P_LP64)
+ pointer_size = 8;
-// DynamicLoaderMacOSX doesn't currently need these fields, so don't send them.
-// mach_header_dict_sp->AddIntegerItem ("ncmds", image_infos[i].mach_header.ncmds);
-// mach_header_dict_sp->AddIntegerItem ("sizeofcmds", image_infos[i].mach_header.sizeofcmds);
-// mach_header_dict_sp->AddIntegerItem ("flags", image_infos[i].mach_header.flags);
- image_info_dict_sp->AddItem ("mach_header", mach_header_dict_sp);
+ std::vector<struct binary_image_information> all_image_infos;
+ GetAllLoadedBinariesViaDYLDSPI (all_image_infos);
- JSONGenerator::ArraySP segments_sp (new JSONGenerator::Array());
- for (size_t j = 0; j < image_infos[i].segments.size(); j++)
+ std::vector<struct binary_image_information> image_infos;
+ const size_t macho_addresses_count = macho_addresses.size();
+ const size_t all_image_infos_count = all_image_infos.size();
+ for (size_t i = 0; i < macho_addresses_count; i++)
+ {
+ for (size_t j = 0; j < all_image_infos_count; j++)
{
- JSONGenerator::DictionarySP segment_sp (new JSONGenerator::Dictionary());
- segment_sp->AddStringItem ("name", image_infos[i].segments[j].name);
- segment_sp->AddIntegerItem ("vmaddr", image_infos[i].segments[j].vmaddr);
- segment_sp->AddIntegerItem ("vmsize", image_infos[i].segments[j].vmsize);
- segment_sp->AddIntegerItem ("fileoff", image_infos[i].segments[j].fileoff);
- segment_sp->AddIntegerItem ("filesize", image_infos[i].segments[j].filesize);
- segment_sp->AddIntegerItem ("maxprot", image_infos[i].segments[j].maxprot);
-
-// DynamicLoaderMacOSX doesn't currently need these fields, so don't send them.
-// segment_sp->AddIntegerItem ("initprot", image_infos[i].segments[j].initprot);
-// segment_sp->AddIntegerItem ("nsects", image_infos[i].segments[j].nsects);
-// segment_sp->AddIntegerItem ("flags", image_infos[i].segments[j].flags);
- segments_sp->AddItem (segment_sp);
+ if (all_image_infos[j].load_address == macho_addresses[i])
+ {
+ image_infos.push_back (all_image_infos[j]);
+ }
}
- image_info_dict_sp->AddItem ("segments", segments_sp);
+ }
- image_infos_array_sp->AddItem (image_info_dict_sp);
+ const size_t image_infos_count = image_infos.size();
+ for (size_t i = 0; i < image_infos_count; i++)
+ {
+ GetMachOInformationFromMemory (image_infos[i].load_address, pointer_size, image_infos[i].macho_info);
+ }
+ return FormatDynamicLibrariesIntoJSON (image_infos);
+ }
+ return reply_sp;
+}
+
+// From dyld's internal podyld_process_info.h:
+
+JSONGenerator::ObjectSP
+MachProcess::GetSharedCacheInfo (nub_process_t pid)
+{
+ JSONGenerator::DictionarySP reply_sp (new JSONGenerator::Dictionary());;
+ kern_return_t kern_ret;
+ if (m_dyld_process_info_create && m_dyld_process_info_get_cache)
+ {
+ dyld_process_info info = m_dyld_process_info_create (m_task.TaskPort(), 0, &kern_ret);
+ if (info)
+ {
+ struct dyld_process_cache_info shared_cache_info;
+ m_dyld_process_info_get_cache (info, &shared_cache_info);
+
+ reply_sp->AddIntegerItem ("shared_cache_base_address", shared_cache_info.cacheBaseAddress);
+
+ uuid_string_t uuidstr;
+ uuid_unparse_upper (shared_cache_info.cacheUUID, uuidstr);
+ reply_sp->AddStringItem ("shared_cache_uuid", uuidstr);
+
+ reply_sp->AddBooleanItem ("no_shared_cache", shared_cache_info.noCache);
+ reply_sp->AddBooleanItem ("shared_cache_private_cache", shared_cache_info.privateCache);
+
+ m_dyld_process_info_release (info);
}
- reply_sp.reset (new JSONGenerator::Dictionary());
- reply_sp->AddItem ("images", image_infos_array_sp);
}
return reply_sp;
}
@@ -1048,6 +1265,7 @@ MachProcess::Interrupt()
if (Signal (m_sent_interrupt_signo))
{
DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Interrupt() - sent %i signal to interrupt process", m_sent_interrupt_signo);
+ return true;
}
else
{
@@ -2274,9 +2492,9 @@ MachProcess::GetGenealogyImageInfo (size_t idx)
bool
MachProcess::GetOSVersionNumbers (uint64_t *major, uint64_t *minor, uint64_t *patch)
{
- bool success = false;
-
-#if (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101000)
+#if defined (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101000)
+ return false;
+#else
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSOperatingSystemVersion vers = [[NSProcessInfo processInfo] operatingSystemVersion];
@@ -2287,12 +2505,10 @@ MachProcess::GetOSVersionNumbers (uint64_t *major, uint64_t *minor, uint64_t *pa
if (patch)
*patch = vers.patchVersion;
- success = true;
-
[pool drain];
+
+ return true;
#endif
-
- return success;
}
// Do the process specific setup for attach. If this returns NULL, then there's no
diff --git a/tools/debugserver/source/MacOSX/MachTask.h b/tools/debugserver/source/MacOSX/MachTask.h
index 96b991478c78..d8021e8f7fe3 100644
--- a/tools/debugserver/source/MacOSX/MachTask.h
+++ b/tools/debugserver/source/MacOSX/MachTask.h
@@ -93,26 +93,6 @@ public:
const MachProcess * Process () const { return m_process; }
nub_size_t PageSize ();
-
- bool HasMallocLoggingEnabled ();
-
- // enumerate the malloc records for a given address (starting with Mac OS X 10.6 Snow Leopard it should include
- // all allocations that *include* address, rather than just those *starting* at address)
- bool EnumerateMallocRecords (mach_vm_address_t address,
- MachMallocEvent *event_buffer,
- uint32_t buffer_size,
- uint32_t *count);
-
- // enumerate every malloc record generated by this task, no matter what the address
- bool EnumerateMallocRecords (MachMallocEvent *event_buffer,
- uint32_t buffer_size,
- uint32_t *count);
-
- // given a malloc event, report every stack frame that led to this event
- bool EnumerateMallocFrames (MachMallocEventId event_id,
- mach_vm_address_t *function_addresses_buffer,
- uint32_t buffer_size,
- uint32_t *count);
protected:
MachProcess * m_process; // The mach process that owns this MachTask
diff --git a/tools/debugserver/source/MacOSX/MachTask.mm b/tools/debugserver/source/MacOSX/MachTask.mm
index 9c725663d559..cc1d6a38ec05 100644
--- a/tools/debugserver/source/MacOSX/MachTask.mm
+++ b/tools/debugserver/source/MacOSX/MachTask.mm
@@ -40,7 +40,6 @@
#include "DNBLog.h"
#include "MachProcess.h"
#include "DNBDataRef.h"
-#include "stack_logging.h"
#ifdef WITH_SPRINGBOARD
@@ -1053,90 +1052,6 @@ MachTask::DeallocateMemory (nub_addr_t addr)
return false;
}
-static void foundStackLog(mach_stack_logging_record_t record, void *context) {
- *((bool*)context) = true;
-}
-
-bool
-MachTask::HasMallocLoggingEnabled ()
-{
- bool found = false;
-
- __mach_stack_logging_enumerate_records(m_task, 0x0, foundStackLog, &found);
- return found;
-}
-
-struct history_enumerator_impl_data
-{
- MachMallocEvent *buffer;
- uint32_t *position;
- uint32_t count;
-};
-
-static void history_enumerator_impl(mach_stack_logging_record_t record, void* enum_obj)
-{
- history_enumerator_impl_data *data = (history_enumerator_impl_data*)enum_obj;
-
- if (*data->position >= data->count)
- return;
-
- data->buffer[*data->position].m_base_address = record.address;
- data->buffer[*data->position].m_size = record.argument;
- data->buffer[*data->position].m_event_id = record.stack_identifier;
- data->buffer[*data->position].m_event_type = record.type_flags == stack_logging_type_alloc ? eMachMallocEventTypeAlloc :
- record.type_flags == stack_logging_type_dealloc ? eMachMallocEventTypeDealloc :
- eMachMallocEventTypeOther;
- *data->position+=1;
-}
-
-bool
-MachTask::EnumerateMallocRecords (MachMallocEvent *event_buffer,
- uint32_t buffer_size,
- uint32_t *count)
-{
- return EnumerateMallocRecords(0,
- event_buffer,
- buffer_size,
- count);
-}
-
-bool
-MachTask::EnumerateMallocRecords (mach_vm_address_t address,
- MachMallocEvent *event_buffer,
- uint32_t buffer_size,
- uint32_t *count)
-{
- if (!event_buffer || !count)
- return false;
-
- if (buffer_size == 0)
- return false;
-
- *count = 0;
- history_enumerator_impl_data data = { event_buffer, count, buffer_size };
- __mach_stack_logging_enumerate_records(m_task, address, history_enumerator_impl, &data);
- return (*count > 0);
-}
-
-bool
-MachTask::EnumerateMallocFrames (MachMallocEventId event_id,
- mach_vm_address_t *function_addresses_buffer,
- uint32_t buffer_size,
- uint32_t *count)
-{
- if (!function_addresses_buffer || !count)
- return false;
-
- if (buffer_size == 0)
- return false;
-
- __mach_stack_logging_frames_for_uniqued_stack(m_task, event_id, &function_addresses_buffer[0], buffer_size, count);
- *count -= 1;
- if (function_addresses_buffer[*count-1] < PageSize())
- *count -= 1;
- return (*count > 0);
-}
-
nub_size_t
MachTask::PageSize ()
{
diff --git a/tools/debugserver/source/MacOSX/Makefile b/tools/debugserver/source/MacOSX/Makefile
deleted file mode 100644
index d047444a9c81..000000000000
--- a/tools/debugserver/source/MacOSX/Makefile
+++ /dev/null
@@ -1,54 +0,0 @@
-##===- tools/debugserver/source/MacOSX/Makefile ------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-LLDB_LEVEL := ../../../..
-
-DIRS := i386 x86_64
-
-TOOLNAME = debugserver
-
-CODESIGN_TOOLS := 1
-
-TOOL_CODESIGN_IDENTITY := lldb_codesign
-
-LLVMLibsOptions += -llldbDebugserverCommon -llldbUtility -llldbDebugserverMacOSX_I386 -llldbDebugserverMacOSX_X86_64 \
- -framework Foundation -framework CoreFoundation
-
-GENERATED_MACH_SOURCES = $(PROJ_OBJ_DIR)/mach_excServer.c $(PROJ_OBJ_DIR)/mach_excUser.c
-
-SOURCES := CFBundle.cpp \
- CFData.cpp \
- CFString.cpp \
- MachException.cpp \
- MachProcess.cpp \
- MachTask.cpp \
- MachThread.cpp \
- MachThreadList.cpp \
- MachVMMemory.cpp \
- MachVMRegion.cpp
-
-BUILT_SOURCES = $(GENERATED_MACH_SOURCES) $(PROJ_OBJ_DIR)/HasAVX.o
-
-CPP.Flags += -I$(PROJ_OBJ_DIR)/../.. -I$(PROJ_SRC_DIR)/..
-
-LD.Flags += -Wl,-sectcreate,__TEXT,__info_plist,$(PROJ_SRC_DIR)/../../resources/lldb-debugserver-Info.plist
-
-include $(LLDB_LEVEL)/Makefile
-
-ObjectsO += $(PROJ_OBJ_DIR)/HasAVX.o
-
-$(PROJ_OBJ_DIR)/HasAVX.o: $(PROJ_SRC_DIR)/HasAVX.s
- $(Echo) "Compiling HasAVX.s for $(BuildMode) build" $(PIC_FLAG)
- $(CC) $(TargetCommonOpts) $(CompileCommonOpts) -c $< -o $@
-
-ifeq ($(HOST_OS),Darwin)
-LLVMLibsOptions += -Wl,-rpath,@loader_path/../lib/
-endif
-
-$(GENERATED_MACH_SOURCES):
- mig -I$(PROJ_OBJ_DIR)/../.. $(PROJ_SRC_DIR)/dbgnub-mig.defs \ No newline at end of file
diff --git a/tools/debugserver/source/MacOSX/i386/Makefile b/tools/debugserver/source/MacOSX/i386/Makefile
deleted file mode 100644
index f770b19834bb..000000000000
--- a/tools/debugserver/source/MacOSX/i386/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-##===- tools/debugserver/source/MacOSX/i386/Makefile -------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LLDB_LEVEL := ../../../../..
-
-LIBRARYNAME := lldbDebugserverMacOSX_I386
-BUILD_ARCHIVE = 1
-
-SOURCES := DNBArchImplI386.cpp
-
-include $(LLDB_LEVEL)/Makefile
-
-CPP.Flags += -I$(PROJ_SRC_DIR)/.. -I$(PROJ_SRC_DIR)/../.. -I$(PROJ_OBJ_DIR)/../../.. \ No newline at end of file
diff --git a/tools/debugserver/source/MacOSX/x86_64/Makefile b/tools/debugserver/source/MacOSX/x86_64/Makefile
deleted file mode 100644
index bf488c859242..000000000000
--- a/tools/debugserver/source/MacOSX/x86_64/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-##===- tools/debugserver/source/MacOSX/i386/Makefile -------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LLDB_LEVEL := ../../../../..
-
-LIBRARYNAME := lldbDebugserverMacOSX_X86_64
-BUILD_ARCHIVE = 1
-
-SOURCES := DNBArchImplX86_64.cpp
-
-include $(LLDB_LEVEL)/Makefile
-
-CPP.Flags += -I$(PROJ_SRC_DIR)/.. -I$(PROJ_SRC_DIR)/../.. -I$(PROJ_OBJ_DIR)/../../.. \ No newline at end of file
diff --git a/tools/debugserver/source/Makefile b/tools/debugserver/source/Makefile
deleted file mode 100644
index 9eaeab4d3827..000000000000
--- a/tools/debugserver/source/Makefile
+++ /dev/null
@@ -1,46 +0,0 @@
-##===- tools/debugserver/source/Makefile -------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-LLDB_LEVEL := ../../..
-
-LIBRARYNAME := lldbDebugserverCommon
-BUILD_ARCHIVE = 1
-
-SOURCES := debugserver.cpp \
- DNBArch.cpp \
- DNBBreakpoint.cpp \
- DNB.cpp \
- DNBDataRef.cpp \
- DNBError.cpp \
- DNBLog.cpp \
- DNBRegisterInfo.cpp \
- DNBThreadResumeActions.cpp \
- libdebugserver.cpp \
- PseudoTerminal.cpp \
- PThreadEvent.cpp \
- PThreadMutex.cpp \
- RNBContext.cpp \
- RNBRemote.cpp \
- RNBServices.cpp \
- RNBSocket.cpp \
- SysSignal.cpp \
- TTYState.cpp
-
-include $(LLDB_LEVEL)/Makefile
-
-ifeq ($(HOST_OS),Darwin)
-DIRS := MacOSX/i386 MacOSX/x86_64 MacOSX
-CPP.Flags += -I$(PROJ_SRC_DIR)/MacOSX
-CPP.Flags += -I$(PROJ_OBJ_DIR)/..
-BUILT_SOURCES = debugserver_vers.c
-endif
-
-ifeq ($(HOST_OS),Darwin)
-debugserver_vers.c: $(PROJ_SRC_DIR)/$(LLDB_LEVEL)/scripts/generate-vers.pl $(PROJ_SRC_DIR)/../debugserver.xcodeproj/project.pbxproj
- "$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/scripts/generate-vers.pl" "$(PROJ_SRC_DIR)/../debugserver.xcodeproj/project.pbxproj" debugserver > debugserver_vers.c
-endif
diff --git a/tools/debugserver/source/RNBDefs.h b/tools/debugserver/source/RNBDefs.h
index 984b91152415..cefa986f8ca7 100644
--- a/tools/debugserver/source/RNBDefs.h
+++ b/tools/debugserver/source/RNBDefs.h
@@ -17,16 +17,27 @@
#include "DNBDefs.h"
#include <memory>
-#define DEBUGSERVER_PROGRAM_NAME "debugserver"
+#define CONCAT2(a,b) a ## b
+#define CONCAT(a,b) CONCAT2(a,b)
+#define STRINGIZE2(x) #x
+#define STRINGIZE(x) STRINGIZE2(x)
+
+#if !defined (DEBUGSERVER_PROGRAM_SYMBOL)
+#define DEBUGSERVER_PROGRAM_SYMBOL debugserver
+#endif
+
+#if !defined (DEBUGSERVER_PROGRAM_NAME)
+#define DEBUGSERVER_PROGRAM_NAME STRINGIZE(DEBUGSERVER_PROGRAM_SYMBOL)
+#endif
#ifndef DEBUGSERVER_VERSION_NUM
-extern "C" const unsigned char debugserverVersionString[];
-#define DEBUGSERVER_VERSION_NUM debugserverVersionNumber
+extern "C" const unsigned char CONCAT(DEBUGSERVER_PROGRAM_SYMBOL, VersionString)[];
+#define DEBUGSERVER_VERSION_NUM CONCAT(DEBUGSERVER_PROGRAM_SYMBOL, VersionNumber)
#endif
#ifndef DEBUGSERVER_VERSION_STR
-extern "C" const double debugserverVersionNumber;
-#define DEBUGSERVER_VERSION_STR debugserverVersionString
+extern "C" const double CONCAT(DEBUGSERVER_PROGRAM_SYMBOL, VersionNumber);
+#define DEBUGSERVER_VERSION_STR CONCAT(DEBUGSERVER_PROGRAM_SYMBOL, VersionString)
#endif
#if defined (__i386__)
diff --git a/tools/debugserver/source/RNBRemote.cpp b/tools/debugserver/source/RNBRemote.cpp
index 6dddb046acc5..30b804316a1d 100644
--- a/tools/debugserver/source/RNBRemote.cpp
+++ b/tools/debugserver/source/RNBRemote.cpp
@@ -284,6 +284,7 @@ RNBRemote::CreatePacketTable ()
t.push_back (Packet (json_query_thread_extended_info,&RNBRemote::HandlePacket_jThreadExtendedInfo , NULL, "jThreadExtendedInfo", "Replies with JSON data of thread extended information."));
t.push_back (Packet (json_query_get_loaded_dynamic_libraries_infos, &RNBRemote::HandlePacket_jGetLoadedDynamicLibrariesInfos, NULL, "jGetLoadedDynamicLibrariesInfos", "Replies with JSON data of all the shared libraries loaded in this process."));
t.push_back (Packet (json_query_threads_info, &RNBRemote::HandlePacket_jThreadsInfo , NULL, "jThreadsInfo", "Replies with JSON data with information about all threads."));
+ t.push_back (Packet (json_query_get_shared_cache_info, &RNBRemote::HandlePacket_jGetSharedCacheInfo, NULL, "jGetSharedCacheInfo", "Replies with JSON data about the location and uuid of the shared cache in the inferior process."));
t.push_back (Packet (start_noack_mode, &RNBRemote::HandlePacket_QStartNoAckMode , NULL, "QStartNoAckMode", "Request that " DEBUGSERVER_PROGRAM_NAME " stop acking remote protocol packets"));
t.push_back (Packet (prefix_reg_packets_with_tid, &RNBRemote::HandlePacket_QThreadSuffixSupported , NULL, "QThreadSuffixSupported", "Check if thread specific packets (register packets 'g', 'G', 'p', and 'P') support having the thread ID appended to the end of the command"));
t.push_back (Packet (set_logging_mode, &RNBRemote::HandlePacket_QSetLogging , NULL, "QSetLogging:", "Check if register packets ('g', 'G', 'p', and 'P' support having the thread ID prefix"));
@@ -1026,7 +1027,6 @@ RNBRemote::ThreadFunctionReadRemoteData(void *arg)
case rnb_success:
break;
- default:
case rnb_err:
DNBLogThreadedIf (LOG_RNB_REMOTE, "RNBSocket::GetCommData returned error %u", err);
done = true;
@@ -1228,7 +1228,9 @@ RNBRemote::InitializeRegisters (bool force)
register_map_entry_t reg_entry = {
regnum++, // register number starts at zero and goes up with no gaps
reg_data_offset, // Offset into register context data, no gaps between registers
- reg_sets[set].registers[reg] // DNBRegisterInfo
+ reg_sets[set].registers[reg], // DNBRegisterInfo
+ {},
+ {},
};
name_to_regnum[reg_entry.nub_info.name] = reg_entry.debugserver_regnum;
@@ -2571,13 +2573,13 @@ RNBRemote::DispatchQueueOffsets::GetThreadQueueInfo (nub_process_t pid,
nub_addr_t pointer_to_label_address = dispatch_queue_t + dqo_label;
nub_addr_t label_addr = DNBProcessMemoryReadPointer (pid, pointer_to_label_address);
if (label_addr)
- queue_name = std::move(DNBProcessMemoryReadCString (pid, label_addr));
+ queue_name = DNBProcessMemoryReadCString(pid, label_addr);
}
else
{
// libdispatch versions 1-3, dispatch name is a fixed width char array
// in the queue structure.
- queue_name = std::move(DNBProcessMemoryReadCStringFixed(pid, dispatch_queue_t + dqo_label, dqo_label_size));
+ queue_name = DNBProcessMemoryReadCStringFixed(pid, dispatch_queue_t + dqo_label, dqo_label_size);
}
}
}
@@ -3554,13 +3556,6 @@ RNBRemote::HandlePacket_v (const char *p)
}
else if (strstr (p, "vCont") == p)
{
- typedef struct
- {
- nub_thread_t tid;
- char action;
- int signal;
- } vcont_action_t;
-
DNBThreadResumeActions thread_actions;
char *c = (char *)(p += strlen("vCont"));
char *c_end = c + strlen(c);
@@ -4433,6 +4428,7 @@ RNBRemote::HandlePacket_stop_process (const char *p)
{
// If we failed to interrupt the process, then send a stop
// reply packet as the process was probably already stopped
+ DNBLogThreaded ("RNBRemote::HandlePacket_stop_process() sending extra stop reply because DNBProcessInterrupt returned false");
HandlePacket_last_signal (NULL);
}
return rnb_success;
@@ -4645,15 +4641,9 @@ RNBRemote::HandlePacket_qHostInfo (const char *p)
uint64_t major, minor, patch;
if (DNBGetOSVersionNumbers (&major, &minor, &patch))
{
- strm << "osmajor:" << major << ";";
- strm << "osminor:" << minor << ";";
- strm << "ospatch:" << patch << ";";
-
- strm << "version:" << major << "." << minor;
- if (patch != 0)
- {
+ strm << "os_version:" << major << "." << minor;
+ if (patch != UINT64_MAX)
strm << "." << patch;
- }
strm << ";";
}
@@ -5072,6 +5062,122 @@ get_integer_value_for_key_name_from_json (const char *key, const char *json_stri
}
+// A helper function that retrieves a boolean value from
+// a one-level-deep JSON dictionary of key-value pairs. e.g.
+// jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true}]
+
+// Returns true if it was able to find the key name, and sets the 'value'
+// argument to the value found.
+
+bool
+get_boolean_value_for_key_name_from_json (const char *key, const char *json_string, bool &value)
+{
+ std::string key_with_quotes = "\"";
+ key_with_quotes += key;
+ key_with_quotes += "\"";
+ const char *c = strstr (json_string, key_with_quotes.c_str());
+ if (c)
+ {
+ c += key_with_quotes.size();
+
+ while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
+ c++;
+
+ if (*c == ':')
+ {
+ c++;
+
+ while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
+ c++;
+
+ if (strncmp (c, "true", 4) == 0)
+ {
+ value = true;
+ return true;
+ } else if (strncmp (c, "false", 5) == 0)
+ {
+ value = false;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+// A helper function that reads an array of uint64_t's from
+// a one-level-deep JSON dictionary of key-value pairs. e.g.
+// jGetLoadedDynamicLibrariesInfos:{"solib_addrs":[31345823,7768020384,7310483024]}]
+
+// Returns true if it was able to find the key name, false if it did not.
+// "ints" will have all integers found in the array appended to it.
+
+bool
+get_array_of_ints_value_for_key_name_from_json (const char *key, const char *json_string, std::vector<uint64_t> &ints)
+{
+ std::string key_with_quotes = "\"";
+ key_with_quotes += key;
+ key_with_quotes += "\"";
+ const char *c = strstr (json_string, key_with_quotes.c_str());
+ if (c)
+ {
+ c += key_with_quotes.size();
+
+ while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
+ c++;
+
+ if (*c == ':')
+ {
+ c++;
+
+ while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
+ c++;
+
+ if (*c == '[')
+ {
+ c++;
+ while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
+ c++;
+ while (1)
+ {
+ if (!isdigit (*c))
+ {
+ return true;
+ }
+
+ errno = 0;
+ char *endptr;
+ uint64_t value = strtoul (c, &endptr, 10);
+ if (errno == 0)
+ {
+ ints.push_back (value);
+ }
+ else
+ {
+ break;
+ }
+ if (endptr == c || endptr == nullptr || *endptr == '\0')
+ {
+ break;
+ }
+ c = endptr;
+
+ while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
+ c++;
+ if (*c == ',')
+ c++;
+ while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r'))
+ c++;
+ if (*c == ']')
+ {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
JSONGenerator::ObjectSP
RNBRemote::GetJSONThreadsInfo(bool threads_with_valid_stop_info_only)
{
@@ -5499,6 +5605,20 @@ RNBRemote::HandlePacket_jThreadExtendedInfo (const char *p)
return SendPacket ("OK");
}
+// This packet may be called in one of three ways:
+//
+// jGetLoadedDynamicLibrariesInfos:{"image_count":40,"image_list_address":4295244704}
+// Look for an array of the old dyld_all_image_infos style of binary infos at the image_list_address.
+// This an array of {void* load_addr, void* mod_date, void* pathname}
+//
+// jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true}
+// Use the new style (macOS 10.12, tvOS 10, iOS 10, watchOS 3) dyld SPI to get a list of all the
+// libraries loaded
+//
+// jGetLoadedDynamicLibrariesInfos:{"solib_addresses":[8382824135,3258302053,830202858503]}
+// Use the new style (macOS 10.12, tvOS 10, iOS 10, watchOS 3) dyld SPI to get the information
+// about the libraries loaded at these addresses.
+//
rnb_err_t
RNBRemote::HandlePacket_jGetLoadedDynamicLibrariesInfos (const char *p)
{
@@ -5516,28 +5636,81 @@ RNBRemote::HandlePacket_jGetLoadedDynamicLibrariesInfos (const char *p)
{
p += strlen (get_loaded_dynamic_libraries_infos_str);
- nub_addr_t image_list_address = get_integer_value_for_key_name_from_json ("image_list_address", p);
- nub_addr_t image_count = get_integer_value_for_key_name_from_json ("image_count", p);
+ JSONGenerator::ObjectSP json_sp;
+
+ std::vector<uint64_t> macho_addresses;
+ bool fetch_all_solibs = false;
+ if (get_boolean_value_for_key_name_from_json ("fetch_all_solibs", p, fetch_all_solibs) && fetch_all_solibs)
+ {
+ json_sp = DNBGetAllLoadedLibrariesInfos (pid);
+ }
+ else if (get_array_of_ints_value_for_key_name_from_json ("solib_addresses", p, macho_addresses))
+ {
+ json_sp = DNBGetLibrariesInfoForAddresses (pid, macho_addresses);
+ }
+ else
+ {
+ nub_addr_t image_list_address = get_integer_value_for_key_name_from_json ("image_list_address", p);
+ nub_addr_t image_count = get_integer_value_for_key_name_from_json ("image_count", p);
+
+ if (image_list_address != INVALID_NUB_ADDRESS && image_count != INVALID_NUB_ADDRESS)
+ {
+ json_sp = DNBGetLoadedDynamicLibrariesInfos (pid, image_list_address, image_count);
+ }
+ }
- if (image_list_address != INVALID_NUB_ADDRESS && image_count != INVALID_NUB_ADDRESS)
+ if (json_sp.get())
{
- JSONGenerator::ObjectSP json_sp;
+ std::ostringstream json_str;
+ json_sp->Dump (json_str);
+ if (json_str.str().size() > 0)
+ {
+ std::string json_str_quoted = binary_encode_string (json_str.str());
+ return SendPacket (json_str_quoted.c_str());
+ }
+ else
+ {
+ SendPacket ("E84");
+ }
+ }
+ }
+ return SendPacket ("OK");
+}
- json_sp = DNBGetLoadedDynamicLibrariesInfos (pid, image_list_address, image_count);
+// This packet does not currently take any arguments. So the behavior is
+// jGetSharedCacheInfo:{}
+// send information about the inferior's shared cache
+// jGetSharedCacheInfo:
+// send "OK" to indicate that this packet is supported
+rnb_err_t
+RNBRemote::HandlePacket_jGetSharedCacheInfo (const char *p)
+{
+ nub_process_t pid;
+ // If we haven't run the process yet, return an error.
+ if (!m_ctx.HasValidProcessID())
+ {
+ return SendPacket ("E85");
+ }
+
+ pid = m_ctx.ProcessID();
+
+ const char get_shared_cache_info_str[] = { "jGetSharedCacheInfo:{" };
+ if (strncmp (p, get_shared_cache_info_str, sizeof (get_shared_cache_info_str) - 1) == 0)
+ {
+ JSONGenerator::ObjectSP json_sp = DNBGetSharedCacheInfo (pid);
- if (json_sp.get())
+ if (json_sp.get())
+ {
+ std::ostringstream json_str;
+ json_sp->Dump (json_str);
+ if (json_str.str().size() > 0)
{
- std::ostringstream json_str;
- json_sp->Dump (json_str);
- if (json_str.str().size() > 0)
- {
- std::string json_str_quoted = binary_encode_string (json_str.str());
- return SendPacket (json_str_quoted.c_str());
- }
- else
- {
- SendPacket ("E84");
- }
+ std::string json_str_quoted = binary_encode_string (json_str.str());
+ return SendPacket (json_str_quoted.c_str());
+ }
+ else
+ {
+ SendPacket ("E86");
}
}
}
@@ -5693,7 +5866,7 @@ RNBRemote::HandlePacket_qSymbol (const char *command)
if (*p)
{
// We have a symbol name
- symbol_name = std::move(decode_hex_ascii_string(p));
+ symbol_name = decode_hex_ascii_string(p);
if (!symbol_value_str.empty())
{
nub_addr_t symbol_value = decode_uint64(symbol_value_str.c_str(), 16);
@@ -5863,7 +6036,7 @@ RNBRemote::HandlePacket_qProcessInfo (const char *p)
DNBLogThreadedIf (LOG_RNB_PROC, "LC_VERSION_MIN_MACOSX -> 'ostype:macosx;'");
break;
-#if defined (TARGET_OS_TV) && TARGET_OS_TV == 1
+#if defined (LC_VERSION_MIN_TVOS)
case LC_VERSION_MIN_TVOS:
os_handled = true;
rep << "ostype:tvos;";
@@ -5871,7 +6044,7 @@ RNBRemote::HandlePacket_qProcessInfo (const char *p)
break;
#endif
-#if defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
+#if defined (LC_VERSION_MIN_WATCHOS)
case LC_VERSION_MIN_WATCHOS:
os_handled = true;
rep << "ostype:watchos;";
diff --git a/tools/debugserver/source/RNBRemote.h b/tools/debugserver/source/RNBRemote.h
index 68dd8c52ea38..1bf7535e141d 100644
--- a/tools/debugserver/source/RNBRemote.h
+++ b/tools/debugserver/source/RNBRemote.h
@@ -105,6 +105,7 @@ public:
json_query_thread_extended_info,// 'jThreadExtendedInfo'
json_query_get_loaded_dynamic_libraries_infos, // 'jGetLoadedDynamicLibrariesInfos'
json_query_threads_info, // 'jThreadsInfo'
+ json_query_get_shared_cache_info, // 'jGetSharedCacheInfo'
pass_signals_to_inferior, // 'QPassSignals'
start_noack_mode, // 'QStartNoAckMode'
prefix_reg_packets_with_tid, // 'QPrefixRegisterPacketsWithThreadID
@@ -194,6 +195,7 @@ public:
rnb_err_t HandlePacket_jThreadExtendedInfo (const char *p);
rnb_err_t HandlePacket_jGetLoadedDynamicLibrariesInfos (const char *p);
rnb_err_t HandlePacket_jThreadsInfo (const char *p);
+ rnb_err_t HandlePacket_jGetSharedCacheInfo (const char *p);
rnb_err_t HandlePacket_qThreadExtraInfo (const char *p);
rnb_err_t HandlePacket_qThreadStopInfo (const char *p);
rnb_err_t HandlePacket_qHostInfo (const char *p);
diff --git a/tools/debugserver/source/debugserver.cpp b/tools/debugserver/source/debugserver.cpp
index 78990a671d82..a22f046771d9 100644
--- a/tools/debugserver/source/debugserver.cpp
+++ b/tools/debugserver/source/debugserver.cpp
@@ -824,8 +824,9 @@ FileLogCallback(void *baton, uint32_t flags, const char *format, va_list args)
if (baton == NULL || format == NULL)
return;
- ::vfprintf ((FILE *)baton, format, args);
- ::fprintf ((FILE *)baton, "\n");
+ ::vfprintf((FILE *)baton, format, args);
+ ::fprintf((FILE *)baton, "\n");
+ ::fflush((FILE *)baton);
}
@@ -885,6 +886,10 @@ static struct option g_long_options[] =
int
main (int argc, char *argv[])
{
+ // If debugserver is launched with DYLD_INSERT_LIBRARIES, unset it so we
+ // don't spawn child processes with this enabled.
+ unsetenv("DYLD_INSERT_LIBRARIES");
+
const char *argv_sub_zero = argv[0]; // save a copy of argv[0] for error reporting post-launch
#if defined (__APPLE__)
@@ -1076,7 +1081,7 @@ main (int argc, char *argv[])
case 'K':
g_detach_on_error = false;
-
+ break;
case 'W':
if (optarg && optarg[0])
working_dir.assign(optarg);