[llvm] ab77fa5 - [AIX][XCOFF][Patch2] decode vector information and extent long table of the traceback table of the xcoff.

via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 19 07:24:30 PST 2020


Author: diggerlin
Date: 2020-11-19T10:23:43-05:00
New Revision: ab77fa515583ca906f2cb09a5f5e1ea3c48ec725

URL: https://github.com/llvm/llvm-project/commit/ab77fa515583ca906f2cb09a5f5e1ea3c48ec725
DIFF: https://github.com/llvm/llvm-project/commit/ab77fa515583ca906f2cb09a5f5e1ea3c48ec725.diff

LOG: [AIX][XCOFF][Patch2] decode vector information and extent long table of the traceback table of the xcoff.

SUMMARY:

1. decode the Vector extension if has_vec is set
2. decode long table fields, if longtbtable is set.

There is conflict on the bit order of HasVectorInfoMask and HasExtensionTableMask between AIX os header and IBM aix compiler XLC.
In the /usr/include/sys/debug.h defines
static constexpr uint32_t HasVectorInfoMask = 0x0040'0000;
static constexpr uint32_t HasExtensionTableMask = 0x0080'0000;
but the XLC defines as

static constexpr uint32_t HasVectorInfoMask = 0x0080'0000;
static constexpr uint32_t HasExtensionTableMask = 0x0040'0000;
we follows the definition of the IBM AIX compiler XLC here.

Reviewer: Jason Liu

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

Added: 
    

Modified: 
    llvm/include/llvm/BinaryFormat/XCOFF.h
    llvm/include/llvm/Object/XCOFFObjectFile.h
    llvm/lib/Object/XCOFFObjectFile.cpp
    llvm/unittests/Object/XCOFFObjectFileTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/BinaryFormat/XCOFF.h b/llvm/include/llvm/BinaryFormat/XCOFF.h
index 3fcac27cfa98..dc5c21469769 100644
--- a/llvm/include/llvm/BinaryFormat/XCOFF.h
+++ b/llvm/include/llvm/BinaryFormat/XCOFF.h
@@ -331,8 +331,8 @@ struct TracebackTable {
   static constexpr uint32_t FPRSavedShift = 24;
 
   // Byte 6
-  static constexpr uint32_t HasExtensionTableMask = 0x0080'0000;
-  static constexpr uint32_t HasVectorInfoMask = 0x0040'0000;
+  static constexpr uint32_t HasVectorInfoMask = 0x0080'0000;
+  static constexpr uint32_t HasExtensionTableMask = 0x0040'0000;
   static constexpr uint32_t GPRSavedMask = 0x003F'0000;
   static constexpr uint32_t GPRSavedShift = 16;
 
@@ -346,8 +346,39 @@ struct TracebackTable {
   static constexpr uint8_t NumberOfFloatingPointParmsShift = 1;
 
   // Masks to select leftmost bits for decoding parameter type information.
+  // Bit to use when vector info is not presented.
   static constexpr uint32_t ParmTypeIsFloatingBit = 0x8000'0000;
   static constexpr uint32_t ParmTypeFloatingIsDoubleBit = 0x4000'0000;
+  // Bits to use when vector info is presented.
+  static constexpr uint32_t ParmTypeIsFixedBits = 0x0000'0000;
+  static constexpr uint32_t ParmTypeIsVectorBits = 0x4000'0000;
+  static constexpr uint32_t ParmTypeIsFloatingBits = 0x8000'0000;
+  static constexpr uint32_t ParmTypeIsDoubleBits = 0xC000'0000;
+  static constexpr uint32_t ParmTypeMask = 0xC000'0000;
+
+  // Vector extension
+  static constexpr uint16_t NumberOfVRSavedMask = 0xFC00;
+  static constexpr uint16_t IsVRSavedOnStackMask = 0x0200;
+  static constexpr uint16_t HasVarArgsMask = 0x0100;
+  static constexpr uint8_t NumberOfVRSavedShift = 10;
+
+  static constexpr uint16_t NumberOfVectorParmsMask = 0x00FE;
+  static constexpr uint16_t HasVMXInstructionMask = 0x0001;
+  static constexpr uint8_t NumberOfVectorParmsShift = 1;
+
+  static constexpr uint32_t ParmTypeIsVectorCharBit = 0x0000'0000;
+  static constexpr uint32_t ParmTypeIsVectorShortBit = 0x4000'0000;
+  static constexpr uint32_t ParmTypeIsVectorIntBit = 0x8000'0000;
+  static constexpr uint32_t ParmTypeIsVectorFloatBit = 0xC000'0000;
+};
+
+// Extended Traceback table flags.
+enum ExtendedTBTableFlag : uint8_t {
+  TB_OS1 = 0x80,         ///< Reserved for OS use
+  TB_RESERVED = 0x40,    ///< Reserved for compiler
+  TB_SSP_CANARY = 0x20,  ///< stack smasher canary present on stack
+  TB_OS2 = 0x10,         ///< Reserved for OS use
+  TB_LONGTBTABLE2 = 0x01 ///< Additional tbtable extension exists
 };
 
 } // end namespace XCOFF

