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

Dhruv Srivastava via lldb-commits lldb-commits at lists.llvm.org
Fri Nov 15 00:22:42 PST 2024


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

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. https://github.com/llvm/llvm-project/issues/101657
The complete changes for porting are present in this draft PR:
https://github.com/llvm/llvm-project/pull/102601

Added XCOFF Object File Header Parsing for AIX.
This PR is an incremental PR to the base: 
#111814

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: @labath @DavidSpickett

>From 0c63800bdcbadcfceed4c9a81305eda7d5a15960 Mon Sep 17 00:00:00 2001
From: Dhruv-Srivastava <dhruv.srivastava at ibm.com>
Date: Fri, 15 Nov 2024 02:16:31 -0600
Subject: [PATCH] Added XCOFF Header Parsing

---
 .../ObjectFile/XCOFF/ObjectFileXCOFF.cpp      | 126 +++++++++++++++++-
 .../ObjectFile/XCOFF/ObjectFileXCOFF.h        |  58 ++++++++
 2 files changed, 181 insertions(+), 3 deletions(-)

diff --git a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp
index 3be900f9a4bc9f..c06ece4347822d 100644
--- a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp
+++ b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp
@@ -81,9 +81,44 @@ ObjectFile *ObjectFileXCOFF::CreateInstance(const lldb::ModuleSP &module_sp,
   if (!objfile_up)
     return nullptr;
 
+  // Cache xcoff binary.
+  if (!objfile_up->CreateBinary())
+    return nullptr;
+
+  if (!objfile_up->ParseHeader())
+    return nullptr;
+
   return objfile_up.release();
 }
 
