[Lldb-commits] [lldb] r348928 - ELF: Simplify program header iteration

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Wed Dec 12 06:20:29 PST 2018


Author: labath
Date: Wed Dec 12 06:20:28 2018
New Revision: 348928

URL: http://llvm.org/viewvc/llvm-project?rev=348928&view=rev
Log:
ELF: Simplify program header iteration

Instead of GetProgramHeaderCount+GetProgramHeaderByIndex, expose an
ArrayRef of all program headers, to enable range-based iteration.
Instead of GetSegmentDataByIndex, expose GetSegmentData, taking a
program header (reference).

This makes the code simpler by enabling range-based loops and also
allowed to remove some null checks, as it became locally obvious that
some pointers can never be null.

Modified:
    lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
    lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
    lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.cpp
    lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.h

Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp?rev=348928&r1=348927&r2=348928&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp (original)
+++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp Wed Dec 12 06:20:28 2018
@@ -539,14 +539,13 @@ static uint32_t calc_gnu_debuglink_crc32
 
 uint32_t ObjectFileELF::CalculateELFNotesSegmentsCRC32(
     const ProgramHeaderColl &program_headers, DataExtractor &object_data) {
-  typedef ProgramHeaderCollConstIter Iter;
 
   uint32_t core_notes_crc = 0;
 
-  for (Iter I = program_headers.begin(); I != program_headers.end(); ++I) {
-    if (I->p_type == llvm::ELF::PT_NOTE) {
-      const elf_off ph_offset = I->p_offset;
-      const size_t ph_size = I->p_filesz;
+  for (const ELFProgramHeader &H : program_headers) {
+    if (H.p_type == llvm::ELF::PT_NOTE) {
+      const elf_off ph_offset = H.p_offset;
+      const size_t ph_size = H.p_filesz;
 
       DataExtractor segment_data;
       if (segment_data.SetData(object_data, ph_offset, ph_size) != ph_size) {
@@ -806,15 +805,11 @@ bool ObjectFileELF::SetLoadAddress(Targe
     if (section_list) {
       if (!value_is_offset) {
         bool found_offset = false;
-        for (size_t i = 1, count = GetProgramHeaderCount(); i <= count; ++i) {
-          const elf::ELFProgramHeader *header = GetProgramHeaderByIndex(i);
-          if (header == nullptr)
+        for (const ELFProgramHeader &H : ProgramHeaders()) {
+          if (H.p_type != PT_LOAD || H.p_offset != 0)
             continue;
 
-          if (header->p_type != PT_LOAD || header->p_offset != 0)
-            continue;
-
-          value = value - header->p_vaddr;
+          value = value - H.p_vaddr;
           found_offset = true;
           break;
         }
@@ -1158,8 +1153,8 @@ size_t ObjectFileELF::GetProgramHeaderIn
 //----------------------------------------------------------------------
 // ParseProgramHeaders
 //----------------------------------------------------------------------
-size_t ObjectFileELF::ParseProgramHeaders() {
-  return GetProgramHeaderInfo(m_program_headers, m_data, m_header);
+bool ObjectFileELF::ParseProgramHeaders() {
+  return GetProgramHeaderInfo(m_program_headers, m_data, m_header) != 0;
 }
 
 lldb_private::Status
@@ -1705,27 +1700,6 @@ size_t ObjectFileELF::GetSectionHeaderIn
   return 0;
 }
 
-size_t ObjectFileELF::GetProgramHeaderCount() { return ParseProgramHeaders(); }
-
-const elf::ELFProgramHeader *
-ObjectFileELF::GetProgramHeaderByIndex(lldb::user_id_t id) {
-  if (!id || !ParseProgramHeaders())
-    return NULL;
-
-  if (--id < m_program_headers.size())
-    return &m_program_headers[id];
-
-  return NULL;
-}
-
-DataExtractor ObjectFileELF::GetSegmentDataByIndex(lldb::user_id_t id) {
-  const elf::ELFProgramHeader *segment_header = GetProgramHeaderByIndex(id);
-  if (segment_header == NULL)
-    return DataExtractor();
-  return DataExtractor(m_data, segment_header->p_offset,
-                       segment_header->p_filesz);
-}
-
 llvm::StringRef
 ObjectFileELF::StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const {
   size_t pos = symbol_name.find('@');
@@ -3181,11 +3155,9 @@ void ObjectFileELF::DumpELFProgramHeader
   s->PutCString("==== --------------- -------- -------- -------- "
                 "-------- -------- ------------------------- --------\n");
 
-  uint32_t idx = 0;
-  for (ProgramHeaderCollConstIter I = m_program_headers.begin();
-       I != m_program_headers.end(); ++I, ++idx) {
-    s->Printf("[%2u] ", idx);
-    ObjectFileELF::DumpELFProgramHeader(s, *I);
+  for (const auto &H : llvm::enumerate(m_program_headers)) {
+    s->Format("[{0,2}] ", H.index());
+    ObjectFileELF::DumpELFProgramHeader(s, H.value());
     s->EOL();
   }
 }
@@ -3305,18 +3277,13 @@ bool ObjectFileELF::GetArchitecture(Arch
       m_arch_spec.TripleOSIsUnspecifiedUnknown()) {
     // Core files don't have section headers yet they have PT_NOTE program
     // headers that might shed more light on the architecture
-    if (ParseProgramHeaders()) {
-      for (size_t i = 1, count = GetProgramHeaderCount(); i <= count; ++i) {
-        const elf::ELFProgramHeader *header = GetProgramHeaderByIndex(i);
-        if (header && header->p_type == PT_NOTE && header->p_offset != 0 &&
-            header->p_filesz > 0) {
-          DataExtractor data;
-          if (data.SetData(m_data, header->p_offset, header->p_filesz) ==
-              header->p_filesz) {
-            lldb_private::UUID uuid;
-            RefineModuleDetailsFromNote(data, m_arch_spec, uuid);
-          }
-        }
+    for (const elf::ELFProgramHeader &H : ProgramHeaders()) {
+      if (H.p_type != PT_NOTE || H.p_offset == 0 || H.p_filesz == 0)
+        continue;
+      DataExtractor data;
+      if (data.SetData(m_data, H.p_offset, H.p_filesz) == H.p_filesz) {
+        UUID uuid;
+        RefineModuleDetailsFromNote(data, m_arch_spec, uuid);
       }
     }
   }
@@ -3448,11 +3415,18 @@ size_t ObjectFileELF::ReadSectionData(Se
   return buffer_sp->GetByteSize();
 }
 
+llvm::ArrayRef<ELFProgramHeader> ObjectFileELF::ProgramHeaders() {
+  ParseProgramHeaders();
+  return m_program_headers;
+}
+
+DataExtractor ObjectFileELF::GetSegmentData(const ELFProgramHeader &H) {
+  return DataExtractor(m_data, H.p_offset, H.p_filesz);
+}
+
 bool ObjectFileELF::AnySegmentHasPhysicalAddress() {
-  size_t header_count = ParseProgramHeaders();
-  for (size_t i = 1; i <= header_count; ++i) {
-    auto header = GetProgramHeaderByIndex(i);
-    if (header->p_paddr != 0)
+  for (const ELFProgramHeader &H : ProgramHeaders()) {
+    if (H.p_paddr != 0)
       return true;
   }
   return false;
@@ -3463,19 +3437,17 @@ ObjectFileELF::GetLoadableData(Target &t
   // Create a list of loadable data from loadable segments, using physical
   // addresses if they aren't all null
   std::vector<LoadableData> loadables;
-  size_t header_count = ParseProgramHeaders();
   bool should_use_paddr = AnySegmentHasPhysicalAddress();
-  for (size_t i = 1; i <= header_count; ++i) {
+  for (const ELFProgramHeader &H : ProgramHeaders()) {
     LoadableData loadable;
-    auto header = GetProgramHeaderByIndex(i);
-    if (header->p_type != llvm::ELF::PT_LOAD)
+    if (H.p_type != llvm::ELF::PT_LOAD)
       continue;
-    loadable.Dest = should_use_paddr ? header->p_paddr : header->p_vaddr;
+    loadable.Dest = should_use_paddr ? H.p_paddr : H.p_vaddr;
     if (loadable.Dest == LLDB_INVALID_ADDRESS)
       continue;
-    if (header->p_filesz == 0)
+    if (H.p_filesz == 0)
       continue;
-    auto segment_data = GetSegmentDataByIndex(i);
+    auto segment_data = GetSegmentData(H);
     loadable.Contents = llvm::ArrayRef<uint8_t>(segment_data.GetDataStart(),
                                                 segment_data.GetByteSize());
     loadables.push_back(loadable);

Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h?rev=348928&r1=348927&r2=348928&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h (original)
+++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h Wed Dec 12 06:20:28 2018
@@ -145,14 +145,8 @@ public:
   size_t ReadSectionData(lldb_private::Section *section,
                          lldb_private::DataExtractor &section_data) override;
 
-  // Returns number of program headers found in the ELF file.
-  size_t GetProgramHeaderCount();
-
-  // Returns the program header with the given index.
-  const elf::ELFProgramHeader *GetProgramHeaderByIndex(lldb::user_id_t id);
-
-  // Returns segment data for the given index.
-  lldb_private::DataExtractor GetSegmentDataByIndex(lldb::user_id_t id);
+  llvm::ArrayRef<elf::ELFProgramHeader> ProgramHeaders();
+  lldb_private::DataExtractor GetSegmentData(const elf::ELFProgramHeader &H);
 
   llvm::StringRef
   StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const override;
@@ -174,8 +168,6 @@ private:
                 const lldb::ProcessSP &process_sp, lldb::addr_t header_addr);
 
   typedef std::vector<elf::ELFProgramHeader> ProgramHeaderColl;
-  typedef ProgramHeaderColl::iterator ProgramHeaderCollIter;
-  typedef ProgramHeaderColl::const_iterator ProgramHeaderCollConstIter;
 
   struct ELFSectionHeaderInfo : public elf::ELFSectionHeader {
     lldb_private::ConstString section_name;
@@ -246,8 +238,8 @@ private:
 
   /// Parses all section headers present in this object file and populates
   /// m_program_headers.  This method will compute the header list only once.
-  /// Returns the number of headers parsed.
-  size_t ParseProgramHeaders();
+  /// Returns true iff the headers have been successfully parsed.
+  bool ParseProgramHeaders();
 
   /// Parses all section headers present in this object file and populates
   /// m_section_headers.  This method will compute the header list only once.

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=348928&r1=348927&r2=348928&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.cpp (original)
+++ lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.cpp Wed Dec 12 06:20:28 2018
@@ -118,10 +118,10 @@ ConstString ProcessElfCore::GetPluginNam
 uint32_t ProcessElfCore::GetPluginVersion() { return 1; }
 
 lldb::addr_t ProcessElfCore::AddAddressRangeFromLoadSegment(
-    const elf::ELFProgramHeader *header) {
-  const lldb::addr_t addr = header->p_vaddr;
-  FileRange file_range(header->p_offset, header->p_filesz);
-  VMRangeToFileOffset::Entry range_entry(addr, header->p_memsz, file_range);
+    const elf::ELFProgramHeader &header) {
+  const lldb::addr_t addr = header.p_vaddr;
+  FileRange file_range(header.p_offset, header.p_filesz);
+  VMRangeToFileOffset::Entry range_entry(addr, header.p_memsz, file_range);
 
   VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();
   if (last_entry && last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&
@@ -136,12 +136,12 @@ lldb::addr_t ProcessElfCore::AddAddressR
   // Keep a separate map of permissions that that isn't coalesced so all ranges
   // are maintained.
   const uint32_t permissions =
-      ((header->p_flags & llvm::ELF::PF_R) ? lldb::ePermissionsReadable : 0u) |
-      ((header->p_flags & llvm::ELF::PF_W) ? lldb::ePermissionsWritable : 0u) |
-      ((header->p_flags & llvm::ELF::PF_X) ? lldb::ePermissionsExecutable : 0u);
+      ((header.p_flags & llvm::ELF::PF_R) ? lldb::ePermissionsReadable : 0u) |
+      ((header.p_flags & llvm::ELF::PF_W) ? lldb::ePermissionsWritable : 0u) |
+      ((header.p_flags & llvm::ELF::PF_X) ? lldb::ePermissionsExecutable : 0u);
 
   m_core_range_infos.Append(
-      VMRangeToPermissions::Entry(addr, header->p_memsz, permissions));
+      VMRangeToPermissions::Entry(addr, header.p_memsz, permissions));
 
   return addr;
 }
@@ -162,8 +162,8 @@ Status ProcessElfCore::DoLoadCore() {
     return error;
   }
 
-  const uint32_t num_segments = core->GetProgramHeaderCount();
-  if (num_segments == 0) {
+  llvm::ArrayRef<elf::ELFProgramHeader> segments = core->ProgramHeaders();
+  if (segments.size() == 0) {
     error.SetErrorString("core file has no segments");
     return error;
   }
@@ -177,20 +177,17 @@ Status ProcessElfCore::DoLoadCore() {
   /// Walk through segments and Thread and Address Map information.
   /// PT_NOTE - Contains Thread and Register information
   /// PT_LOAD - Contains a contiguous range of Process Address Space
-  for (uint32_t i = 1; i <= num_segments; i++) {
-    const elf::ELFProgramHeader *header = core->GetProgramHeaderByIndex(i);
-    assert(header != NULL);
-
-    DataExtractor data = core->GetSegmentDataByIndex(i);
+  for (const elf::ELFProgramHeader &H : segments) {
+    DataExtractor data = core->GetSegmentData(H);
 
     // Parse thread contexts and auxv structure
-    if (header->p_type == llvm::ELF::PT_NOTE) {
-      if (llvm::Error error = ParseThreadContextsFromNoteSegment(header, data))
+    if (H.p_type == llvm::ELF::PT_NOTE) {
+      if (llvm::Error error = ParseThreadContextsFromNoteSegment(H, data))
         return Status(std::move(error));
     }
     // PT_LOAD segments contains address map
-    if (header->p_type == llvm::ELF::PT_LOAD) {
-      lldb::addr_t last_addr = AddAddressRangeFromLoadSegment(header);
+    if (H.p_type == llvm::ELF::PT_LOAD) {
+      lldb::addr_t last_addr = AddAddressRangeFromLoadSegment(H);
       if (vm_addr > last_addr)
         ranges_are_sorted = false;
       vm_addr = last_addr;
@@ -710,8 +707,8 @@ llvm::Error ProcessElfCore::parseLinuxNo
 /// 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);
+    const elf::ELFProgramHeader &segment_header, DataExtractor segment_data) {
+  assert(segment_header.p_type == llvm::ELF::PT_NOTE);
 
   auto notes_or_error = parseSegment(segment_data);
   if(!notes_or_error)

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=348928&r1=348927&r2=348928&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.h (original)
+++ lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.h Wed Dec 12 06:20:28 2018
@@ -166,7 +166,7 @@ private:
 
   // Parse thread(s) data structures(prstatus, prpsinfo) from given NOTE segment
   llvm::Error ParseThreadContextsFromNoteSegment(
-      const elf::ELFProgramHeader *segment_header,
+      const elf::ELFProgramHeader &segment_header,
       lldb_private::DataExtractor segment_data);
 
   // Returns number of thread contexts stored in the core file
@@ -174,7 +174,7 @@ private:
 
   // Parse a contiguous address range of the process from LOAD segment
   lldb::addr_t
-  AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader *header);
+  AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader &header);
 
   llvm::Expected<std::vector<lldb_private::CoreNote>>
   parseSegment(const lldb_private::DataExtractor &segment);




More information about the lldb-commits mailing list