Add support for pushsection and popsection. Patch by Joerg Sonnenberger.
authorRafael Espindola <rafael.espindola@gmail.com>
Wed, 16 Feb 2011 01:08:29 +0000 (01:08 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Wed, 16 Feb 2011 01:08:29 +0000 (01:08 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@125629 91177308-0d34-0410-b5e6-96231b3b80d8

13 files changed:
include/llvm/MC/MCObjectStreamer.h
include/llvm/MC/MCStreamer.h
lib/MC/MCAsmStreamer.cpp
lib/MC/MCELFStreamer.cpp
lib/MC/MCLoggingStreamer.cpp
lib/MC/MCMachOStreamer.cpp
lib/MC/MCNullStreamer.cpp
lib/MC/MCObjectStreamer.cpp
lib/MC/MCParser/ELFAsmParser.cpp
lib/MC/MCPureStreamer.cpp
lib/MC/MCStreamer.cpp
lib/Target/PTX/PTXMCAsmStreamer.cpp
test/MC/AsmParser/section.s [new file with mode: 0644]

index f6fd9d73c7bf141bb63d7398eb83635b6bbcaeb7..833341eb97f50f6a58a8a60b93071d31668d3bd1 100644 (file)
@@ -64,7 +64,7 @@ public:
   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 ChangeSection(const MCSection *Section);
   virtual void EmitInstruction(const MCInst &Inst);
   virtual void EmitInstToFragment(const MCInst &Inst);
   virtual void EmitValueToOffset(const MCExpr *Offset, unsigned char Value);
index 1be2dc6bb6d7d840090afe73493b0ed2746bf063..fc2451f9c19ca97a8f4cb6dd057854477b8db728 100644 (file)
@@ -14,6 +14,7 @@
 #ifndef LLVM_MC_MCSTREAMER_H
 #define LLVM_MC_MCSTREAMER_H
 
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/Support/DataTypes.h"
 #include "llvm/MC/MCDirectives.h"
 #include "llvm/MC/MCDwarf.h"
@@ -56,16 +57,16 @@ namespace llvm {
     MCDwarfFrameInfo *getCurrentFrameInfo();
     void EnsureValidFrame();
 
-  protected:
-    MCStreamer(MCContext &Ctx);
+    /// CurSectionStack - This is stack of CurSection values saved by
+    /// PushSection.
+    SmallVector<const MCSection *, 4> CurSectionStack;
 
-    /// CurSection - This is the current section code is being emitted to, it is
-    /// kept up to date by SwitchSection.
-    const MCSection *CurSection;
+    /// PrevSectionStack - This is stack of PrevSection values saved by
+    /// PushSection.
+    SmallVector<const MCSection *, 4> PrevSectionStack;
 
-    /// PrevSection - This is the previous section code is being emitted to, it
-    /// is kept up to date by SwitchSection.
-    const MCSection *PrevSection;
+  protected:
+    MCStreamer(MCContext &Ctx);
 
   public:
     virtual ~MCStreamer();
@@ -115,17 +116,63 @@ namespace llvm {
 
     /// getCurrentSection - Return the current section that the streamer is
     /// emitting code to.
-    const MCSection *getCurrentSection() const { return CurSection; }
+    const MCSection *getCurrentSection() const {
+      if (!CurSectionStack.empty())
+        return CurSectionStack.back();
+      return NULL;
+    }
 
     /// getPreviousSection - Return the previous section that the streamer is
     /// emitting code to.
-    const MCSection *getPreviousSection() const { return PrevSection; }
+    const MCSection *getPreviousSection() const {
+      if (!PrevSectionStack.empty())
+        return PrevSectionStack.back();
+      return NULL;
+    }
+
+    /// ChangeSection - Update streamer for a new active section.
+    ///
+    /// This is called by PopSection and SwitchSection, if the current
+    /// section changes.
+    virtual void ChangeSection(const MCSection *) = 0;
+
+    /// pushSection - Save the current and previous section on the
+    /// section stack.
+    void PushSection() {
+      PrevSectionStack.push_back(getPreviousSection());
+      CurSectionStack.push_back(getCurrentSection());
+    }
+
+    /// popSection - Restore the current and previous section from
+    /// the section stack.  Calls ChangeSection as needed.
+    ///
+    /// Returns false if the stack was empty.
+    bool PopSection() {
+      if (PrevSectionStack.size() <= 1)
+        return false;
+      assert(CurSectionStack.size() > 1);
+      PrevSectionStack.pop_back();
+      const MCSection *oldSection = CurSectionStack.pop_back_val();
+      const MCSection *curSection = CurSectionStack.back();
+
+      if (oldSection != curSection)
+        ChangeSection(curSection);
+      return true;
+    }
 
     /// SwitchSection - Set the current section where code is being emitted to
     /// @p Section.  This is required to update CurSection.
     ///
     /// This corresponds to assembler directives like .section, .text, etc.
-    virtual void SwitchSection(const MCSection *Section) = 0;
+    void SwitchSection(const MCSection *Section) {
+      assert(Section && "Cannot switch to a null section!");
+      const MCSection *curSection = CurSectionStack.back();
+      PrevSectionStack.back() = curSection;
+      if (Section != curSection) {
+        CurSectionStack.back() = Section;
+        ChangeSection(Section);
+      }
+    }
 
     /// InitSections - Create the default sections and set the initial one.
     virtual void InitSections() = 0;
index 6aabfe188a32abf4a4726ced9c4b4840618a1060..8d0698216f60e5c62cebe245c4f84fdee30b49a0 100644 (file)
@@ -107,7 +107,7 @@ public:
   /// @name MCStreamer Interface
   /// @{
 
-  virtual void SwitchSection(const MCSection *Section);
+  virtual void ChangeSection(const MCSection *Section);
 
   virtual void InitSections() {
     // FIXME, this is MachO specific, but the testsuite
@@ -254,23 +254,19 @@ static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) {
   return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8));
 }
 
-void MCAsmStreamer::SwitchSection(const MCSection *Section) {
+void MCAsmStreamer::ChangeSection(const MCSection *Section) {
   assert(Section && "Cannot switch to a null section!");
-  if (Section != CurSection) {
-    PrevSection = CurSection;
-    CurSection = Section;
-    Section->PrintSwitchToSection(MAI, OS);
-  }
+  Section->PrintSwitchToSection(MAI, OS);
 }
 
 void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) {
   assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
   assert(!Symbol->isVariable() && "Cannot emit a variable symbol!");
-  assert(CurSection && "Cannot emit before setting section!");
+  assert(getCurrentSection() && "Cannot emit before setting section!");
 
   OS << *Symbol << MAI.getLabelSuffix();
   EmitEOL();
-  Symbol->setSection(*CurSection);
+  Symbol->setSection(*getCurrentSection());
 }
 
 void MCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
@@ -486,7 +482,7 @@ static void PrintQuotedString(StringRef Data, raw_ostream &OS) {
 
 
 void MCAsmStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) {
-  assert(CurSection && "Cannot emit contents before setting section!");
+  assert(getCurrentSection() && "Cannot emit contents before setting section!");
   if (Data.empty()) return;
 
   if (Data.size() == 1) {
@@ -517,7 +513,7 @@ void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size,
 
 void MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
                                   bool isPCRel, unsigned AddrSpace) {
-  assert(CurSection && "Cannot emit contents before setting section!");
+  assert(getCurrentSection() && "Cannot emit contents before setting section!");
   assert(!isPCRel && "Cannot emit pc relative relocations!");
   const char *Directive = 0;
   switch (Size) {
@@ -864,7 +860,7 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) {
 }
 
 void MCAsmStreamer::EmitInstruction(const MCInst &Inst) {
-  assert(CurSection && "Cannot emit contents before setting section!");
+  assert(getCurrentSection() && "Cannot emit contents before setting section!");
 
   if (!UseLoc)
     MCLineEntry::Make(this, getCurrentSection());
index ac3105706531842e7b03a0da2c8d5c797bc80248..e49074da399458f703100a26b9f853ced2c8bf55 100644 (file)
@@ -80,12 +80,12 @@ public:
   /// @{
 
   virtual void InitSections();
+  virtual void ChangeSection(const MCSection *Section);
   virtual void EmitLabel(MCSymbol *Symbol);
   virtual void EmitAssemblerFlag(MCAssemblerFlag Flag);
   virtual void EmitThumbFunc(MCSymbol *Func);
   virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value);
   virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol);
-  virtual void SwitchSection(const MCSection *Section);
   virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute);
   virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
     assert(0 && "ELF doesn't support this directive");
@@ -222,11 +222,11 @@ void MCELFStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
   Symbol->setVariableValue(AddValueSymbols(Value));
 }
 
-void MCELFStreamer::SwitchSection(const MCSection *Section) {
+void MCELFStreamer::ChangeSection(const MCSection *Section) {
   const MCSymbol *Grp = static_cast<const MCSectionELF *>(Section)->getGroup();
   if (Grp)
     getAssembler().getOrCreateSymbolData(*Grp);
-  this->MCObjectStreamer::SwitchSection(Section);
+  this->MCObjectStreamer::ChangeSection(Section);
 }
 
 void MCELFStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
@@ -411,7 +411,7 @@ void MCELFStreamer::EmitCodeAlignment(unsigned ByteAlignment,
 // entry in the module's symbol table (the first being the null symbol).
 void MCELFStreamer::EmitFileDirective(StringRef Filename) {
   MCSymbol *Symbol = getAssembler().getContext().GetOrCreateSymbol(Filename);
-  Symbol->setSection(*CurSection);
+  Symbol->setSection(*getCurrentSection());
   Symbol->setAbsolute();
 
   MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
index d94748138378625f6ff9306b1b8b9344ba5d26ac..012c7f62f8afabdcc95bf9efcdbf6020a82747ae 100644 (file)
@@ -48,10 +48,9 @@ public:
     return Child->AddBlankLine();
   }
 
-  virtual void SwitchSection(const MCSection *Section) {
-    CurSection = Section;
-    LogCall("SwitchSection");
-    return Child->SwitchSection(Section);
+  virtual void ChangeSection(const MCSection *Section) {
+    LogCall("ChangeSection");
+    return Child->ChangeSection(Section);
   }
 
   virtual void InitSections() {
index 7e1cda25b6f38b44aac7723b1e197db976860d54..d1f9f5cd568e7a6ff2e4d2425ba07cb882b6c82e 100644 (file)
@@ -105,7 +105,7 @@ void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) {
   assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
 
   // isSymbolLinkerVisible uses the section.
-  Symbol->setSection(*CurSection);
+  Symbol->setSection(*getCurrentSection());
   // We have to create a new fragment if this is an atom defining symbol,
   // fragments cannot span atoms.
   if (getAssembler().isSymbolLinkerVisible(*Symbol))
index b9393ffd2e9f9d7d9648a1ca4551751833c69ba8..08ddf01d1a36ad671bfb5444e11d256a64cf693f 100644 (file)
@@ -28,15 +28,13 @@ namespace {
     virtual void InitSections() {
     }
 
-    virtual void SwitchSection(const MCSection *Section) {
-      PrevSection = CurSection;
-      CurSection = Section;
+    virtual void ChangeSection(const MCSection *Section) {
     }
 
     virtual void EmitLabel(MCSymbol *Symbol) {
       assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
-      assert(CurSection && "Cannot emit before setting section!");
-      Symbol->setSection(*CurSection);
+      assert(getCurrentSection() && "Cannot emit before setting section!");
+      Symbol->setSection(*getCurrentSection());
     }
 
     virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) {}
index ecd7257c70a096ec232025b47d6bb208b49a5031..035826690cdfaba2c1caa4f975dc47fe22885859 100644 (file)
@@ -101,9 +101,9 @@ void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
 
 void MCObjectStreamer::EmitLabel(MCSymbol *Symbol) {
   assert(!Symbol->isVariable() && "Cannot emit a variable symbol!");
-  assert(CurSection && "Cannot emit before setting section!");
+  assert(getCurrentSection() && "Cannot emit before setting section!");
 
-  Symbol->setSection(*CurSection);
+  Symbol->setSection(*getCurrentSection());
 
   MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
 
@@ -142,14 +142,9 @@ void MCObjectStreamer::EmitWeakReference(MCSymbol *Alias,
   report_fatal_error("This file format doesn't support weak aliases.");
 }
 
-void MCObjectStreamer::SwitchSection(const MCSection *Section) {
+void MCObjectStreamer::ChangeSection(const MCSection *Section) {
   assert(Section && "Cannot switch to a null section!");
 
-  // If already in this section, then this is a noop.
-  if (Section == CurSection) return;
-
-  PrevSection = CurSection;
-  CurSection = Section;
   CurSectionData = &getAssembler().getOrCreateSectionData(*Section);
 }
 
index 7b88ea2d1da39949d39bb511562c6d16562fcdbd..bfaf36a451b3d805c4bed62dc4d2723176ca476b 100644 (file)
@@ -49,6 +49,8 @@ public:
     AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveDataRelRoLocal>(".data.rel.ro.local");
     AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveEhFrame>(".eh_frame");
     AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSection>(".section");
+    AddDirectiveHandler<&ELFAsmParser::ParseDirectivePushSection>(".pushsection");
+    AddDirectiveHandler<&ELFAsmParser::ParseDirectivePopSection>(".popsection");
     AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSize>(".size");
     AddDirectiveHandler<&ELFAsmParser::ParseDirectivePrevious>(".previous");
     AddDirectiveHandler<&ELFAsmParser::ParseDirectiveType>(".type");
@@ -115,6 +117,8 @@ public:
                               ELF::SHF_WRITE,
                               SectionKind::getDataRel());
   }
+  bool ParseDirectivePushSection(StringRef, SMLoc);
+  bool ParseDirectivePopSection(StringRef, SMLoc);
   bool ParseDirectiveSection(StringRef, SMLoc);
   bool ParseDirectiveSize(StringRef, SMLoc);
   bool ParseDirectivePrevious(StringRef, SMLoc);
@@ -253,6 +257,23 @@ static int parseSectionFlags(StringRef flagsStr) {
   return flags;
 }
 
+bool ELFAsmParser::ParseDirectivePushSection(StringRef s, SMLoc loc) {
+  getStreamer().PushSection();
+
+  if (ParseDirectiveSection(s, loc)) {
+    getStreamer().PopSection();
+    return true;
+  }
+
+  return false;
+}
+
+bool ELFAsmParser::ParseDirectivePopSection(StringRef, SMLoc) {
+  if (!getStreamer().PopSection())
+    return TokError(".popsection without corresponding .pushsection");
+  return false;
+}
+
 // FIXME: This is a work in progress.
 bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
   StringRef SectionName;
@@ -364,8 +385,9 @@ bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
 
 bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) {
   const MCSection *PreviousSection = getStreamer().getPreviousSection();
-  if (PreviousSection != NULL)
-    getStreamer().SwitchSection(PreviousSection);
+  if (PreviousSection == NULL)
+      return TokError(".previous without corresponding .section");
+  getStreamer().SwitchSection(PreviousSection);
 
   return false;
 }
@@ -427,7 +449,6 @@ bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) {
 
   Lex();
 
-  const MCSection *OldSection = getStreamer().getCurrentSection();
   const MCSection *Comment =
     getContext().getELFSection(".comment", ELF::SHT_PROGBITS,
                                ELF::SHF_MERGE |
@@ -437,13 +458,14 @@ bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) {
 
   static bool First = true;
 
+  getStreamer().PushSection();
   getStreamer().SwitchSection(Comment);
   if (First)
     getStreamer().EmitIntValue(0, 1);
   First = false;
   getStreamer().EmitBytes(Data, 0);
   getStreamer().EmitIntValue(0, 1);
-  getStreamer().SwitchSection(OldSection);
+  getStreamer().PopSection();
   return false;
 }
 
index 5341844f7408f31a391c3294f8289f620efcecf9..6098e6b8f38bb6f353aa5b0465aefe2304f82bdb 100644 (file)
@@ -113,9 +113,9 @@ void MCPureStreamer::InitSections() {
 void MCPureStreamer::EmitLabel(MCSymbol *Symbol) {
   assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
   assert(!Symbol->isVariable() && "Cannot emit a variable symbol!");
-  assert(CurSection && "Cannot emit before setting section!");
+  assert(getCurrentSection() && "Cannot emit before setting section!");
 
-  Symbol->setSection(*CurSection);
+  Symbol->setSection(*getCurrentSection());
 
   MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
 
index 1cb5165e6d74274001b76163d71338eb2c30ab3a..3dcdba13135f6d8245660127d296f5a1398eb3a2 100644 (file)
@@ -19,8 +19,9 @@
 #include <cstdlib>
 using namespace llvm;
 
-MCStreamer::MCStreamer(MCContext &Ctx) : Context(Ctx), CurSection(0),
-                                         PrevSection(0) {
+MCStreamer::MCStreamer(MCContext &Ctx) : Context(Ctx) {
+  PrevSectionStack.push_back(NULL);
+  CurSectionStack.push_back(NULL);
 }
 
 MCStreamer::~MCStreamer() {
index fc3dd5feeb8e022347b1fdade31a32597496ae5e..0886ba8008f34152e88bff2772875419bddaa3f2 100644 (file)
@@ -100,8 +100,7 @@ public:
   /// @name MCStreamer Interface
   /// @{
 
-  virtual void SwitchSection(const MCSection *Section);
-
+  virtual void ChangeSection(const MCSection *Section);
   virtual void InitSections() {}
 
   virtual void EmitLabel(MCSymbol *Symbol);
@@ -227,22 +226,18 @@ static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) {
   return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8));
 }
 
-void PTXMCAsmStreamer::SwitchSection(const MCSection *Section) {
+void PTXMCAsmStreamer::ChangeSection(const MCSection *Section) {
   assert(Section && "Cannot switch to a null section!");
-  if (Section != CurSection) {
-    PrevSection = CurSection;
-    CurSection = Section;
-  }
 }
 
 void PTXMCAsmStreamer::EmitLabel(MCSymbol *Symbol) {
   assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
   assert(!Symbol->isVariable() && "Cannot emit a variable symbol!");
-  assert(CurSection && "Cannot emit before setting section!");
+  assert(getCurrentSection() && "Cannot emit before setting section!");
 
   OS << *Symbol << MAI.getLabelSuffix();
   EmitEOL();
-  Symbol->setSection(*CurSection);
+  Symbol->setSection(*getCurrentSection());
 }
 
 void PTXMCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {}
@@ -332,7 +327,7 @@ static void PrintQuotedString(StringRef Data, raw_ostream &OS) {
 }
 
 void PTXMCAsmStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) {
-  assert(CurSection && "Cannot emit contents before setting section!");
+  assert(getCurrentSection() && "Cannot emit contents before setting section!");
   if (Data.empty()) return;
 
   if (Data.size() == 1) {
@@ -358,7 +353,7 @@ void PTXMCAsmStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) {
 
 void PTXMCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
                                      bool isPCRel, unsigned AddrSpace) {
-  assert(CurSection && "Cannot emit contents before setting section!");
+  assert(getCurrentSection() && "Cannot emit contents before setting section!");
   assert(!isPCRel && "Cannot emit pc relative relocations!");
   const char *Directive = 0;
   switch (Size) {
@@ -502,7 +497,7 @@ bool PTXMCAsmStreamer::EmitDwarfFileDirective(unsigned FileNo,
 void PTXMCAsmStreamer::AddEncodingComment(const MCInst &Inst) {}
 
 void PTXMCAsmStreamer::EmitInstruction(const MCInst &Inst) {
-  assert(CurSection && "Cannot emit contents before setting section!");
+  assert(getCurrentSection() && "Cannot emit contents before setting section!");
 
   // Show the encoding in a comment if we have a code emitter.
   if (Emitter)
diff --git a/test/MC/AsmParser/section.s b/test/MC/AsmParser/section.s
new file mode 100644 (file)
index 0000000..414fc6d
--- /dev/null
@@ -0,0 +1,107 @@
+# RUN: llvm-mc -triple i386-pc-linux-gnu -filetype=obj -o %t %s
+# RUN: elf-dump --dump-section-data < %t | FileCheck %s
+.section test1
+.byte 1
+.section test2
+.byte 2
+.previous
+.byte 1
+.section test2
+.byte 2
+.previous
+.byte 1
+.section test1
+.byte 1
+.previous
+.byte 1
+.section test2
+.byte 2
+.pushsection test3
+.byte 3
+.pushsection test4
+.byte 4
+.pushsection test5
+.byte 5
+.popsection
+.byte 4
+.popsection
+.byte 3
+.popsection
+.byte 2
+.pushsection test3
+.byte 3
+.pushsection test4
+.byte 4
+.previous
+.byte 3
+.popsection
+.byte 3
+.previous
+.byte 2
+.section test1
+.byte 1
+.popsection
+.byte 2
+.previous
+.byte 1
+.previous
+# CHECK:       (('sh_name', 0x00000012) # 'test1'
+# CHECK-NEXT:   ('sh_type', 0x00000001)
+# CHECK-NEXT:   ('sh_flags', 0x00000000)
+# CHECK-NEXT:   ('sh_addr', 0x00000000)
+# CHECK-NEXT:   ('sh_offset', 0x00000034)
+# CHECK-NEXT:   ('sh_size', 0x00000007)
+# CHECK-NEXT:   ('sh_link', 0x00000000)
+# CHECK-NEXT:   ('sh_info', 0x00000000)
+# CHECK-NEXT:   ('sh_addralign', 0x00000001)
+# CHECK-NEXT:   ('sh_entsize', 0x00000000)
+# CHECK-NEXT:   ('_section_data', '01010101 010101')
+# CHECK-NEXT:  ),
+# CHECK:       (('sh_name', 0x00000018) # 'test2'
+# CHECK-NEXT:   ('sh_type', 0x00000001)
+# CHECK-NEXT:   ('sh_flags', 0x00000000)
+# CHECK-NEXT:   ('sh_addr', 0x00000000)
+# CHECK-NEXT:   ('sh_offset', 0x0000003b)
+# CHECK-NEXT:   ('sh_size', 0x00000006)
+# CHECK-NEXT:   ('sh_link', 0x00000000)
+# CHECK-NEXT:   ('sh_info', 0x00000000)
+# CHECK-NEXT:   ('sh_addralign', 0x00000001)
+# CHECK-NEXT:   ('sh_entsize', 0x00000000)
+# CHECK-NEXT:   ('_section_data', '02020202 0202')
+# CHECK-NEXT:  ),
+# CHECK:       (('sh_name', 0x0000001e) # 'test3'
+# CHECK-NEXT:   ('sh_type', 0x00000001)
+# CHECK-NEXT:   ('sh_flags', 0x00000000)
+# CHECK-NEXT:   ('sh_addr', 0x00000000)
+# CHECK-NEXT:   ('sh_offset', 0x00000041)
+# CHECK-NEXT:   ('sh_size', 0x00000005)
+# CHECK-NEXT:   ('sh_link', 0x00000000)
+# CHECK-NEXT:   ('sh_info', 0x00000000)
+# CHECK-NEXT:   ('sh_addralign', 0x00000001)
+# CHECK-NEXT:   ('sh_entsize', 0x00000000)
+# CHECK-NEXT:   ('_section_data', '03030303 03')
+# CHECK-NEXT:  ),
+# CHECK:       (('sh_name', 0x00000024) # 'test4'
+# CHECK-NEXT:   ('sh_type', 0x00000001)
+# CHECK-NEXT:   ('sh_flags', 0x00000000)
+# CHECK-NEXT:   ('sh_addr', 0x00000000)
+# CHECK-NEXT:   ('sh_offset', 0x00000046)
+# CHECK-NEXT:   ('sh_size', 0x00000003)
+# CHECK-NEXT:   ('sh_link', 0x00000000)
+# CHECK-NEXT:   ('sh_info', 0x00000000)
+# CHECK-NEXT:   ('sh_addralign', 0x00000001)
+# CHECK-NEXT:   ('sh_entsize', 0x00000000)
+# CHECK-NEXT:   ('_section_data', '040404')
+# CHECK-NEXT:  ),
+# CHECK:       (('sh_name', 0x0000002a) # 'test5'
+# CHECK-NEXT:   ('sh_type', 0x00000001)
+# CHECK-NEXT:   ('sh_flags', 0x00000000)
+# CHECK-NEXT:   ('sh_addr', 0x00000000)
+# CHECK-NEXT:   ('sh_offset', 0x00000049)
+# CHECK-NEXT:   ('sh_size', 0x00000001)
+# CHECK-NEXT:   ('sh_link', 0x00000000)
+# CHECK-NEXT:   ('sh_info', 0x00000000)
+# CHECK-NEXT:   ('sh_addralign', 0x00000001)
+# CHECK-NEXT:   ('sh_entsize', 0x00000000)
+# CHECK-NEXT:   ('_section_data', '05')
+# CHECK-NEXT:  ),