From: Rafael Espindola Date: Mon, 1 Nov 2010 14:28:48 +0000 (+0000) Subject: Implement .weakref. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=484291c27319668ad99cb87def000254357736fb;p=oota-llvm.git Implement .weakref. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@117911 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/MC/MCELFSymbolFlags.h b/include/llvm/MC/MCELFSymbolFlags.h index eb7978b18c5..d798fb07727 100644 --- a/include/llvm/MC/MCELFSymbolFlags.h +++ b/include/llvm/MC/MCELFSymbolFlags.h @@ -21,9 +21,10 @@ namespace llvm { enum { - ELF_STT_Shift = 0, // Shift value for STT_* flags. - ELF_STB_Shift = 4, // Shift value for STB_* flags. - ELF_STV_Shift = 8 // Shift value ofr STV_* flags. + ELF_STT_Shift = 0, // Shift value for STT_* flags. + ELF_STB_Shift = 4, // Shift value for STB_* flags. + ELF_STV_Shift = 8, // Shift value for STV_* flags. + ELF_Other_Shift = 10 // Shift value for other flags. }; enum SymbolFlags { @@ -46,7 +47,9 @@ namespace llvm { ELF_STV_Default = (ELF::STV_DEFAULT << ELF_STV_Shift), ELF_STV_Internal = (ELF::STV_INTERNAL << ELF_STV_Shift), ELF_STV_Hidden = (ELF::STV_HIDDEN << ELF_STV_Shift), - ELF_STV_Protected = (ELF::STV_PROTECTED << ELF_STV_Shift) + ELF_STV_Protected = (ELF::STV_PROTECTED << ELF_STV_Shift), + + ELF_Other_Weakref = (1 << ELF_Other_Shift) }; } // end namespace llvm diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index 6836ec52e11..61f4d51f0d9 100644 --- a/include/llvm/MC/MCObjectStreamer.h +++ b/include/llvm/MC/MCObjectStreamer.h @@ -57,6 +57,7 @@ public: /// @name MCStreamer Interface /// @{ + virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); virtual void SwitchSection(const MCSection *Section); virtual void Finish(); diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 1f4f23de6f1..53877b1add0 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -139,6 +139,15 @@ namespace llvm { /// @param Value - The value for the symbol. virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) = 0; + /// EmitWeakReference - Emit an weak reference from @p Alias to @p Symbol. + /// + /// This corresponds to an assembler statement such as: + /// .weakref alias, symbol + /// + /// @param Alias - The alias that is being created. + /// @param Symbol - The symbol being aliased. + virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) = 0; + /// EmitSymbolAttribute - Add the given @p Attribute to @p Symbol. virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) = 0; diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index 850983fa1a0..a0e326db284 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -143,6 +143,7 @@ namespace { }; SmallPtrSet UsedInReloc; + SmallPtrSet WeakrefUsedInReloc; DenseMap Renames; llvm::DenseMapgetSymbol()); Renamed = Renames.lookup(Symbol); if (!Renamed) - Renamed = Symbol; + Renamed = &Target.getSymA()->getSymbol(); MCSymbolData &SD = Asm.getSymbolData(*Symbol); MCFragment *F = SD.getFragment(); @@ -727,6 +728,10 @@ void ELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm, Value += Layout.getSymbolAddress(&SD) - Layout.getSectionAddress(FSD); } else { UsedInReloc.insert(Renamed); + MCSymbolData &RenamedSD = Asm.getSymbolData(*Renamed); + if (RenamedSD.getFlags() & ELF_Other_Weakref) { + WeakrefUsedInReloc.insert(Symbol); + } Index = -1; } Addend = Value; @@ -901,6 +906,9 @@ ELFObjectWriterImpl::getSymbolIndexInSymbolTable(const MCAssembler &Asm, static bool isInSymtab(const MCAssembler &Asm, const MCSymbolData &Data, bool Used, bool Renamed) { + if (Data.getFlags() & ELF_Other_Weakref) + return false; + if (Used) return true; @@ -963,7 +971,9 @@ void ELFObjectWriterImpl::ComputeSymbolTable(MCAssembler &Asm) { ie = Asm.symbol_end(); it != ie; ++it) { const MCSymbol &Symbol = it->getSymbol(); - if (!isInSymtab(Asm, *it, UsedInReloc.count(&Symbol), + bool Used = UsedInReloc.count(&Symbol); + bool WeakrefUsed = WeakrefUsedInReloc.count(&Symbol); + if (!isInSymtab(Asm, *it, Used || WeakrefUsed, Renames.count(&Symbol))) continue; @@ -972,6 +982,9 @@ void ELFObjectWriterImpl::ComputeSymbolTable(MCAssembler &Asm) { bool Local = isLocal(*it); const MCSymbol &RefSymbol = AliasedSymbol(Symbol); + if (RefSymbol.isUndefined() && !Used && WeakrefUsed) + SetBinding(*it, ELF::STB_WEAK); + if (it->isCommon()) { assert(!Local); MSD.SectionIndex = ELF::SHN_COMMON; diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index 6c240cf4148..ca8dc965f29 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -113,6 +113,7 @@ public: virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); + virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); @@ -258,6 +259,11 @@ void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { Symbol->setVariableValue(Value); } +void MCAsmStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { + OS << ".weakref " << *Alias << ", " << *Symbol; + EmitEOL(); +} + void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) { switch (Attribute) { diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp index 65a0a7d7e65..e794e57e93a 100644 --- a/lib/MC/MCELFStreamer.cpp +++ b/lib/MC/MCELFStreamer.cpp @@ -24,6 +24,7 @@ #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCValue.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ELF.h" #include "llvm/Support/ErrorHandling.h" @@ -51,6 +52,7 @@ public: virtual void EmitLabel(MCSymbol *Symbol); virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); + virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { assert(0 && "ELF doesn't support this directive"); @@ -193,6 +195,64 @@ void MCELFStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { Symbol->setVariableValue(AddValueSymbols(Value)); } +// This is a hack. To be able to implement weakrefs the writer has to be able +// to distinguish +// .weakref foo, bar +// .long foo +// from +// .weakref foo, bar +// .long bar +// since the first case should produce a weak undefined reference and the second +// one a strong one. +// If we created foo as a regular alias pointing to bar (foo = bar), then +// MCExpr::EvaluateAsRelocatable would recurse on foo and the writer would +// never see it used in a relocation. +// What we do is create a MCTargetExpr that when evaluated produces a symbol +// ref to a temporary symbol. This temporary symbol in turn is a variable +// that equals the original symbol (tmp = bar). With this hack the writer +// gets a relocation with tmp and can correctly implement weak references. + +class WeakRefExpr : public MCTargetExpr { +private: + const MCSymbolRefExpr *Alias; + + explicit WeakRefExpr(const MCSymbolRefExpr *Alias_) + : MCTargetExpr(), Alias(Alias_) {} + +public: + virtual void PrintImpl(raw_ostream &OS) const { + llvm_unreachable("Unimplemented"); + } + + virtual bool EvaluateAsRelocatableImpl(MCValue &Res, + const MCAsmLayout *Layout) const { + Res = MCValue::get(Alias, 0, 0); + return true; + } + + static const WeakRefExpr *Create(const MCSymbol *Alias, MCContext &Ctx) { + const MCSymbolRefExpr *A = MCSymbolRefExpr::Create(Alias, Ctx); + return new (Ctx) WeakRefExpr(A); + } +}; + +void MCELFStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { + getAssembler().getOrCreateSymbolData(*Symbol); + MCSymbolData &AliasSD = getAssembler().getOrCreateSymbolData(*Alias); + AliasSD.setFlags(AliasSD.getFlags() | ELF_Other_Weakref); + + // Create the alias that actually points to Symbol + const MCSymbolRefExpr *SymRef = MCSymbolRefExpr::Create(Symbol, getContext()); + MCSymbol *RealAlias = getContext().CreateTempSymbol(); + RealAlias->setVariableValue(SymRef); + + MCSymbolData &RealAliasSD = getAssembler().getOrCreateSymbolData(*RealAlias); + RealAliasSD.setFlags(RealAliasSD.getFlags() | ELF_Other_Weakref); + + const MCExpr *Value = WeakRefExpr::Create(RealAlias, getContext()); + Alias->setVariableValue(Value); +} + static void SetBinding(MCSymbolData &SD, unsigned Binding) { assert(Binding == ELF::STB_LOCAL || Binding == ELF::STB_GLOBAL || Binding == ELF::STB_WEAK); diff --git a/lib/MC/MCLoggingStreamer.cpp b/lib/MC/MCLoggingStreamer.cpp index 761574545f7..a907c11f118 100644 --- a/lib/MC/MCLoggingStreamer.cpp +++ b/lib/MC/MCLoggingStreamer.cpp @@ -74,6 +74,11 @@ public: return Child->EmitAssignment(Symbol, Value); } + virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { + LogCall("EmitWeakReference"); + return Child->EmitWeakReference(Alias, Symbol); + } + virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) { LogCall("EmitSymbolAttribute"); return Child->EmitSymbolAttribute(Symbol, Attribute); diff --git a/lib/MC/MCNullStreamer.cpp b/lib/MC/MCNullStreamer.cpp index b2db410c111..5f29b46d370 100644 --- a/lib/MC/MCNullStreamer.cpp +++ b/lib/MC/MCNullStreamer.cpp @@ -42,6 +42,7 @@ namespace { virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) {} virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {} + virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol){} virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute){} diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp index 8a481e8bb30..3883f121522 100644 --- a/lib/MC/MCObjectStreamer.cpp +++ b/lib/MC/MCObjectStreamer.cpp @@ -74,6 +74,11 @@ const MCExpr *MCObjectStreamer::AddValueSymbols(const MCExpr *Value) { return Value; } +void MCObjectStreamer::EmitWeakReference(MCSymbol *Alias, + const MCSymbol *Symbol) { + report_fatal_error("This file format doesn't support weak aliases."); +} + void MCObjectStreamer::SwitchSection(const MCSection *Section) { assert(Section && "Cannot switch to a null section!"); diff --git a/lib/MC/MCParser/ELFAsmParser.cpp b/lib/MC/MCParser/ELFAsmParser.cpp index 62cf6c6e7a0..9883018dd15 100644 --- a/lib/MC/MCParser/ELFAsmParser.cpp +++ b/lib/MC/MCParser/ELFAsmParser.cpp @@ -53,6 +53,7 @@ public: AddDirectiveHandler<&ELFAsmParser::ParseDirectiveType>(".type"); AddDirectiveHandler<&ELFAsmParser::ParseDirectiveIdent>(".ident"); AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSymver>(".symver"); + AddDirectiveHandler<&ELFAsmParser::ParseDirectiveWeakref>(".weakref"); } // FIXME: Part of this logic is duplicated in the MCELFStreamer. What is @@ -119,6 +120,7 @@ public: bool ParseDirectiveType(StringRef, SMLoc); bool ParseDirectiveIdent(StringRef, SMLoc); bool ParseDirectiveSymver(StringRef, SMLoc); + bool ParseDirectiveWeakref(StringRef, SMLoc); private: bool ParseSectionName(StringRef &SectionName); @@ -443,6 +445,32 @@ bool ELFAsmParser::ParseDirectiveSymver(StringRef, SMLoc) { return false; } +/// ParseDirectiveWeakref +/// ::= .weakref foo, bar +bool ELFAsmParser::ParseDirectiveWeakref(StringRef, SMLoc) { + // FIXME: Share code with the other alias building directives. + + StringRef AliasName; + if (getParser().ParseIdentifier(AliasName)) + return TokError("expected identifier in directive"); + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("expected a comma"); + + Lex(); + + StringRef Name; + if (getParser().ParseIdentifier(Name)) + return TokError("expected identifier in directive"); + + MCSymbol *Alias = getContext().GetOrCreateSymbol(AliasName); + + MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); + + getStreamer().EmitWeakReference(Alias, Sym); + return false; +} + namespace llvm { MCAsmParserExtension *createELFAsmParser() { diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index 54071eba463..351d9fce4c3 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -10,6 +10,7 @@ #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCObjectWriter.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" diff --git a/test/MC/ELF/weakref.s b/test/MC/ELF/weakref.s new file mode 100644 index 00000000000..212e2c3c52f --- /dev/null +++ b/test/MC/ELF/weakref.s @@ -0,0 +1,234 @@ +// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | elf-dump | FileCheck %s + +// This is a long test that checks that the aliases created by weakref are +// never in the symbol table and that the only case it causes a symbol to +// be output as a weak undefined symbol is if that variable is not defined +// in this file and all the references to it are done via the alias. + + .weakref foo1, bar1 + + .weakref foo2, bar2 + .long bar2 + + .weakref foo3, bar3 + .long foo3 + + .weakref foo4, bar4 + .long foo4 + .long bar4 + + .weakref foo5, bar5 + .long bar5 + .long foo5 + +bar6: + .weakref foo6, bar6 + +bar7: + .weakref foo7, bar7 + .long bar7 + +bar8: + .weakref foo8, bar8 + .long foo8 + +bar9: + .weakref foo9, bar9 + .long foo9 + .long bar9 + +bar10: + .global bar10 + .weakref foo10, bar10 + .long bar10 + .long foo10 + +bar11: + .global bar11 + .weakref foo11, bar11 + +bar12: + .global bar12 + .weakref foo12, bar12 + .long bar12 + +bar13: + .global bar13 + .weakref foo13, bar13 + .long foo13 + +bar14: + .global bar14 + .weakref foo14, bar14 + .long foo14 + .long bar14 + +bar15: + .global bar15 + .weakref foo15, bar15 + .long bar15 + .long foo15 + +// CHECK: # Symbol 0x00000000 +// CHECK-NEXT: (('st_name', 0x00000000) # '' +// CHECK-NEXT: ('st_bind', 0x00000000) +// CHECK-NEXT: ('st_type', 0x00000000) +// CHECK-NEXT: ('st_other', 0x00000000) +// CHECK-NEXT: ('st_shndx', 0x00000000) +// CHECK-NEXT: ('st_value', 0x00000000) +// CHECK-NEXT: ('st_size', 0x00000000) +// CHECK-NEXT: ), +// CHECK-NEXT: # Symbol 0x00000001 +// CHECK-NEXT: (('st_name', 0x00000015) # 'bar6' +// CHECK-NEXT: ('st_bind', 0x00000000) +// CHECK-NEXT: ('st_type', 0x00000000) +// CHECK-NEXT: ('st_other', 0x00000000) +// CHECK-NEXT: ('st_shndx', 0x00000001) +// CHECK-NEXT: ('st_value', 0x00000018) +// CHECK-NEXT: ('st_size', 0x00000000) +// CHECK-NEXT: ), +// CHECK-NEXT: # Symbol 0x00000002 +// CHECK-NEXT: (('st_name', 0x0000001a) # 'bar7' +// CHECK-NEXT: ('st_bind', 0x00000000) +// CHECK-NEXT: ('st_type', 0x00000000) +// CHECK-NEXT: ('st_other', 0x00000000) +// CHECK-NEXT: ('st_shndx', 0x00000001) +// CHECK-NEXT: ('st_value', 0x00000018) +// CHECK-NEXT: ('st_size', 0x00000000) +// CHECK-NEXT: ), +// CHECK-NEXT: # Symbol 0x00000003 +// CHECK-NEXT: (('st_name', 0x0000001f) # 'bar8' +// CHECK-NEXT: ('st_bind', 0x00000000) +// CHECK-NEXT: ('st_type', 0x00000000) +// CHECK-NEXT: ('st_other', 0x00000000) +// CHECK-NEXT: ('st_shndx', 0x00000001) +// CHECK-NEXT: ('st_value', 0x0000001c) +// CHECK-NEXT: ('st_size', 0x00000000) +// CHECK-NEXT: ), +// CHECK-NEXT: # Symbol 0x00000004 +// CHECK-NEXT: (('st_name', 0x00000024) # 'bar9' +// CHECK-NEXT: ('st_bind', 0x00000000) +// CHECK-NEXT: ('st_type', 0x00000000) +// CHECK-NEXT: ('st_other', 0x00000000) +// CHECK-NEXT: ('st_shndx', 0x00000001) +// CHECK-NEXT: ('st_value', 0x00000020) +// CHECK-NEXT: ('st_size', 0x00000000) +// CHECK-NEXT: ), +// CHECK-NEXT: # Symbol 0x00000005 +// CHECK-NEXT: (('st_name', 0x00000000) # '' +// CHECK-NEXT: ('st_bind', 0x00000000) +// CHECK-NEXT: ('st_type', 0x00000003) +// CHECK-NEXT: ('st_other', 0x00000000) +// CHECK-NEXT: ('st_shndx', 0x00000001) +// CHECK-NEXT: ('st_value', 0x00000000) +// CHECK-NEXT: ('st_size', 0x00000000) +// CHECK-NEXT: ), +// CHECK-NEXT: # Symbol 0x00000006 +// CHECK-NEXT: (('st_name', 0x00000000) # '' +// CHECK-NEXT: ('st_bind', 0x00000000) +// CHECK-NEXT: ('st_type', 0x00000003) +// CHECK-NEXT: ('st_other', 0x00000000) +// CHECK-NEXT: ('st_shndx', 0x00000002) +// CHECK-NEXT: ('st_value', 0x00000000) +// CHECK-NEXT: ('st_size', 0x00000000) +// CHECK-NEXT: ), +// CHECK-NEXT: # Symbol 0x00000007 +// CHECK-NEXT: (('st_name', 0x00000000) # '' +// CHECK-NEXT: ('st_bind', 0x00000000) +// CHECK-NEXT: ('st_type', 0x00000003) +// CHECK-NEXT: ('st_other', 0x00000000) +// CHECK-NEXT: ('st_shndx', 0x00000003) +// CHECK-NEXT: ('st_value', 0x00000000) +// CHECK-NEXT: ('st_size', 0x00000000) +// CHECK-NEXT: ), +// CHECK-NEXT: # Symbol 0x00000008 +// CHECK-NEXT: (('st_name', 0x00000029) # 'bar10' +// CHECK-NEXT: ('st_bind', 0x00000001) +// CHECK-NEXT: ('st_type', 0x00000000) +// CHECK-NEXT: ('st_other', 0x00000000) +// CHECK-NEXT: ('st_shndx', 0x00000001) +// CHECK-NEXT: ('st_value', 0x00000028) +// CHECK-NEXT: ('st_size', 0x00000000) +// CHECK-NEXT: ), +// CHECK-NEXT: # Symbol 0x00000009 +// CHECK-NEXT: (('st_name', 0x0000002f) # 'bar11' +// CHECK-NEXT: ('st_bind', 0x00000001) +// CHECK-NEXT: ('st_type', 0x00000000) +// CHECK-NEXT: ('st_other', 0x00000000) +// CHECK-NEXT: ('st_shndx', 0x00000001) +// CHECK-NEXT: ('st_value', 0x00000030) +// CHECK-NEXT: ('st_size', 0x00000000) +// CHECK-NEXT: ), +// CHECK-NEXT: # Symbol 0x0000000a +// CHECK-NEXT: (('st_name', 0x00000035) # 'bar12' +// CHECK-NEXT: ('st_bind', 0x00000001) +// CHECK-NEXT: ('st_type', 0x00000000) +// CHECK-NEXT: ('st_other', 0x00000000) +// CHECK-NEXT: ('st_shndx', 0x00000001) +// CHECK-NEXT: ('st_value', 0x00000030) +// CHECK-NEXT: ('st_size', 0x00000000) +// CHECK-NEXT: ), +// CHECK-NEXT: # Symbol 0x0000000b +// CHECK-NEXT: (('st_name', 0x0000003b) # 'bar13' +// CHECK-NEXT: ('st_bind', 0x00000001) +// CHECK-NEXT: ('st_type', 0x00000000) +// CHECK-NEXT: ('st_other', 0x00000000) +// CHECK-NEXT: ('st_shndx', 0x00000001) +// CHECK-NEXT: ('st_value', 0x00000034) +// CHECK-NEXT: ('st_size', 0x00000000) +// CHECK-NEXT: ), +// CHECK-NEXT: # Symbol 0x0000000c +// CHECK-NEXT: (('st_name', 0x00000041) # 'bar14' +// CHECK-NEXT: ('st_bind', 0x00000001) +// CHECK-NEXT: ('st_type', 0x00000000) +// CHECK-NEXT: ('st_other', 0x00000000) +// CHECK-NEXT: ('st_shndx', 0x00000001) +// CHECK-NEXT: ('st_value', 0x00000038) +// CHECK-NEXT: ('st_size', 0x00000000) +// CHECK-NEXT: ), +// CHECK-NEXT: # Symbol 0x0000000d +// CHECK-NEXT: (('st_name', 0x00000047) # 'bar15' +// CHECK-NEXT: ('st_bind', 0x00000001) +// CHECK-NEXT: ('st_type', 0x00000000) +// CHECK-NEXT: ('st_other', 0x00000000) +// CHECK-NEXT: ('st_shndx', 0x00000001) +// CHECK-NEXT: ('st_value', 0x00000040) +// CHECK-NEXT: ('st_size', 0x00000000) +// CHECK-NEXT: ), +// CHECK-NEXT: # Symbol 0x0000000e +// CHECK-NEXT: (('st_name', 0x00000001) # 'bar2' +// CHECK-NEXT: ('st_bind', 0x00000001) +// CHECK-NEXT: ('st_type', 0x00000000) +// CHECK-NEXT: ('st_other', 0x00000000) +// CHECK-NEXT: ('st_shndx', 0x00000000) +// CHECK-NEXT: ('st_value', 0x00000000) +// CHECK-NEXT: ('st_size', 0x00000000) +// CHECK-NEXT: ), +// CHECK-NEXT: # Symbol 0x0000000f +// CHECK-NEXT: (('st_name', 0x00000006) # 'bar3' +// CHECK-NEXT: ('st_bind', 0x00000002) +// CHECK-NEXT: ('st_type', 0x00000000) +// CHECK-NEXT: ('st_other', 0x00000000) +// CHECK-NEXT: ('st_shndx', 0x00000000) +// CHECK-NEXT: ('st_value', 0x00000000) +// CHECK-NEXT: ('st_size', 0x00000000) +// CHECK-NEXT: ), +// CHECK-NEXT: # Symbol 0x00000010 +// CHECK-NEXT: (('st_name', 0x0000000b) # 'bar4' +// CHECK-NEXT: ('st_bind', 0x00000001) +// CHECK-NEXT: ('st_type', 0x00000000) +// CHECK-NEXT: ('st_other', 0x00000000) +// CHECK-NEXT: ('st_shndx', 0x00000000) +// CHECK-NEXT: ('st_value', 0x00000000) +// CHECK-NEXT: ('st_size', 0x00000000) +// CHECK-NEXT: ), +// CHECK-NEXT: # Symbol 0x00000011 +// CHECK-NEXT: (('st_name', 0x00000010) # 'bar5' +// CHECK-NEXT: ('st_bind', 0x00000001) +// CHECK-NEXT: ('st_type', 0x00000000) +// CHECK-NEXT: ('st_other', 0x00000000) +// CHECK-NEXT: ('st_shndx', 0x00000000) +// CHECK-NEXT: ('st_value', 0x00000000) +// CHECK-NEXT: ('st_size', 0x00000000) +// CHECK-NEXT: ), +// CHECK-NEXT: ])