[PATCH] D13360: [llvm-objdump] Teach -d about AArch64 mapping symbols
authorDavide Italiano <davide@freebsd.org>
Thu, 1 Oct 2015 21:57:09 +0000 (21:57 +0000)
committerDavide Italiano <davide@freebsd.org>
Thu, 1 Oct 2015 21:57:09 +0000 (21:57 +0000)
AArch64 uses $d* and $x* to interleave between text and data.
llvm-objdump didn't know about this so it ended up printing garbage.
This patch is a first step towards a solution of the problem.

Differential Revision:  http://reviews.llvm.org/D13360

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@249083 91177308-0d34-0410-b5e6-96231b3b80d8

test/tools/llvm-objdump/AArch64/elf-aarch64-mapping-symbols.test [new file with mode: 0644]
tools/llvm-objdump/llvm-objdump.cpp

diff --git a/test/tools/llvm-objdump/AArch64/elf-aarch64-mapping-symbols.test b/test/tools/llvm-objdump/AArch64/elf-aarch64-mapping-symbols.test
new file mode 100644 (file)
index 0000000..cb9560d
--- /dev/null
@@ -0,0 +1,30 @@
+# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %t
+# RUN: llvm-objdump -d %t | FileCheck %s
+
+.section .mysection,"ax",@progbits
+.globl _start
+_start:
+  adr x1,msg
+msg:  .asciz  "Hello, world\n"
+msgend:
+
+.section .myothersection,"ax",@progbits
+  adrp x1,mystr
+mystr:
+  .asciz "blah"
+  .size mystr, 4
+
+# CHECK: Disassembly of section .mysection:
+# CHECK: _start:
+# CHECK:        0:       21 00 00 10     adr     x1, #4
+# CHECK: msg:
+# CHECK:        4:       48 65 6c 6c     .word
+# CHECK:        8:       6f 2c 20 77     .word
+# CHECK:        c:       6f 72 6c 64     .word
+# CHECK:       10:       0a 00   .short
+# CHECK: Disassembly of section .myothersection:
+# CHECK: $x.2:
+# CHECK:        0:       01 00 00 90     adrp    x1, #0
+# CHECK: mystr:
+# CHECK:        4:       62 6c 61 68     .word
+# CHECK:        8:       00      .byte
index 09b6d8f3af74ecfab555da115093760d9c7b11fa..169e5c0d9acbe7aa3360ffd5de2e33c365be250c 100644 (file)
@@ -917,6 +917,8 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
 
     // Make a list of all the symbols in this section.
     std::vector<std::pair<uint64_t, StringRef>> Symbols;
 
     // Make a list of all the symbols in this section.
     std::vector<std::pair<uint64_t, StringRef>> Symbols;
+    std::vector<uint64_t> DataMappingSymsAddr;
+    std::vector<uint64_t> TextMappingSymsAddr;
     for (const SymbolRef &Symbol : Obj->symbols()) {
       if (Section.containsSymbol(Symbol)) {
         ErrorOr<uint64_t> AddressOrErr = Symbol.getAddress();
     for (const SymbolRef &Symbol : Obj->symbols()) {
       if (Section.containsSymbol(Symbol)) {
         ErrorOr<uint64_t> AddressOrErr = Symbol.getAddress();
@@ -929,11 +931,19 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
         ErrorOr<StringRef> Name = Symbol.getName();
         error(Name.getError());
         Symbols.push_back(std::make_pair(Address, *Name));
         ErrorOr<StringRef> Name = Symbol.getName();
         error(Name.getError());
         Symbols.push_back(std::make_pair(Address, *Name));
+        if (Obj->isELF() && Obj->getArch() == Triple::aarch64) {
+          if (Name->startswith("$d"))
+            DataMappingSymsAddr.push_back(Address);
+          if (Name->startswith("$x"))
+            TextMappingSymsAddr.push_back(Address);
+        }
       }
     }
 
     // Sort the symbols by address, just in case they didn't come in that way.
     array_pod_sort(Symbols.begin(), Symbols.end());
       }
     }
 
     // Sort the symbols by address, just in case they didn't come in that way.
     array_pod_sort(Symbols.begin(), Symbols.end());
+    std::sort(DataMappingSymsAddr.begin(), DataMappingSymsAddr.end());
+    std::sort(TextMappingSymsAddr.begin(), TextMappingSymsAddr.end());
 
     // Make a list of all the relocations for this section.
     std::vector<RelocationRef> Rels;
 
     // Make a list of all the relocations for this section.
     std::vector<RelocationRef> Rels;
@@ -998,6 +1008,45 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
       for (Index = Start; Index < End; Index += Size) {
         MCInst Inst;
 
       for (Index = Start; Index < End; Index += Size) {
         MCInst Inst;
 
+        // AArch64 ELF binaries can interleave data and text in the
+        // same section. We rely on the markers introduced to
+        // understand what we need to dump.
+        if (Obj->isELF() && Obj->getArch() == Triple::aarch64) {
+          uint64_t Stride = 0;
+
+          auto DAI = std::lower_bound(DataMappingSymsAddr.begin(),
+                                      DataMappingSymsAddr.end(), Index);
+          if (DAI != DataMappingSymsAddr.end() && *DAI == Index) {
+            // Switch to data.
+            while (Index < End) {
+              outs() << format("%8" PRIx64 ":", SectionAddr + Index);
+              outs() << "\t";
+              if (Index + 4 <= End) {
+                Stride = 4;
+                dumpBytes(Bytes.slice(Index, 4), outs());
+                outs() << "\t.word";
+              } else if (Index + 2 <= End) {
+                Stride = 2;
+                dumpBytes(Bytes.slice(Index, 2), outs());
+                outs() << "\t.short";
+              } else {
+                Stride = 1;
+                dumpBytes(Bytes.slice(Index, 1), outs());
+                outs() << "\t.byte";
+              }
+              Index += Stride;
+              outs() << "\n";
+              auto TAI = std::lower_bound(TextMappingSymsAddr.begin(),
+                                          TextMappingSymsAddr.end(), Index);
+              if (TAI != TextMappingSymsAddr.end() && *TAI == Index)
+                break;
+            }
+          }
+        }
+
+        if (Index >= End)
+          break;
+
         if (DisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
                                    SectionAddr + Index, DebugOut,
                                    CommentStream)) {
         if (DisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
                                    SectionAddr + Index, DebugOut,
                                    CommentStream)) {