[Lldb-commits] [lldb] [lldb][AIX] Added XCOFF Object File Header for AIX (PR #111814)

Dhruv Srivastava via lldb-commits lldb-commits at lists.llvm.org
Thu Oct 10 04:36:28 PDT 2024


https://github.com/DhruvSrivastavaX created https://github.com/llvm/llvm-project/pull/111814

This PR is in reference to porting LLDB on AIX.

Link to discussions on llvm discourse and github:
1. https://discourse.llvm.org/t/port-lldb-to-ibm-aix/80640
2. #101657
The complete changes for porting are present in this draft PR:
#102601

Added XCOFF Object File Header for AIX.

Commit 1: Taken Linux version for reference.
Commit 2: Modified the class and header for AIX.
Details about XCOFF file format on AIX: [XCOFF](https://www.ibm.com/docs/en/aix/7.3?topic=formats-xcoff-object-file-format)

Review Request: @DavidSpickett

>From 08c9d5ae66ca857d165dc878ebd1b2e0de364a24 Mon Sep 17 00:00:00 2001
From: Dhruv-Srivastava <dhruv.srivastava at ibm.com>
Date: Thu, 10 Oct 2024 02:24:42 -0500
Subject: [PATCH 1/3] Taking base file structure from ELF as reference

---
 .../ObjectFile/XCOFF/ObjectFileXCOFF.h        | 440 ++++++++++++++++++
 1 file changed, 440 insertions(+)
 create mode 100644 lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h

diff --git a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h
new file mode 100644
index 00000000000000..aba3a5bfcbf5b6
--- /dev/null
+++ b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h
@@ -0,0 +1,440 @@
+//===-- ObjectFileELF.h --------------------------------------- -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_OBJECTFILE_ELF_OBJECTFILEELF_H
+#define LLDB_SOURCE_PLUGINS_OBJECTFILE_ELF_OBJECTFILEELF_H
+
+#include <cstdint>
+
+#include <optional>
+#include <vector>
+
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/UUID.h"
+#include "lldb/lldb-private.h"
+
+#include "ELFHeader.h"
+
+struct ELFNote {
+  elf::elf_word n_namesz = 0;
+  elf::elf_word n_descsz = 0;
+  elf::elf_word n_type = 0;
+
+  std::string n_name;
+
+  ELFNote() = default;
+
+  /// Parse an ELFNote entry from the given DataExtractor starting at position
+  /// \p offset.
+  ///
+  /// \param[in] data
+  ///    The DataExtractor to read from.
+  ///
+  /// \param[in,out] offset
+  ///    Pointer to an offset in the data.  On return the offset will be
+  ///    advanced by the number of bytes read.
+  ///
+  /// \return
+  ///    True if the ELFRel entry was successfully read and false otherwise.
+  bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
+
+  size_t GetByteSize() const {
+    return 12 + llvm::alignTo(n_namesz, 4) + llvm::alignTo(n_descsz, 4);
+  }
+};
+
+/// \class ObjectFileELF
+/// Generic ELF object file reader.
+///
+/// This class provides a generic ELF (32/64 bit) reader plugin implementing
+/// the ObjectFile protocol.
+class ObjectFileELF : public lldb_private::ObjectFile {
+public:
+  // Static Functions
+  static void Initialize();
+
+  static void Terminate();
+
+  static llvm::StringRef GetPluginNameStatic() { return "elf"; }
+
+  static llvm::StringRef GetPluginDescriptionStatic() {
+    return "ELF object file reader.";
+  }
+
+  static lldb_private::ObjectFile *
+  CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp,
+                 lldb::offset_t data_offset, const lldb_private::FileSpec *file,
+                 lldb::offset_t file_offset, lldb::offset_t length);
+
+  static lldb_private::ObjectFile *CreateMemoryInstance(
+      const lldb::ModuleSP &module_sp, lldb::WritableDataBufferSP data_sp,
+      const lldb::ProcessSP &process_sp, lldb::addr_t header_addr);
+
+  static size_t GetModuleSpecifications(const lldb_private::FileSpec &file,
+                                        lldb::DataBufferSP &data_sp,
+                                        lldb::offset_t data_offset,
+                                        lldb::offset_t file_offset,
+                                        lldb::offset_t length,
+                                        lldb_private::ModuleSpecList &specs);
+
+  static bool MagicBytesMatch(lldb::DataBufferSP &data_sp, lldb::addr_t offset,
+                              lldb::addr_t length);
+
+  // PluginInterface protocol
+  llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
+
+  // LLVM RTTI support
+  static char ID;
+  bool isA(const void *ClassID) const override {
+    return ClassID == &ID || ObjectFile::isA(ClassID);
+  }
+  static bool classof(const ObjectFile *obj) { return obj->isA(&ID); }
+
+  // ObjectFile Protocol.
+  bool ParseHeader() override;
+
+  bool SetLoadAddress(lldb_private::Target &target, lldb::addr_t value,
+                      bool value_is_offset) override;
+
+  lldb::ByteOrder GetByteOrder() const override;
+
+  bool IsExecutable() const override;
+
+  uint32_t GetAddressByteSize() const override;
+
+  lldb_private::AddressClass GetAddressClass(lldb::addr_t file_addr) override;
+
+  void ParseSymtab(lldb_private::Symtab &symtab) override;
+
+  bool IsStripped() override;
+
+  void CreateSections(lldb_private::SectionList &unified_section_list) override;
+
+  void Dump(lldb_private::Stream *s) override;
+
+  lldb_private::ArchSpec GetArchitecture() override;
+
+  lldb_private::UUID GetUUID() override;
+
+  /// Return the contents of the .gnu_debuglink section, if the object file
+  /// contains it.
+  std::optional<lldb_private::FileSpec> GetDebugLink();
+
+  uint32_t GetDependentModules(lldb_private::FileSpecList &files) override;
+
+  lldb_private::Address
+  GetImageInfoAddress(lldb_private::Target *target) override;
+
+  lldb_private::Address GetEntryPointAddress() override;
+
+  lldb_private::Address GetBaseAddress() override;
+
+  ObjectFile::Type CalculateType() override;
+
+  ObjectFile::Strata CalculateStrata() override;
+
+  size_t ReadSectionData(lldb_private::Section *section,
+                         lldb::offset_t section_offset, void *dst,
+                         size_t dst_len) override;
+
+  size_t ReadSectionData(lldb_private::Section *section,
+                         lldb_private::DataExtractor &section_data) override;
+
+  llvm::ArrayRef<elf::ELFProgramHeader> ProgramHeaders();
+  lldb_private::DataExtractor GetSegmentData(const elf::ELFProgramHeader &H);
+
+  llvm::StringRef
+  StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const override;
+
+  void RelocateSection(lldb_private::Section *section) override;
+
+protected:
+
+  std::vector<LoadableData>
+  GetLoadableData(lldb_private::Target &target) override;
+
+  static lldb::WritableDataBufferSP
+  MapFileDataWritable(const lldb_private::FileSpec &file, uint64_t Size,
+                      uint64_t Offset);
+
+private:
+  ObjectFileELF(const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp,
+                lldb::offset_t data_offset, const lldb_private::FileSpec *file,
+                lldb::offset_t offset, lldb::offset_t length);
+
+  ObjectFileELF(const lldb::ModuleSP &module_sp,
+                lldb::DataBufferSP header_data_sp,
+                const lldb::ProcessSP &process_sp, lldb::addr_t header_addr);
+
+  typedef std::vector<elf::ELFProgramHeader> ProgramHeaderColl;
+
+  struct ELFSectionHeaderInfo : public elf::ELFSectionHeader {
+    lldb_private::ConstString section_name;
+  };
+
+  typedef std::vector<ELFSectionHeaderInfo> SectionHeaderColl;
+  typedef SectionHeaderColl::iterator SectionHeaderCollIter;
+  typedef SectionHeaderColl::const_iterator SectionHeaderCollConstIter;
+
+  struct ELFDynamicWithName {
+    elf::ELFDynamic symbol;
+    std::string name;
+  };
+  typedef std::vector<ELFDynamicWithName> DynamicSymbolColl;
+  typedef DynamicSymbolColl::iterator DynamicSymbolCollIter;
+  typedef DynamicSymbolColl::const_iterator DynamicSymbolCollConstIter;
+
+  /// An ordered map of file address to address class. Used on architectures
+  /// like Arm where there is an alternative ISA mode like Thumb. The container
+  /// is ordered so that it can be binary searched.
+  typedef std::map<lldb::addr_t, lldb_private::AddressClass>
+      FileAddressToAddressClassMap;
+
+  /// Version of this reader common to all plugins based on this class.
+  static const uint32_t m_plugin_version = 1;
+  static const uint32_t g_core_uuid_magic;
+
+  /// ELF file header.
+  elf::ELFHeader m_header;
+
+  /// ELF build ID.
+  lldb_private::UUID m_uuid;
+
+  /// ELF .gnu_debuglink file and crc data if available.
+  std::string m_gnu_debuglink_file;
+  uint32_t m_gnu_debuglink_crc = 0;
+
+  /// Collection of program headers.
+  ProgramHeaderColl m_program_headers;
+
+  /// Collection of section headers.
+  SectionHeaderColl m_section_headers;
+
+  /// The file address of the .dynamic section. This can be found in the p_vaddr
+  /// of the PT_DYNAMIC program header.
+  lldb::addr_t m_dynamic_base_addr = LLDB_INVALID_ADDRESS;
+
+  /// Collection of symbols from the dynamic table.
+  DynamicSymbolColl m_dynamic_symbols;
+
+  /// Object file parsed from .gnu_debugdata section (\sa
+  /// GetGnuDebugDataObjectFile())
+  std::shared_ptr<ObjectFileELF> m_gnu_debug_data_object_file;
+
+  /// List of file specifications corresponding to the modules (shared
+  /// libraries) on which this object file depends.
+  mutable std::unique_ptr<lldb_private::FileSpecList> m_filespec_up;
+
+  /// Cached value of the entry point for this module.
+  lldb_private::Address m_entry_point_address;
+
+  /// The architecture detected from parsing elf file contents.
+  lldb_private::ArchSpec m_arch_spec;
+
+  /// The address class for each symbol in the elf file
+  FileAddressToAddressClassMap m_address_class_map;
+
+  /// Returns the index of the given section header.
+  size_t SectionIndex(const SectionHeaderCollIter &I);
+
+  /// Returns the index of the given section header.
+  size_t SectionIndex(const SectionHeaderCollConstIter &I) const;
+
+  // Parses the ELF program headers.
+  static size_t GetProgramHeaderInfo(ProgramHeaderColl &program_headers,
+                                     lldb_private::DataExtractor &object_data,
+                                     const elf::ELFHeader &header);
+
+  // Finds PT_NOTE segments and calculates their crc sum.
+  static uint32_t
+  CalculateELFNotesSegmentsCRC32(const ProgramHeaderColl &program_headers,
+                                 lldb_private::DataExtractor &data);
+
+  /// Parses all section headers present in this object file and populates
+  /// m_program_headers.  This method will compute the header list only once.
+  /// 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.
+  /// Returns the number of headers parsed.
+  size_t ParseSectionHeaders();
+
+  lldb::SectionType GetSectionType(const ELFSectionHeaderInfo &H) const;
+
+  static void ParseARMAttributes(lldb_private::DataExtractor &data,
+                                 uint64_t length,
+                                 lldb_private::ArchSpec &arch_spec);
+
+  /// Parses the elf section headers and returns the uuid, debug link name,
+  /// crc, archspec.
+  static size_t GetSectionHeaderInfo(SectionHeaderColl &section_headers,
+                                     lldb_private::DataExtractor &object_data,
+                                     const elf::ELFHeader &header,
+                                     lldb_private::UUID &uuid,
+                                     std::string &gnu_debuglink_file,
+                                     uint32_t &gnu_debuglink_crc,
+                                     lldb_private::ArchSpec &arch_spec);
+
+  /// Scans the dynamic section and locates all dependent modules (shared
+  /// libraries) populating m_filespec_up.  This method will compute the
+  /// dependent module list only once.  Returns the number of dependent
+  /// modules parsed.
+  size_t ParseDependentModules();
+
+  /// Parses the dynamic symbol table and populates m_dynamic_symbols.  The
+  /// vector retains the order as found in the object file.  Returns the
+  /// number of dynamic symbols parsed.
+  size_t ParseDynamicSymbols();
+
+  /// Populates the symbol table with all non-dynamic linker symbols.  This
+  /// method will parse the symbols only once.  Returns the number of symbols
+  /// parsed and a map of address types (used by targets like Arm that have
+  /// an alternative ISA mode like Thumb).
+  std::pair<unsigned, FileAddressToAddressClassMap>
+  ParseSymbolTable(lldb_private::Symtab *symbol_table, lldb::user_id_t start_id,
+                   lldb_private::Section *symtab);
+
+  /// Helper routine for ParseSymbolTable().
+  std::pair<unsigned, FileAddressToAddressClassMap>
+  ParseSymbols(lldb_private::Symtab *symbol_table, lldb::user_id_t start_id,
+               lldb_private::SectionList *section_list,
+               const size_t num_symbols,
+               const lldb_private::DataExtractor &symtab_data,
+               const lldb_private::DataExtractor &strtab_data);
+
+  /// Scans the relocation entries and adds a set of artificial symbols to the
+  /// given symbol table for each PLT slot.  Returns the number of symbols
+  /// added.
+  unsigned ParseTrampolineSymbols(lldb_private::Symtab *symbol_table,
+                                  lldb::user_id_t start_id,
+                                  const ELFSectionHeaderInfo *rela_hdr,
+                                  lldb::user_id_t section_id);
+
+  void ParseUnwindSymbols(lldb_private::Symtab *symbol_table,
+                          lldb_private::DWARFCallFrameInfo *eh_frame);
+
+  /// Relocates debug sections
+  unsigned RelocateDebugSections(const elf::ELFSectionHeader *rel_hdr,
+                                 lldb::user_id_t rel_id,
+                                 lldb_private::Symtab *thetab);
+
+  unsigned ApplyRelocations(lldb_private::Symtab *symtab,
+                            const elf::ELFHeader *hdr,
+                            const elf::ELFSectionHeader *rel_hdr,
+                            const elf::ELFSectionHeader *symtab_hdr,
+                            const elf::ELFSectionHeader *debug_hdr,
+                            lldb_private::DataExtractor &rel_data,
+                            lldb_private::DataExtractor &symtab_data,
+                            lldb_private::DataExtractor &debug_data,
+                            lldb_private::Section *rel_section);
+
+  /// Loads the section name string table into m_shstr_data.  Returns the
+  /// number of bytes constituting the table.
+  size_t GetSectionHeaderStringTable();
+
+  /// Utility method for looking up a section given its name.  Returns the
+  /// index of the corresponding section or zero if no section with the given
+  /// name can be found (note that section indices are always 1 based, and so
+  /// section index 0 is never valid).
+  lldb::user_id_t GetSectionIndexByName(const char *name);
+
+  /// Returns the section header with the given id or NULL.
+  const ELFSectionHeaderInfo *GetSectionHeaderByIndex(lldb::user_id_t id);
+
+  /// \name  ELF header dump routines
+  //@{
+  static void DumpELFHeader(lldb_private::Stream *s,
+                            const elf::ELFHeader &header);
+
+  static void DumpELFHeader_e_ident_EI_DATA(lldb_private::Stream *s,
+                                            unsigned char ei_data);
+
+  static void DumpELFHeader_e_type(lldb_private::Stream *s,
+                                   elf::elf_half e_type);
+  //@}
+
+  /// \name ELF program header dump routines
+  //@{
+  void DumpELFProgramHeaders(lldb_private::Stream *s);
+
+  static void DumpELFProgramHeader(lldb_private::Stream *s,
+                                   const elf::ELFProgramHeader &ph);
+
+  static void DumpELFProgramHeader_p_type(lldb_private::Stream *s,
+                                          elf::elf_word p_type);
+
+  static void DumpELFProgramHeader_p_flags(lldb_private::Stream *s,
+                                           elf::elf_word p_flags);
+  //@}
+
+  /// \name ELF section header dump routines
+  //@{
+  void DumpELFSectionHeaders(lldb_private::Stream *s);
+
+  static void DumpELFSectionHeader(lldb_private::Stream *s,
+                                   const ELFSectionHeaderInfo &sh);
+
+  static void DumpELFSectionHeader_sh_type(lldb_private::Stream *s,
+                                           elf::elf_word sh_type);
+
+  static void DumpELFSectionHeader_sh_flags(lldb_private::Stream *s,
+                                            elf::elf_xword sh_flags);
+  //@}
+
+  /// ELF dependent module dump routine.
+  void DumpDependentModules(lldb_private::Stream *s);
+
+  /// ELF dump the .dynamic section
+  void DumpELFDynamic(lldb_private::Stream *s);
+
+  const elf::ELFDynamic *FindDynamicSymbol(unsigned tag);
+
+  unsigned PLTRelocationType();
+
+  static lldb_private::Status
+  RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
+                              lldb_private::ArchSpec &arch_spec,
+                              lldb_private::UUID &uuid);
+
+  bool AnySegmentHasPhysicalAddress();
+
+  /// Takes the .gnu_debugdata and returns the decompressed object file that is
+  /// stored within that section.
+  ///
+  /// \returns either the decompressed object file stored within the
+  /// .gnu_debugdata section or \c nullptr if an error occured or if there's no
+  /// section with that name.
+  std::shared_ptr<ObjectFileELF> GetGnuDebugDataObjectFile();
+
+  /// Get the bytes that represent the .dynamic section.
+  ///
+  /// This function will fetch the data for the .dynamic section in an ELF file.
+  /// The PT_DYNAMIC program header will be used to extract the data and this
+  /// function will fall back to using the section headers if PT_DYNAMIC isn't
+  /// found.
+  ///
+  /// \return The bytes that represent the string table data or \c std::nullopt
+  ///         if an error occured.
+  std::optional<lldb_private::DataExtractor> GetDynamicData();
+
+  /// Get the bytes that represent the dynamic string table data.
+  ///
+  /// This function will fetch the data for the string table in an ELF file. If
+  /// the ELF file is loaded from a file on disk, it will use the section
+  /// headers to extract the data and fall back to using the DT_STRTAB and
+  /// DT_STRSZ .dynamic entries.
+  ///
+  /// \return The bytes that represent the string table data or \c std::nullopt
+  ///         if an error occured.
+  std::optional<lldb_private::DataExtractor> GetDynstrData();
+};
+
+#endif // LLDB_SOURCE_PLUGINS_OBJECTFILE_ELF_OBJECTFILEELF_H