diff  --git a/llvm/include/llvm/Object/XCOFFObjectFile.h b/llvm/include/llvm/Object/XCOFFObjectFile.h
index fbc542fd3e6d..b649c12717f1 100644
--- a/llvm/include/llvm/Object/XCOFFObjectFile.h
+++ b/llvm/include/llvm/Object/XCOFFObjectFile.h
@@ -395,6 +395,23 @@ class XCOFFSymbolRef {
   bool isFunction() const;
 };
 
+class TBVectorExt {
+  friend class XCOFFTracebackTable;
+
+  uint16_t Data;
+  uint32_t VecParmsInfo;
+
+  TBVectorExt(StringRef TBvectorStrRef);
+
+public:
+  uint8_t geNumberOfVRSaved() const;
+  bool isVRSavedOnStack() const;
+  bool hasVarArgs() const;
+  uint8_t getNumberOfVectorParms() const;
+  bool hasVMXInstruction() const;
+  SmallString<32> getVectorParmsInfoString() const;
+};
+
 /// This class provides methods to extract traceback table data from a buffer.
 /// The various accessors may reference the buffer provided via the constructor.
 
@@ -407,9 +424,10 @@ class XCOFFTracebackTable {
   Optional<SmallVector<uint32_t, 8>> ControlledStorageInfoDisp;
   Optional<StringRef> FunctionName;
   Optional<uint8_t> AllocaRegister;
+  Optional<TBVectorExt> VecExt;
+  Optional<uint8_t> ExtensionTable;
 
   XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size, Error &Err);
-
 public:
   /// Parse an XCOFF Traceback Table from \a Ptr with \a Size bytes.
   /// Returns an XCOFFTracebackTable upon successful parsing, otherwise an
@@ -469,6 +487,8 @@ class XCOFFTracebackTable {
   }
   const Optional<StringRef> &getFunctionName() const { return FunctionName; }
   const Optional<uint8_t> &getAllocaRegister() const { return AllocaRegister; }
+  const Optional<TBVectorExt> &getVectorExt() const { return VecExt; }
+  const Optional<uint8_t> &getExtensionTable() const { return ExtensionTable; }
 };
 
 bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes);

diff  --git a/llvm/lib/Object/XCOFFObjectFile.cpp b/llvm/lib/Object/XCOFFObjectFile.cpp
index 23ecafde2670..9c4f97d0a5e9 100644
--- a/llvm/lib/Object/XCOFFObjectFile.cpp
+++ b/llvm/lib/Object/XCOFFObjectFile.cpp
@@ -845,6 +845,103 @@ bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes) {
   return support::endian::read32be(Bytes.data()) == 0;
 }
 
