Index: llvm/include/llvm/Object/ELFObjectFile.h =================================================================== --- llvm/include/llvm/Object/ELFObjectFile.h +++ llvm/include/llvm/Object/ELFObjectFile.h @@ -56,6 +56,7 @@ virtual uint16_t getEMachine() const = 0; virtual uint64_t getSymbolSize(DataRefImpl Symb) const = 0; + virtual uint8_t getSymbolBinding(DataRefImpl Symb) const = 0; virtual uint8_t getSymbolOther(DataRefImpl Symb) const = 0; virtual uint8_t getSymbolELFType(DataRefImpl Symb) const = 0; @@ -145,6 +146,10 @@ return getObject()->getSymbolSize(getRawDataRefImpl()); } + uint8_t getBinding() const { + return getObject()->getSymbolBinding(getRawDataRefImpl()); + } + uint8_t getOther() const { return getObject()->getSymbolOther(getRawDataRefImpl()); } @@ -252,6 +257,7 @@ uint32_t getSymbolAlignment(DataRefImpl Symb) const override; uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override; + uint8_t getSymbolBinding(DataRefImpl Symb) const override; uint8_t getSymbolOther(DataRefImpl Symb) const override; uint8_t getSymbolELFType(DataRefImpl Symb) const override; Expected getSymbolType(DataRefImpl Symb) const override; @@ -554,6 +560,11 @@ } template +uint8_t ELFObjectFile::getSymbolBinding(DataRefImpl Symb) const { + return getSymbol(Symb)->getBinding(); +} + +template uint8_t ELFObjectFile::getSymbolOther(DataRefImpl Symb) const { return getSymbol(Symb)->st_other; } Index: llvm/test/tools/llvm-nm/X86/unique_alloc.test =================================================================== --- /dev/null +++ llvm/test/tools/llvm-nm/X86/unique_alloc.test @@ -0,0 +1,20 @@ +## Check that we print 'u' for unique symbols. +# RUN: yaml2obj < %s | llvm-nm - | FileCheck %s + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .data + Type: SHT_PROGBITS + Flags: [SHF_ALLOC] +Symbols: + - Name: foo + Section: .data + Binding: STB_GNU_UNIQUE +... + +# CHECK: 0000000000000000 u foo Index: llvm/test/tools/llvm-nm/X86/unique_alloc_write.test =================================================================== --- /dev/null +++ llvm/test/tools/llvm-nm/X86/unique_alloc_write.test @@ -0,0 +1,20 @@ +## Check that we print 'u' for unique symbols. +# RUN: yaml2obj < %s | llvm-nm - | FileCheck %s + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .data + Type: SHT_PROGBITS + Flags: [SHF_ALLOC, SHF_WRITE] +Symbols: + - Name: foo + Section: .data + Binding: STB_GNU_UNIQUE +... + +# CHECK: 0000000000000000 u foo Index: llvm/test/tools/llvm-nm/X86/unique_execinstr.test =================================================================== --- /dev/null +++ llvm/test/tools/llvm-nm/X86/unique_execinstr.test @@ -0,0 +1,20 @@ +## Check that we print 'u' for unique symbols. +# RUN: yaml2obj < %s | llvm-nm - | FileCheck %s + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .data + Type: SHT_PROGBITS + Flags: [SHF_EXECINSTR] +Symbols: + - Name: foo + Section: .data + Binding: STB_GNU_UNIQUE +... + +# CHECK: 0000000000000000 u foo Index: llvm/test/tools/llvm-nm/X86/unique_nobits.test =================================================================== --- /dev/null +++ llvm/test/tools/llvm-nm/X86/unique_nobits.test @@ -0,0 +1,19 @@ +## Check that we print 'u' for unique symbols. +# RUN: yaml2obj < %s | llvm-nm - | FileCheck %s + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .data + Type: SHT_NOBITS +Symbols: + - Name: foo + Section: .data + Binding: STB_GNU_UNIQUE +... + +# CHECK: 0000000000000000 u foo Index: llvm/test/tools/llvm-nm/X86/unique_progbits.test =================================================================== --- /dev/null +++ llvm/test/tools/llvm-nm/X86/unique_progbits.test @@ -0,0 +1,19 @@ +## Check that we print 'u' for unique symbols. +# RUN: yaml2obj < %s | llvm-nm - | FileCheck %s + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .data + Type: SHT_PROGBITS +Symbols: + - Name: foo + Section: .data + Binding: STB_GNU_UNIQUE +... + +# CHECK: 0000000000000000 u foo Index: llvm/tools/llvm-nm/llvm-nm.cpp =================================================================== --- llvm/tools/llvm-nm/llvm-nm.cpp +++ llvm/tools/llvm-nm/llvm-nm.cpp @@ -903,6 +903,9 @@ if (SecI != Obj.section_end()) { uint32_t Type = SecI->getType(); uint64_t Flags = SecI->getFlags(); + uint8_t Binding = SymI->getBinding(); + if (Binding == ELF::STB_GNU_UNIQUE) + return 'u'; if (Flags & ELF::SHF_EXECINSTR) return 't'; if (Type == ELF::SHT_NOBITS) @@ -1124,10 +1127,13 @@ else Ret = getSymbolNMTypeChar(cast(Obj), I); - if (Symflags & object::SymbolRef::SF_Global) - Ret = toupper(Ret); + if (!(Symflags & object::SymbolRef::SF_Global)) + return Ret; + + if (Obj.isELF() && ELFSymbolRef(*I).getBinding() == ELF::STB_GNU_UNIQUE) + return Ret; - return Ret; + return toupper(Ret); } // getNsectForSegSect() is used to implement the Mach-O "-s segname sectname"