diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:50:09 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:50:09 +0000 | 
| commit | f3fbd1c0586ff6ec7895991e6c28f61a503c36a8 (patch) | |
| tree | 48d008fd3df8c0e73271a4b18474e0aac6dbfe33 /tools/debugserver/source/RNBRemote.cpp | |
| parent | 2fc5d2d1dfaf623ce4e24cd8590565902f8c557c (diff) | |
Notes
Diffstat (limited to 'tools/debugserver/source/RNBRemote.cpp')
| -rw-r--r-- | tools/debugserver/source/RNBRemote.cpp | 251 | 
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;";  | 
