diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index ac8c250a833..fb0518b2ec4 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -58,6 +58,14 @@ static void SetBinding(MCSymbolData &SD, unsigned Binding) { SD.setFlags(OtherFlags | (Binding << ELF_STB_Shift)); } +static unsigned GetVisibility(MCSymbolData &SD) { + unsigned Visibility = + (SD.getFlags() & (0xf << ELF_STV_Shift)) >> ELF_STV_Shift; + assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL || + Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED); + return Visibility; +} + static bool isFixupKindX86PCRel(unsigned Kind) { switch (Kind) { default: @@ -429,9 +437,23 @@ static uint64_t SymbolValue(MCSymbolData &Data, const MCAsmLayout &Layout) { void ELFObjectWriterImpl::WriteSymbol(MCDataFragment *F, ELFSymbolData &MSD, const MCAsmLayout &Layout) { - MCSymbolData &Data = *MSD.SymbolData; - uint8_t Info = (Data.getFlags() & 0xff); - uint8_t Other = ((Data.getFlags() & 0xf00) >> ELF_STV_Shift); + MCSymbolData &OrigData = *MSD.SymbolData; + MCSymbolData *AliasData = NULL; + if (OrigData.Symbol->isVariable()) { + const MCExpr *Value = OrigData.getSymbol().getVariableValue(); + assert (Value->getKind() == MCExpr::SymbolRef && "Unimplemented"); + const MCSymbolRefExpr *Ref = static_cast(Value); + AliasData = &Layout.getAssembler().getSymbolData(Ref->getSymbol()); + } + MCSymbolData &Data = AliasData ? *AliasData : OrigData; + + uint8_t Binding = GetBinding(OrigData); + uint8_t Visibility = GetVisibility(OrigData); + uint8_t Type = GetType(Data); + + uint8_t Info = (Binding << ELF_STB_Shift) | (Type << ELF_STT_Shift); + uint8_t Other = Visibility; + uint64_t Value = SymbolValue(Data, Layout); uint64_t Size = 0; const MCExpr *ESize; diff --git a/test/MC/ELF/alias.s b/test/MC/ELF/alias.s index 0f6cce1ca1f..4a30e496a1f 100644 --- a/test/MC/ELF/alias.s +++ b/test/MC/ELF/alias.s @@ -10,6 +10,11 @@ foo3: .globl bar3 bar3 = foo3 +// Test that bar4 is also a function + .type foo4,@function +foo4: +bar4 = foo4 + // CHECK: # Symbol 1 // CHECK-NEXT: (('st_name', 5) # 'bar' // CHECK-NEXT: ('st_bind', 0) @@ -20,6 +25,15 @@ bar3 = foo3 // CHECK-NEXT: ('st_size', 0) // CHECK-NEXT: ), // CHECK-NEXT: # Symbol 2 +// CHECK-NEXT: (('st_name', 19) # 'bar4' +// CHECK-NEXT: ('st_bind', 0) +// CHECK-NEXT: ('st_type', 2) +// CHECK-NEXT: ('st_other', 0) +// CHECK-NEXT: ('st_shndx', 1) +// CHECK-NEXT: ('st_value', 0) +// CHECK-NEXT: ('st_size', 0) +// CHECK-NEXT: ), +// CHECK-NEXT: # Symbol 3 // CHECK-NEXT: (('st_name', 1) # 'foo' // CHECK-NEXT: ('st_bind', 0) // CHECK-NEXT: ('st_type', 0) @@ -27,7 +41,8 @@ bar3 = foo3 // CHECK-NEXT: ('st_shndx', 1) // CHECK-NEXT: ('st_value', 0) // CHECK-NEXT: ('st_size', 0) -// CHECK: # Symbol 3 +// CHECK-NEXT: ), +// CHECK-NEXT: # Symbol 4 // CHECK-NEXT: (('st_name', 9) # 'foo3' // CHECK-NEXT: ('st_bind', 0) // CHECK-NEXT: ('st_type', 0) @@ -35,22 +50,32 @@ bar3 = foo3 // CHECK-NEXT: ('st_shndx', 1) // CHECK-NEXT: ('st_value', 0) // CHECK-NEXT: ('st_size', 0) -// CHECK: # Symbol 4 -// CHECK-NEXT: (('st_name', 0) # '' -// CHECK: # Symbol 5 -// CHECK-NEXT: (('st_name', 0) # '' -// CHECK: # Symbol 6 -// CHECK-NEXT: (('st_name', 0) # '' +// CHECK-NEXT: ), +// CHECK-NEXT: # Symbol 5 +// CHECK-NEXT: (('st_name', 14) # 'foo4' +// CHECK-NEXT: ('st_bind', 0) +// CHECK-NEXT: ('st_type', 2) +// CHECK-NEXT: ('st_other', 0) +// CHECK-NEXT: ('st_shndx', 1) +// CHECK-NEXT: ('st_value', 0) +// CHECK-NEXT: ('st_size', 0) +// CHECK-NEXT: ), +// CHECK-NEXT: # Symbol 6 +// CHECK-NEXT: (('st_name', 0) # '' // CHECK: # Symbol 7 -// CHECK-NEXT: (('st_name', 24) # 'bar3' +// CHECK-NEXT: (('st_name', 0) # '' +// CHECK: # Symbol 8 +// CHECK-NEXT: (('st_name', 0) # '' +// CHECK: # Symbol 9 +// CHECK-NEXT: (('st_name', 34) # 'bar3' // CHECK-NEXT: ('st_bind', 1) // CHECK-NEXT: ('st_type', 0) // CHECK-NEXT: ('st_other', 0) // CHECK-NEXT: ('st_shndx', 1) // CHECK-NEXT: ('st_value', 0) // CHECK-NEXT: ('st_size', 0) -// CHECK: # Symbol 8 -// CHECK-NEXT: (('st_name', 19) # 'bar2' +// CHECK: # Symbol 10 +// CHECK-NEXT: (('st_name', 29) # 'bar2' // CHECK-NEXT: ('st_bind', 1) // CHECK-NEXT: ('st_type', 0) // CHECK-NEXT: ('st_other', 0)