diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2010-09-23 19:55:14 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2010-09-23 19:55:14 +0000 |
commit | e15eb4e14cd543b925a837026cbdde9f94393e1c (patch) | |
tree | 465078356955175e24249963efeebc2b8070a404 | |
parent | b2dda4bd346fe9a2795f83f659c0e60191b2e6a0 (diff) |
Correctly handle weak undefined symbols. Before we would get a invalid binding
(2 == STB_WEAK | STB_GLOBAL).
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@114690 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/MC/ELFObjectWriter.cpp | 25 | ||||
-rw-r--r-- | test/MC/ELF/weak.s | 14 |
2 files changed, 34 insertions, 5 deletions
diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index 587489c26b..9eb9bcac46 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -43,6 +43,20 @@ static unsigned GetType(const MCSymbolData &SD) { return Type; } +static unsigned GetBinding(const MCSymbolData &SD) { + uint32_t Binding = (SD.getFlags() & (0xf << ELF_STB_Shift)) >> ELF_STB_Shift; + assert(Binding == ELF::STB_LOCAL || Binding == ELF::STB_GLOBAL || + Binding == ELF::STB_WEAK); + return Binding; +} + +static void SetBinding(MCSymbolData &SD, unsigned Binding) { + assert(Binding == ELF::STB_LOCAL || Binding == ELF::STB_GLOBAL || + Binding == ELF::STB_WEAK); + uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STB_Shift); + SD.setFlags(OtherFlags | (Binding << ELF_STB_Shift)); +} + namespace { class ELFObjectWriterImpl { @@ -460,16 +474,15 @@ void ELFObjectWriterImpl::WriteSymbolTable(MCDataFragment *F, assert((Data.getFlags() & ELF_STB_Global) && "External symbol requires STB_GLOBAL flag"); WriteSymbol(F, MSD, Layout); - if ((Data.getFlags() & (0xf << ELF_STB_Shift)) == ELF_STB_Local) + if (GetBinding(Data) == ELF::STB_LOCAL) LastLocalSymbolIndex++; } for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) { ELFSymbolData &MSD = UndefinedSymbolData[i]; MCSymbolData &Data = *MSD.SymbolData; - Data.setFlags(Data.getFlags() | ELF_STB_Global); WriteSymbol(F, MSD, Layout); - if ((Data.getFlags() & (0xf << ELF_STB_Shift)) == ELF_STB_Local) + if (GetBinding(Data) == ELF::STB_LOCAL) LastLocalSymbolIndex++; } } @@ -682,8 +695,10 @@ void ELFObjectWriterImpl::ComputeSymbolTable(MCAssembler &Asm) { ExternalSymbolData.push_back(MSD); } else if (Symbol.isUndefined()) { MSD.SectionIndex = ELF::SHN_UNDEF; - // XXX: for some reason we dont Emit* this - it->setFlags(it->getFlags() | ELF_STB_Global); + // FIXME: Undefined symbols are global, but this is the first place we + // are able to set it. + if (GetBinding(*it) == ELF::STB_LOCAL) + SetBinding(*it, ELF::STB_GLOBAL); UndefinedSymbolData.push_back(MSD); } else if (Symbol.isAbsolute()) { MSD.SectionIndex = ELF::SHN_ABS; diff --git a/test/MC/ELF/weak.s b/test/MC/ELF/weak.s new file mode 100644 index 0000000000..ef8e000c60 --- /dev/null +++ b/test/MC/ELF/weak.s @@ -0,0 +1,14 @@ +// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | elf-dump | FileCheck %s + +// Test that this produces a weak undefined symbol. + + .weak foo + .long foo + +//CHECK: (('st_name', 1) # 'foo' +//CHECK-NEXT: ('st_bind', 2) +//CHECK-NEXT: ('st_type', 0) +//CHECK-NEXT: ('st_other', 0) +//CHECK-NEXT: ('st_shndx', 0) +//CHECK-NEXT: ('st_value', 0) +//CHECK-NEXT: ('st_size', 0) |