[llvm] r359244 - [Object][XCOFF] Add intial support for section header table.

Sean Fertile via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 25 14:36:04 PDT 2019


Author: sfertile
Date: Thu Apr 25 14:36:04 2019
New Revision: 359244

URL: http://llvm.org/viewvc/llvm-project?rev=359244&view=rev
Log:
[Object][XCOFF] Add intial support for section header table.

Adds a representation of the section header table to XCOFFObjectFile,
and implements enough to dump the section headers with llvm-obdump.

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

Added:
    llvm/trunk/include/llvm/BinaryFormat/XCOFF.h
    llvm/trunk/test/tools/llvm-objdump/Inputs/xcoff-long-sec-names.o   (with props)
    llvm/trunk/test/tools/llvm-objdump/Inputs/xcoff-section-headers-truncate.o   (with props)
    llvm/trunk/test/tools/llvm-objdump/Inputs/xcoff-section-headers.o   (with props)
    llvm/trunk/test/tools/llvm-objdump/xcoff-section-headers.test
Modified:
    llvm/trunk/include/llvm/Object/XCOFFObjectFile.h
    llvm/trunk/lib/Object/XCOFFObjectFile.cpp

Added: llvm/trunk/include/llvm/BinaryFormat/XCOFF.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/BinaryFormat/XCOFF.h?rev=359244&view=auto
==============================================================================
--- llvm/trunk/include/llvm/BinaryFormat/XCOFF.h (added)
+++ llvm/trunk/include/llvm/BinaryFormat/XCOFF.h Thu Apr 25 14:36:04 2019
@@ -0,0 +1,43 @@
+//===-- llvm/BinaryFormat/XCOFF.h - The XCOFF file format -------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines manifest constants for the XCOFF object file format.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_BINARYFORMAT_XCOFF_H
+#define LLVM_BINARYFORMAT_XCOFF_H
+
+namespace llvm {
+namespace XCOFF {
+
+// Constants used in the XCOFF definition.
+enum { SectionNameSize = 8 };
+
+// Flags for defining the section type. Used for the s_flags field of
+// the section header structure. Defined in the system header `scnhdr.h`.
+enum SectionTypeFlags {
+  STYP_PAD = 0x0008,
+  STYP_DWARF = 0x0010,
+  STYP_TEXT = 0x0020,
+  STYP_DATA = 0x0040,
+  STYP_BSS = 0x0080,
+  STYP_EXCEPT = 0x0100,
+  STYP_INFO = 0x0200,
+  STYP_TDATA = 0x0400,
+  STYP_TBSS = 0x0800,
+  STYP_LOADER = 0x1000,
+  STYP_DEBUG = 0x2000,
+  STYP_TYPCHK = 0x4000,
+  STYP_OVRFLO = 0x8000
+};
+
+} // end namespace XCOFF
+} // end namespace llvm
+
+#endif

Modified: llvm/trunk/include/llvm/Object/XCOFFObjectFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/XCOFFObjectFile.h?rev=359244&r1=359243&r2=359244&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/XCOFFObjectFile.h (original)
+++ llvm/trunk/include/llvm/Object/XCOFFObjectFile.h Thu Apr 25 14:36:04 2019
@@ -16,6 +16,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/iterator_range.h"
 #include "llvm/BinaryFormat/Magic.h"
+#include "llvm/BinaryFormat/XCOFF.h"
 #include "llvm/MC/SubtargetFeature.h"
 #include "llvm/Object/Binary.h"
 #include "llvm/Object/Error.h"
@@ -47,9 +48,30 @@ struct XCOFFFileHeader {
   support::ubig16_t Flags;
 };
 
