Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[lldb][AIX] Header Parsing for XCOFF Object File in AIX #116338

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

DhruvSrivastavaX
Copy link
Contributor

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. Extending LLDB to work on AIX #101657
    The complete changes for porting are present in this draft PR:
    Extending LLDB to work on AIX #102601

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

Details about XCOFF file format on AIX: XCOFF

Review Request: @labath @DavidSpickett

@DhruvSrivastavaX
Copy link
Contributor Author

Hi @labath , not sure why the Labelling new pull requests check failed. Also, the build check didnt automatically start for this one.

Copy link

github-actions bot commented Nov 15, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Collaborator

@labath labath left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you actually need to parse the headers yourself? The reason for using the llvm implementation was so that we can avoid that. FWICS, all of this data should be available through the (file|auxiliary)Header(32|64) APIs.

BTW, this is exactly the kind of granularity I was looking for.

@labath
Copy link
Collaborator

labath commented Nov 15, 2024

Hi @labath , not sure why the Labelling new pull requests check failed. Also, the build check didnt automatically start for this one.

I don't know, but I wouldn't be worried about that. The test failure is more of a concern.

@DhruvSrivastavaX
Copy link
Contributor Author

Do you actually need to parse the headers yourself? The reason for using the llvm implementation was so that we can avoid that. FWICS, all of this data should be available through the (file|auxiliary)Header(32|64) APIs.

Okay, I'll take a look at that.

BTW, this is exactly the kind of granularity I was looking for.

Happy to hear that! Will follow the similar practice.

I don't know, but I wouldn't be worried about that. The test failure is more of a concern.

Yeah, I think I missed the test case modification accordingly. Will update!

@llvmbot llvmbot added the lldb label Nov 16, 2024
@llvmbot
Copy link

llvmbot commented Nov 16, 2024

@llvm/pr-subscribers-lldb

Author: Dhruv Srivastava (DhruvSrivastavaX)

Changes

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. Extending LLDB to work on AIX #101657
    The complete changes for porting are present in this draft PR:
    Extending LLDB to work on AIX #102601

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

Details about XCOFF file format on AIX: XCOFF

Review Request: @labath @DavidSpickett


Full diff: https://github.com/llvm/llvm-project/pull/116338.diff

2 Files Affected:

  • (modified) lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp (+125-3)
  • (modified) lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h (+58)
diff --git a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp
index 3be900f9a4bc9f..255171997db399 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,94 @@ 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 +278,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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants