Index: llvm/include/llvm/Object/ELFObjectFile.h =================================================================== --- llvm/include/llvm/Object/ELFObjectFile.h +++ llvm/include/llvm/Object/ELFObjectFile.h @@ -78,6 +78,9 @@ public: using elf_symbol_iterator_range = iterator_range; + // As getSymbolAddress, but do not mask the Thumb bit or microMips indicator. + virtual Expected getRawSymbolAddress(DataRefImpl Symb) const = 0; + virtual elf_symbol_iterator_range getDynamicSymbolIterators() const = 0; /// Returns platform-specific object flags, if any. @@ -285,6 +288,7 @@ Expected getSymbolType(DataRefImpl Symb) const override; Expected getSymbolSection(const Elf_Sym *Symb, const Elf_Shdr *SymTab) const; + Expected getSectionAddressFromSymbol(DataRefImpl Symb) const; Expected getSymbolSection(DataRefImpl Symb) const override; void moveSectionNext(DataRefImpl &Sec) const override; @@ -438,6 +442,8 @@ section_iterator section_begin() const override; section_iterator section_end() const override; + Expected getRawSymbolAddress(DataRefImpl Symb) const override; + Expected getRelocationAddend(DataRefImpl Rel) const override; uint8_t getBytesInAddress() const override; @@ -585,6 +591,49 @@ return Result; } + auto SectionAddressOrError = getSectionAddressFromSymbol(Symb); + if (!SectionAddressOrError) + // TODO: Test this error. + return SectionAddressOrError.takeError(); + + return Result + *SectionAddressOrError; +} + +template +Expected +ELFObjectFile::getRawSymbolAddress(DataRefImpl Symb) const { + uint64_t Result; + uint32_t Flags; + if (Error E = getSymbolFlags(Symb).moveInto(Flags)) + return std::move(E); + if (Flags & SymbolRef::SF_Undefined) + Result = 0; + if (Flags & SymbolRef::SF_Common) + Result = getCommonSymbolSize(Symb); + Expected SymOrErr = getSymbol(Symb); + if (!SymOrErr) + // TODO: Test this error. + return SymOrErr.takeError(); + Result = (*SymOrErr)->st_value; + + switch ((*SymOrErr)->st_shndx) { + case ELF::SHN_COMMON: + case ELF::SHN_UNDEF: + case ELF::SHN_ABS: + return Result; + } + + auto SectionAddressOrError = getSectionAddressFromSymbol(Symb); + if (!SectionAddressOrError) + // TODO: Test this error. + return SectionAddressOrError.takeError(); + + return Result + *SectionAddressOrError; +} + +template +Expected +ELFObjectFile::getSectionAddressFromSymbol(DataRefImpl Symb) const { auto SymTabOrErr = EF.getSection(Symb.d.a); if (!SymTabOrErr) return SymTabOrErr.takeError(); @@ -599,6 +648,9 @@ else return ShndxTableOrErr.takeError(); } + Expected SymOrErr = getSymbol(Symb); + if (!SymOrErr) + return SymOrErr.takeError(); Expected SectionOrErr = EF.getSection(**SymOrErr, *SymTabOrErr, ShndxTable); @@ -606,10 +658,9 @@ return SectionOrErr.takeError(); const Elf_Shdr *Section = *SectionOrErr; if (Section) - Result += Section->sh_addr; + return Section->sh_addr; } - - return Result; + return 0; } template Index: llvm/test/tools/llvm-nm/ARM/address-check.test =================================================================== --- /dev/null +++ llvm/test/tools/llvm-nm/ARM/address-check.test @@ -0,0 +1,28 @@ +## Test for function type symbols with odd valued address to reflect raw value +## on ARM when --print-raw-values is used +# +# RUN: yaml2obj %s -o %t +# RUN: llvm-nm %t | FileCheck %s +# RUN: llvm-nm %t --print-raw-values | FileCheck %s --check-prefix=CHECKRAW + +!ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_ARM + Flags: [ EF_ARM_EABI_VER5 ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x4 +Symbols: + - Name: foo + Value: 0x1003 + Section: .text + Type: STT_FUNC + Binding: STB_GLOBAL + +# CHECK: 00001002 T foo +# CHECKRAW: 00001003 T foo Index: llvm/test/tools/llvm-nm/ARM/address-sort.test =================================================================== --- /dev/null +++ llvm/test/tools/llvm-nm/ARM/address-sort.test @@ -0,0 +1,35 @@ +## Test for function type symbols with odd valued address to reflect raw value +## on ARM when --print-raw-values is used along with --numeric-sort +# +# RUN: yaml2obj %s -o %t +# RUN: llvm-nm %t --numeric-sort | FileCheck %s +# RUN: llvm-nm %t --print-raw-values --numeric-sort | FileCheck %s --check-prefix=CHECKRAW + +!ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_ARM + Flags: [ EF_ARM_EABI_VER5 ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x4 +Symbols: + - Name: foo + Value: 0x1003 + Section: .text + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: bar + Value: 0x1002 + Section: .text + Type: STT_FUNC + Binding: STB_GLOBAL + +# CHECK-DAG: 00001002 T foo +# CHECK-DAG: 00001002 T bar +# CHECKRAW-DAG: 00001003 T foo +# CHECKRAW-DAG: 00001002 T bar Index: llvm/tools/llvm-nm/Opts.td =================================================================== --- llvm/tools/llvm-nm/Opts.td +++ llvm/tools/llvm-nm/Opts.td @@ -55,6 +55,9 @@ def no_rsrc : FF<"no-rsrc", "Exclude resource file symbols (__rsrc) from the export symbol list.">, Group; +// ARM and microMIPS specific option. +def print_raw_values: FF<"print-raw-values", "Print raw values for symbols">; + def : FF<"just-symbol-name", "Alias for --format=just-symbols">, Alias, AliasArgs<["just-symbols"]>, Flags<[HelpHidden]>; def : FF<"portability", "Alias for --format=posix">, Alias, AliasArgs<["posix"]>; Index: llvm/tools/llvm-nm/llvm-nm.cpp =================================================================== --- llvm/tools/llvm-nm/llvm-nm.cpp +++ llvm/tools/llvm-nm/llvm-nm.cpp @@ -130,6 +130,9 @@ static std::vector SegSect; static bool MachOPrintSizeWarning = false; +// ARM and microMIPS specific option. +static bool PrintRawValues = false; + // Miscellaneous states. static bool PrintAddress = true; static bool MultipleFiles = false; @@ -1827,7 +1830,10 @@ if (PrintAddress && isa(Obj)) { SymbolRef SymRef(Sym); - Expected AddressOrErr = SymRef.getAddress(); + Expected AddressOrErr = + PrintRawValues && ELFObj + ? ELFObj->getRawSymbolAddress(Sym.getRawDataRefImpl()) + : SymRef.getAddress(); if (!AddressOrErr) { consumeError(AddressOrErr.takeError()); break; @@ -2352,6 +2358,7 @@ PrintSize = Args.hasArg(OPT_print_size); ReverseSort = Args.hasArg(OPT_reverse_sort); ExportSymbols = Args.hasArg(OPT_export_symbols); + PrintRawValues = Args.hasArg(OPT_print_raw_values); if (ExportSymbols) { ExternalOnly = true; DefinedOnly = true;