>From d05a2c386e33a343fd7103b6803eed8437eed1af Mon Sep 17 00:00:00 2001
From: Dhruv-Srivastava <dhruv.srivastava at ibm.com>
Date: Thu, 10 Oct 2024 03:08:23 -0500
Subject: [PATCH 2/3] Modified code for XOCFF

---
 .../ObjectFile/XCOFF/ObjectFileXCOFF.h        | 435 +++++-------------
 1 file changed, 119 insertions(+), 316 deletions(-)

diff --git a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h
index aba3a5bfcbf5b6..5a12d16886489d 100644
--- a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h
+++ b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h
@@ -1,4 +1,4 @@
-//===-- ObjectFileELF.h --------------------------------------- -*- C++ -*-===//
+//===-- ObjectFileXCOFF.h --------------------------------------- -*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,12 +6,11 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLDB_SOURCE_PLUGINS_OBJECTFILE_ELF_OBJECTFILEELF_H
-#define LLDB_SOURCE_PLUGINS_OBJECTFILE_ELF_OBJECTFILEELF_H
+#ifndef LLDB_SOURCE_PLUGINS_OBJECTFILE_XCOFF_OBJECTFILEXCOFF_H
+#define LLDB_SOURCE_PLUGINS_OBJECTFILE_XCOFF_OBJECTFILEXCOFF_H
 
 #include <cstdint>
 