+bool ObjectFileXCOFF::CreateBinary() {
+  if (m_binary)
+    return true;
+
+  Log *log = GetLog(LLDBLog::Object);
+
+  auto binary = llvm::object::XCOFFObjectFile::createObjectFile(
+      llvm::MemoryBufferRef(toStringRef(m_data.GetData()),
+                            m_file.GetFilename().GetStringRef()),
+      file_magic::xcoff_object_64);
+  if (!binary) {
+    LLDB_LOG_ERROR(log, binary.takeError(),
+                   "Failed to create binary for file ({1}): {0}", m_file);
+    return false;
+  }
+
+  // Make sure we only handle XCOFF format.
+  m_binary =
+      llvm::unique_dyn_cast<llvm::object::XCOFFObjectFile>(std::move(*binary));
+  if (!m_binary)
+    return false;
+
+  LLDB_LOG(log, "this = {0}, module = {1} ({2}), file = {3}, binary = {4}",
+           this, GetModule().get(), GetModule()->GetSpecificationDescription(),
+           m_file.GetPath(), m_binary.get());
+  return true;
+}
+
 ObjectFile *ObjectFileXCOFF::CreateMemoryInstance(
     const lldb::ModuleSP &module_sp, WritableDataBufferSP data_sp,
     const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) {
@@ -136,13 +171,92 @@ bool ObjectFileXCOFF::MagicBytesMatch(DataBufferSP &data_sp,
   return XCOFFHeaderSizeFromMagic(magic) != 0;
 }
 
-bool ObjectFileXCOFF::ParseHeader() { return false; }
+bool ObjectFileXCOFF::ParseHeader() {
+  ModuleSP module_sp(GetModule());
+  if (module_sp) {
+    std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
+    lldb::offset_t offset = 0;
+
+    if (ParseXCOFFHeader(m_data, &offset, m_xcoff_header)) {
+      m_data.SetAddressByteSize(GetAddressByteSize());
+      if (m_xcoff_header.auxhdrsize > 0)
+        ParseXCOFFOptionalHeader(m_data, &offset);
+    }
+    return true;
+  }
+
+  return false;
+}
+
+bool ObjectFileXCOFF::ParseXCOFFHeader(lldb_private::DataExtractor &data,
+                                       lldb::offset_t *offset_ptr,
+                                       xcoff_header_t &xcoff_header) {
+  // FIXME: data.ValidOffsetForDataOfSize
+  xcoff_header.magic = data.GetU16(offset_ptr);
+  xcoff_header.nsects = data.GetU16(offset_ptr);
+  xcoff_header.modtime = data.GetU32(offset_ptr);
+  xcoff_header.symoff = data.GetU64(offset_ptr);
+  xcoff_header.auxhdrsize = data.GetU16(offset_ptr);
+  xcoff_header.flags = data.GetU16(offset_ptr);
+  xcoff_header.nsyms = data.GetU32(offset_ptr);
+  return true;
+}
+
+bool ObjectFileXCOFF::ParseXCOFFOptionalHeader(
+    lldb_private::DataExtractor &data, lldb::offset_t *offset_ptr) {
+  lldb::offset_t init_offset = *offset_ptr;
+  // FIXME: data.ValidOffsetForDataOfSize
+  m_xcoff_aux_header.AuxMagic = data.GetU16(offset_ptr);
+  m_xcoff_aux_header.Version = data.GetU16(offset_ptr);
+  m_xcoff_aux_header.ReservedForDebugger = data.GetU32(offset_ptr);
+  m_xcoff_aux_header.TextStartAddr = data.GetU64(offset_ptr);
+  m_xcoff_aux_header.DataStartAddr = data.GetU64(offset_ptr);
+  m_xcoff_aux_header.TOCAnchorAddr = data.GetU64(offset_ptr);
+  m_xcoff_aux_header.SecNumOfEntryPoint = data.GetU16(offset_ptr);
+  m_xcoff_aux_header.SecNumOfText = data.GetU16(offset_ptr);
+  m_xcoff_aux_header.SecNumOfData = data.GetU16(offset_ptr);
+  m_xcoff_aux_header.SecNumOfTOC = data.GetU16(offset_ptr);
+  m_xcoff_aux_header.SecNumOfLoader = data.GetU16(offset_ptr);
+  m_xcoff_aux_header.SecNumOfBSS = data.GetU16(offset_ptr);
+  m_xcoff_aux_header.MaxAlignOfText = data.GetU16(offset_ptr);
+  m_xcoff_aux_header.MaxAlignOfData = data.GetU16(offset_ptr);
+  m_xcoff_aux_header.ModuleType = data.GetU16(offset_ptr);
+  m_xcoff_aux_header.CpuFlag = data.GetU8(offset_ptr);
+  m_xcoff_aux_header.CpuType = data.GetU8(offset_ptr);
+  m_xcoff_aux_header.TextPageSize = data.GetU8(offset_ptr);
+  m_xcoff_aux_header.DataPageSize = data.GetU8(offset_ptr);
+  m_xcoff_aux_header.StackPageSize = data.GetU8(offset_ptr);
+  m_xcoff_aux_header.FlagAndTDataAlignment = data.GetU8(offset_ptr);
+  m_xcoff_aux_header.TextSize = data.GetU64(offset_ptr);
+  m_xcoff_aux_header.InitDataSize = data.GetU64(offset_ptr);
+  m_xcoff_aux_header.BssDataSize = data.GetU64(offset_ptr);
+  m_xcoff_aux_header.EntryPointAddr = data.GetU64(offset_ptr);
+  m_xcoff_aux_header.MaxStackSize = data.GetU64(offset_ptr);
+  m_xcoff_aux_header.MaxDataSize = data.GetU64(offset_ptr);
+  m_xcoff_aux_header.SecNumOfTData = data.GetU16(offset_ptr);
+  m_xcoff_aux_header.SecNumOfTBSS = data.GetU16(offset_ptr);
+  m_xcoff_aux_header.XCOFF64Flag = data.GetU16(offset_ptr);
+  lldb::offset_t last_offset = *offset_ptr;
+  if ((last_offset - init_offset) < m_xcoff_header.auxhdrsize)
+    *offset_ptr += (m_xcoff_header.auxhdrsize - (last_offset - init_offset));
+  return true;
+}
 
 ByteOrder ObjectFileXCOFF::GetByteOrder() const { return eByteOrderBig; }
 
 bool ObjectFileXCOFF::IsExecutable() const { return true; }
 
-uint32_t ObjectFileXCOFF::GetAddressByteSize() const { return 8; }
+uint32_t ObjectFileXCOFF::GetAddressByteSize() const {
+  if (m_xcoff_header.magic == XCOFF::XCOFF64)
+    return 8;
+  else if (m_xcoff_header.magic == XCOFF::XCOFF32)
+    return 4;
+  return 4;
+}
+
+AddressClass ObjectFileXCOFF::GetAddressClass(addr_t file_addr) {
+  return AddressClass::eUnknown;
+}
 
 void ObjectFileXCOFF::ParseSymtab(Symtab &lldb_symtab) {}
 
@@ -162,7 +276,13 @@ UUID ObjectFileXCOFF::GetUUID() { return UUID(); }
 
 uint32_t ObjectFileXCOFF::GetDependentModules(FileSpecList &files) { return 0; }
 
-ObjectFile::Type ObjectFileXCOFF::CalculateType() { return eTypeExecutable; }
+ObjectFile::Type ObjectFileXCOFF::CalculateType() {
+  if (m_xcoff_header.flags & XCOFF::F_EXEC)
+    return eTypeExecutable;
+  else if (m_xcoff_header.flags & XCOFF::F_SHROBJ)
+    return eTypeSharedLibrary;
+  return eTypeUnknown;
+}
 
 ObjectFile::Strata ObjectFileXCOFF::CalculateStrata() { return eStrataUnknown; }
 
diff --git a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h
index 3a33b97b9e8da1..a155441135bfcb 100644
--- a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h
+++ b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h
@@ -70,6 +70,8 @@ class ObjectFileXCOFF : public lldb_private::ObjectFile {
 
   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;
@@ -98,9 +100,65 @@ class ObjectFileXCOFF : public lldb_private::ObjectFile {
                   const lldb::ProcessSP &process_sp, lldb::addr_t header_addr);
 
 protected:
+  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;
+
+  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);
+
   static lldb::WritableDataBufferSP
   MapFileDataWritable(const lldb_private::FileSpec &file, uint64_t Size,
                       uint64_t Offset);
+
+private:
+  bool CreateBinary();
+
+  xcoff_header_t m_xcoff_header;
+  xcoff_aux_header_t m_xcoff_aux_header;
+  std::unique_ptr<llvm::object::XCOFFObjectFile> m_binary;
 };
 
 #endif // LLDB_SOURCE_PLUGINS_OBJECTFILE_XCOFF_OBJECTFILE_H



More information about the lldb-commits mailing list