diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index f6fd9d73c7b..833341eb97f 100644 --- a/include/llvm/MC/MCObjectStreamer.h +++ b/include/llvm/MC/MCObjectStreamer.h @@ -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); diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 1be2dc6bb6d..fc2451f9c19 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -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,17 +57,17 @@ namespace llvm { MCDwarfFrameInfo *getCurrentFrameInfo(); void EnsureValidFrame(); + /// CurSectionStack - This is stack of CurSection values saved by + /// PushSection. + SmallVector CurSectionStack; + + /// PrevSectionStack - This is stack of PrevSection values saved by + /// PushSection. + SmallVector PrevSectionStack; + protected: MCStreamer(MCContext &Ctx); - /// CurSection - This is the current section code is being emitted to, it is - /// kept up to date by SwitchSection. - const MCSection *CurSection; - - /// PrevSection - This is the previous section code is being emitted to, it - /// is kept up to date by SwitchSection. - const MCSection *PrevSection; - 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; diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index 6aabfe188a3..8d0698216f6 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -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()); diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp index ac310570653..e49074da399 100644 --- a/lib/MC/MCELFStreamer.cpp +++ b/lib/MC/MCELFStreamer.cpp @@ -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(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); diff --git a/lib/MC/MCLoggingStreamer.cpp b/lib/MC/MCLoggingStreamer.cpp index d9474813837..012c7f62f8a 100644 --- a/lib/MC/MCLoggingStreamer.cpp +++ b/lib/MC/MCLoggingStreamer.cpp @@ -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() { diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index 7e1cda25b6f..d1f9f5cd568 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -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)) diff --git a/lib/MC/MCNullStreamer.cpp b/lib/MC/MCNullStreamer.cpp index b9393ffd2e9..08ddf01d1a3 100644 --- a/lib/MC/MCNullStreamer.cpp +++ b/lib/MC/MCNullStreamer.cpp @@ -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) {} diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp index ecd7257c70a..035826690cd 100644 --- a/lib/MC/MCObjectStreamer.cpp +++ b/lib/MC/MCObjectStreamer.cpp @@ -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); } diff --git a/lib/MC/MCParser/ELFAsmParser.cpp b/lib/MC/MCParser/ELFAsmParser.cpp index 7b88ea2d1da..bfaf36a451b 100644 --- a/lib/MC/MCParser/ELFAsmParser.cpp +++ b/lib/MC/MCParser/ELFAsmParser.cpp @@ -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; } diff --git a/lib/MC/MCPureStreamer.cpp b/lib/MC/MCPureStreamer.cpp index 5341844f740..6098e6b8f38 100644 --- a/lib/MC/MCPureStreamer.cpp +++ b/lib/MC/MCPureStreamer.cpp @@ -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); diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index 1cb5165e6d7..3dcdba13135 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -19,8 +19,9 @@ #include 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() { diff --git a/lib/Target/PTX/PTXMCAsmStreamer.cpp b/lib/Target/PTX/PTXMCAsmStreamer.cpp index fc3dd5feeb8..0886ba8008f 100644 --- a/lib/Target/PTX/PTXMCAsmStreamer.cpp +++ b/lib/Target/PTX/PTXMCAsmStreamer.cpp @@ -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 index 00000000000..414fc6d5397 --- /dev/null +++ b/test/MC/AsmParser/section.s @@ -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: ),