+struct XCOFFSectionHeader {
+  char Name[XCOFF::SectionNameSize];
+  support::ubig32_t PhysicalAddress;
+  support::ubig32_t VirtualAddress;
+  support::ubig32_t SectionSize;
+  support::ubig32_t FileOffsetToRawData;
+  support::ubig32_t FileOffsetToRelocationInfo;
+  support::ubig32_t FileOffsetToLineNumberInfo;
+  support::ubig16_t NumberOfRelocations;
+  support::ubig16_t NumberOfLineNumbers;
+  support::big32_t Flags;
+};
+
 class XCOFFObjectFile : public ObjectFile {
 private:
   const XCOFFFileHeader *FileHdrPtr = nullptr;
+  const XCOFFSectionHeader *SectionHdrTablePtr = nullptr;
+
+  size_t getFileHeaderSize() const;
+  size_t getSectionHeaderSize() const;
+
+  const XCOFFSectionHeader *toSection(DataRefImpl Ref) const;
+
+  uint16_t getNumberOfSections() const;
 
 public:
   void moveSymbolNext(DataRefImpl &Symb) const override;
@@ -95,13 +117,12 @@ public:
   StringRef getFileFormatName() const override;
   Triple::ArchType getArch() const override;
   SubtargetFeatures getFeatures() const override;
+  Expected<uint64_t> getStartAddress() const override;
   bool isRelocatableObject() const override;
 
-public:
   XCOFFObjectFile(MemoryBufferRef Object, std::error_code &EC);
 
   const XCOFFFileHeader *getFileHeader() const { return FileHdrPtr; }
-
 }; // XCOFFObjectFile
 
 } // namespace object

