diff --git a/llvm/test/tools/llvm-readobj/ELF/stack-sizes.test b/llvm/test/tools/llvm-readobj/ELF/stack-sizes.test --- a/llvm/test/tools/llvm-readobj/ELF/stack-sizes.test +++ b/llvm/test/tools/llvm-readobj/ELF/stack-sizes.test @@ -92,27 +92,35 @@ Binding: STB_GLOBAL ## Check that we correctly report the stack sizes in an executable (non-relocatable) -## object file. +## object file. This also shows that the sh_link field is ignored in this situation +## without warning. # RUN: yaml2obj --docnum=2 %s -o %t02 -# RUN: llvm-readelf --stack-sizes %t02 \ -# RUN: | FileCheck %s --check-prefix=EXEC-GNU --strict-whitespace --match-full-lines -# RUN: llvm-readobj --stack-sizes %t02 | FileCheck %s --check-prefix=EXEC-LLVM +# RUN: llvm-readelf --stack-sizes %t02 2>&1 \ +# RUN: | FileCheck %s --check-prefix=EXEC-GNU --strict-whitespace \ +# RUN: --match-full-lines --implicit-check-not=warning +# RUN: llvm-readobj --stack-sizes %t02 2>&1 \ +# RUN: | FileCheck %s --check-prefix=EXEC-LLVM --implicit-check-not=warning # EXEC-GNU: Size Function -# EXEC-GNU-NEXT: 16 foo -# EXEC-GNU-NEXT: 32 bar +# EXEC-GNU-NEXT: 16 other +# EXEC-GNU-NEXT: 32 other_end +# EXEC-GNU-NEXT: 48 bar # EXEC-GNU-NOT:{{.}} # EXEC-LLVM: StackSizes [ # EXEC-LLVM-NEXT: Entry { -# EXEC-LLVM-NEXT: Function: foo +# EXEC-LLVM-NEXT: Function: other # EXEC-LLVM-NEXT: Size: 0x10 # EXEC-LLVM-NEXT: } # EXEC-LLVM-NEXT: Entry { -# EXEC-LLVM-NEXT: Function: bar +# EXEC-LLVM-NEXT: Function: other_end # EXEC-LLVM-NEXT: Size: 0x20 # EXEC-LLVM-NEXT: } +# EXEC-LLVM-NEXT: Entry { +# EXEC-LLVM-NEXT: Function: bar +# EXEC-LLVM-NEXT: Size: 0x30 +# EXEC-LLVM-NEXT: } # EXEC-LLVM-NEXT: ] --- !ELF @@ -126,22 +134,45 @@ Type: SHT_PROGBITS Flags: [SHF_ALLOC] Size: 16 + - Name: .text2 + Type: SHT_PROGBITS + Flags: [SHF_ALLOC] + Size: 16 - Name: .stack_sizes Type: SHT_PROGBITS Entries: - - Address: 0x10 + - Address: 0x0 Size: 0x10 - - Address: 0x20 + - Address: 0x10 Size: 0x20 - Link: .text + - Address: 0x20 + Size: 0x30 + Link: .text2 Symbols: - - Name: foo + ## Undefined symbols are ignored. + - Name: undefined + Type: STT_FUNC + Binding: STB_GLOBAL + ## sh_link of .stack_sizes is ignored for non-reloctable objects. + - Name: other + Section: .text + Value: 0 + Type: STT_FUNC + Binding: STB_GLOBAL + ## If two symbols have the same value, the first is picked, regardless of + ## the sh_link value of the .stack_sizes section. + - Name: other_end Section: .text Value: 0x10 Type: STT_FUNC Binding: STB_GLOBAL + - Name: foo + Section: .text2 + Value: 0x10 + Type: STT_FUNC + Binding: STB_GLOBAL - Name: bar - Section: .text + Section: .text2 Value: 0x20 Type: STT_FUNC Binding: STB_GLOBAL @@ -184,7 +215,8 @@ Binding: STB_GLOBAL ## Check that we warn about a function symbol that is not in the section -## that is referenced by the stack sizes section's sh_link. +## that is referenced by the stack sizes section's sh_link, for relocatable +## output. # RUN: yaml2obj --docnum=4 %s -o %t04 # RUN: llvm-readelf --stack-sizes %t04 2> %t04-gnu.err | FileCheck %s --check-prefix=WRONGSECTION-GNU @@ -437,18 +469,23 @@ # MULTIPLE-GNU-EMPTY: # MULTIPLE-GNU-NEXT:Stack Sizes: # MULTIPLE-GNU-NEXT: Size Function -# MULTIPLE-GNU-NEXT: 16 foo -# MULTIPLE-GNU-NEXT: 32 bar +# MULTIPLE-GNU-NEXT: 16 other +# MULTIPLE-GNU-NEXT: 32 other_end +# MULTIPLE-GNU-NEXT: 48 bar # MULTIPLE-LLVM: StackSizes [ # MULTIPLE-LLVM-NEXT: Entry { -# MULTIPLE-LLVM-NEXT: Function: foo +# MULTIPLE-LLVM-NEXT: Function: other # MULTIPLE-LLVM-NEXT: Size: 0x10 # MULTIPLE-LLVM-NEXT: } # MULTIPLE-LLVM-NEXT: Entry { -# MULTIPLE-LLVM-NEXT: Function: bar +# MULTIPLE-LLVM-NEXT: Function: other_end # MULTIPLE-LLVM-NEXT: Size: 0x20 # MULTIPLE-LLVM-NEXT: } +# MULTIPLE-LLVM-NEXT: Entry { +# MULTIPLE-LLVM-NEXT: Function: bar +# MULTIPLE-LLVM-NEXT: Size: 0x30 +# MULTIPLE-LLVM-NEXT: } # MULTIPLE-LLVM-NEXT: ] ## Check that we do not consider symbols that are not function symbols, even though diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -754,7 +754,7 @@ void printRelocatableStackSizes(const ELFObjectFile *Obj, std::function PrintHeader); void printFunctionStackSize(const ELFObjectFile *Obj, uint64_t SymValue, - SectionRef FunctionSec, + Optional FunctionSec, const StringRef SectionName, DataExtractor Data, uint64_t *Offset); void printStackSize(const ELFObjectFile *Obj, RelocationRef Rel, @@ -5204,9 +5204,12 @@ } template -void DumpStyle::printFunctionStackSize( - const ELFObjectFile *Obj, uint64_t SymValue, SectionRef FunctionSec, - const StringRef SectionName, DataExtractor Data, uint64_t *Offset) { +void DumpStyle::printFunctionStackSize(const ELFObjectFile *Obj, + uint64_t SymValue, + Optional FunctionSec, + const StringRef SectionName, + DataExtractor Data, + uint64_t *Offset) { // This function ignores potentially erroneous input, unless it is directly // related to stack size reporting. SymbolRef FuncSym; @@ -5216,9 +5219,15 @@ consumeError(SymAddrOrErr.takeError()); continue; } + if (Expected SymFlags = Symbol.getFlags()) { + if (*SymFlags & SymbolRef::SF_Undefined) + continue; + } else + consumeError(SymFlags.takeError()); if (Symbol.getELFType() == ELF::STT_FUNC && *SymAddrOrErr == SymValue) { - // Check if the symbol is in the right section. - if (FunctionSec.containsSymbol(Symbol)) { + // Check if the symbol is in the right section. FunctionSec == None means + // "any section". + if (!FunctionSec || FunctionSec->containsSymbol(Symbol)) { FuncSym = Symbol; break; } @@ -5329,11 +5338,6 @@ ArrayRef Contents = unwrapOrError(this->FileName, EF->getSectionContents(ElfSec)); DataExtractor Data(Contents, Obj->isLittleEndian(), sizeof(Elf_Addr)); - // A .stack_sizes section header's sh_link field is supposed to point - // to the section that contains the functions whose stack sizes are - // described in it. - const Elf_Shdr *FunctionELFSec = - unwrapOrError(this->FileName, EF->getSection(ElfSec->sh_link)); uint64_t Offset = 0; while (Offset < Contents.size()) { // The function address is followed by a ULEB representing the stack @@ -5347,8 +5351,8 @@ FileStr); } uint64_t SymValue = Data.getAddress(&Offset); - printFunctionStackSize(Obj, SymValue, Obj->toSectionRef(FunctionELFSec), - SectionName, Data, &Offset); + printFunctionStackSize(Obj, SymValue, /*FunctionSec=*/None, SectionName, + Data, &Offset); } } }