Add support for expressions in .sleb/.uleb directives.
authorRafael Espindola <rafael.espindola@gmail.com>
Tue, 2 Nov 2010 17:22:24 +0000 (17:22 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Tue, 2 Nov 2010 17:22:24 +0000 (17:22 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@118023 91177308-0d34-0410-b5e6-96231b3b80d8

12 files changed:
include/llvm/MC/MCAssembler.h
include/llvm/MC/MCObjectStreamer.h
include/llvm/MC/MCStreamer.h
lib/MC/MCAsmStreamer.cpp
lib/MC/MCAssembler.cpp
lib/MC/MCDwarf.cpp
lib/MC/MCLoggingStreamer.cpp
lib/MC/MCNullStreamer.cpp
lib/MC/MCObjectStreamer.cpp
lib/MC/MCParser/AsmParser.cpp
lib/MC/MCStreamer.cpp
test/MC/ELF/leb128.s [new file with mode: 0644]

index d48a0b40a7b7582d832232652c3ab0f2c4f674e1..174a75527227757f1a84cd8707488f27211bb2f8 100644 (file)
@@ -50,7 +50,8 @@ public:
     FT_Fill,
     FT_Inst,
     FT_Org,
-    FT_Dwarf
+    FT_Dwarf,
+    FT_LEB
   };
 
 private:
@@ -338,6 +339,40 @@ public:
   static bool classof(const MCOrgFragment *) { return true; }
 };
 
+class MCLEBFragment : public MCFragment {
+  /// Value - The value this fragment should contain.
+  const MCExpr *Value;
+
+  /// IsSigned - True if this is a sleb128, false if uleb128.
+  bool IsSigned;
+
+  /// Size - The current size estimate.
+  uint64_t Size;
+
+public:
+  MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSectionData *SD)
+    : MCFragment(FT_LEB, SD),
+      Value(&Value_), IsSigned(IsSigned_), Size(1) {}
+
+  /// @name Accessors
+  /// @{
+
+  const MCExpr &getValue() const { return *Value; }
+
+  bool isSigned() const { return IsSigned; }
+
+  uint64_t getSize() const { return Size; }
+
+  void setSize(uint64_t Size_) { Size = Size_; }
+
+  /// @}
+
+  static bool classof(const MCFragment *F) {
+    return F->getKind() == MCFragment::FT_LEB;
+  }
+  static bool classof(const MCLEBFragment *) { return true; }
+};
+
 class MCDwarfLineAddrFragment : public MCFragment {
   /// LineDelta - the value of the difference between the two line numbers
   /// between two .loc dwarf directives.
@@ -677,6 +712,12 @@ private:
   /// were adjusted.
   bool LayoutOnce(const MCObjectWriter &Writer, MCAsmLayout &Layout);
 
+  bool RelaxInstruction(const MCObjectWriter &Writer, MCAsmLayout &Layout,
+                        MCInstFragment &IF);
+
+  bool RelaxLEB(const MCObjectWriter &Writer, MCAsmLayout &Layout,
+                MCLEBFragment &IF);
+
   /// FinishLayout - Finalize a layout, including fragment lowering.
   void FinishLayout(MCAsmLayout &Layout);
 
index 3e8b7561e42e0ff770334c11c77e5d0edacb8075..8c21c10522c1cc55c8786418c5a9c46676da7286 100644 (file)
@@ -60,6 +60,8 @@ public:
   /// @name MCStreamer Interface
   /// @{
 
+  virtual void EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace = 0);
+  virtual void EmitSLEB128Value(const MCExpr *Value, unsigned AddrSpace = 0);
   virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol);
   virtual void SwitchSection(const MCSection *Section);
   virtual void EmitInstruction(const MCInst &Inst);