Modified: llvm/trunk/lib/Object/XCOFFObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/XCOFFObjectFile.cpp?rev=359244&r1=359243&r2=359244&view=diff
==============================================================================
--- llvm/trunk/lib/Object/XCOFFObjectFile.cpp (original)
+++ llvm/trunk/lib/Object/XCOFFObjectFile.cpp Thu Apr 25 14:36:04 2019
@@ -22,6 +22,10 @@
 namespace llvm {
 namespace object {
 
+enum { XCOFF32FileHeaderSize = 20 };
+static_assert(sizeof(XCOFFFileHeader) == XCOFF32FileHeaderSize,
+              "Wrong size for XCOFF file header.");
+
 // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
 // Returns unexpected_eof on error.
 template <typename T>
@@ -35,6 +39,40 @@ static std::error_code getObject(const T
   return std::error_code();
 }
 
+template <typename T> static const T *viewAs(uintptr_t in) {
+  return reinterpret_cast<const T *>(in);
+}
+
+const XCOFFSectionHeader *XCOFFObjectFile::toSection(DataRefImpl Ref) const {
+  auto Sec = viewAs<XCOFFSectionHeader>(Ref.p);
+#ifndef NDEBUG
+  if (Sec < SectionHdrTablePtr ||
+      Sec >= (SectionHdrTablePtr + getNumberOfSections()))
+    report_fatal_error("Section header outside of section header table.");
+
+  uintptr_t Offset = uintptr_t(Sec) - uintptr_t(SectionHdrTablePtr);
+  if (Offset % getSectionHeaderSize() != 0)
+    report_fatal_error(
+        "Section header pointer does not point to a valid section header.");
+#endif
+  return Sec;
+}
+
+// The next 2 functions are not exactly necessary yet, but they are useful to
+// abstract over the size difference between XCOFF32 and XCOFF64 structure
+// definitions.
+size_t XCOFFObjectFile::getFileHeaderSize() const {
+  return sizeof(XCOFFFileHeader);
+}
+
+size_t XCOFFObjectFile::getSectionHeaderSize() const {
+  return sizeof(XCOFFSectionHeader);
+}
+
+uint16_t XCOFFObjectFile::getNumberOfSections() const {
+  return FileHdrPtr->NumberOfSections;
+}
+
 void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
   llvm_unreachable("Not yet implemented!");
   return;
@@ -77,32 +115,32 @@ XCOFFObjectFile::getSymbolSection(DataRe
 }
 
 void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {
-  llvm_unreachable("Not yet implemented!");
-  return;
+  const char *Ptr = reinterpret_cast<const char *>(Sec.p);
+  Sec.p = reinterpret_cast<uintptr_t>(Ptr + getSectionHeaderSize());
 }
 
 std::error_code XCOFFObjectFile::getSectionName(DataRefImpl Sec,
                                                 StringRef &Res) const {
-  llvm_unreachable("Not yet implemented!");
+  const char *Name = toSection(Sec)->Name;
+  auto NulCharPtr =
+      static_cast<const char *>(memchr(Name, '\0', XCOFF::SectionNameSize));
+  Res = NulCharPtr ? StringRef(Name, NulCharPtr - Name)
+                   : StringRef(Name, XCOFF::SectionNameSize);
   return std::error_code();
 }
 
 uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec) const {
-  uint64_t Result = 0;
-  llvm_unreachable("Not yet implemented!");
-  return Result;
+  return toSection(Sec)->VirtualAddress;
 }
 
 uint64_t XCOFFObjectFile::getSectionIndex(DataRefImpl Sec) const {
-  uint64_t Result = 0;
-  llvm_unreachable("Not yet implemented!");
-  return Result;
+  // Section numbers in XCOFF are numbered beginning at 1. A section number of
+  // zero is used to indicate that a symbol is being imported or is undefined.
+  return toSection(Sec) - SectionHdrTablePtr + 1;
 }
 
 uint64_t XCOFFObjectFile::getSectionSize(DataRefImpl Sec) const {
-  uint64_t Result = 0;
-  llvm_unreachable("Not yet implemented!");
-  return Result;
+  return toSection(Sec)->SectionSize;
 }
 
 std::error_code XCOFFObjectFile::getSectionContents(DataRefImpl Sec,
@@ -124,21 +162,17 @@ bool XCOFFObjectFile::isSectionCompresse
 }
 
 bool XCOFFObjectFile::isSectionText(DataRefImpl Sec) const {
-  bool Result = false;
-  llvm_unreachable("Not yet implemented!");
-  return Result;
+  return toSection(Sec)->Flags & XCOFF::STYP_TEXT;
 }
 
 bool XCOFFObjectFile::isSectionData(DataRefImpl Sec) const {
-  bool Result = false;
-  llvm_unreachable("Not yet implemented!");
-  return Result;
+  unsigned Flags = toSection(Sec)->Flags;
+  return Flags & (XCOFF::STYP_DATA | XCOFF::STYP_TDATA);
 }
 
 bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec) const {
-  bool Result = false;
-  llvm_unreachable("Not yet implemented!");
-  return Result;
+  unsigned Flags = toSection(Sec)->Flags;
+  return Flags & (XCOFF::STYP_BSS | XCOFF::STYP_TBSS);
 }
 
 bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const {
@@ -202,13 +236,16 @@ basic_symbol_iterator XCOFFObjectFile::s
 }
 
 section_iterator XCOFFObjectFile::section_begin() const {
-  llvm_unreachable("Not yet implemented!");
-  return section_iterator(SectionRef());
+  DataRefImpl DRI;
+  DRI.p = reinterpret_cast<uintptr_t>(SectionHdrTablePtr);
+  return section_iterator(SectionRef(DRI, this));
 }
 
 section_iterator XCOFFObjectFile::section_end() const {
-  llvm_unreachable("Not yet implemented!");
-  return section_iterator(SectionRef());
+  DataRefImpl DRI;
+  DRI.p =
+      reinterpret_cast<uintptr_t>(SectionHdrTablePtr + getNumberOfSections());
+  return section_iterator(SectionRef(DRI, this));
 }
 
 uint8_t XCOFFObjectFile::getBytesInAddress() const {
@@ -218,13 +255,13 @@ uint8_t XCOFFObjectFile::getBytesInAddre
 }
 
 StringRef XCOFFObjectFile::getFileFormatName() const {
-  llvm_unreachable("Not yet implemented!");
-  return "";
+  assert(getFileHeaderSize() == XCOFF32FileHeaderSize);
+  return "aixcoff-rs6000";
 }
 
 Triple::ArchType XCOFFObjectFile::getArch() const {
-  llvm_unreachable("Not yet implemented!");
-  return Triple::UnknownArch;
+  assert(getFileHeaderSize() == XCOFF32FileHeaderSize);
+  return Triple::ppc;
 }
 
 SubtargetFeatures XCOFFObjectFile::getFeatures() const {
@@ -238,6 +275,12 @@ bool XCOFFObjectFile::isRelocatableObjec
   return Result;
 }
 
