diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-04 22:11:59 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-04 22:11:59 +0000 | 
| commit | cce7c2b0d24e364b1907670cf6f843531e5fe052 (patch) | |
| tree | dc8d10317720644d161fe86b0933b71e87ed0842 /source/Plugins/Process | |
| parent | 14f1b3e8826ce43b978db93a62d1166055db5394 (diff) | |
Notes
Diffstat (limited to 'source/Plugins/Process')
| -rw-r--r-- | source/Plugins/Process/Linux/NativeProcessLinux.cpp | 193 | ||||
| -rw-r--r-- | source/Plugins/Process/Linux/NativeProcessLinux.h | 4 | ||||
| -rw-r--r-- | source/Plugins/Process/elf-core/ThreadElfCore.cpp | 157 | 
3 files changed, 149 insertions, 205 deletions
| diff --git a/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/source/Plugins/Process/Linux/NativeProcessLinux.cpp index 94b9efc2b2b0..fb84729dd5f4 100644 --- a/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ b/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -1689,68 +1689,14 @@ Error NativeProcessLinux::GetMemoryRegionInfo(lldb::addr_t load_addr,    // Assume proc maps entries are in ascending order.    // FIXME assert if we find differently. -  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); -  Error error; -    if (m_supports_mem_region == LazyBool::eLazyBoolNo) {      // We're done. -    error.SetErrorString("unsupported"); -    return error; +    return Error("unsupported");    } -  // If our cache is empty, pull the latest.  There should always be at least -  // one memory region -  // if memory region handling is supported. -  if (m_mem_region_cache.empty()) { -    error = ProcFileReader::ProcessLineByLine( -        GetID(), "maps", [&](const std::string &line) -> bool { -          MemoryRegionInfo info; -          const Error parse_error = -              ParseMemoryRegionInfoFromProcMapsLine(line, info); -          if (parse_error.Success()) { -            m_mem_region_cache.push_back(info); -            return true; -          } else { -            if (log) -              log->Printf("NativeProcessLinux::%s failed to parse proc maps " -                          "line '%s': %s", -                          __FUNCTION__, line.c_str(), error.AsCString()); -            return false; -          } -        }); - -    // If we had an error, we'll mark unsupported. -    if (error.Fail()) { -      m_supports_mem_region = LazyBool::eLazyBoolNo; -      return error; -    } else if (m_mem_region_cache.empty()) { -      // No entries after attempting to read them.  This shouldn't happen if -      // /proc/{pid}/maps -      // is supported.  Assume we don't support map entries via procfs. -      if (log) -        log->Printf("NativeProcessLinux::%s failed to find any procfs maps " -                    "entries, assuming no support for memory region metadata " -                    "retrieval", -                    __FUNCTION__); -      m_supports_mem_region = LazyBool::eLazyBoolNo; -      error.SetErrorString("not supported"); -      return error; -    } - -    if (log) -      log->Printf("NativeProcessLinux::%s read %" PRIu64 -                  " memory region entries from /proc/%" PRIu64 "/maps", -                  __FUNCTION__, -                  static_cast<uint64_t>(m_mem_region_cache.size()), GetID()); - -    // We support memory retrieval, remember that. -    m_supports_mem_region = LazyBool::eLazyBoolYes; -  } else { -    if (log) -      log->Printf("NativeProcessLinux::%s reusing %" PRIu64 -                  " cached memory region entries", -                  __FUNCTION__, -                  static_cast<uint64_t>(m_mem_region_cache.size())); +  Error error = PopulateMemoryRegionCache(); +  if (error.Fail()) { +    return error;    }    lldb::addr_t prev_base_address = 0; @@ -1760,7 +1706,7 @@ Error NativeProcessLinux::GetMemoryRegionInfo(lldb::addr_t load_addr,    // There can be a ton of regions on pthreads apps with lots of threads.    for (auto it = m_mem_region_cache.begin(); it != m_mem_region_cache.end();         ++it) { -    MemoryRegionInfo &proc_entry_info = *it; +    MemoryRegionInfo &proc_entry_info = it->first;      // Sanity check assumption that /proc/{pid}/maps entries are ascending.      assert((proc_entry_info.GetRange().GetRangeBase() >= prev_base_address) && @@ -1803,6 +1749,67 @@ Error NativeProcessLinux::GetMemoryRegionInfo(lldb::addr_t load_addr,    return error;  } +Error NativeProcessLinux::PopulateMemoryRegionCache() { +  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + +  // If our cache is empty, pull the latest.  There should always be at least +  // one memory region if memory region handling is supported. +  if (!m_mem_region_cache.empty()) { +    if (log) +      log->Printf("NativeProcessLinux::%s reusing %" PRIu64 +                  " cached memory region entries", +                  __FUNCTION__, +                  static_cast<uint64_t>(m_mem_region_cache.size())); +    return Error(); +  } + +  Error error = ProcFileReader::ProcessLineByLine( +      GetID(), "maps", [&](const std::string &line) -> bool { +        MemoryRegionInfo info; +        const Error parse_error = +            ParseMemoryRegionInfoFromProcMapsLine(line, info); +        if (parse_error.Success()) { +          m_mem_region_cache.emplace_back( +              info, FileSpec(info.GetName().GetCString(), true)); +          return true; +        } else { +          if (log) +            log->Printf("NativeProcessLinux::%s failed to parse proc maps " +                        "line '%s': %s", +                        __FUNCTION__, line.c_str(), parse_error.AsCString()); +          return false; +        } +      }); + +  // If we had an error, we'll mark unsupported. +  if (error.Fail()) { +    m_supports_mem_region = LazyBool::eLazyBoolNo; +    return error; +  } else if (m_mem_region_cache.empty()) { +    // No entries after attempting to read them.  This shouldn't happen if +    // /proc/{pid}/maps is supported. Assume we don't support map entries +    // via procfs. +    if (log) +      log->Printf("NativeProcessLinux::%s failed to find any procfs maps " +                  "entries, assuming no support for memory region metadata " +                  "retrieval", +                  __FUNCTION__); +    m_supports_mem_region = LazyBool::eLazyBoolNo; +    error.SetErrorString("not supported"); +    return error; +  } + +  if (log) +    log->Printf("NativeProcessLinux::%s read %" PRIu64 +                " memory region entries from /proc/%" PRIu64 "/maps", +                __FUNCTION__, static_cast<uint64_t>(m_mem_region_cache.size()), +                GetID()); + +  // We support memory retrieval, remember that. +  m_supports_mem_region = LazyBool::eLazyBoolYes; +  return Error(); +} +  void NativeProcessLinux::DoStopIDBumped(uint32_t newBumpId) {    Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));    if (log) @@ -2463,60 +2470,38 @@ Error NativeProcessLinux::FixupBreakpointPCAsNeeded(NativeThreadLinux &thread) {  Error NativeProcessLinux::GetLoadedModuleFileSpec(const char *module_path,                                                    FileSpec &file_spec) { +  Error error = PopulateMemoryRegionCache(); +  if (error.Fail()) +    return error; +    FileSpec module_file_spec(module_path, true); -  bool found = false;    file_spec.Clear(); -  ProcFileReader::ProcessLineByLine( -      GetID(), "maps", [&](const std::string &line) { -        SmallVector<StringRef, 16> columns; -        StringRef(line).split(columns, " ", -1, false); -        if (columns.size() < 6) -          return true; // continue searching - -        FileSpec this_file_spec(columns[5].str(), false); -        if (this_file_spec.GetFilename() != module_file_spec.GetFilename()) -          return true; // continue searching - -        file_spec = this_file_spec; -        found = true; -        return false; // we are done -      }); - -  if (!found) -    return Error("Module file (%s) not found in /proc/%" PRIu64 "/maps file!", -                 module_file_spec.GetFilename().AsCString(), GetID()); - -  return Error(); +  for (const auto &it : m_mem_region_cache) { +    if (it.second.GetFilename() == module_file_spec.GetFilename()) { +      file_spec = it.second; +      return Error(); +    } +  } +  return Error("Module file (%s) not found in /proc/%" PRIu64 "/maps file!", +               module_file_spec.GetFilename().AsCString(), GetID());  }  Error NativeProcessLinux::GetFileLoadAddress(const llvm::StringRef &file_name,                                               lldb::addr_t &load_addr) {    load_addr = LLDB_INVALID_ADDRESS; -  Error error = ProcFileReader::ProcessLineByLine( -      GetID(), "maps", [&](const std::string &line) -> bool { -        StringRef maps_row(line); - -        SmallVector<StringRef, 16> maps_columns; -        maps_row.split(maps_columns, StringRef(" "), -1, false); - -        if (maps_columns.size() < 6) { -          // Return true to continue reading the proc file -          return true; -        } - -        if (maps_columns[5] == file_name) { -          StringExtractor addr_extractor(maps_columns[0].str().c_str()); -          load_addr = addr_extractor.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); - -          // Return false to stop reading the proc file further -          return false; -        } +  Error error = PopulateMemoryRegionCache(); +  if (error.Fail()) +    return error; -        // Return true to continue reading the proc file -        return true; -      }); -  return error; +  FileSpec file(file_name, false); +  for (const auto &it : m_mem_region_cache) { +    if (it.second == file) { +      load_addr = it.first.GetRange().GetRangeBase(); +      return Error(); +    } +  } +  return Error("No load address found for specified file.");  }  NativeThreadLinuxSP NativeProcessLinux::GetThreadByID(lldb::tid_t tid) { diff --git a/source/Plugins/Process/Linux/NativeProcessLinux.h b/source/Plugins/Process/Linux/NativeProcessLinux.h index fcb13c8b016b..5f51a6bc138e 100644 --- a/source/Plugins/Process/Linux/NativeProcessLinux.h +++ b/source/Plugins/Process/Linux/NativeProcessLinux.h @@ -119,7 +119,7 @@ private:    ArchSpec m_arch;    LazyBool m_supports_mem_region; -  std::vector<MemoryRegionInfo> m_mem_region_cache; +  std::vector<std::pair<MemoryRegionInfo, FileSpec>> m_mem_region_cache;    lldb::tid_t m_pending_notification_tid; @@ -217,6 +217,8 @@ private:    void ThreadWasCreated(NativeThreadLinux &thread);    void SigchldHandler(); + +  Error PopulateMemoryRegionCache();  };  } // namespace process_linux diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/source/Plugins/Process/elf-core/ThreadElfCore.cpp index 86b15c0d2fbe..bdf0c69bef24 100644 --- a/source/Plugins/Process/elf-core/ThreadElfCore.cpp +++ b/source/Plugins/Process/elf-core/ThreadElfCore.cpp @@ -202,7 +202,6 @@ ELFLinuxPrStatus::ELFLinuxPrStatus() {  Error ELFLinuxPrStatus::Parse(DataExtractor &data, ArchSpec &arch) {    Error error; -  ByteOrder byteorder = data.GetByteOrder();    if (GetSize(arch) > data.GetByteSize()) {      error.SetErrorStringWithFormat(          "NT_PRSTATUS size should be %zu, but the remaining bytes are: %" PRIu64, @@ -210,50 +209,36 @@ Error ELFLinuxPrStatus::Parse(DataExtractor &data, ArchSpec &arch) {      return error;    } -  switch (arch.GetCore()) { -  case ArchSpec::eCore_s390x_generic: -  case ArchSpec::eCore_x86_64_x86_64: -    data.ExtractBytes(0, sizeof(ELFLinuxPrStatus), byteorder, this); -    break; -  case ArchSpec::eCore_x86_32_i386: -  case ArchSpec::eCore_x86_32_i486: { -    // Parsing from a 32 bit ELF core file, and populating/reusing the structure -    // properly, because the struct is for the 64 bit version -    offset_t offset = 0; -    si_signo = data.GetU32(&offset); -    si_code = data.GetU32(&offset); -    si_errno = data.GetU32(&offset); +  // Read field by field to correctly account for endianess +  // of both the core dump and the platform running lldb. +  offset_t offset = 0; +  si_signo = data.GetU32(&offset); +  si_code = data.GetU32(&offset); +  si_errno = data.GetU32(&offset); -    pr_cursig = data.GetU16(&offset); -    offset += 2; // pad +  pr_cursig = data.GetU16(&offset); +  offset += 2; // pad -    pr_sigpend = data.GetU32(&offset); -    pr_sighold = data.GetU32(&offset); +  pr_sigpend = data.GetPointer(&offset); +  pr_sighold = data.GetPointer(&offset); -    pr_pid = data.GetU32(&offset); -    pr_ppid = data.GetU32(&offset); -    pr_pgrp = data.GetU32(&offset); -    pr_sid = data.GetU32(&offset); +  pr_pid = data.GetU32(&offset); +  pr_ppid = data.GetU32(&offset); +  pr_pgrp = data.GetU32(&offset); +  pr_sid = data.GetU32(&offset); -    pr_utime.tv_sec = data.GetU32(&offset); -    pr_utime.tv_usec = data.GetU32(&offset); +  pr_utime.tv_sec = data.GetPointer(&offset); +  pr_utime.tv_usec = data.GetPointer(&offset); -    pr_stime.tv_sec = data.GetU32(&offset); -    pr_stime.tv_usec = data.GetU32(&offset); +  pr_stime.tv_sec = data.GetPointer(&offset); +  pr_stime.tv_usec = data.GetPointer(&offset); -    pr_cutime.tv_sec = data.GetU32(&offset); -    pr_cutime.tv_usec = data.GetU32(&offset); +  pr_cutime.tv_sec = data.GetPointer(&offset); +  pr_cutime.tv_usec = data.GetPointer(&offset); -    pr_cstime.tv_sec = data.GetU32(&offset); -    pr_cstime.tv_usec = data.GetU32(&offset); +  pr_cstime.tv_sec = data.GetPointer(&offset); +  pr_cstime.tv_usec = data.GetPointer(&offset); -    break; -  } -  default: -    error.SetErrorStringWithFormat("ELFLinuxPrStatus::%s Unknown architecture", -                                   __FUNCTION__); -    break; -  }    return error;  } @@ -274,49 +259,37 @@ Error ELFLinuxPrPsInfo::Parse(DataExtractor &data, ArchSpec &arch) {          GetSize(arch), data.GetByteSize());      return error;    } - -  switch (arch.GetCore()) { -  case ArchSpec::eCore_s390x_generic: -  case ArchSpec::eCore_x86_64_x86_64: -    data.ExtractBytes(0, sizeof(ELFLinuxPrPsInfo), byteorder, this); -    break; -  case ArchSpec::eCore_x86_32_i386: -  case ArchSpec::eCore_x86_32_i486: { -    // Parsing from a 32 bit ELF core file, and populating/reusing the structure -    // properly, because the struct is for the 64 bit version -    size_t size = 0; -    offset_t offset = 0; - -    pr_state = data.GetU8(&offset); -    pr_sname = data.GetU8(&offset); -    pr_zomb = data.GetU8(&offset); -    pr_nice = data.GetU8(&offset); - -    pr_flag = data.GetU32(&offset); -    pr_uid = data.GetU16(&offset); -    pr_gid = data.GetU16(&offset); - -    pr_pid = data.GetU32(&offset); -    pr_ppid = data.GetU32(&offset); -    pr_pgrp = data.GetU32(&offset); -    pr_sid = data.GetU32(&offset); - -    size = 16; -    data.ExtractBytes(offset, size, byteorder, pr_fname); -    offset += size; - -    size = 80; -    data.ExtractBytes(offset, size, byteorder, pr_psargs); -    offset += size; - -    break; -  } -  default: -    error.SetErrorStringWithFormat("ELFLinuxPrPsInfo::%s Unknown architecture", -                                   __FUNCTION__); -    break; +  size_t size = 0; +  offset_t offset = 0; + +  pr_state = data.GetU8(&offset); +  pr_sname = data.GetU8(&offset); +  pr_zomb = data.GetU8(&offset); +  pr_nice = data.GetU8(&offset); +  if (data.GetAddressByteSize() == 8) { +    // Word align the next field on 64 bit. +    offset += 4;    } +  pr_flag = data.GetPointer(&offset); + +  // 16 bit on 32 bit platforms, 32 bit on 64 bit platforms +  pr_uid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1); +  pr_gid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1); + +  pr_pid = data.GetU32(&offset); +  pr_ppid = data.GetU32(&offset); +  pr_pgrp = data.GetU32(&offset); +  pr_sid = data.GetU32(&offset); + +  size = 16; +  data.ExtractBytes(offset, size, byteorder, pr_fname); +  offset += size; + +  size = 80; +  data.ExtractBytes(offset, size, byteorder, pr_psargs); +  offset += size; +    return error;  } @@ -329,7 +302,6 @@ ELFLinuxSigInfo::ELFLinuxSigInfo() {  Error ELFLinuxSigInfo::Parse(DataExtractor &data, const ArchSpec &arch) {    Error error; -  ByteOrder byteorder = data.GetByteOrder();    if (GetSize(arch) > data.GetByteSize()) {      error.SetErrorStringWithFormat(          "NT_SIGINFO size should be %zu, but the remaining bytes are: %" PRIu64, @@ -337,27 +309,12 @@ Error ELFLinuxSigInfo::Parse(DataExtractor &data, const ArchSpec &arch) {      return error;    } -  switch (arch.GetCore()) { -  case ArchSpec::eCore_x86_64_x86_64: -    data.ExtractBytes(0, sizeof(ELFLinuxPrStatus), byteorder, this); -    break; -  case ArchSpec::eCore_s390x_generic: -  case ArchSpec::eCore_x86_32_i386: -  case ArchSpec::eCore_x86_32_i486: { -    // Parsing from a 32 bit ELF core file, and populating/reusing the structure -    // properly, because the struct is for the 64 bit version -    offset_t offset = 0; -    si_signo = data.GetU32(&offset); -    si_code = data.GetU32(&offset); -    si_errno = data.GetU32(&offset); - -    break; -  } -  default: -    error.SetErrorStringWithFormat("ELFLinuxSigInfo::%s Unknown architecture", -                                   __FUNCTION__); -    break; -  } +  // Parsing from a 32 bit ELF core file, and populating/reusing the structure +  // properly, because the struct is for the 64 bit version +  offset_t offset = 0; +  si_signo = data.GetU32(&offset); +  si_code = data.GetU32(&offset); +  si_errno = data.GetU32(&offset);    return error;  } | 