+TBVectorExt::TBVectorExt(StringRef TBvectorStrRef) {
+  const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(TBvectorStrRef.data());
+  Data = support::endian::read16be(Ptr);
+  VecParmsInfo = support::endian::read32be(Ptr + 2);
+}
+
+#define GETVALUEWITHMASK(X) (Data & (TracebackTable::X))
+#define GETVALUEWITHMASKSHIFT(X, S)                                            \
+  ((Data & (TracebackTable::X)) >> (TracebackTable::S))
+uint8_t TBVectorExt::geNumberOfVRSaved() const {
+  return GETVALUEWITHMASKSHIFT(NumberOfVRSavedMask, NumberOfVRSavedShift);
+}
+
+bool TBVectorExt::isVRSavedOnStack() const {
+  return GETVALUEWITHMASK(IsVRSavedOnStackMask);
+}
+
+bool TBVectorExt::hasVarArgs() const {
+  return GETVALUEWITHMASK(HasVarArgsMask);
+}
+uint8_t TBVectorExt::getNumberOfVectorParms() const {
+  return GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask,
+                               NumberOfVectorParmsShift);
+}
+
+bool TBVectorExt::hasVMXInstruction() const {
+  return GETVALUEWITHMASK(HasVMXInstructionMask);
+}
+#undef GETVALUEWITHMASK
+#undef GETVALUEWITHMASKSHIFT
+
+SmallString<32> TBVectorExt::getVectorParmsInfoString() const {
+  SmallString<32> ParmsType;
+  uint32_t Value = VecParmsInfo;
+  for (uint8_t I = 0; I < getNumberOfVectorParms(); ++I) {
+    if (I != 0)
+      ParmsType += ", ";
+    switch (Value & TracebackTable::ParmTypeMask) {
+    case TracebackTable::ParmTypeIsVectorCharBit:
+      ParmsType += "vc";
+      break;
+
+    case TracebackTable::ParmTypeIsVectorShortBit:
+      ParmsType += "vs";
+      break;
+
+    case TracebackTable::ParmTypeIsVectorIntBit:
+      ParmsType += "vi";
+      break;
+
+    case TracebackTable::ParmTypeIsVectorFloatBit:
+      ParmsType += "vf";
+      break;
+    }
+    Value <<= 2;
+  }
+  return ParmsType;
+}
+
+static SmallString<32> parseParmsTypeWithVecInfo(uint32_t Value,
+                                                 unsigned int ParmsNum) {
+  SmallString<32> ParmsType;
+  unsigned I = 0;
+  bool Begin = false;
+  while (I < ParmsNum || Value) {
+    if (Begin)
+      ParmsType += ", ";
+    else
+      Begin = true;
+
+    switch (Value & TracebackTable::ParmTypeMask) {
+    case TracebackTable::ParmTypeIsFixedBits:
+      ParmsType += "i";
+      ++I;
+      break;
+    case TracebackTable::ParmTypeIsVectorBits:
+      ParmsType += "v";
+      break;
+    case TracebackTable::ParmTypeIsFloatingBits:
+      ParmsType += "f";
+      ++I;
+      break;
+    case TracebackTable::ParmTypeIsDoubleBits:
+      ParmsType += "d";
+      ++I;
+      break;
+    default:
+      assert(false && "Unrecognized bits in ParmsType.");
+    }
+    Value <<= 2;
+  }
+  assert(I == ParmsNum &&
+         "The total parameters number of fixed-point or floating-point "
+         "parameters not equal to the number in the parameter type!");
+  return ParmsType;
+}
+
 static SmallString<32> parseParmsType(uint32_t Value, unsigned ParmsNum) {
   SmallString<32> ParmsType;
   for (unsigned I = 0; I < ParmsNum; ++I) {
@@ -897,10 +994,10 @@ XCOFFTracebackTable::XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size,
     // indicates the presence of vector parameters.
     if (ParmNum > 0) {
       uint32_t ParamsTypeValue = DE.getU32(Cur);
-      // TODO: when hasVectorInfo() is true, we need to implement a new version
-      // of parsing parameter type for vector info.
-      if (Cur && !hasVectorInfo())
-        ParmsType = parseParmsType(ParamsTypeValue, ParmNum);
+      if (Cur)
+        ParmsType = hasVectorInfo()
+                        ? parseParmsTypeWithVecInfo(ParamsTypeValue, ParmNum)
+                        : parseParmsType(ParamsTypeValue, ParmNum);
     }
   }
 
@@ -931,7 +1028,14 @@ XCOFFTracebackTable::XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size,
   if (Cur && isAllocaUsed())
     AllocaRegister = DE.getU8(Cur);
 
-  // TODO: Need to parse vector info and extension table if there is one.
+  if (Cur && hasVectorInfo()) {
+    StringRef VectorExtRef = DE.getBytes(Cur, 6);
+    if (Cur)
+      VecExt = TBVectorExt(VectorExtRef);
+  }
+
+  if (Cur && hasExtensionTable())
+    ExtensionTable = DE.getU8(Cur);
 
   if (!Cur)
     Err = Cur.takeError();

diff  --git a/llvm/unittests/Object/XCOFFObjectFileTest.cpp b/llvm/unittests/Object/XCOFFObjectFileTest.cpp
index 47e200c12cfe..c4c59d93e0b8 100644
--- a/llvm/unittests/Object/XCOFFObjectFileTest.cpp
+++ b/llvm/unittests/Object/XCOFFObjectFileTest.cpp
@@ -13,6 +13,7 @@
 
 using namespace llvm;
 using namespace llvm::object;
+using namespace llvm::XCOFF;
 
 TEST(XCOFFObjectFileTest, XCOFFObjectType) {
   // Create an arbitrary object of a non-XCOFF type and test that
@@ -142,14 +143,14 @@ TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIParmsType) {
   EXPECT_EQ(TT3.getParmsType().getValue(), "d, i, f, f");
 }
 
-const uint8_t TBTableData[] = {0x00, 0x00, 0x2A, 0x40, 0x80, 0x40, 0x01, 0x05,
-                               0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
-                               0x00, 0x00, 0x00, 0x02, 0x05, 0x05, 0x00, 0x00,
-                               0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x61, 0x64,
-                               0x64, 0x5f, 0x61, 0x6c, 0x6c, 0x00, 0x00, 0x00};
+const uint8_t TBTableData[] = {
+    0x00, 0x00, 0x2A, 0x60, 0x80, 0xc0, 0x03, 0x05, 0x48, 0xc4, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x05, 0x05, 0x00, 0x00,
+    0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x61, 0x64, 0x64, 0x5f, 0x61, 0x6c,
+    0x6c, 0x1f, 0x02, 0x05, 0xf0, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00};
 
 TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIControlledStorageInfoDisp) {
-  uint64_t Size = 40;
+  uint64_t Size = sizeof(TBTableData);
   Expected<XCOFFTracebackTable> TTOrErr =
       XCOFFTracebackTable::create(TBTableData, Size);
   ASSERT_THAT_EXPECTED(TTOrErr, Succeeded());
@@ -165,17 +166,86 @@ TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIControlledStorageInfoDisp) {
   ASSERT_EQ(Disp.size(), 2UL);
   EXPECT_EQ(Disp[0], 0x05050000u);
   EXPECT_EQ(Disp[1], 0x06060000u);
+  EXPECT_EQ(Size, 45u);
+}
+
+TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIAllocaRegister) {
+  uint64_t Size = sizeof(TBTableData);
+  Expected<XCOFFTracebackTable> TTOrErr =
+      XCOFFTracebackTable::create(TBTableData, Size);
+  ASSERT_THAT_EXPECTED(TTOrErr, Succeeded());
+  XCOFFTracebackTable TT = *TTOrErr;
+  ASSERT_TRUE(TT.getAllocaRegister());
+  EXPECT_EQ(TT.getAllocaRegister().getValue(), 31u);
 }
 
 TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIHasVectorInfo) {
-  uint64_t Size = 40;
+
+  uint64_t Size = sizeof(TBTableData);
   Expected<XCOFFTracebackTable> TTOrErr =
       XCOFFTracebackTable::create(TBTableData, Size);
   ASSERT_THAT_EXPECTED(TTOrErr, Succeeded());
   XCOFFTracebackTable TT = *TTOrErr;
 
+  EXPECT_EQ(TT.getNumberOfFixedParms(), 3);
+  EXPECT_EQ(TT.getNumberOfFPParms(), 2);
   EXPECT_TRUE(TT.hasVectorInfo());
-  EXPECT_FALSE(TT.getParmsType());
+  EXPECT_TRUE(TT.hasExtensionTable());
+
+  ASSERT_TRUE(TT.getParmsType());
+  EXPECT_EQ(TT.getParmsType().getValue(), "v, i, f, i, d, i, v");
+
+  ASSERT_TRUE(TT.getVectorExt());
+  TBVectorExt VecExt = TT.getVectorExt().getValue();
+
+  EXPECT_EQ(VecExt.geNumberOfVRSaved(), 0);
+  EXPECT_TRUE(VecExt.isVRSavedOnStack());
+  EXPECT_FALSE(VecExt.hasVarArgs());
+
+  EXPECT_EQ(VecExt.getNumberOfVectorParms(), 2u);
+  EXPECT_TRUE(VecExt.hasVMXInstruction());
+
+  EXPECT_EQ(VecExt.getVectorParmsInfoString(), "vf, vf");
+
+  ASSERT_TRUE(TT.getExtensionTable());
+  EXPECT_EQ(TT.getExtensionTable().getValue(),
+            ExtendedTBTableFlag::TB_SSP_CANARY);
+
+  EXPECT_EQ(Size, 45u);
+}
+
+TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIHasVectorInfo1) {
+  const uint8_t TBTableData[] = {
+      0x00, 0x00, 0x2A, 0x40, 0x80, 0xc0, 0x03, 0x05, 0x48, 0xc0, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x05, 0x05, 0x00, 0x00,
+      0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x61, 0x64, 0x64, 0x5f, 0x61, 0x6c,
+      0x6c, 0x11, 0x07, 0x90, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00};
+  uint64_t Size = sizeof(TBTableData);
+  Expected<XCOFFTracebackTable> TTOrErr =
+      XCOFFTracebackTable::create(TBTableData, Size);
+  ASSERT_THAT_EXPECTED(TTOrErr, Succeeded());
+  XCOFFTracebackTable TT = *TTOrErr;
+
+  ASSERT_TRUE(TT.getParmsType());
+  EXPECT_EQ(TT.getParmsType().getValue(), "v, i, f, i, d, i");
+
+  ASSERT_TRUE(TT.getVectorExt());
+  TBVectorExt VecExt = TT.getVectorExt().getValue();
+
+  EXPECT_EQ(VecExt.geNumberOfVRSaved(), 4);
+  EXPECT_FALSE(VecExt.isVRSavedOnStack());
+  EXPECT_TRUE(VecExt.hasVarArgs());
+
+  EXPECT_EQ(VecExt.getNumberOfVectorParms(), 3u);
+  EXPECT_TRUE(VecExt.hasVMXInstruction());
+
+  EXPECT_EQ(VecExt.getVectorParmsInfoString(), "vi, vs, vc");
+
+  ASSERT_TRUE(TT.getExtensionTable());
+  EXPECT_EQ(TT.getExtensionTable().getValue(),
+            ExtendedTBTableFlag::TB_SSP_CANARY);
+
+  EXPECT_EQ(Size, 44u);
 }
 
 TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtMandatory) {
@@ -186,7 +256,7 @@ TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtMandatory) {
       TTOrErr.takeError(),
       FailedWithMessage(
           "unexpected end of data at offset 0x6 while reading [0x0, 0x8)"));