-#include <optional>
 #include <vector>
 
 #include "lldb/Symbol/ObjectFile.h"
@@ -19,53 +18,24 @@
 #include "lldb/Utility/FileSpec.h"
 #include "lldb/Utility/UUID.h"
 #include "lldb/lldb-private.h"
+#include "llvm/Object/XCOFFObjectFile.h"
 
-#include "ELFHeader.h"
-
-struct ELFNote {
-  elf::elf_word n_namesz = 0;
-  elf::elf_word n_descsz = 0;
-  elf::elf_word n_type = 0;
-
-  std::string n_name;
-
-  ELFNote() = default;
-
-  /// Parse an ELFNote entry from the given DataExtractor starting at position
-  /// \p offset.
-  ///
-  /// \param[in] data
-  ///    The DataExtractor to read from.
-  ///
-  /// \param[in,out] offset
-  ///    Pointer to an offset in the data.  On return the offset will be
-  ///    advanced by the number of bytes read.
-  ///
-  /// \return
-  ///    True if the ELFRel entry was successfully read and false otherwise.
-  bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
-
-  size_t GetByteSize() const {
-    return 12 + llvm::alignTo(n_namesz, 4) + llvm::alignTo(n_descsz, 4);
-  }
-};
-
-/// \class ObjectFileELF
-/// Generic ELF object file reader.
+/// \class ObjectFileXCOFF
+/// Generic XCOFF object file reader.
 ///
