[llvm-size][libobject] Add explicit "inTextSegment" methods similar to "isText" secti...
authorJordan Rupprecht <rupprecht@google.com>
Thu, 13 Dec 2018 19:40:12 +0000 (19:40 +0000)
committerJordan Rupprecht <rupprecht@google.com>
Thu, 13 Dec 2018 19:40:12 +0000 (19:40 +0000)
Summary:
llvm-size uses "isText()" etc. which seem to indicate whether the section contains code-like things, not whether or not it will actually go in the text segment when in a fully linked executable.

The unit test added (elf-sizes.test) shows some types of sections that cause discrepencies versus the GNU size tool. llvm-size is not correctly reporting sizes of things mapping to text/data segments, at least for ELF files.

This fixes pr38723.

Reviewers: echristo, Bigcheese, MaskRay

Reviewed By: MaskRay

Subscribers: llvm-commits

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

llvm-svn: 349074

llvm/include/llvm/Object/ELFObjectFile.h
llvm/include/llvm/Object/ObjectFile.h
llvm/lib/Object/ObjectFile.cpp
llvm/test/tools/llvm-size/X86/elf-sizes.test [new file with mode: 0644]
llvm/test/tools/llvm-size/X86/ignore-sections.s
llvm/tools/llvm-size/llvm-size.cpp

index f8dab21..0f62068 100644 (file)
@@ -260,6 +260,8 @@ protected:
   bool isSectionData(DataRefImpl Sec) const override;
   bool isSectionBSS(DataRefImpl Sec) const override;
   bool isSectionVirtual(DataRefImpl Sec) const override;
+  bool isBerkeleyText(DataRefImpl Sec) const override;
+  bool isBerkeleyData(DataRefImpl Sec) const override;
   relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
   relocation_iterator section_rel_end(DataRefImpl Sec) const override;
   std::vector<SectionRef> dynamic_relocation_sections() const override;
@@ -760,6 +762,20 @@ bool ELFObjectFile<ELFT>::isSectionVirtual(DataRefImpl Sec) const {
 }
 
 template <class ELFT>
