summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/Support/ELF.h1
-rw-r--r--llvm/lib/MC/MCELF.cpp4
-rw-r--r--llvm/lib/MC/MCELFStreamer.cpp8
-rw-r--r--llvm/test/MC/ELF/type.s12
-rw-r--r--llvm/tools/llvm-readobj/ELFDumper.cpp7
5 files changed, 25 insertions, 7 deletions
diff --git a/llvm/include/llvm/Support/ELF.h b/llvm/include/llvm/Support/ELF.h
index 3d49205fa16..ef7db394573 100644
--- a/llvm/include/llvm/Support/ELF.h
+++ b/llvm/include/llvm/Support/ELF.h
@@ -761,6 +761,7 @@ enum {
STB_LOCAL = 0, // Local symbol, not visible outside obj file containing def
STB_GLOBAL = 1, // Global symbol, visible to all object files being combined
STB_WEAK = 2, // Weak symbol, like global but lower-precedence
+ STB_GNU_UNIQUE = 10,
STB_LOOS = 10, // Lowest operating system-specific binding type
STB_HIOS = 12, // Highest operating system-specific binding type
STB_LOPROC = 13, // Lowest processor-specific binding type
diff --git a/llvm/lib/MC/MCELF.cpp b/llvm/lib/MC/MCELF.cpp
index 386c2099f2e..369063431fe 100644
--- a/llvm/lib/MC/MCELF.cpp
+++ b/llvm/lib/MC/MCELF.cpp
@@ -21,7 +21,7 @@ namespace llvm {
void MCELF::SetBinding(MCSymbolData &SD, unsigned Binding) {
assert(Binding == ELF::STB_LOCAL || Binding == ELF::STB_GLOBAL ||
- Binding == ELF::STB_WEAK);
+ Binding == ELF::STB_WEAK || Binding == ELF::STB_GNU_UNIQUE);
uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STB_Shift);
SD.setFlags(OtherFlags | (Binding << ELF_STB_Shift));
}
@@ -29,7 +29,7 @@ void MCELF::SetBinding(MCSymbolData &SD, unsigned Binding) {
unsigned MCELF::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);
+ Binding == ELF::STB_WEAK || Binding == ELF::STB_GNU_UNIQUE);
return Binding;
}
diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp
index bdc4a8410fb..5cfcfe5874e 100644
--- a/llvm/lib/MC/MCELFStreamer.cpp
+++ b/llvm/lib/MC/MCELFStreamer.cpp
@@ -171,10 +171,16 @@ bool MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
return false;
case MCSA_NoDeadStrip:
- case MCSA_ELF_TypeGnuUniqueObject:
// Ignore for now.
break;
+ case MCSA_ELF_TypeGnuUniqueObject:
+ MCELF::SetType(SD, CombineSymbolTypes(MCELF::GetType(SD), ELF::STT_OBJECT));
+ MCELF::SetBinding(SD, ELF::STB_GNU_UNIQUE);
+ SD.setExternal(true);
+ BindingExplicitlySet.insert(Symbol);
+ break;
+
case MCSA_Global:
MCELF::SetBinding(SD, ELF::STB_GLOBAL);
SD.setExternal(true);
diff --git a/llvm/test/MC/ELF/type.s b/llvm/test/MC/ELF/type.s
index c82d3006cfe..f7745d88ea3 100644
--- a/llvm/test/MC/ELF/type.s
+++ b/llvm/test/MC/ELF/type.s
@@ -9,8 +9,8 @@ foo:
.type bar,@object
bar:
-// Test that gnu_unique_object is accepted.
.type zed,@gnu_unique_object
+zed:
obj:
.global obj
@@ -310,3 +310,13 @@ alias12:
// CHECK-NEXT: Other: 0
// CHECK-NEXT: Section: .text (0x1)
// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: zed (32)
+// CHECK-NEXT: Value: 0x0
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Unique (0xA)
+// CHECK-NEXT: Type: Object (0x1)
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text (0x1)
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index d68c78682d2..e4b760172a3 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -372,9 +372,10 @@ static const EnumEntry<unsigned> ElfMachineType[] = {
};
static const EnumEntry<unsigned> ElfSymbolBindings[] = {
- { "Local", ELF::STB_LOCAL },
- { "Global", ELF::STB_GLOBAL },
- { "Weak", ELF::STB_WEAK }
+ { "Local", ELF::STB_LOCAL },
+ { "Global", ELF::STB_GLOBAL },
+ { "Weak", ELF::STB_WEAK },
+ { "Unique", ELF::STB_GNU_UNIQUE }
};
static const EnumEntry<unsigned> ElfSymbolTypes[] = {
OpenPOWER on IntegriCloud