index 53877b1add0f445ca2e591f55c562a103a413d7d..fd6e6901ffa3bba2b83f455fecc2e1304ec00172 100644 (file)
@@ -244,13 +244,20 @@ namespace llvm {
     virtual void EmitIntValue(uint64_t Value, unsigned Size,
                               unsigned AddrSpace = 0);
 
-    /// EmitULEB128Value - Special case of EmitValue that takes an ULEB128 and
-    /// emits the needed bytes for the encoded value.
-    virtual void EmitULEB128Value(uint64_t Value, unsigned AddrSpace = 0);
 
-    /// EmitSLEB128Value - Special case of EmitValue that takes an SLEB128 and
-    /// emits the needed bytes for the encoded value.
-    virtual void EmitSLEB128Value(int64_t Value, unsigned AddrSpace = 0);
+    virtual void EmitULEB128Value(const MCExpr *Value,
+                                  unsigned AddrSpace = 0) = 0;
+
+    virtual void EmitSLEB128Value(const MCExpr *Value,
+                                  unsigned AddrSpace = 0) = 0;
+
+    /// EmitULEB128Value - Special case of EmitULEB128Value that avoids the
+    /// client having to pass in a MCExpr for constant integers.
+    virtual void EmitULEB128IntValue(uint64_t Value, unsigned AddrSpace = 0);
+
+    /// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the
+    /// client having to pass in a MCExpr for constant integers.
+    virtual void EmitSLEB128IntValue(int64_t Value, unsigned AddrSpace = 0);
 
     /// EmitSymbolValue - Special case of EmitValue that avoids the client
     /// having to pass in a MCExpr for MCSymbols.
index ca8dc965f290851480f38d83a52bfa037490e5de..9bb25eef95b226cecd439696ae5aaf05c39a7505 100644 (file)
@@ -141,7 +141,13 @@ public:
   virtual void EmitBytes(StringRef Data, unsigned AddrSpace);
 
   virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace);
+
   virtual void EmitIntValue(uint64_t Value, unsigned Size, unsigned AddrSpace);
+
+  virtual void EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace = 0);
+
+  virtual void EmitSLEB128Value(const MCExpr *Value, unsigned AddrSpace = 0);
+
   virtual void EmitGPRel32Value(const MCExpr *Value);
 
 
@@ -505,6 +511,16 @@ void MCAsmStreamer::EmitValue(const MCExpr *Value, unsigned Size,
   EmitEOL();
 }
 
