diff options
author | Jason Molenda <jmolenda@apple.com> | 2016-07-07 01:09:23 +0000 |
---|---|---|
committer | Jason Molenda <jmolenda@apple.com> | 2016-07-07 01:09:23 +0000 |
commit | a2992311a2a81e96486602ebf400ff14369537b2 (patch) | |
tree | 09e49285125c176999d4435f33eb6a09c1364c32 /lldb/tools/debugserver/source/RNBRemote.cpp | |
parent | 2454a3b4e7512dc2614e82ae30ddb32c1c73b67b (diff) | |
download | bcm5719-llvm-a2992311a2a81e96486602ebf400ff14369537b2.tar.gz bcm5719-llvm-a2992311a2a81e96486602ebf400ff14369537b2.zip |
Add support to debugserver for some new ways to interact with dyld
to find the solibs loaded in a process. Support two new ways of
sending the jGetLoadedDynamicLibrariesInfos packet to debugserver
and add a new jGetSharedCacheInfo packet. Update the documentation
for these packets as well. The changes to lldb to use these will
be a separate commit.
<rdar://problem/25251243>
llvm-svn: 274718
Diffstat (limited to 'lldb/tools/debugserver/source/RNBRemote.cpp')
-rw-r--r-- | lldb/tools/debugserver/source/RNBRemote.cpp | 218 |
1 files changed, 201 insertions, 17 deletions
diff --git a/lldb/tools/debugserver/source/RNBRemote.cpp b/lldb/tools/debugserver/source/RNBRemote.cpp index d51afbf80b0..30b804316a1 100644 --- a/lldb/tools/debugserver/source/RNBRemote.cpp +++ b/lldb/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")); @@ -5061,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) { @@ -5488,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) { @@ -5505,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(); - if (json_sp.get()) + 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()) + { + 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"); } } } |