-  EXPECT_EQ(Size, 0UL);
+  EXPECT_EQ(Size, 0u);
 }
 
 TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtParmsType) {
@@ -269,15 +339,48 @@ TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtFunctionName) {
 }
 
 TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtAllocaUsed) {
-  uint8_t V[] = {0x00, 0x00, 0x2A, 0x60, 0x80, 0x00, 0x01, 0x05, 0x58, 0x00,
-                 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02,
-                 0x05, 0x05, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x07,
-                 0x61, 0x64, 0x64, 0x5f, 0x61, 0x6c, 0x6c};
-  uint64_t Size = sizeof(V);
-  Expected<XCOFFTracebackTable> TTOrErr = XCOFFTracebackTable::create(V, Size);
+  uint64_t Size = 37;
+  Expected<XCOFFTracebackTable> TTOrErr =
+      XCOFFTracebackTable::create(TBTableData, Size);
   EXPECT_THAT_ERROR(
       TTOrErr.takeError(),
       FailedWithMessage(
           "unexpected end of data at offset 0x25 while reading [0x25, 0x26)"));
   EXPECT_EQ(Size, 37u);
 }
+
+TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtVectorInfoData) {
+  uint64_t Size = 39;
+  Expected<XCOFFTracebackTable> TTOrErr =
+      XCOFFTracebackTable::create(TBTableData, Size);
+
+  EXPECT_THAT_ERROR(
+      TTOrErr.takeError(),
+      FailedWithMessage(
+          "unexpected end of data at offset 0x27 while reading [0x26, 0x2c)"));
+  EXPECT_EQ(Size, 38u);
+}
+
+TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtVectorInfoParmsInfo) {
+  uint64_t Size = 43;
+  Expected<XCOFFTracebackTable> TTOrErr =
+      XCOFFTracebackTable::create(TBTableData, Size);
+
+  EXPECT_THAT_ERROR(
+      TTOrErr.takeError(),
+      FailedWithMessage(
+          "unexpected end of data at offset 0x2b while reading [0x26, 0x2c)"));
+  EXPECT_EQ(Size, 38u);
+}
+
+TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtExtLongTBTable) {
+  uint64_t Size = 44;
+  Expected<XCOFFTracebackTable> TTOrErr =
+      XCOFFTracebackTable::create(TBTableData, Size);
+
+  EXPECT_THAT_ERROR(
+      TTOrErr.takeError(),
+      FailedWithMessage(
+          "unexpected end of data at offset 0x2c while reading [0x2c, 0x2d)"));
+  EXPECT_EQ(Size, 44u);
+}


        


More information about the llvm-commits mailing list