[llvm] 86b093d - [llvm-readobj] Allow syms from all sections to match stack size entries

James Henderson via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 20 03:56:21 PDT 2020


Author: James Henderson
Date: 2020-03-20T10:54:18Z
New Revision: 86b093d1a18c1d4ccd3578e70e738a0f249ab19e

URL: https://github.com/llvm/llvm-project/commit/86b093d1a18c1d4ccd3578e70e738a0f249ab19e
DIFF: https://github.com/llvm/llvm-project/commit/86b093d1a18c1d4ccd3578e70e738a0f249ab19e.diff

LOG: [llvm-readobj] Allow syms from all sections to match stack size entries

Prior to this change, for non-relocatable objects llvm-readobj would
assume that all symbols that corresponded to a stack size section's
entries were in the section specified by the section's sh_link field.
In the presence of an output section description combining
SHF_LINK_ORDER sections linking different output sections, this cannot
be respected, since linker script section patterns are "by name" by
nature. Consequently, the sh_link value would not be correct for all
section entries.

This patch changes llvm-readobj to ignore the section of symbols in a
non-relocatable object.

Fixes https://bugs.llvm.org/show_bug.cgi?id=45228.

Reviewed by: grimar, MaskRay

Differential Revision: https://reviews.llvm.org/D76425

Added: 
    

Modified: 
    llvm/test/tools/llvm-readobj/ELF/stack-sizes.test
    llvm/tools/llvm-readobj/ELFDumper.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/tools/llvm-readobj/ELF/stack-sizes.test b/llvm/test/tools/llvm-readobj/ELF/stack-sizes.test
index d1f6dabdbf08..c315749ba425 100644
--- a/llvm/test/tools/llvm-readobj/ELF/stack-sizes.test
+++ b/llvm/test/tools/llvm-readobj/ELF/stack-sizes.test
@@ -92,27 +92,35 @@ Symbols:
     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 @@ Sections:
     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 @@ Symbols:
     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 @@ Sections:
 # 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
index 283f1b24020d..fe7ee7fa6048 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -752,7 +752,7 @@ template <typename ELFT> class DumpStyle {
   void printRelocatableStackSizes(const ELFObjectFile<ELFT> *Obj,
                                   std::function<void()> PrintHeader);
   void printFunctionStackSize(const ELFObjectFile<ELFT> *Obj, uint64_t SymValue,
-                              SectionRef FunctionSec,
+                              Optional<SectionRef> FunctionSec,
                               const StringRef SectionName, DataExtractor Data,
                               uint64_t *Offset);
   void printStackSize(const ELFObjectFile<ELFT> *Obj, RelocationRef Rel,
@@ -5174,9 +5174,12 @@ static std::string getSymbolName(const ELFSymbolRef &Sym) {
 }
 
 template <class ELFT>
-void DumpStyle<ELFT>::printFunctionStackSize(
-    const ELFObjectFile<ELFT> *Obj, uint64_t SymValue, SectionRef FunctionSec,
-    const StringRef SectionName, DataExtractor Data, uint64_t *Offset) {
+void DumpStyle<ELFT>::printFunctionStackSize(const ELFObjectFile<ELFT> *Obj,
+                                             uint64_t SymValue,
+                                             Optional<SectionRef> 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;
@@ -5186,9 +5189,15 @@ void DumpStyle<ELFT>::printFunctionStackSize(
       consumeError(SymAddrOrErr.takeError());
       continue;
     }
+    if (Expected<uint32_t> 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;
       }
@@ -5299,11 +5308,6 @@ void DumpStyle<ELFT>::printNonRelocatableStackSizes(
     ArrayRef<uint8_t> 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
@@ -5317,8 +5321,8 @@ void DumpStyle<ELFT>::printNonRelocatableStackSizes(
             FileStr);
       }
       uint64_t SymValue = Data.getAddress(&Offset);
-      printFunctionStackSize(Obj, SymValue, Obj->toSectionRef(FunctionELFSec),
-                             SectionName, Data, &Offset);
+      printFunctionStackSize(Obj, SymValue, /*FunctionSec=*/None, SectionName,
+                             Data, &Offset);
     }
   }
 }


        


More information about the llvm-commits mailing list