+bool ELFObjectFile<ELFT>::isBerkeleyText(DataRefImpl Sec) const {
+  return getSection(Sec)->sh_flags & ELF::SHF_ALLOC &&
+         (getSection(Sec)->sh_flags & ELF::SHF_EXECINSTR ||
+          !(getSection(Sec)->sh_flags & ELF::SHF_WRITE));
+}
+
+template <class ELFT>
+bool ELFObjectFile<ELFT>::isBerkeleyData(DataRefImpl Sec) const {
+  const Elf_Shdr *EShdr = getSection(Sec);
+  return !isBerkeleyText(Sec) && EShdr->sh_type != ELF::SHT_NOBITS &&
+         EShdr->sh_flags & ELF::SHF_ALLOC;
+}
+
+template <class ELFT>
 relocation_iterator
 ELFObjectFile<ELFT>::section_rel_begin(DataRefImpl Sec) const {
   DataRefImpl RelData;
index 02d62e8..036c99c 100644 (file)
@@ -104,13 +104,25 @@ public:
   uint64_t getAlignment() const;
 
   bool isCompressed() const;
+  /// Whether this section contains instructions.
   bool isText() const;
+  /// Whether this section contains data, not instructions.
   bool isData() const;
+  /// Whether this section contains BSS uninitialized data.
   bool isBSS() const;
   bool isVirtual() const;
   bool isBitcode() const;
   bool isStripped() const;
 
+  /// Whether this section will be placed in the text segment, according to the
+  /// Berkeley size format. This is true if the section is allocatable, and
+  /// contains either code or readonly data.
+  bool isBerkeleyText() const;
+  /// Whether this section will be placed in the data segment, according to the
+  /// Berkeley size format. This is true if the section is allocatable and
+  /// contains data (e.g. PROGBITS), but is not text.
+  bool isBerkeleyData() const;
+
   bool containsSymbol(SymbolRef S) const;
 
   relocation_iterator relocation_begin() const;
@@ -238,6 +250,8 @@ protected:
   virtual bool isSectionVirtual(DataRefImpl Sec) const = 0;
   virtual bool isSectionBitcode(DataRefImpl Sec) const;
   virtual bool isSectionStripped(DataRefImpl Sec) const;
+  virtual bool isBerkeleyText(DataRefImpl Sec) const;
+  virtual bool isBerkeleyData(DataRefImpl Sec) const;
   virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0;
   virtual relocation_iterator section_rel_end(DataRefImpl Sec) const = 0;
   virtual section_iterator getRelocatedSection(DataRefImpl Sec) const;
@@ -449,6 +463,14 @@ inline bool SectionRef::isStripped() const {
   return OwningObject->isSectionStripped(SectionPimpl);
 }
 
+inline bool SectionRef::isBerkeleyText() const {
+  return OwningObject->isBerkeleyText(SectionPimpl);
+}
+
+inline bool SectionRef::isBerkeleyData() const {
+  return OwningObject->isBerkeleyData(SectionPimpl);
+}
+
 inline relocation_iterator SectionRef::relocation_begin() const {
   return OwningObject->section_rel_begin(SectionPimpl);
 }
index db0ff22..cf63b89 100644 (file)
@@ -77,6 +77,14 @@ bool ObjectFile::isSectionBitcode(DataRefImpl Sec) const {
 
 bool ObjectFile::isSectionStripped(DataRefImpl Sec) const { return false; }
 
+bool ObjectFile::isBerkeleyText(DataRefImpl Sec) const {
+  return isSectionText(Sec);
+}
+
+bool ObjectFile::isBerkeleyData(DataRefImpl Sec) const {
+  return isSectionData(Sec);
+}
+
 section_iterator ObjectFile::getRelocatedSection(DataRefImpl Sec) const {
   return section_iterator(SectionRef(Sec, this));
 }
diff --git a/llvm/test/tools/llvm-size/X86/elf-sizes.test b/llvm/test/tools/llvm-size/X86/elf-sizes.test
new file mode 100644 (file)
index 0000000..cb7fcd3
--- /dev/null
@@ -0,0 +1,55 @@
+# RUN: yaml2obj %s > %t.o
+# RUN: llvm-size -B %t.o | FileCheck %s
+
+!ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_EXEC
+  Machine:         EM_X86_64
+Sections:
+  - Name:            .bss
+    Type:            SHT_NOBITS
+    Flags:           [ SHF_ALLOC, SHF_WRITE ]
+    Size:            1
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Size:            2
+  - Name:            .unusual_name_for_code
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Size:            64
+  - Name:            .eh_frame
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC ]
+    Size:            4
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_WRITE ]
+    Size:            8
+  - Name:            .moar_stuff
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_WRITE ]
+    Size:            128
+  - Name:            .text.but_not_really
+    Type:            SHT_PROGBITS
+    Flags:           [ ]
+    Size:            256
+  - Name:            .debug_info
+    Type:            SHT_PROGBITS
+    Flags:           [ ]
+    Size:            16
+  - Name:            .init_array
+    Type:            SHT_INIT_ARRAY
+    Flags:           [ SHF_ALLOC, SHF_WRITE ]
+    Size:            32
+
+# text is .text, .eh_frame, .unusual_name_for_code: 2 + 4 + 64 = 70
+# data is .data, .init_array, .moar_stuff: 8 + 32 + 128 = 168
+# bss is .bss: 1
+# total: 239
+# unaccounted for (not affecting total) is .debug_info, .text.but_not_really
+
+# CHECK: text data bss dec
+# CHECK: 70   168  1   239
index c597f84..61aa2e7 100644 (file)
@@ -25,5 +25,5 @@
 // SYSV-NEXT:    Total                 69
 
 // BSD:        text    data     bss     dec     hex filename
-// BSD-NEXT:      4       4       4      12       c {{[ -\(\)_A-Za-z0-9.\\/:]+}}
-// BSD-NEXT:      4       4       4      12       c (TOTALS)
+// BSD-NEXT:     52       4       4      60      3c {{[ -\(\)_A-Za-z0-9.\\/:]+}}
+// BSD-NEXT:     52       4       4      60      3c (TOTALS)
index a92a8ab..be1e5bb 100644 (file)
@@ -457,8 +457,8 @@ static void printObjectSectionSizes(ObjectFile *Obj) {
     // Make one pass over the section table to calculate sizes.
     for (const SectionRef &Section : Obj->sections()) {
       uint64_t size = Section.getSize();
-      bool isText = Section.isText();
-      bool isData = Section.isData();
+      bool isText = Section.isBerkeleyText();
+      bool isData = Section.isBerkeleyData();
       bool isBSS = Section.isBSS();
       if (isText)
         total_text += size;