aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/MC/MCELFSymbolFlags.h11
-rw-r--r--include/llvm/MC/MCObjectStreamer.h1
-rw-r--r--include/llvm/MC/MCStreamer.h9
-rw-r--r--lib/MC/ELFObjectWriter.cpp17
-rw-r--r--lib/MC/MCAsmStreamer.cpp6
-rw-r--r--lib/MC/MCELFStreamer.cpp60
-rw-r--r--lib/MC/MCLoggingStreamer.cpp5
-rw-r--r--lib/MC/MCNullStreamer.cpp1
-rw-r--r--lib/MC/MCObjectStreamer.cpp5
-rw-r--r--lib/MC/MCParser/ELFAsmParser.cpp28
-rw-r--r--lib/MC/MCStreamer.cpp1
-rw-r--r--test/MC/ELF/weakref.s234
12 files changed, 372 insertions, 6 deletions
diff --git a/include/llvm/MC/MCELFSymbolFlags.h b/include/llvm/MC/MCELFSymbolFlags.h
index eb7978b18c..d798fb0772 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 6836ec52e1..61f4d51f0d 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 1f4f23de6f..53877b1add 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 850983fa1a..a0e326db28 100644
--- a/lib/MC/ELFObjectWriter.cpp
+++ b/lib/MC/ELFObjectWriter.cpp
@@ -143,6 +143,7 @@ namespace {
};
SmallPtrSet<const MCSymbol *, 16> UsedInReloc;
+ SmallPtrSet<const MCSymbol *, 16> WeakrefUsedInReloc;
DenseMap<const MCSymbol *, const MCSymbol *> Renames;
llvm::DenseMap<const MCSectionData*,
@@ -691,7 +692,7 @@ void ELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm,
Symbol = &AliasedSymbol(Target.getSymA()->getSymbol());
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 6c240cf414..ca8dc965f2 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 65a0a7d7e6..e794e57e93 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 761574545f..a907c11f11 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 b2db410c11..5f29b46d37 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 8a481e8bb3..3883f12152 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 62cf6c6e7a..9883018dd1 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 54071eba46..351d9fce4c 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 0000000000..212e2c3c52
--- /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: ])