aboutsummaryrefslogtreecommitdiff
path: root/tools/debugserver/source/RNBRemote.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/debugserver/source/RNBRemote.cpp')
-rw-r--r--tools/debugserver/source/RNBRemote.cpp251
1 files changed, 212 insertions, 39 deletions
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;";