+Expected<uint64_t> XCOFFObjectFile::getStartAddress() const {
+  // TODO FIXME Should get from auxiliary_header->o_entry when support for the
+  // auxiliary_header is added.
+  return 0;
+}
+
 XCOFFObjectFile::XCOFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
     : ObjectFile(Binary::ID_XCOFF32, Object) {
 
@@ -246,6 +289,17 @@ XCOFFObjectFile::XCOFFObjectFile(MemoryB
 
   if ((EC = getObject(FileHdrPtr, Data, base() + CurPtr)))
     return;
+
+  CurPtr += getFileHeaderSize();
+  // TODO FIXME we don't have support for an optional header yet, so just skip
+  // past it.
+  CurPtr += FileHdrPtr->AuxHeaderSize;
+
+  if (getNumberOfSections() != 0) {
+    if ((EC = getObject(SectionHdrTablePtr, Data, base() + CurPtr,
+                        getNumberOfSections() * getSectionHeaderSize())))
+      return;
+  }
 }
 
 Expected<std::unique_ptr<ObjectFile>>

Added: llvm/trunk/test/tools/llvm-objdump/Inputs/xcoff-long-sec-names.o
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objdump/Inputs/xcoff-long-sec-names.o?rev=359244&view=auto
==============================================================================
Binary file - no diff available.

Propchange: llvm/trunk/test/tools/llvm-objdump/Inputs/xcoff-long-sec-names.o
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: llvm/trunk/test/tools/llvm-objdump/Inputs/xcoff-section-headers-truncate.o
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objdump/Inputs/xcoff-section-headers-truncate.o?rev=359244&view=auto
==============================================================================
Binary file - no diff available.

Propchange: llvm/trunk/test/tools/llvm-objdump/Inputs/xcoff-section-headers-truncate.o
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: llvm/trunk/test/tools/llvm-objdump/Inputs/xcoff-section-headers.o
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objdump/Inputs/xcoff-section-headers.o?rev=359244&view=auto
==============================================================================
Binary file - no diff available.

Propchange: llvm/trunk/test/tools/llvm-objdump/Inputs/xcoff-section-headers.o
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: llvm/trunk/test/tools/llvm-objdump/xcoff-section-headers.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objdump/xcoff-section-headers.test?rev=359244&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-objdump/xcoff-section-headers.test (added)
+++ llvm/trunk/test/tools/llvm-objdump/xcoff-section-headers.test Thu Apr 25 14:36:04 2019
@@ -0,0 +1,43 @@
+# RUN: llvm-objdump --section-headers %p/Inputs/xcoff-section-headers.o | \
+# RUN: FileCheck %s
+
+# RUN: llvm-objdump --section-headers %p/Inputs/xcoff-long-sec-names.o | \
+# RUN: FileCheck --check-prefix=LONG %s
+
+# RUN: not llvm-objdump --section-headers 2>&1 \
+# RUN: %p/Inputs/xcoff-section-headers-truncate.o | FileCheck \
+# RUN: --check-prefix=ERROR %s
+
+# ERROR: The end of the file was unexpectedly encountered
+
+# CHECK: xcoff-section-headers.o:      file format aixcoff-rs6000
+# CHECK: Sections:
+# CHECK: Idx Name          Size     VMA          Type
+# CHECK:   1 .text         00000080 0000000000000000 TEXT
+# CHECK:   2 .data         00000024 0000000000000080 DATA
+# CHECK:   3 .bss          00000004 00000000000000a4 BSS
+# CHECK:   4 .tdata        00000008 0000000000000000 DATA
+# CHECK:   5 .tbss         00000004 0000000000000008 BSS
+
+# xcoff-section-headers.o Compiled with IBM XL C/C++ for AIX, V16.1.0
+# test.c:
+# int a;
+# int b = 12345;
+# __thread int c;
+# __thread double d = 3.14159;
+#
+# int func(void)  {
+#   return a;
+# }
+
+# LONG: xcoff-long-sec-names.o:      file format aixcoff-rs6000
+# LONG: Sections:
+# LONG: Idx Name          Size     VMA          Type
+# LONG: 1 .dwarnge      00000004 0000000000000000
+# LONG: 2 .dwpbnms      00000004 0000000000000000
+# LONG: 3 .dwpbtyp      00000004 0000000000000000
+
+# xcoff-long-sec-names.o was generated by assembling the following .s file:
+#  .dwsect 0x30000 # .dwpbnms section
+#  .dwsect 0x40000 # .dwpbtyp section
+#  .dwsect 0x50000 # .dwarnge section




More information about the llvm-commits mailing list