+void MCAsmStreamer::EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace) {
+  OS << ".uleb " << *Value;
+  EmitEOL();
+}
+
+void MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value, unsigned AddrSpace) {
+  OS << ".sleb " << *Value;
+  EmitEOL();
+}
+
 void MCAsmStreamer::EmitGPRel32Value(const MCExpr *Value) {
   assert(MAI.getGPRel32Directive() != 0);
   OS << MAI.getGPRel32Directive() << *Value;
index 9cd0a12c12639a833cdbf5086b43e6d9e41d36d2..1b464ee98fddc3920a08bd94899900f18fa7623f 100644 (file)
@@ -318,6 +318,9 @@ uint64_t MCAssembler::ComputeFragmentSize(MCAsmLayout &Layout,
   case MCFragment::FT_Inst:
     return cast<MCInstFragment>(F).getInstSize();
 
+  case MCFragment::FT_LEB:
+    return cast<MCLEBFragment>(F).getSize();
+
   case MCFragment::FT_Align: {
     const MCAlignFragment &AF = cast<MCAlignFragment>(F);
 
@@ -514,6 +517,23 @@ static void WriteFragmentData(const MCAssembler &Asm, const MCAsmLayout &Layout,
     llvm_unreachable("unexpected inst fragment after lowering");
     break;
 
+  case MCFragment::FT_LEB: {
+    MCLEBFragment &LF = cast<MCLEBFragment>(F);
+
+    // FIXME: It is probably better if we don't call EvaluateAsAbsolute in
+    // here.
+    int64_t Value;
+    LF.getValue().EvaluateAsAbsolute(Value, &Layout);
+    SmallString<32> Tmp;
+    raw_svector_ostream OSE(Tmp);
+    if (LF.isSigned())
+      MCObjectWriter::EncodeSLEB128(Value, OSE);
+    else
+      MCObjectWriter::EncodeULEB128(Value, OSE);
+    OW->WriteBytes(OSE.str());
+    break;
+  }
+
   case MCFragment::FT_Org: {
     MCOrgFragment &OF = cast<MCOrgFragment>(F);
 
@@ -781,6 +801,63 @@ bool MCAssembler::FragmentNeedsRelaxation(const MCObjectWriter &Writer,
   return false;
 }
 
+bool MCAssembler::RelaxInstruction(const MCObjectWriter &Writer,
+                                   MCAsmLayout &Layout,
+                                   MCInstFragment &IF) {
+  if (!FragmentNeedsRelaxation(Writer, &IF, Layout))
+    return false;
+
+  ++stats::RelaxedInstructions;
+
+  // FIXME-PERF: We could immediately lower out instructions if we can tell
+  // they are fully resolved, to avoid retesting on later passes.
+
+  // Relax the fragment.
+
+  MCInst Relaxed;
+  getBackend().RelaxInstruction(IF.getInst(), Relaxed);
+
+  // Encode the new instruction.
+  //
+  // FIXME-PERF: If it matters, we could let the target do this. It can
+  // probably do so more efficiently in many cases.
+  SmallVector<MCFixup, 4> Fixups;
+  SmallString<256> Code;
+  raw_svector_ostream VecOS(Code);
+  getEmitter().EncodeInstruction(Relaxed, VecOS, Fixups);
+  VecOS.flush();
+
+  // Update the instruction fragment.
+  int SlideAmount = Code.size() - IF.getInstSize();
+  IF.setInst(Relaxed);
+  IF.getCode() = Code;
+  IF.getFixups().clear();
+  // FIXME: Eliminate copy.
+  for (unsigned i = 0, e = Fixups.size(); i != e; ++i)
+    IF.getFixups().push_back(Fixups[i]);
+
+  // Update the layout, and remember that we relaxed.
+  Layout.UpdateForSlide(&IF, SlideAmount);
+  return true;
+}
+
+bool MCAssembler::RelaxLEB(const MCObjectWriter &Writer,
+                           MCAsmLayout &Layout,
+                           MCLEBFragment &LF) {
+  int64_t Value;
+  LF.getValue().EvaluateAsAbsolute(Value, &Layout);
+  SmallString<32> Tmp;
+  raw_svector_ostream OSE(Tmp);
+  if (LF.isSigned())
+    MCObjectWriter::EncodeSLEB128(Value, OSE);
+  else
+    MCObjectWriter::EncodeULEB128(Value, OSE);
+  uint64_t OldSize = LF.getSize();
+  LF.setSize(OSE.GetNumBytesInBuffer());
+  return OldSize != LF.getSize();
+}
+
+
 bool MCAssembler::LayoutOnce(const MCObjectWriter &Writer,
                              MCAsmLayout &Layout) {
   ++stats::RelaxationSteps;
@@ -795,43 +872,18 @@ bool MCAssembler::LayoutOnce(const MCObjectWriter &Writer,
 
     for (MCSectionData::iterator it2 = SD.begin(),
            ie2 = SD.end(); it2 != ie2; ++it2) {
-      // Check if this is an instruction fragment that needs relaxation.
-      MCInstFragment *IF = dyn_cast<MCInstFragment>(it2);
-      if (!IF || !FragmentNeedsRelaxation(Writer, IF, Layout))
-        continue;
-
-      ++stats::RelaxedInstructions;
-
-      // FIXME-PERF: We could immediately lower out instructions if we can tell
-      // they are fully resolved, to avoid retesting on later passes.
-
-      // Relax the fragment.
-
-      MCInst Relaxed;
-      getBackend().RelaxInstruction(IF->getInst(), Relaxed);
-
-      // Encode the new instruction.
-      //
-      // FIXME-PERF: If it matters, we could let the target do this. It can
-      // probably do so more efficiently in many cases.
-      SmallVector<MCFixup, 4> Fixups;
-      SmallString<256> Code;
-      raw_svector_ostream VecOS(Code);
-      getEmitter().EncodeInstruction(Relaxed, VecOS, Fixups);
-      VecOS.flush();
-
-      // Update the instruction fragment.
-      int SlideAmount = Code.size() - IF->getInstSize();
-      IF->setInst(Relaxed);
-      IF->getCode() = Code;
-      IF->getFixups().clear();
-      // FIXME: Eliminate copy.
-      for (unsigned i = 0, e = Fixups.size(); i != e; ++i)
-        IF->getFixups().push_back(Fixups[i]);
-
-      // Update the layout, and remember that we relaxed.
-      Layout.UpdateForSlide(IF, SlideAmount);
-      WasRelaxed = true;
+      // Check if this is an fragment that needs relaxation.
+      switch(it2->getKind()) {
+      default:
+        break;
+      case MCFragment::FT_Inst:
+        WasRelaxed |= RelaxInstruction(Writer, Layout,
+                                       *cast<MCInstFragment>(it2));
+        break;
+      case MCFragment::FT_LEB:
+        WasRelaxed |= RelaxLEB(Writer, Layout, *cast<MCLEBFragment>(it2));
+        break;
+      }
     }
   }
 
@@ -903,6 +955,7 @@ void MCFragment::dump() {
   case MCFragment::FT_Inst:  OS << "MCInstFragment"; break;
   case MCFragment::FT_Org:   OS << "MCOrgFragment"; break;
   case MCFragment::FT_Dwarf: OS << "MCDwarfFragment"; break;
+  case MCFragment::FT_LEB:   OS << "MCLEBFragment"; break;
   }
 
   OS << "<MCFragment " << (void*) this << " LayoutOrder:" << LayoutOrder
@@ -970,6 +1023,12 @@ void MCFragment::dump() {
        << " LineDelta:" << OF->getLineDelta();
     break;
   }
+  case MCFragment::FT_LEB: {
+    const MCLEBFragment *LF = cast<MCLEBFragment>(this);
+    OS << "\n       ";
+    OS << " Value:" << LF->getValue() << " Signed:" << LF->isSigned();
+    break;
+  }
   }
   OS << ">";
 }
index 17d164f2c7b628f7bc8f40ad0fd2ad81930678d2..d481ecf89bc73df02d4b63c7987b3916d5bde6f8 100644 (file)
@@ -125,7 +125,7 @@ static inline void EmitDwarfSetAddress(MCObjectStreamer *MCOS,
   MCOS->EmitIntValue(dwarf::DW_LNS_extended_op, 1);
 
   int sizeof_address = MCOS->getAssembler().getBackend().getPointerSize();
-  MCOS->EmitULEB128Value(sizeof_address + 1);
+  MCOS->EmitULEB128IntValue(sizeof_address + 1);
 
   MCOS->EmitIntValue(dwarf::DW_LNE_set_address, 1);
   MCOS->EmitSymbolValue(Symbol, sizeof_address);
@@ -157,17 +157,17 @@ static inline bool EmitDwarfLineTable(MCObjectStreamer *MCOS,
     if (FileNum != it->getFileNum()) {
       FileNum = it->getFileNum();
       MCOS->EmitIntValue(dwarf::DW_LNS_set_file, 1);
-      MCOS->EmitULEB128Value(FileNum);
+      MCOS->EmitULEB128IntValue(FileNum);
     }
     if (Column != it->getColumn()) {
       Column = it->getColumn();
       MCOS->EmitIntValue(dwarf::DW_LNS_set_column, 1);
-      MCOS->EmitULEB128Value(Column);
+      MCOS->EmitULEB128IntValue(Column);
     }
     if (Isa != it->getIsa()) {
       Isa = it->getIsa();
       MCOS->EmitIntValue(dwarf::DW_LNS_set_isa, 1);
-      MCOS->EmitULEB128Value(Isa);
+      MCOS->EmitULEB128IntValue(Isa);
     }
     if ((it->getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) {
       Flags = it->getFlags();
@@ -303,7 +303,8 @@ void MCDwarfFileTable::Emit(MCObjectStreamer *MCOS,
   for (unsigned i = 1; i < MCDwarfFiles.size(); i++) {
     MCOS->EmitBytes(MCDwarfFiles[i]->getName(), 0); // FileName
     MCOS->EmitBytes(StringRef("\0", 1), 0); // the null term. of the string
-    MCOS->EmitULEB128Value(MCDwarfFiles[i]->getDirIndex()); // the Directory num
+    // the Directory num
+    MCOS->EmitULEB128IntValue(MCDwarfFiles[i]->getDirIndex());
     MCOS->EmitIntValue(0, 1); // last modification timestamp (always 0)
     MCOS->EmitIntValue(0, 1); // filesize (always 0)
   }
index a907c11f118e72a3da76d0e16cf88c82ee4bb8f8..cb217c780c57332fe08c6e8d043b129c27c22b00 100644 (file)
@@ -152,6 +152,18 @@ public:
     return Child->EmitIntValue(Value, Size, AddrSpace);
   }
 
+  virtual void EmitULEB128Value(const MCExpr *Value,
+                                unsigned AddrSpace = 0) {
+    LogCall("EmitULEB128Value");
+    return Child->EmitULEB128Value(Value, AddrSpace);
+  }
+
+  virtual void EmitSLEB128Value(const MCExpr *Value,
+                                unsigned AddrSpace = 0) {
+    LogCall("EmitSLEB128Value");
+    return Child->EmitSLEB128Value(Value, AddrSpace);
+  }
+
   virtual void EmitGPRel32Value(const MCExpr *Value) {
     LogCall("EmitGPRel32Value");
     return Child->EmitGPRel32Value(Value);
index 5f29b46d370451a4920a5bf66e24b2474dfdb240..9dfb28c30422cb9797c3f7bba3b0e6b0355e77e3 100644 (file)
@@ -66,6 +66,10 @@ namespace {
 
     virtual void EmitValue(const MCExpr *Value, unsigned Size,
                            unsigned AddrSpace) {}
+    virtual void EmitULEB128Value(const MCExpr *Value,
+                                  unsigned AddrSpace = 0) {}
+    virtual void EmitSLEB128Value(const MCExpr *Value,
+                                  unsigned AddrSpace = 0) {}
     virtual void EmitGPRel32Value(const MCExpr *Value) {}
     virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
                                       unsigned ValueSize = 1,
index da1b7c05b1b5ff3af3495d6eb1ff96850e347638..a40c75465808edde81906d907fe8a55699849233 100644 (file)
@@ -75,6 +75,16 @@ const MCExpr *MCObjectStreamer::AddValueSymbols(const MCExpr *Value) {
   return Value;
 }
 
+void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value,
+                                        unsigned AddrSpace) {
+  new MCLEBFragment(*Value, false, getCurrentSectionData());
+}
+
+void MCObjectStreamer::EmitSLEB128Value(const MCExpr *Value,
+                                        unsigned AddrSpace) {
+  new MCLEBFragment(*Value, true, getCurrentSectionData());
+}
+
 void MCObjectStreamer::EmitWeakReference(MCSymbol *Alias,
                                          const MCSymbol *Symbol) {
   report_fatal_error("This file format doesn't support weak aliases.");
index 8aaee95eda86436964e075bc21b0f684672d80a0..877bae9e1c1d6ebcdba40aaa27d5965f6a2613ec 100644 (file)
@@ -261,8 +261,6 @@ public:
   bool ParseDirectiveMacro(StringRef, SMLoc DirectiveLoc);
   bool ParseDirectiveEndMacro(StringRef, SMLoc DirectiveLoc);
 
-  void ParseUleb128(uint64_t Value);
-  void ParseSleb128(int64_t Value);
   bool ParseDirectiveLEB128(StringRef, SMLoc);
 };
 
@@ -2178,44 +2176,22 @@ bool GenericAsmParser::ParseDirectiveEndMacro(StringRef Directive,
                   "no current macro definition");
 }
 
-void GenericAsmParser::ParseUleb128(uint64_t Value) {
-  const uint64_t Mask = (1 << 7) - 1;
-  do {
-    unsigned Byte = Value & Mask;
-    Value >>= 7;
-    if (Value) // Not the last one
-      Byte |= (1 << 7);
-    getStreamer().EmitIntValue(Byte, 1, DEFAULT_ADDRSPACE);
-  } while (Value);
-}
+bool GenericAsmParser::ParseDirectiveLEB128(StringRef DirName, SMLoc) {
+  getParser().CheckForValidSection();
 
-void GenericAsmParser::ParseSleb128(int64_t Value) {
-  const int64_t Mask = (1 << 7) - 1;
-  for(;;) {
-    unsigned Byte = Value & Mask;
-    Value >>= 7;
-    bool Done = ((Value ==  0 && (Byte & 0x40) == 0) ||
-                 (Value == -1 && (Byte & 0x40) != 0));
-    if (!Done)
-      Byte |= (1 << 7);
-    getStreamer().EmitIntValue(Byte, 1, DEFAULT_ADDRSPACE);
-    if (Done)
-      break;
-  }
-}
+  const MCExpr *Value;
 
-bool GenericAsmParser::ParseDirectiveLEB128(StringRef DirName, SMLoc) {
-  int64_t Value;
-  if (getParser().ParseAbsoluteExpression(Value))
+  if (getParser().ParseExpression(Value))
     return true;
 
   if (getLexer().isNot(AsmToken::EndOfStatement))
     return TokError("unexpected token in directive");
 
   if (DirName[1] == 's')
-    ParseSleb128(Value);
+    getStreamer().EmitSLEB128Value(Value);
   else
-    ParseUleb128(Value);
+    getStreamer().EmitULEB128Value(Value);
+
   return false;
 }
 
index 351d9fce4c34e3fc4a9a185014377bba6f1447ce..98667f42d6a8bfddd541d7c491485f31b8cdc5df 100644 (file)
@@ -37,22 +37,16 @@ void MCStreamer::EmitIntValue(uint64_t Value, unsigned Size,
   EmitValue(MCConstantExpr::Create(Value, getContext()), Size, AddrSpace);
 }
 
-// EmitULEB128Value - Special case of EmitValue that emits a ULEB128 of the
-// Value as the sequence of ULEB128 encoded bytes.
-void MCStreamer::EmitULEB128Value(uint64_t Value, unsigned AddrSpace) {
-  SmallString<32> Tmp;
-  raw_svector_ostream OS(Tmp);
-  MCObjectWriter::EncodeULEB128(Value, OS);
-  EmitBytes(OS.str(), AddrSpace);
+/// EmitULEB128Value - Special case of EmitULEB128Value that avoids the
+/// client having to pass in a MCExpr for constant integers.
+void MCStreamer::EmitULEB128IntValue(uint64_t Value, unsigned AddrSpace) {
+  EmitULEB128Value(MCConstantExpr::Create(Value, getContext()), AddrSpace);
 }
 
-// EmitSLEB128Value - Special case of EmitValue that emits a SLEB128 of the
-// Value as the sequence of ULEB128 encoded bytes.
-void MCStreamer::EmitSLEB128Value(int64_t Value, unsigned AddrSpace) {
-  SmallString<32> Tmp;
-  raw_svector_ostream OS(Tmp);
-  MCObjectWriter::EncodeSLEB128(Value, OS);
-  EmitBytes(OS.str(), AddrSpace);
+/// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the
+/// client having to pass in a MCExpr for constant integers.
+void MCStreamer::EmitSLEB128IntValue(int64_t Value, unsigned AddrSpace) {
+  EmitSLEB128Value(MCConstantExpr::Create(Value, getContext()), AddrSpace);
 }
 
 void MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size,
diff --git a/test/MC/ELF/leb128.s b/test/MC/ELF/leb128.s
new file mode 100644 (file)
index 0000000..e5f31f4
--- /dev/null
@@ -0,0 +1,19 @@
+// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | elf-dump  --dump-section-data | FileCheck %s
+
+        .sleb128 .Lfoo - .Lbar
+.Lfoo:
+        .uleb128 .Lbar - .Lfoo
+        .fill 126, 1, 0x90
+.Lbar:
+
+// CHECK:     (('sh_name', 0x00000001) # '.text'
+// CHECK-NEXT: ('sh_type', 0x00000001)
+// CHECK-NEXT: ('sh_flags', 0x00000006)
+// CHECK-NEXT: ('sh_addr', 0x00000000)
+// CHECK-NEXT: ('sh_offset', 0x00000040)
+// CHECK-NEXT: ('sh_size', 0x00000081)
+// CHECK-NEXT: ('sh_link', 0x00000000)
+// CHECK-NEXT: ('sh_info', 0x00000000)
+// CHECK-NEXT: ('sh_addralign', 0x00000004)
+// CHECK-NEXT: ('sh_entsize', 0x00000000)
+// CHECK-NEXT: ('_section_data', '817f7f90 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90909090 90')