[Lldb-commits] [lldb] r318903 - elf-core: Split up parsing code into os-specific functions

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Thu Nov 23 02:50:34 PST 2017


Author: labath
Date: Thu Nov 23 02:50:34 2017
New Revision: 318903

URL: http://llvm.org/viewvc/llvm-project?rev=318903&view=rev
Log:
elf-core: Split up parsing code into os-specific functions

Summary:
We've had a single function responsible for splitting a core segment
into notes, and parsing the notes themselves, bearing in mind variations
between 4 supported OS types. This commit splits that code into 5
pieces:
- (os-independent) code for splitting a segment into individual notes
- per-os function for parsing the notes into thread information

Reviewers: clayborg, krytarowski, emaste, alexandreyy, kettenis

Subscribers: lldb-commits

Differential Revision: https://reviews.llvm.org/D40311

Modified:
    lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.cpp
    lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.h
    lldb/trunk/source/Plugins/Process/elf-core/ThreadElfCore.cpp
    lldb/trunk/source/Plugins/Process/elf-core/ThreadElfCore.h
    lldb/trunk/source/Plugins/Process/elf-core/elf-core-enums.h

Modified: lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.cpp?rev=318903&r1=318902&r2=318903&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.cpp (original)
+++ lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.cpp Thu Nov 23 02:50:34 2017
@@ -102,10 +102,7 @@ bool ProcessElfCore::CanDebug(lldb::Targ
 ProcessElfCore::ProcessElfCore(lldb::TargetSP target_sp,
                                lldb::ListenerSP listener_sp,
                                const FileSpec &core_file)
-    : Process(target_sp, listener_sp), m_core_module_sp(),
-      m_core_file(core_file), m_dyld_plugin_name(),
-      m_os(llvm::Triple::UnknownOS), m_thread_data_valid(false),
-      m_thread_data(), m_core_aranges() {}
+    : Process(target_sp, listener_sp), m_core_file(core_file) {}
 
 //----------------------------------------------------------------------
 // Destructor
@@ -194,9 +191,8 @@ Status ProcessElfCore::DoLoadCore() {
 
     // Parse thread contexts and auxv structure
     if (header->p_type == llvm::ELF::PT_NOTE) {
-      error = ParseThreadContextsFromNoteSegment(header, data);
-      if (error.Fail())
-        return error;
+      if (llvm::Error error = ParseThreadContextsFromNoteSegment(header, data))
+        return Status(std::move(error));
     }
     // PT_LOAD segments contains address map
     if (header->p_type == llvm::ELF::PT_LOAD) {
@@ -405,7 +401,6 @@ size_t ProcessElfCore::DoReadMemory(lldb
 
 void ProcessElfCore::Clear() {
   m_thread_list.Clear();
-  m_os = llvm::Triple::UnknownOS;
 
   SetUnixSignals(std::make_shared<UnixSignals>());
 }
@@ -429,8 +424,9 @@ lldb::addr_t ProcessElfCore::GetImageInf
 }
 
 // Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details.
-static void ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data,
-                                 ArchSpec &arch) {
+static void ParseFreeBSDPrStatus(ThreadData &thread_data,
+                                 const DataExtractor &data,
+                                 const ArchSpec &arch) {
   lldb::offset_t offset = 0;
   bool lp64 = (arch.GetMachine() == llvm::Triple::aarch64 ||
                arch.GetMachine() == llvm::Triple::mips64 ||
@@ -459,12 +455,8 @@ static void ParseFreeBSDPrStatus(ThreadD
   thread_data.gpregset = DataExtractor(data, offset, len);
 }
 
-static void ParseFreeBSDThrMisc(ThreadData &thread_data, DataExtractor &data) {
-  lldb::offset_t offset = 0;
-  thread_data.name = data.GetCStr(&offset, 20);
-}
-
-static void ParseNetBSDProcInfo(ThreadData &thread_data, DataExtractor &data) {
+static void ParseNetBSDProcInfo(ThreadData &thread_data,
+                                const DataExtractor &data) {
   lldb::offset_t offset = 0;
 
   int version = data.GetU32(&offset);
@@ -475,7 +467,8 @@ static void ParseNetBSDProcInfo(ThreadDa
   thread_data.signo = data.GetU32(&offset);
 }
 
-static void ParseOpenBSDProcInfo(ThreadData &thread_data, DataExtractor &data) {
+static void ParseOpenBSDProcInfo(ThreadData &thread_data,
+                                 const DataExtractor &data) {
   lldb::offset_t offset = 0;
 
   int version = data.GetU32(&offset);
@@ -486,217 +479,290 @@ static void ParseOpenBSDProcInfo(ThreadD
   thread_data.signo = data.GetU32(&offset);
 }
 
-/// Parse Thread context from PT_NOTE segment and store it in the thread list
-/// Notes:
-/// 1) A PT_NOTE segment is composed of one or more NOTE entries.
-/// 2) NOTE Entry contains a standard header followed by variable size data.
-///   (see ELFNote structure)
-/// 3) A Thread Context in a core file usually described by 3 NOTE entries.
-///    a) NT_PRSTATUS - Register context
-///    b) NT_PRPSINFO - Process info(pid..)
-///    c) NT_FPREGSET - Floating point registers
-/// 4) The NOTE entries can be in any order
-/// 5) If a core file contains multiple thread contexts then there is two data
-/// forms
-///    a) Each thread context(2 or more NOTE entries) contained in its own
-///    segment (PT_NOTE)
-///    b) All thread context is stored in a single segment(PT_NOTE).
-///        This case is little tricker since while parsing we have to find where
-///        the
-///        new thread starts. The current implementation marks beginning of
-///        new thread when it finds NT_PRSTATUS or NT_PRPSINFO NOTE entry.
-///    For case (b) there may be either one NT_PRPSINFO per thread, or a single
-///    one that applies to all threads (depending on the platform type).
-Status ProcessElfCore::ParseThreadContextsFromNoteSegment(
-    const elf::ELFProgramHeader *segment_header, DataExtractor segment_data) {
-  assert(segment_header && segment_header->p_type == llvm::ELF::PT_NOTE);
-
+llvm::Expected<std::vector<CoreNote>>
+ProcessElfCore::parseSegment(const DataExtractor &segment) {
   lldb::offset_t offset = 0;
-  std::unique_ptr<ThreadData> thread_data(new ThreadData);
-  bool have_prstatus = false;
-  bool have_prpsinfo = false;
+  std::vector<CoreNote> result;
 
-  ArchSpec arch = GetArchitecture();
-  ELFLinuxPrPsInfo prpsinfo;
-  ELFLinuxPrStatus prstatus;
-  ELFLinuxSigInfo siginfo;
-  size_t header_size;
-  size_t len;
-  Status error;
-
-  // Loop through the NOTE entires in the segment
-  while (offset < segment_header->p_filesz) {
+  while (offset < segment.GetByteSize()) {
     ELFNote note = ELFNote();
-    note.Parse(segment_data, &offset);
+    if (!note.Parse(segment, &offset))
+      return llvm::make_error<llvm::StringError>(
+          "Unable to parse note segment", llvm::inconvertibleErrorCode());
+
+    size_t note_start = offset;
+    size_t note_size = llvm::alignTo(note.n_descsz, 4);
+    DataExtractor note_data(segment, note_start, note_size);
+
+    result.push_back({note, note_data});
+    offset += note_size;
+  }
+
+  return std::move(result);
+}
 
-    // Beginning of new thread
-    if (((note.n_type == LINUX::NT_PRSTATUS ||
-          note.n_type == FREEBSD::NT_PRSTATUS) &&
-         have_prstatus) ||
-        ((note.n_type == LINUX::NT_PRPSINFO ||
-          note.n_type == FREEBSD::NT_PRPSINFO) &&
-         have_prpsinfo)) {
-      assert(thread_data->gpregset.GetByteSize() > 0);
+llvm::Error ProcessElfCore::parseFreeBSDNotes(llvm::ArrayRef<CoreNote> notes) {
+  bool have_prstatus = false;
+  bool have_prpsinfo = false;
+  ThreadData thread_data;
+  for (const auto &note : notes) {
+    if (note.info.n_name != "FreeBSD")
+      continue;
+
+    if ((note.info.n_type == FREEBSD::NT_PRSTATUS && have_prstatus) ||
+        (note.info.n_type == FREEBSD::NT_PRPSINFO && have_prpsinfo)) {
+      assert(thread_data.gpregset.GetByteSize() > 0);
       // Add the new thread to thread list
-      m_thread_data.push_back(*thread_data);
-      *thread_data = ThreadData();
+      m_thread_data.push_back(thread_data);
+      thread_data = ThreadData();
       have_prstatus = false;
       have_prpsinfo = false;
     }
 
-    size_t note_start, note_size;
-    note_start = offset;
-    note_size = llvm::alignTo(note.n_descsz, 4);
-
-    // Store the NOTE information in the current thread
-    DataExtractor note_data(segment_data, note_start, note_size);
-    note_data.SetAddressByteSize(
-        m_core_module_sp->GetArchitecture().GetAddressByteSize());
-    if (note.n_name == "FreeBSD") {
-      m_os = llvm::Triple::FreeBSD;
-      switch (note.n_type) {
-      case FREEBSD::NT_PRSTATUS:
-        have_prstatus = true;
-        ParseFreeBSDPrStatus(*thread_data, note_data, arch);
-        break;
-      case FREEBSD::NT_FPREGSET:
-        thread_data->fpregset = note_data;
-        break;
-      case FREEBSD::NT_PRPSINFO:
-        have_prpsinfo = true;
-        break;
-      case FREEBSD::NT_THRMISC:
-        ParseFreeBSDThrMisc(*thread_data, note_data);
-        break;
-      case FREEBSD::NT_PROCSTAT_AUXV:
-        // FIXME: FreeBSD sticks an int at the beginning of the note
-        m_auxv = DataExtractor(segment_data, note_start + 4, note_size - 4);
-        break;
-      case FREEBSD::NT_PPC_VMX:
-        thread_data->vregset = note_data;
+    switch (note.info.n_type) {
+    case FREEBSD::NT_PRSTATUS:
+      have_prstatus = true;
+      ParseFreeBSDPrStatus(thread_data, note.data, GetArchitecture());
+      break;
+    case FREEBSD::NT_FPREGSET:
+      thread_data.fpregset = note.data;
+      break;
+    case FREEBSD::NT_PPC_VMX:
+      thread_data.vregset = note.data;
+      break;
+    case FREEBSD::NT_PRPSINFO:
+      have_prpsinfo = true;
+      break;
+    case FREEBSD::NT_THRMISC: {
+      lldb::offset_t offset = 0;
+      thread_data.name = note.data.GetCStr(&offset, 20);
+      break;
+    }
+    case FREEBSD::NT_PROCSTAT_AUXV:
+      // FIXME: FreeBSD sticks an int at the beginning of the note
+      m_auxv = DataExtractor(note.data, 4, note.data.GetByteSize() - 4);
+      break;
+    default:
+      break;
+    }
+  }
+  if (!have_prstatus) {
+    return llvm::make_error<llvm::StringError>(
+        "Could not find NT_PRSTATUS note in core file.",
+        llvm::inconvertibleErrorCode());
+  }
+  m_thread_data.push_back(thread_data);
+  return llvm::Error::success();
+}
+
+llvm::Error ProcessElfCore::parseNetBSDNotes(llvm::ArrayRef<CoreNote> notes) {
+  ThreadData thread_data;
+  for (const auto &note : notes) {
+    // NetBSD per-thread information is stored in notes named
+    // "NetBSD-CORE at nnn" so match on the initial part of the string.
+    if (!llvm::StringRef(note.info.n_name).startswith("NetBSD-CORE"))
+      continue;
+
+    if (note.info.n_type == NETBSD::NT_PROCINFO) {
+      ParseNetBSDProcInfo(thread_data, note.data);
+      continue;
+    }
+    if (note.info.n_type == NETBSD::NT_AUXV) {
+      m_auxv = note.data;
+      continue;
+    }
+
+    if (GetArchitecture().GetMachine() == llvm::Triple::x86_64) {
+      switch (note.info.n_type) {
+      case NETBSD::NT_AMD64_REGS:
+        thread_data.gpregset = note.data;
         break;
-      default:
+      case NETBSD::NT_AMD64_FPREGS:
+        thread_data.fpregset = note.data;
         break;
       }
-    } else if (note.n_name.substr(0, 11) == "NetBSD-CORE") {
-      // NetBSD per-thread information is stored in notes named
-      // "NetBSD-CORE at nnn" so match on the initial part of the string.
-      m_os = llvm::Triple::NetBSD;
-      if (note.n_type == NETBSD::NT_PROCINFO) {
-        ParseNetBSDProcInfo(*thread_data, note_data);
-      } else if (note.n_type == NETBSD::NT_AUXV) {
-        m_auxv = DataExtractor(note_data);
-      } else if (arch.GetMachine() == llvm::Triple::x86_64 &&
-                 note.n_type == NETBSD::NT_AMD64_REGS) {
-        thread_data->gpregset = note_data;
-      } else if (arch.GetMachine() == llvm::Triple::x86_64 &&
-                 note.n_type == NETBSD::NT_AMD64_FPREGS) {
-        thread_data->fpregset = note_data;
-      }
-    } else if (note.n_name.substr(0, 7) == "OpenBSD") {
-      // OpenBSD per-thread information is stored in notes named
-      // "OpenBSD at nnn" so match on the initial part of the string.
-      m_os = llvm::Triple::OpenBSD;
-      switch (note.n_type) {
-      case OPENBSD::NT_PROCINFO:
-        ParseOpenBSDProcInfo(*thread_data, note_data);
-        break;
-      case OPENBSD::NT_AUXV:
-        m_auxv = DataExtractor(note_data);
-        break;
-      case OPENBSD::NT_REGS:
-        thread_data->gpregset = note_data;
-        break;
-      case OPENBSD::NT_FPREGS:
-        thread_data->fpregset = note_data;
-        break;
+    }
+  }
+  if (thread_data.gpregset.GetByteSize() == 0) {
+    return llvm::make_error<llvm::StringError>(
+        "Could not find general purpose registers note in core file.",
+        llvm::inconvertibleErrorCode());
+  }
+  m_thread_data.push_back(thread_data);
+  return llvm::Error::success();
+}
+
+llvm::Error ProcessElfCore::parseOpenBSDNotes(llvm::ArrayRef<CoreNote> notes) {
+  ThreadData thread_data;
+  for (const auto &note : notes) {
+    // OpenBSD per-thread information is stored in notes named
+    // "OpenBSD at nnn" so match on the initial part of the string.
+    if (!llvm::StringRef(note.info.n_name).startswith("OpenBSD"))
+      continue;
+
+    switch (note.info.n_type) {
+    case OPENBSD::NT_PROCINFO:
+      ParseOpenBSDProcInfo(thread_data, note.data);
+      break;
+    case OPENBSD::NT_AUXV:
+      m_auxv = note.data;
+      break;
+    case OPENBSD::NT_REGS:
+      thread_data.gpregset = note.data;
+      break;
+    case OPENBSD::NT_FPREGS:
+      thread_data.fpregset = note.data;
+      break;
+    }
+  }
+  if (thread_data.gpregset.GetByteSize() == 0) {
+    return llvm::make_error<llvm::StringError>(
+        "Could not find general purpose registers note in core file.",
+        llvm::inconvertibleErrorCode());
+  }
+  m_thread_data.push_back(thread_data);
+  return llvm::Error::success();
+}
+
+/// A description of a linux process usually contains the following NOTE
+/// entries:
+/// - NT_PRPSINFO - General process information like pid, uid, name, ...
+/// - NT_SIGINFO - Information about the signal that terminated the process
+/// - NT_AUXV - Process auxiliary vector
+/// - NT_FILE - Files mapped into memory
+/// 
+/// Additionally, for each thread in the process the core file will contain at
+/// least the NT_PRSTATUS note, containing the thread id and general purpose
+/// registers. It may include additional notes for other register sets (floating
+/// point and vector registers, ...). The tricky part here is that some of these
+/// notes have "CORE" in their owner fields, while other set it to "LINUX".
+llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) {
+  const ArchSpec &arch = GetArchitecture();
+  bool have_prstatus = false;
+  bool have_prpsinfo = false;
+  ThreadData thread_data;
+  for (const auto &note : notes) {
+    if (note.info.n_name != "CORE" && note.info.n_name != "LINUX")
+      continue;
+
+    if ((note.info.n_type == LINUX::NT_PRSTATUS && have_prstatus) ||
+        (note.info.n_type == LINUX::NT_PRPSINFO && have_prpsinfo)) {
+      assert(thread_data.gpregset.GetByteSize() > 0);
+      // Add the new thread to thread list
+      m_thread_data.push_back(thread_data);
+      thread_data = ThreadData();
+      have_prstatus = false;
+      have_prpsinfo = false;
+    }
+
+    switch (note.info.n_type) {
+    case LINUX::NT_PRSTATUS: {
+      have_prstatus = true;
+      ELFLinuxPrStatus prstatus;
+      Status status = prstatus.Parse(note.data, arch);
+      if (status.Fail())
+        return status.ToError();
+      thread_data.prstatus_sig = prstatus.pr_cursig;
+      thread_data.tid = prstatus.pr_pid;
+      uint32_t header_size = ELFLinuxPrStatus::GetSize(arch);
+      size_t len = note.data.GetByteSize() - header_size;
+      thread_data.gpregset = DataExtractor(note.data, header_size, len);
+      if (arch.GetCore() == ArchSpec::eCore_ppc64le_generic)
+        thread_data.regsets.try_emplace(note.info.n_type, thread_data.gpregset);
+      break;
+    }
+    case LINUX::NT_PRPSINFO: {
+      have_prpsinfo = true;
+      ELFLinuxPrPsInfo prpsinfo;
+      Status status = prpsinfo.Parse(note.data, arch);
+      if (status.Fail())
+        return status.ToError();
+      thread_data.name = prpsinfo.pr_fname;
+      SetID(prpsinfo.pr_pid);
+      break;
+    }
+    case LINUX::NT_SIGINFO: {
+      ELFLinuxSigInfo siginfo;
+      Status status = siginfo.Parse(note.data, arch);
+      if (status.Fail())
+        return status.ToError();
+      thread_data.signo = siginfo.si_signo;
+      break;
+    }
+    case LINUX::NT_FILE: {
+      m_nt_file_entries.clear();
+      lldb::offset_t offset = 0;
+      const uint64_t count = note.data.GetAddress(&offset);
+      note.data.GetAddress(&offset); // Skip page size
+      for (uint64_t i = 0; i < count; ++i) {
+        NT_FILE_Entry entry;
+        entry.start = note.data.GetAddress(&offset);
+        entry.end = note.data.GetAddress(&offset);
+        entry.file_ofs = note.data.GetAddress(&offset);
+        m_nt_file_entries.push_back(entry);
       }
-    } else if (note.n_name == "CORE") {
-      switch (note.n_type) {
-      case LINUX::NT_PRSTATUS:
-        have_prstatus = true;
-        error = prstatus.Parse(note_data, arch);
-        if (error.Fail())
-          return error;
-        thread_data->prstatus_sig = prstatus.pr_cursig;
-        thread_data->tid = prstatus.pr_pid;
-        header_size = ELFLinuxPrStatus::GetSize(arch);
-        len = note_data.GetByteSize() - header_size;
-        thread_data->gpregset = DataExtractor(note_data, header_size, len);
-
-        if (arch.GetCore() == ArchSpec::eCore_ppc64le_generic)
-          thread_data->regsets.insert(
-              std::make_pair(note.n_type, thread_data->gpregset));
-        break;
-      case LINUX::NT_FPREGSET:
-        // In a i386 core file NT_FPREGSET is present, but it's not the result
-        // of the FXSAVE instruction like in 64 bit files.
-        // The result from FXSAVE is in NT_PRXFPREG for i386 core files
-        if (arch.GetCore() == ArchSpec::eCore_x86_64_x86_64 || arch.IsMIPS())
-          thread_data->fpregset = note_data;
-        else if (arch.GetCore() == ArchSpec::eCore_ppc64le_generic) {
-          thread_data->regsets.insert(std::make_pair(note.n_type, note_data));
-        }
-        break;
-      case LINUX::NT_PRPSINFO:
-        have_prpsinfo = true;
-        error = prpsinfo.Parse(note_data, arch);
-        if (error.Fail())
-          return error;
-        thread_data->name = prpsinfo.pr_fname;
-        SetID(prpsinfo.pr_pid);
-        break;
-      case LINUX::NT_AUXV:
-        m_auxv = DataExtractor(note_data);
-        break;
-      case LINUX::NT_FILE: {
-        m_nt_file_entries.clear();
-        lldb::offset_t offset = 0;
-        const uint64_t count = note_data.GetAddress(&offset);
-        note_data.GetAddress(&offset); // Skip page size
-        for (uint64_t i = 0; i < count; ++i) {
-          NT_FILE_Entry entry;
-          entry.start = note_data.GetAddress(&offset);
-          entry.end = note_data.GetAddress(&offset);
-          entry.file_ofs = note_data.GetAddress(&offset);
-          m_nt_file_entries.push_back(entry);
-        }
-        for (uint64_t i = 0; i < count; ++i) {
-          const char *path = note_data.GetCStr(&offset);
-          if (path && path[0])
-            m_nt_file_entries[i].path.SetCString(path);
-        }
-      } break;
-      case LINUX::NT_SIGINFO: {
-        error = siginfo.Parse(note_data, arch);
-        if (error.Fail())
-          return error;
-        thread_data->signo = siginfo.si_signo;
-      } break;
-      default:
-        break;
+      for (uint64_t i = 0; i < count; ++i) {
+        const char *path = note.data.GetCStr(&offset);
+        if (path && path[0])
+          m_nt_file_entries[i].path.SetCString(path);
       }
-    } else if (note.n_name == "LINUX") {
-      switch (note.n_type) {
-      case LINUX::NT_PRXFPREG:
-        thread_data->fpregset = note_data;
-        break;
-      case LINUX::NT_PPC_VMX:
-      case LINUX::NT_PPC_VSX:
-        if (arch.GetCore() == ArchSpec::eCore_ppc64le_generic)
-          thread_data->regsets.insert(std::make_pair(note.n_type, note_data));
-        break;
+      break;
+    }
+    case LINUX::NT_AUXV:
+      m_auxv = note.data;
+      break;
+    case LINUX::NT_FPREGSET:
+      // In a i386 core file NT_FPREGSET is present, but it's not the result
+      // of the FXSAVE instruction like in 64 bit files.
+      // The result from FXSAVE is in NT_PRXFPREG for i386 core files
+      //
+
+      if (arch.GetCore() == ArchSpec::eCore_x86_64_x86_64 || arch.IsMIPS())
+        thread_data.fpregset = note.data;
+      else if (arch.GetCore() == ArchSpec::eCore_ppc64le_generic) {
+        thread_data.regsets.insert(std::make_pair(note.info.n_type, note.data));
       }
+      break;
+    case LINUX::NT_PPC_VMX:
+    case LINUX::NT_PPC_VSX:
+      if (arch.GetCore() == ArchSpec::eCore_ppc64le_generic)
+        thread_data.regsets.insert(std::make_pair(note.info.n_type, note.data));
+      break;
+    case LINUX::NT_PRXFPREG:
+      thread_data.fpregset = note.data;
+      break;
     }
-
-    offset += note_size;
   }
   // Add last entry in the note section
-  if (thread_data && thread_data->gpregset.GetByteSize() > 0) {
-    m_thread_data.push_back(*thread_data);
-  }
+  if (have_prstatus)
+    m_thread_data.push_back(thread_data);
+  return llvm::Error::success();
+}
 
-  return error;
+/// Parse Thread context from PT_NOTE segment and store it in the thread list
+/// A note segment consists of one or more NOTE entries, but their types and
+/// meaning differ depending on the OS.
+llvm::Error ProcessElfCore::ParseThreadContextsFromNoteSegment(
+    const elf::ELFProgramHeader *segment_header, DataExtractor segment_data) {
+  assert(segment_header && segment_header->p_type == llvm::ELF::PT_NOTE);
+
+  auto notes_or_error = parseSegment(segment_data);
+  if(!notes_or_error)
+    return notes_or_error.takeError();
+  switch (GetArchitecture().GetTriple().getOS()) {
+  case llvm::Triple::FreeBSD:
+    return parseFreeBSDNotes(*notes_or_error);
+  case llvm::Triple::Linux:
+    return parseLinuxNotes(*notes_or_error);
+  case llvm::Triple::NetBSD:
+    return parseNetBSDNotes(*notes_or_error);
+  case llvm::Triple::OpenBSD:
+    return parseOpenBSDNotes(*notes_or_error);
+  default:
+    return llvm::make_error<llvm::StringError>(
+        "Don't know how to parse core file. Unsupported OS.",
+        llvm::inconvertibleErrorCode());
+  }
 }
 
 uint32_t ProcessElfCore::GetNumThreadContexts() {

Modified: lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.h?rev=318903&r1=318902&r2=318903&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.h (original)
+++ lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.h Thu Nov 23 02:50:34 2017
@@ -29,6 +29,7 @@
 #include "lldb/Utility/Status.h"
 
 #include "Plugins/ObjectFile/ELF/ELFHeader.h"
+#include "Plugins/Process/elf-core/elf-core-enums.h"
 
 struct ThreadData;
 
@@ -149,10 +150,8 @@ private:
   std::string m_dyld_plugin_name;
   DISALLOW_COPY_AND_ASSIGN(ProcessElfCore);
 
-  llvm::Triple::OSType m_os;
-
   // True if m_thread_contexts contains valid entries
-  bool m_thread_data_valid;
+  bool m_thread_data_valid = false;
 
   // Contain thread data read from NOTE segments
   std::vector<ThreadData> m_thread_data;
@@ -170,7 +169,7 @@ private:
   std::vector<NT_FILE_Entry> m_nt_file_entries;
 
   // Parse thread(s) data structures(prstatus, prpsinfo) from given NOTE segment
-  lldb_private::Status ParseThreadContextsFromNoteSegment(
+  llvm::Error ParseThreadContextsFromNoteSegment(
       const elf::ELFProgramHeader *segment_header,
       lldb_private::DataExtractor segment_data);
 
@@ -180,6 +179,13 @@ private:
   // Parse a contiguous address range of the process from LOAD segment
   lldb::addr_t
   AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader *header);
+
+  llvm::Expected<std::vector<lldb_private::CoreNote>>
+  parseSegment(const lldb_private::DataExtractor &segment);
+  llvm::Error parseFreeBSDNotes(llvm::ArrayRef<lldb_private::CoreNote> notes);
+  llvm::Error parseNetBSDNotes(llvm::ArrayRef<lldb_private::CoreNote> notes);
+  llvm::Error parseOpenBSDNotes(llvm::ArrayRef<lldb_private::CoreNote> notes);
+  llvm::Error parseLinuxNotes(llvm::ArrayRef<lldb_private::CoreNote> notes);
 };
 
 #endif // liblldb_ProcessElfCore_h_

Modified: lldb/trunk/source/Plugins/Process/elf-core/ThreadElfCore.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/elf-core/ThreadElfCore.cpp?rev=318903&r1=318902&r2=318903&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/elf-core/ThreadElfCore.cpp (original)
+++ lldb/trunk/source/Plugins/Process/elf-core/ThreadElfCore.cpp Thu Nov 23 02:50:34 2017
@@ -259,7 +259,7 @@ ELFLinuxPrStatus::ELFLinuxPrStatus() {
   memset(this, 0, sizeof(ELFLinuxPrStatus));
 }
 
-size_t ELFLinuxPrStatus::GetSize(lldb_private::ArchSpec &arch) {
+size_t ELFLinuxPrStatus::GetSize(const lldb_private::ArchSpec &arch) {
   constexpr size_t mips_linux_pr_status_size_o32 = 96;
   constexpr size_t mips_linux_pr_status_size_n32 = 72;
   if (arch.IsMIPS()) {
@@ -285,7 +285,8 @@ size_t ELFLinuxPrStatus::GetSize(lldb_pr
   }
 }
 
-Status ELFLinuxPrStatus::Parse(DataExtractor &data, ArchSpec &arch) {
+Status ELFLinuxPrStatus::Parse(const DataExtractor &data,
+                               const ArchSpec &arch) {
   Status error;
   if (GetSize(arch) > data.GetByteSize()) {
     error.SetErrorStringWithFormat(
@@ -334,7 +335,7 @@ ELFLinuxPrPsInfo::ELFLinuxPrPsInfo() {
   memset(this, 0, sizeof(ELFLinuxPrPsInfo));
 }
 
-size_t ELFLinuxPrPsInfo::GetSize(lldb_private::ArchSpec &arch) {
+size_t ELFLinuxPrPsInfo::GetSize(const lldb_private::ArchSpec &arch) {
   constexpr size_t mips_linux_pr_psinfo_size_o32_n32 = 128;
   if (arch.IsMIPS()) {
     uint8_t address_byte_size = arch.GetAddressByteSize();
@@ -355,7 +356,8 @@ size_t ELFLinuxPrPsInfo::GetSize(lldb_pr
   }
 }
 
-Status ELFLinuxPrPsInfo::Parse(DataExtractor &data, ArchSpec &arch) {
+Status ELFLinuxPrPsInfo::Parse(const DataExtractor &data,
+                               const ArchSpec &arch) {
   Status error;
   ByteOrder byteorder = data.GetByteOrder();
   if (GetSize(arch) > data.GetByteSize()) {
@@ -424,7 +426,7 @@ size_t ELFLinuxSigInfo::GetSize(const ll
   }
 }
 
-Status ELFLinuxSigInfo::Parse(DataExtractor &data, const ArchSpec &arch) {
+Status ELFLinuxSigInfo::Parse(const DataExtractor &data, const ArchSpec &arch) {
   Status error;
   if (GetSize(arch) > data.GetByteSize()) {
     error.SetErrorStringWithFormat(

Modified: lldb/trunk/source/Plugins/Process/elf-core/ThreadElfCore.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/elf-core/ThreadElfCore.h?rev=318903&r1=318902&r2=318903&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/elf-core/ThreadElfCore.h (original)
+++ lldb/trunk/source/Plugins/Process/elf-core/ThreadElfCore.h Thu Nov 23 02:50:34 2017
@@ -58,15 +58,15 @@ struct ELFLinuxPrStatus {
 
   ELFLinuxPrStatus();
 
-  lldb_private::Status Parse(lldb_private::DataExtractor &data,
-                             lldb_private::ArchSpec &arch);
+  lldb_private::Status Parse(const lldb_private::DataExtractor &data,
+                             const lldb_private::ArchSpec &arch);
 
   // Return the bytesize of the structure
   // 64 bit - just sizeof
   // 32 bit - hardcoded because we are reusing the struct, but some of the
   // members are smaller -
   // so the layout is not the same
-  static size_t GetSize(lldb_private::ArchSpec &arch);
+  static size_t GetSize(const lldb_private::ArchSpec &arch);
 };
 
 static_assert(sizeof(ELFLinuxPrStatus) == 112,
@@ -79,7 +79,7 @@ struct ELFLinuxSigInfo {
 
   ELFLinuxSigInfo();
 
-  lldb_private::Status Parse(lldb_private::DataExtractor &data,
+  lldb_private::Status Parse(const lldb_private::DataExtractor &data,
                              const lldb_private::ArchSpec &arch);
 
   // Return the bytesize of the structure
@@ -114,15 +114,15 @@ struct ELFLinuxPrPsInfo {
 
   ELFLinuxPrPsInfo();
 
-  lldb_private::Status Parse(lldb_private::DataExtractor &data,
-                             lldb_private::ArchSpec &arch);
+  lldb_private::Status Parse(const lldb_private::DataExtractor &data,
+                             const lldb_private::ArchSpec &arch);
 
   // Return the bytesize of the structure
   // 64 bit - just sizeof
   // 32 bit - hardcoded because we are reusing the struct, but some of the
   // members are smaller -
   // so the layout is not the same
-  static size_t GetSize(lldb_private::ArchSpec &arch);
+  static size_t GetSize(const lldb_private::ArchSpec &arch);
 };
 
 static_assert(sizeof(ELFLinuxPrPsInfo) == 136,

Modified: lldb/trunk/source/Plugins/Process/elf-core/elf-core-enums.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/elf-core/elf-core-enums.h?rev=318903&r1=318902&r2=318903&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/elf-core/elf-core-enums.h (original)
+++ lldb/trunk/source/Plugins/Process/elf-core/elf-core-enums.h Thu Nov 23 02:50:34 2017
@@ -10,6 +10,10 @@
 #ifndef LLDB_ELF_CORE_ENUMS_H
 #define LLDB_ELF_CORE_ENUMS_H
 
+#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
+#include "lldb/Utility/DataExtractor.h"
+
+namespace lldb_private {
 /// Core files PT_NOTE segment descriptor types
 
 namespace FREEBSD {
@@ -52,4 +56,11 @@ enum {
 };
 }
 
+struct CoreNote {
+  ELFNote info;
+  DataExtractor data;
+};
+
+} // namespace lldb_private
+
 #endif // #ifndef LLDB_ELF_CORE_ENUMS_H




More information about the lldb-commits mailing list