[lld] [llvm] [llvm-readelf] Print more information for RELR (PR #89162)

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 17 18:52:41 PDT 2024


https://github.com/MaskRay created https://github.com/llvm/llvm-project/pull/89162

llvm-readelf/llvm-readobj print RELR as REL relocations with a fixed
type (e.g. `R_*_RELATIVE`). GNU readelf printed only addresses and have
recently switched to a more descritive style that includes a symbolic
address column (symbolized using .symtab/.strtab) (milestone: binutils
2.43).

This patch implements the new GNU style, which seems superior to the
current REL style and essentially obsoletes LLVM-specific --raw-relr
(`printRelrReloc`).


>From 3b5c2a8fb4b176bdce1061e30553aaae8a610b2a Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Wed, 17 Apr 2024 18:52:32 -0700
Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?=
 =?UTF-8?q?l=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.5-bogner
---
 lld/test/ELF/pack-dyn-relocs.s                |  50 +++----
 lld/test/ELF/partition-pack-dyn-relocs.s      |   6 +-
 .../tools/llvm-readobj/ELF/relr-relocs.test   | 126 ++++++++++++------
 llvm/tools/llvm-readobj/ELFDumper.cpp         |  88 +++++++++++-
 4 files changed, 198 insertions(+), 72 deletions(-)

diff --git a/lld/test/ELF/pack-dyn-relocs.s b/lld/test/ELF/pack-dyn-relocs.s
index dd5d366ae23448..c462cbe9668d68 100644
--- a/lld/test/ELF/pack-dyn-relocs.s
+++ b/lld/test/ELF/pack-dyn-relocs.s
@@ -328,31 +328,31 @@
 // RELR64-NEXT:  0000000000030510  0000000200000101 R_AARCH64_ABS64        0000000000000000 zed2 + 0
 // RELR64-EMPTY: 
 // RELR64-NEXT:  Relocation section '.relr.dyn' at offset {{.*}} contains 24 entries:
-// RELR64-NEXT:      Offset             Info             Type               Symbol's Value  Symbol's Name
-// RELR64-NEXT:  0000000000030490  0000000000000403 R_AARCH64_RELATIVE
-// RELR64-NEXT:  0000000000030498  0000000000000403 R_AARCH64_RELATIVE
-// RELR64-NEXT:  00000000000304a0  0000000000000403 R_AARCH64_RELATIVE
-// RELR64-NEXT:  00000000000304a8  0000000000000403 R_AARCH64_RELATIVE
-// RELR64-NEXT:  00000000000304b0  0000000000000403 R_AARCH64_RELATIVE
-// RELR64-NEXT:  00000000000304b8  0000000000000403 R_AARCH64_RELATIVE
-// RELR64-NEXT:  00000000000304c0  0000000000000403 R_AARCH64_RELATIVE
-// RELR64-NEXT:  00000000000304c8  0000000000000403 R_AARCH64_RELATIVE
-// RELR64-NEXT:  00000000000304d8  0000000000000403 R_AARCH64_RELATIVE
-// RELR64-NEXT:  00000000000304e0  0000000000000403 R_AARCH64_RELATIVE
-// RELR64-NEXT:  00000000000304e8  0000000000000403 R_AARCH64_RELATIVE
-// RELR64-NEXT:  00000000000304f0  0000000000000403 R_AARCH64_RELATIVE
-// RELR64-NEXT:  00000000000304f8  0000000000000403 R_AARCH64_RELATIVE
-// RELR64-NEXT:  0000000000030500  0000000000000403 R_AARCH64_RELATIVE
-// RELR64-NEXT:  0000000000030508  0000000000000403 R_AARCH64_RELATIVE
-// RELR64-NEXT:  0000000000030520  0000000000000403 R_AARCH64_RELATIVE
-// RELR64-NEXT:  0000000000030528  0000000000000403 R_AARCH64_RELATIVE
-// RELR64-NEXT:  0000000000030530  0000000000000403 R_AARCH64_RELATIVE
-// RELR64-NEXT:  0000000000030538  0000000000000403 R_AARCH64_RELATIVE
-// RELR64-NEXT:  0000000000030540  0000000000000403 R_AARCH64_RELATIVE
-// RELR64-NEXT:  0000000000030548  0000000000000403 R_AARCH64_RELATIVE
-// RELR64-NEXT:  0000000000030550  0000000000000403 R_AARCH64_RELATIVE
-// RELR64-NEXT:  0000000000030558  0000000000000403 R_AARCH64_RELATIVE
-// RELR64-NEXT:  0000000000030560  0000000000000403 R_AARCH64_RELATIVE
+// RELR64-NEXT:  Symbolic Address
+// RELR64-NEXT:  $d.0
+// RELR64-NEXT:  $d.0 + 0x8
+// RELR64-NEXT:  $d.0 + 0x10
+// RELR64-NEXT:  $d.0 + 0x18
+// RELR64-NEXT:  $d.0 + 0x20
+// RELR64-NEXT:  $d.0 + 0x28
+// RELR64-NEXT:  $d.0 + 0x30
+// RELR64-NEXT:  $d.0 + 0x38
+// RELR64-NEXT:  $d.0 + 0x48
+// RELR64-NEXT:  $d.0 + 0x50
+// RELR64-NEXT:  $d.0 + 0x58
+// RELR64-NEXT:  $d.0 + 0x60
+// RELR64-NEXT:  $d.0 + 0x68
+// RELR64-NEXT:  $d.0 + 0x70
+// RELR64-NEXT:  $d.0 + 0x78
+// RELR64-NEXT:  $d.0 + 0x90
+// RELR64-NEXT:  $d.0 + 0x98
+// RELR64-NEXT:  $d.0 + 0xa0
+// RELR64-NEXT:  $d.0 + 0xa8
+// RELR64-NEXT:  $d.0 + 0xb0
+// RELR64-NEXT:  $d.0 + 0xb8
+// RELR64-NEXT:  $d.0 + 0xc0
+// RELR64-NEXT:  $d.0 + 0xc8
+// RELR64-NEXT:  $d.0 + 0xd0
 // RELR64-EMPTY:
 // RELR64-NEXT: Hex dump of section '.data':
 // RELR64-NEXT: 0x00030490 90040300 00000000 91040300 00000000 .
diff --git a/lld/test/ELF/partition-pack-dyn-relocs.s b/lld/test/ELF/partition-pack-dyn-relocs.s
index 3727bcc21614d8..8127110e348c55 100644
--- a/lld/test/ELF/partition-pack-dyn-relocs.s
+++ b/lld/test/ELF/partition-pack-dyn-relocs.s
@@ -29,9 +29,9 @@
 // CHECK-EMPTY:
 
 // CHECK: Relocation section '.relr.dyn'
-// CHECK-NEXT: Offset
-// PART0-NEXT: 000000000000[[DATA_SEGMENT]]378 {{.*}} R_X86_64_RELATIVE
-// PART1-NEXT: 000000000000[[DATA_SEGMENT]]340 {{.*}} R_X86_64_RELATIVE
+// CHECK-NEXT: Address Symbolic Address
+// PART0-NEXT: 000000000000[[DATA_SEGMENT]]378 p0{{$}}
+// PART1-NEXT: 000000000000[[DATA_SEGMENT]]340 p1{{$}}
 // CHECK-EMPTY:
 
 .section .llvm_sympart,"", at llvm_sympart
diff --git a/llvm/test/tools/llvm-readobj/ELF/relr-relocs.test b/llvm/test/tools/llvm-readobj/ELF/relr-relocs.test
index 91b148ebb6e3c8..9525ab8fc5b449 100644
--- a/llvm/test/tools/llvm-readobj/ELF/relr-relocs.test
+++ b/llvm/test/tools/llvm-readobj/ELF/relr-relocs.test
@@ -1,6 +1,7 @@
 ## This is a test to test how SHT_RELR sections are dumped.
 
 # RUN: yaml2obj --docnum=1 %s -o %t1
+# RUN: llvm-objcopy --strip-all %t1 %t1.stripped
 # RUN: llvm-readobj --relocations --raw-relr %t1 \
 # RUN:   | FileCheck --check-prefix=RAW-LLVM1 %s
 # RAW-LLVM1:      Section (1) .relr.dyn {
@@ -47,29 +48,37 @@
 # RAW-GNU1-NEXT: 00000000000f0501
 # RAW-GNU1-NEXT: 000a700550400009
 
-# RUN: llvm-readelf --relocations %t1 | FileCheck --check-prefix=GNU1 %s
-# GNU1:      Relocation section '.relr.dyn' at offset 0x40 contains 21 entries:
-# GNU1:      0000000000010d60  0000000000000008 R_X86_64_RELATIVE
-# GNU1-NEXT: 0000000000010d68  0000000000000008 R_X86_64_RELATIVE
-# GNU1-NEXT: 0000000000010da0  0000000000000008 R_X86_64_RELATIVE
-# GNU1-NEXT: 0000000000020000  0000000000000008 R_X86_64_RELATIVE
-# GNU1-NEXT: 0000000000020040  0000000000000008 R_X86_64_RELATIVE
-# GNU1-NEXT: 0000000000020050  0000000000000008 R_X86_64_RELATIVE
-# GNU1-NEXT: 0000000000020080  0000000000000008 R_X86_64_RELATIVE
-# GNU1-NEXT: 0000000000020088  0000000000000008 R_X86_64_RELATIVE
-# GNU1-NEXT: 0000000000020090  0000000000000008 R_X86_64_RELATIVE
-# GNU1-NEXT: 0000000000020098  0000000000000008 R_X86_64_RELATIVE
-# GNU1-NEXT: 0000000000020210  0000000000000008 R_X86_64_RELATIVE
-# GNU1-NEXT: 00000000000202a8  0000000000000008 R_X86_64_RELATIVE
-# GNU1-NEXT: 00000000000202d8  0000000000000008 R_X86_64_RELATIVE
-# GNU1-NEXT: 00000000000202e8  0000000000000008 R_X86_64_RELATIVE
-# GNU1-NEXT: 00000000000202f8  0000000000000008 R_X86_64_RELATIVE
-# GNU1-NEXT: 0000000000020308  0000000000000008 R_X86_64_RELATIVE
-# GNU1-NEXT: 0000000000020358  0000000000000008 R_X86_64_RELATIVE
-# GNU1-NEXT: 0000000000020360  0000000000000008 R_X86_64_RELATIVE
-# GNU1-NEXT: 0000000000020368  0000000000000008 R_X86_64_RELATIVE
-# GNU1-NEXT: 0000000000020380  0000000000000008 R_X86_64_RELATIVE
-# GNU1-NEXT: 0000000000020390  0000000000000008 R_X86_64_RELATIVE
+# RUN: llvm-readelf --relocations %t1 | FileCheck --check-prefix=GNU1 --match-full-lines --strict-whitespace %s
+#      GNU1:Relocation section '.relr.dyn' at offset 0x40 contains 21 entries:
+# GNU1-NEXT:Index: Entry            Address           Symbolic Address
+# GNU1-NEXT:0000:  0000000000010d60 0000000000010d60  base + 0x60
+# GNU1-NEXT:0001:  0000000000000103 0000000000010d68  base + 0x68
+# GNU1-NEXT:                        0000000000010da0  base + 0xa0
+# GNU1-NEXT:0002:  0000000000020000 0000000000020000  foo
+# GNU1-NEXT:0003:  00000000000f0501 0000000000020040  foo + 0x40
+# GNU1-NEXT:                        0000000000020050  foo + 0x50
+# GNU1-NEXT:                        0000000000020080  foo + 0x80
+# GNU1-NEXT:                        0000000000020088  foo + 0x88
+# GNU1-NEXT:                        0000000000020090  foo + 0x90
+# GNU1-NEXT:                        0000000000020098  foo + 0x98
+# GNU1-NEXT:0004:  000a700550400009 0000000000020210  bar + 0x10
+# GNU1-NEXT:                        00000000000202a8  bar + 0xa8
+# GNU1-NEXT:                        00000000000202d8  bar + 0xd8
+# GNU1-NEXT:                        00000000000202e8  bar + 0xe8
+# GNU1-NEXT:                        00000000000202f8  bar + 0xf8
+# GNU1-NEXT:                        0000000000020308  bar + 0x108
+# GNU1-NEXT:                        0000000000020358  bar + 0x158
+# GNU1-NEXT:                        0000000000020360  bar + 0x160
+# GNU1-NEXT:                        0000000000020368  bar + 0x168
+# GNU1-NEXT:                        0000000000020380  bar + 0x180
+# GNU1-NEXT:                        0000000000020390  bar + 0x190
+
+## The addresses are not symbolized in the absence of .symtab.
+# RUN: llvm-readelf --relocations %t1.stripped | FileCheck --check-prefix=GNU1S --match-full-lines --strict-whitespace %s
+#      GNU1S:Relocation section '.relr.dyn' at offset 0x40 contains 21 entries:
+# GNU1S-NEXT:Index: Entry            Address           Symbolic Address
+# GNU1S-NEXT:0000:  0000000000010d60 0000000000010d60
+# GNU1S-NEXT:0001:  0000000000000103 0000000000010d68
 
 --- !ELF
 FileHeader:
@@ -83,6 +92,13 @@ Sections:
     Flags: [ SHF_ALLOC ]
     Entries: [ 0x0000000000010D60, 0x0000000000000103, 0x0000000000020000,
                0x00000000000F0501, 0x000A700550400009 ]
+Symbols:
+  - Name:  bar
+    Value: 0x20200
+  - Name:  foo
+    Value: 0x20000
+  - Name:  base
+    Value: 0x10d00
 
 # RUN: yaml2obj --docnum=2 %s -o %t2
 # RUN: llvm-readobj --relocations --raw-relr %t2 | \
@@ -126,20 +142,21 @@ Sections:
 
 # RUN: llvm-readelf --relocations %t2 | FileCheck --check-prefix=GNU2 %s
 # GNU2:      Relocation section '.relr.dyn' at offset 0x34 contains 14 entries:
-# GNU2:      00010d60  00000008 R_386_RELATIVE
-# GNU2-NEXT: 00010d64  00000008 R_386_RELATIVE
-# GNU2-NEXT: 00010d80  00000008 R_386_RELATIVE
-# GNU2-NEXT: 00020000  00000008 R_386_RELATIVE
-# GNU2-NEXT: 00020020  00000008 R_386_RELATIVE
-# GNU2-NEXT: 00020028  00000008 R_386_RELATIVE
-# GNU2-NEXT: 00020040  00000008 R_386_RELATIVE
-# GNU2-NEXT: 00020044  00000008 R_386_RELATIVE
-# GNU2-NEXT: 00020048  00000008 R_386_RELATIVE
-# GNU2-NEXT: 0002004c  00000008 R_386_RELATIVE
-# GNU2-NEXT: 00020088  00000008 R_386_RELATIVE
-# GNU2-NEXT: 000200d4  00000008 R_386_RELATIVE
-# GNU2-NEXT: 000200ec  00000008 R_386_RELATIVE
-# GNU2-NEXT: 000200f4  00000008 R_386_RELATIVE
+# GNU2-NEXT: Index: Entry            Address           Symbolic Address
+# GNU2-NEXT: 0000:  00010d60 00010d60  .relr.dyn
+# GNU2-NEXT: 0001:  00000103 00010d64  .relr.dyn + 0x4
+# GNU2-NEXT:                 00010d80  .relr.dyn + 0x20
+# GNU2-NEXT: 0002:  00020000 00020000  .relr.dyn + 0xf2a0
+# GNU2-NEXT: 0003:  000f0501 00020020  .relr.dyn + 0xf2c0
+# GNU2-NEXT:                 00020028  .relr.dyn + 0xf2c8
+# GNU2-NEXT:                 00020040  .relr.dyn + 0xf2e0
+# GNU2-NEXT:                 00020044  .relr.dyn + 0xf2e4
+# GNU2-NEXT:                 00020048  .relr.dyn + 0xf2e8
+# GNU2-NEXT:                 0002004c  .relr.dyn + 0xf2ec
+# GNU2-NEXT: 0004:  50400009 00020088  .relr.dyn + 0xf328
+# GNU2-NEXT:                 000200d4  .relr.dyn + 0xf374
+# GNU2-NEXT:                 000200ec  .relr.dyn + 0xf38c
+# GNU2-NEXT:                 000200f4  .relr.dyn + 0xf394
 
 --- !ELF
 FileHeader:
@@ -156,6 +173,11 @@ Sections:
     EntSize: [[ENTSIZE=<none>]]
     ShType:  [[SHTYPE=<none>]]
     Link:    [[LINK=<none>]]
+Symbols:
+  - Name:    .relr.dyn
+    Type:    STT_SECTION
+    Value:   0x10D60
+    Section: .relr.dyn
 
 ## Check we report a warning when we are unable to dump relocations
 ## for a SHT_RELR/SHT_ANDROID_RELR/SHT_AARCH64_AUTH_RELR section.
@@ -175,7 +197,6 @@ Sections:
 
 # BROKEN-GNU:      warning: '[[FILE]]': unable to get the number of relocations in [[SECNAME]] section with index 1: section [index 1] has invalid sh_entsize: expected 4, but got 1
 # BROKEN-GNU:      Relocation section '.relr.dyn' at offset 0x34 contains <?> entries:
-# BROKEN-GNU-NEXT:  Offset     Info    Type                Sym. Value  Symbol's Name
 # BROKEN-GNU-NEXT: warning: '[[FILE]]': unable to read relocations from [[SECNAME]] section with index 1: section [index 1] has invalid sh_entsize: expected 4, but got 1
 
 ## Case B: check the case when relocations can't be read from an SHT_ANDROID_RELR section.
@@ -218,3 +239,32 @@ Sections:
 # RUN:   FileCheck -DFILE=%t2.has.link --check-prefix=RAW-LLVM2 %s
 # RUN: llvm-readelf --relocations --raw-relr %t2.has.link 2>&1 | \
 # RUN:   FileCheck -DFILE=%t2.has.link --check-prefix=RAW-GNU2 %s
+
+# RUN: yaml2obj --docnum=3 %s -o %t3
+# RUN: llvm-readelf -r %t3 2>&1 | FileCheck -DFILE=%t3 --check-prefix=GNU3 %s
+
+## .symtab is invalid. Check we report a warning and print entries without symbolization.
+# GNU3:      Index: Entry            Address           Symbolic Address
+# GNU3-NEXT: warning: '[[FILE]]': section [index 2] has invalid sh_entsize: expected 24, but got 1
+# GNU3-NEXT: 0000:  0000000000010d60 0000000000010d60
+# GNU3-NEXT: 0001:  0000000000000103 0000000000010d68
+# GNU3-NEXT:                         0000000000010da0
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_DYN
+  Machine: EM_X86_64
+Sections:
+  - Name:  .relr.dyn
+    Type:  SHT_RELR
+    Flags: [ SHF_ALLOC ]
+    Entries: [ 0x0000000000010D60, 0x0000000000000103 ]
+  - Name:    .symtab
+    Type:    SHT_SYMTAB
+    Link:    .strtab
+    EntSize: 1
+Symbols:
+  - Name:  bar
+    Value: 0x10D60
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index 1108672003fc76..688be8327de417 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -658,6 +658,7 @@ template <typename ELFT> class GNUELFDumper : public ELFDumper<ELFT> {
   void printHashedSymbol(const Elf_Sym *Sym, unsigned SymIndex,
                          DataRegion<Elf_Word> ShndxTable, StringRef StrTable,
                          uint32_t Bucket);
+  void printRelr(const Elf_Shdr &Sec);
   void printRelrReloc(const Elf_Relr &R) override;
   void printRelRelaReloc(const Relocation<ELFT> &R,
                          const RelSymbol<ELFT> &RelSym) override;
@@ -3882,6 +3883,12 @@ static bool isRelocationSec(const typename ELFT::Shdr &Sec,
 }
 
 template <class ELFT> void GNUELFDumper<ELFT>::printRelocations() {
+  auto PrintAsRelr = [&](const Elf_Shdr &Sec) {
+    return !opts::RawRelr && (Sec.sh_type == ELF::SHT_RELR ||
+                              Sec.sh_type == ELF::SHT_ANDROID_RELR ||
+                              (this->Obj.getHeader().e_machine == EM_AARCH64 &&
+                               Sec.sh_type == ELF::SHT_AARCH64_AUTH_RELR));
+  };
   auto GetEntriesNum = [&](const Elf_Shdr &Sec) -> Expected<size_t> {
     // Android's packed relocation section needs to be unpacked first
     // to get the actual number of entries.
@@ -3894,10 +3901,7 @@ template <class ELFT> void GNUELFDumper<ELFT>::printRelocations() {
       return RelasOrErr->size();
     }
 
-    if (!opts::RawRelr &&
-        (Sec.sh_type == ELF::SHT_RELR || Sec.sh_type == ELF::SHT_ANDROID_RELR ||
-         (this->Obj.getHeader().e_machine == EM_AARCH64 &&
-          Sec.sh_type == ELF::SHT_AARCH64_AUTH_RELR))) {
+    if (PrintAsRelr(Sec)) {
       Expected<Elf_Relr_Range> RelrsOrErr = this->Obj.relrs(Sec);
       if (!RelrsOrErr)
         return RelrsOrErr.takeError();
@@ -3926,13 +3930,85 @@ template <class ELFT> void GNUELFDumper<ELFT>::printRelocations() {
     OS << "\nRelocation section '" << Name << "' at offset 0x"
        << utohexstr(Offset, /*LowerCase=*/true) << " contains " << EntriesNum
        << " entries:\n";
-    printRelocHeaderFields<ELFT>(OS, Sec.sh_type, this->Obj.getHeader());
-    this->printRelocationsHelper(Sec);
+
+    if (PrintAsRelr(Sec)) {
+      printRelr(Sec);
+    } else {
+      printRelocHeaderFields<ELFT>(OS, Sec.sh_type, this->Obj.getHeader());
+      this->printRelocationsHelper(Sec);
+    }
   }
   if (!HasRelocSections)
     OS << "\nThere are no relocations in this file.\n";
 }
 
+template <class ELFT> void GNUELFDumper<ELFT>::printRelr(const Elf_Shdr &Sec) {
+  Expected<Elf_Relr_Range> RangeOrErr = this->Obj.relrs(Sec);
+  if (!RangeOrErr) {
+    this->reportUniqueWarning("unable to read relocations from " +
+                              this->describe(Sec) + ": " +
+                              toString(RangeOrErr.takeError()));
+    return;
+  }
+  if (ELFT::Is64Bits)
+    OS << "Index: Entry            Address           Symbolic Address\n";
+  else
+    OS << "Index: Entry    Address   Symbolic Address\n";
+
+  SmallVector<std::pair<uint64_t, std::string>, 0> Syms;
+  if (this->DotSymtabSec) {
+    if (auto SymsOrErr = this->Obj.symbols(this->DotSymtabSec)) {
+      StringRef Strtab =
+          unwrapOrError(this->FileName,
+                        this->Obj.getStringTableForSymtab(*this->DotSymtabSec));
+      for (auto [I, Sym] : enumerate(*SymsOrErr)) {
+        Syms.emplace_back(Sym.st_value,
+                          this->getFullSymbolName(Sym, I, ArrayRef<Elf_Word>(),
+                                                  Strtab, false));
+      }
+    } else {
+      this->reportUniqueWarning(SymsOrErr.takeError());
+    }
+  }
+  llvm::stable_sort(Syms);
+
+  typename ELFT::uint Base = 0;
+  size_t I = 0;
+  auto Print = [&](uint64_t Where) {
+    OS << format_hex_no_prefix(Where, ELFT::Is64Bits ? 16 : 8);
+    for (; I < Syms.size() && Syms[I].first <= Where; ++I)
+      ;
+    if (I) {
+      OS << "  " << Syms[I - 1].second;
+      if (Syms[I - 1].first < Where)
+        OS << " + 0x" << Twine::utohexstr(Where - Syms[I - 1].first);
+    }
+    OS << '\n';
+  };
+  for (auto [I, R] : enumerate(*RangeOrErr)) {
+    typename ELFT::uint Entry = R;
+    OS << formatv("{0:4}:  ", I)
+       << format_hex_no_prefix(Entry, ELFT::Is64Bits ? 16 : 8) << ' ';
+    if ((Entry & 1) == 0) {
+      Print(Entry);
+      Base = Entry + sizeof(typename ELFT::uint);
+    } else {
+      bool First = true;
+      for (auto Where = Base; Entry >>= 1;
+           Where += sizeof(typename ELFT::uint)) {
+        if (Entry & 1) {
+          if (First)
+            First = false;
+          else
+            OS.indent(ELFT::Is64Bits ? 24 : 16);
+          Print(Where);
+        }
+      }
+      Base += (CHAR_BIT * sizeof(Entry) - 1) * sizeof(typename ELFT::uint);
+    }
+  }
+}
+
 // Print the offset of a particular section from anyone of the ranges:
 // [SHT_LOOS, SHT_HIOS], [SHT_LOPROC, SHT_HIPROC], [SHT_LOUSER, SHT_HIUSER].
 // If 'Type' does not fall within any of those ranges, then a string is



More information about the llvm-commits mailing list