-/// This class provides a generic ELF (32/64 bit) reader plugin implementing
+/// This class provides a generic XCOFF (32/64 bit) reader plugin implementing
 /// the ObjectFile protocol.
-class ObjectFileELF : public lldb_private::ObjectFile {
+class ObjectFileXCOFF : public lldb_private::ObjectFile {
 public:
   // Static Functions
   static void Initialize();
 
   static void Terminate();
 
-  static llvm::StringRef GetPluginNameStatic() { return "elf"; }
+  static llvm::StringRef GetPluginNameStatic() { return "xcoff"; }
 
   static llvm::StringRef GetPluginDescriptionStatic() {
-    return "ELF object file reader.";
+    return "XCOFF object file reader.";
   }
 
   static lldb_private::ObjectFile *
@@ -87,6 +57,8 @@ class ObjectFileELF : public lldb_private::ObjectFile {
   static bool MagicBytesMatch(lldb::DataBufferSP &data_sp, lldb::addr_t offset,
                               lldb::addr_t length);
 
+  static lldb::SymbolType MapSymbolType(llvm::object::SymbolRef::Type sym_type);
+
   // PluginInterface protocol
   llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
 
@@ -103,6 +75,9 @@ class ObjectFileELF : public lldb_private::ObjectFile {
   bool SetLoadAddress(lldb_private::Target &target, lldb::addr_t value,
                       bool value_is_offset) override;
 
+  bool SetLoadAddressByType(lldb_private::Target &target, lldb::addr_t value,
+                              bool value_is_offset, int type_id) override;
+
   lldb::ByteOrder GetByteOrder() const override;
 
   bool IsExecutable() const override;
@@ -140,301 +115,129 @@ class ObjectFileELF : public lldb_private::ObjectFile {
 
   ObjectFile::Strata CalculateStrata() override;
 
-  size_t ReadSectionData(lldb_private::Section *section,
-                         lldb::offset_t section_offset, void *dst,
-                         size_t dst_len) override;
-
-  size_t ReadSectionData(lldb_private::Section *section,
-                         lldb_private::DataExtractor &section_data) override;
-
-  llvm::ArrayRef<elf::ELFProgramHeader> ProgramHeaders();
-  lldb_private::DataExtractor GetSegmentData(const elf::ELFProgramHeader &H);
-
   llvm::StringRef
   StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const override;
 
   void RelocateSection(lldb_private::Section *section) override;
 
-protected:
+  lldb_private::DataExtractor ReadImageData(uint32_t offset, size_t size);
 
-  std::vector<LoadableData>
-  GetLoadableData(lldb_private::Target &target) override;
-
-  static lldb::WritableDataBufferSP
-  MapFileDataWritable(const lldb_private::FileSpec &file, uint64_t Size,
-                      uint64_t Offset);
-
-private:
-  ObjectFileELF(const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp,
+  ObjectFileXCOFF(const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp,
                 lldb::offset_t data_offset, const lldb_private::FileSpec *file,
                 lldb::offset_t offset, lldb::offset_t length);
 
-  ObjectFileELF(const lldb::ModuleSP &module_sp,
+  ObjectFileXCOFF(const lldb::ModuleSP &module_sp,
                 lldb::DataBufferSP header_data_sp,
                 const lldb::ProcessSP &process_sp, lldb::addr_t header_addr);
 
-  typedef std::vector<elf::ELFProgramHeader> ProgramHeaderColl;
-
-  struct ELFSectionHeaderInfo : public elf::ELFSectionHeader {
-    lldb_private::ConstString section_name;
-  };
-
-  typedef std::vector<ELFSectionHeaderInfo> SectionHeaderColl;
-  typedef SectionHeaderColl::iterator SectionHeaderCollIter;
-  typedef SectionHeaderColl::const_iterator SectionHeaderCollConstIter;
-
-  struct ELFDynamicWithName {
-    elf::ELFDynamic symbol;
-    std::string name;
-  };
-  typedef std::vector<ELFDynamicWithName> DynamicSymbolColl;
-  typedef DynamicSymbolColl::iterator DynamicSymbolCollIter;
-  typedef DynamicSymbolColl::const_iterator DynamicSymbolCollConstIter;
-
-  /// An ordered map of file address to address class. Used on architectures
-  /// like Arm where there is an alternative ISA mode like Thumb. The container
-  /// is ordered so that it can be binary searched.
-  typedef std::map<lldb::addr_t, lldb_private::AddressClass>
-      FileAddressToAddressClassMap;
-
-  /// Version of this reader common to all plugins based on this class.
-  static const uint32_t m_plugin_version = 1;
-  static const uint32_t g_core_uuid_magic;
-
-  /// ELF file header.
-  elf::ELFHeader m_header;
-
-  /// ELF build ID.
-  lldb_private::UUID m_uuid;
-
-  /// ELF .gnu_debuglink file and crc data if available.
-  std::string m_gnu_debuglink_file;
-  uint32_t m_gnu_debuglink_crc = 0;
-
-  /// Collection of program headers.
-  ProgramHeaderColl m_program_headers;
+protected:
 
-  /// Collection of section headers.
-  SectionHeaderColl m_section_headers;
+  typedef struct xcoff_header {
+    uint16_t magic;
+    uint16_t nsects;
+    uint32_t modtime;
+    uint64_t symoff;
+    uint32_t nsyms;
+    uint16_t auxhdrsize;
+    uint16_t flags;
+  } xcoff_header_t;
+
+  typedef struct xcoff_aux_header {
+    uint16_t AuxMagic;
+    uint16_t Version;
+    uint32_t ReservedForDebugger;
+    uint64_t TextStartAddr;
+    uint64_t DataStartAddr;
+    uint64_t TOCAnchorAddr;
+    uint16_t SecNumOfEntryPoint;
+    uint16_t SecNumOfText;
+    uint16_t SecNumOfData;
+    uint16_t SecNumOfTOC;
+    uint16_t SecNumOfLoader;
+    uint16_t SecNumOfBSS;
+    uint16_t MaxAlignOfText;
+    uint16_t MaxAlignOfData;
+    uint16_t ModuleType;
+    uint8_t CpuFlag;
+    uint8_t CpuType;
+    uint8_t TextPageSize;
+    uint8_t DataPageSize;
+    uint8_t StackPageSize;
+    uint8_t FlagAndTDataAlignment;
+    uint64_t TextSize;
+    uint64_t InitDataSize;
+    uint64_t BssDataSize;
+    uint64_t EntryPointAddr;
+    uint64_t MaxStackSize;
+    uint64_t MaxDataSize;
+    uint16_t SecNumOfTData;
+    uint16_t SecNumOfTBSS;
+    uint16_t XCOFF64Flag;
+  } xcoff_aux_header_t;
+
+  typedef struct section_header {
+    char name[8];
+    uint64_t phyaddr; // Physical Addr
+    uint64_t vmaddr;  // Virtual Addr
+    uint64_t size;    // Section size
+    uint64_t offset;  // File offset to raw data
+    uint64_t reloff;  // Offset to relocations
+    uint64_t lineoff; // Offset to line table entries
+    uint32_t nreloc;  // Number of relocation entries
+    uint32_t nline;   // Number of line table entries
+    uint32_t flags;
+  } section_header_t;
+
+  typedef struct xcoff_symbol {
+    uint64_t value;
+    uint32_t offset;
+    uint16_t sect;
+    uint16_t type;
+    uint8_t storage;
+    uint8_t naux;
+  } xcoff_symbol_t;
+
+  typedef struct xcoff_sym_csect_aux_entry {
+    uint32_t section_or_len_low_byte;
+    uint32_t parameter_hash_index;
+    uint16_t type_check_sect_num;
+    uint8_t symbol_alignment_and_type;
+    uint8_t storage_mapping_class;
+    uint32_t section_or_len_high_byte;
+    uint8_t pad;
+    uint8_t aux_type;
+  } xcoff_sym_csect_aux_entry_t;
+
+  static bool ParseXCOFFHeader(lldb_private::DataExtractor &data,
+                              lldb::offset_t *offset_ptr,
+                              xcoff_header_t &xcoff_header);
+  bool ParseXCOFFOptionalHeader(lldb_private::DataExtractor &data,
+                                lldb::offset_t *offset_ptr);
+  bool ParseSectionHeaders(uint32_t offset);
 
-  /// The file address of the .dynamic section. This can be found in the p_vaddr
-  /// of the PT_DYNAMIC program header.
-  lldb::addr_t m_dynamic_base_addr = LLDB_INVALID_ADDRESS;
+  std::vector<LoadableData>
+  GetLoadableData(lldb_private::Target &target) override;
 
-  /// Collection of symbols from the dynamic table.
-  DynamicSymbolColl m_dynamic_symbols;
+  static lldb::WritableDataBufferSP
+  MapFileDataWritable(const lldb_private::FileSpec &file, uint64_t Size,
+                      uint64_t Offset);
+  llvm::StringRef GetSectionName(const section_header_t &sect);
+  static lldb::SectionType GetSectionType(llvm::StringRef sect_name,
+                                          const section_header_t &sect);
 
-  /// Object file parsed from .gnu_debugdata section (\sa
-  /// GetGnuDebugDataObjectFile())
-  std::shared_ptr<ObjectFileELF> m_gnu_debug_data_object_file;
+  uint32_t ParseDependentModules();
+  typedef std::vector<section_header_t> SectionHeaderColl;
 
-  /// List of file specifications corresponding to the modules (shared
-  /// libraries) on which this object file depends.
-  mutable std::unique_ptr<lldb_private::FileSpecList> m_filespec_up;
+private:
+  bool CreateBinary();
 
-  /// Cached value of the entry point for this module.
+  xcoff_header_t m_xcoff_header;
+  xcoff_aux_header_t m_xcoff_aux_header;
+  SectionHeaderColl m_sect_headers;
+  std::unique_ptr<llvm::object::XCOFFObjectFile> m_binary;
   lldb_private::Address m_entry_point_address;
-
-  /// The architecture detected from parsing elf file contents.
-  lldb_private::ArchSpec m_arch_spec;
-
-  /// The address class for each symbol in the elf file
-  FileAddressToAddressClassMap m_address_class_map;
-
-  /// Returns the index of the given section header.
-  size_t SectionIndex(const SectionHeaderCollIter &I);
-
-  /// Returns the index of the given section header.
-  size_t SectionIndex(const SectionHeaderCollConstIter &I) const;
-
-  // Parses the ELF program headers.
-  static size_t GetProgramHeaderInfo(ProgramHeaderColl &program_headers,
-                                     lldb_private::DataExtractor &object_data,
-                                     const elf::ELFHeader &header);
-
-  // Finds PT_NOTE segments and calculates their crc sum.
-  static uint32_t
-  CalculateELFNotesSegmentsCRC32(const ProgramHeaderColl &program_headers,
-                                 lldb_private::DataExtractor &data);
-
-  /// Parses all section headers present in this object file and populates
-  /// m_program_headers.  This method will compute the header list only once.
-  /// 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.
-  /// Returns the number of headers parsed.
-  size_t ParseSectionHeaders();
-
-  lldb::SectionType GetSectionType(const ELFSectionHeaderInfo &H) const;
-
-  static void ParseARMAttributes(lldb_private::DataExtractor &data,
-                                 uint64_t length,
-                                 lldb_private::ArchSpec &arch_spec);
-
-  /// Parses the elf section headers and returns the uuid, debug link name,
-  /// crc, archspec.
-  static size_t GetSectionHeaderInfo(SectionHeaderColl &section_headers,
-                                     lldb_private::DataExtractor &object_data,
-                                     const elf::ELFHeader &header,
-                                     lldb_private::UUID &uuid,
-                                     std::string &gnu_debuglink_file,
-                                     uint32_t &gnu_debuglink_crc,
-                                     lldb_private::ArchSpec &arch_spec);
-
-  /// Scans the dynamic section and locates all dependent modules (shared
-  /// libraries) populating m_filespec_up.  This method will compute the
-  /// dependent module list only once.  Returns the number of dependent
-  /// modules parsed.
-  size_t ParseDependentModules();
-
-  /// Parses the dynamic symbol table and populates m_dynamic_symbols.  The
-  /// vector retains the order as found in the object file.  Returns the
-  /// number of dynamic symbols parsed.
-  size_t ParseDynamicSymbols();
-
-  /// Populates the symbol table with all non-dynamic linker symbols.  This
-  /// method will parse the symbols only once.  Returns the number of symbols
-  /// parsed and a map of address types (used by targets like Arm that have
-  /// an alternative ISA mode like Thumb).
-  std::pair<unsigned, FileAddressToAddressClassMap>
-  ParseSymbolTable(lldb_private::Symtab *symbol_table, lldb::user_id_t start_id,
-                   lldb_private::Section *symtab);
-
-  /// Helper routine for ParseSymbolTable().
-  std::pair<unsigned, FileAddressToAddressClassMap>
-  ParseSymbols(lldb_private::Symtab *symbol_table, lldb::user_id_t start_id,
-               lldb_private::SectionList *section_list,
-               const size_t num_symbols,
-               const lldb_private::DataExtractor &symtab_data,
-               const lldb_private::DataExtractor &strtab_data);
-
-  /// Scans the relocation entries and adds a set of artificial symbols to the
-  /// given symbol table for each PLT slot.  Returns the number of symbols
-  /// added.
-  unsigned ParseTrampolineSymbols(lldb_private::Symtab *symbol_table,
-                                  lldb::user_id_t start_id,
-                                  const ELFSectionHeaderInfo *rela_hdr,
-                                  lldb::user_id_t section_id);
-
-  void ParseUnwindSymbols(lldb_private::Symtab *symbol_table,
-                          lldb_private::DWARFCallFrameInfo *eh_frame);
-
-  /// Relocates debug sections
-  unsigned RelocateDebugSections(const elf::ELFSectionHeader *rel_hdr,
-                                 lldb::user_id_t rel_id,
-                                 lldb_private::Symtab *thetab);
-
-  unsigned ApplyRelocations(lldb_private::Symtab *symtab,
-                            const elf::ELFHeader *hdr,
-                            const elf::ELFSectionHeader *rel_hdr,
-                            const elf::ELFSectionHeader *symtab_hdr,
-                            const elf::ELFSectionHeader *debug_hdr,
-                            lldb_private::DataExtractor &rel_data,
-                            lldb_private::DataExtractor &symtab_data,
-                            lldb_private::DataExtractor &debug_data,
-                            lldb_private::Section *rel_section);
-
-  /// Loads the section name string table into m_shstr_data.  Returns the
-  /// number of bytes constituting the table.
-  size_t GetSectionHeaderStringTable();
-
-  /// Utility method for looking up a section given its name.  Returns the
-  /// index of the corresponding section or zero if no section with the given
-  /// name can be found (note that section indices are always 1 based, and so
-  /// section index 0 is never valid).
-  lldb::user_id_t GetSectionIndexByName(const char *name);
-
-  /// Returns the section header with the given id or NULL.
-  const ELFSectionHeaderInfo *GetSectionHeaderByIndex(lldb::user_id_t id);
-
-  /// \name  ELF header dump routines
-  //@{
-  static void DumpELFHeader(lldb_private::Stream *s,
-                            const elf::ELFHeader &header);
-
-  static void DumpELFHeader_e_ident_EI_DATA(lldb_private::Stream *s,
-                                            unsigned char ei_data);
-
-  static void DumpELFHeader_e_type(lldb_private::Stream *s,
-                                   elf::elf_half e_type);
-  //@}
-
-  /// \name ELF program header dump routines
-  //@{
-  void DumpELFProgramHeaders(lldb_private::Stream *s);
-
-  static void DumpELFProgramHeader(lldb_private::Stream *s,
-                                   const elf::ELFProgramHeader &ph);
-
-  static void DumpELFProgramHeader_p_type(lldb_private::Stream *s,
-                                          elf::elf_word p_type);
-
-  static void DumpELFProgramHeader_p_flags(lldb_private::Stream *s,
-                                           elf::elf_word p_flags);
-  //@}
-
-  /// \name ELF section header dump routines
-  //@{
-  void DumpELFSectionHeaders(lldb_private::Stream *s);
-
-  static void DumpELFSectionHeader(lldb_private::Stream *s,
-                                   const ELFSectionHeaderInfo &sh);
-
-  static void DumpELFSectionHeader_sh_type(lldb_private::Stream *s,
-                                           elf::elf_word sh_type);
-
-  static void DumpELFSectionHeader_sh_flags(lldb_private::Stream *s,
-                                            elf::elf_xword sh_flags);
-  //@}
-
-  /// ELF dependent module dump routine.
-  void DumpDependentModules(lldb_private::Stream *s);
-
-  /// ELF dump the .dynamic section
-  void DumpELFDynamic(lldb_private::Stream *s);
-
-  const elf::ELFDynamic *FindDynamicSymbol(unsigned tag);
-
-  unsigned PLTRelocationType();
-
-  static lldb_private::Status
-  RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
-                              lldb_private::ArchSpec &arch_spec,
-                              lldb_private::UUID &uuid);
-
-  bool AnySegmentHasPhysicalAddress();
-
-  /// Takes the .gnu_debugdata and returns the decompressed object file that is
-  /// stored within that section.
-  ///
-  /// \returns either the decompressed object file stored within the
-  /// .gnu_debugdata section or \c nullptr if an error occured or if there's no
-  /// section with that name.
-  std::shared_ptr<ObjectFileELF> GetGnuDebugDataObjectFile();
-
-  /// Get the bytes that represent the .dynamic section.
-  ///
-  /// This function will fetch the data for the .dynamic section in an ELF file.
-  /// The PT_DYNAMIC program header will be used to extract the data and this
-  /// function will fall back to using the section headers if PT_DYNAMIC isn't
-  /// found.
-  ///
-  /// \return The bytes that represent the string table data or \c std::nullopt
-  ///         if an error occured.
-  std::optional<lldb_private::DataExtractor> GetDynamicData();
-
-  /// Get the bytes that represent the dynamic string table data.
-  ///
-  /// This function will fetch the data for the string table in an ELF file. If
-  /// the ELF file is loaded from a file on disk, it will use the section
-  /// headers to extract the data and fall back to using the DT_STRTAB and
-  /// DT_STRSZ .dynamic entries.
-  ///
-  /// \return The bytes that represent the string table data or \c std::nullopt
-  ///         if an error occured.
-  std::optional<lldb_private::DataExtractor> GetDynstrData();
+  std::optional<lldb_private::FileSpecList> m_deps_filespec;
+  std::map<std::string, std::vector<std::string>> m_deps_base_members;
 };
 
 #endif // LLDB_SOURCE_PLUGINS_OBJECTFILE_ELF_OBJECTFILEELF_H

>From 95336864307c50186bd9dfafb9770c0ce16d4daa Mon Sep 17 00:00:00 2001
From: Dhruv-Srivastava <dhruv.srivastava at ibm.com>
Date: Thu, 10 Oct 2024 06:27:03 -0500
Subject: [PATCH 3/3] clang-format changes

---
 .../ObjectFile/XCOFF/ObjectFileXCOFF.h        | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h
index 5a12d16886489d..2cb73394a0306d 100644
--- a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h
+++ b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h
@@ -1,4 +1,5 @@
-//===-- ObjectFileXCOFF.h --------------------------------------- -*- C++ -*-===//
+//===-- ObjectFileXCOFF.h --------------------------------------- -*- C++
+//-*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -76,7 +77,7 @@ class ObjectFileXCOFF : public lldb_private::ObjectFile {
                       bool value_is_offset) override;
 
   bool SetLoadAddressByType(lldb_private::Target &target, lldb::addr_t value,
-                              bool value_is_offset, int type_id) override;
+                            bool value_is_offset, int type_id) override;
 
   lldb::ByteOrder GetByteOrder() const override;
 
@@ -123,15 +124,15 @@ class ObjectFileXCOFF : public lldb_private::ObjectFile {
   lldb_private::DataExtractor ReadImageData(uint32_t offset, size_t size);
 
   ObjectFileXCOFF(const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp,
-                lldb::offset_t data_offset, const lldb_private::FileSpec *file,
-                lldb::offset_t offset, lldb::offset_t length);
+                  lldb::offset_t data_offset,
+                  const lldb_private::FileSpec *file, lldb::offset_t offset,
+                  lldb::offset_t length);
 
   ObjectFileXCOFF(const lldb::ModuleSP &module_sp,
-                lldb::DataBufferSP header_data_sp,
-                const lldb::ProcessSP &process_sp, lldb::addr_t header_addr);
+                  lldb::DataBufferSP header_data_sp,
+                  const lldb::ProcessSP &process_sp, lldb::addr_t header_addr);
 
 protected:
-
   typedef struct xcoff_header {
     uint16_t magic;
     uint16_t nsects;
@@ -209,8 +210,8 @@ class ObjectFileXCOFF : public lldb_private::ObjectFile {
   } xcoff_sym_csect_aux_entry_t;
 
   static bool ParseXCOFFHeader(lldb_private::DataExtractor &data,
-                              lldb::offset_t *offset_ptr,
-                              xcoff_header_t &xcoff_header);
+                               lldb::offset_t *offset_ptr,
+                               xcoff_header_t &xcoff_header);
   bool ParseXCOFFOptionalHeader(lldb_private::DataExtractor &data,
                                 lldb::offset_t *offset_ptr);
   bool ParseSectionHeaders(uint32_t offset);



More information about the lldb-commits mailing list