llvm-objdump: Add --start-address and --stop-address options
authorHemant Kulkarni <khemant@codeaurora.org>
Mon, 12 Sep 2016 17:08:22 +0000 (17:08 +0000)
committerHemant Kulkarni <khemant@codeaurora.org>
Mon, 12 Sep 2016 17:08:22 +0000 (17:08 +0000)
Differential Revision: https://reviews.llvm.org/D24160

llvm-svn: 281232

llvm/test/tools/llvm-objdump/Inputs/simple-executable-x86_64.yaml [new file with mode: 0644]
llvm/test/tools/llvm-objdump/start-stop-address.test [new file with mode: 0644]
llvm/tools/llvm-objdump/llvm-objdump.cpp

diff --git a/llvm/test/tools/llvm-objdump/Inputs/simple-executable-x86_64.yaml b/llvm/test/tools/llvm-objdump/Inputs/simple-executable-x86_64.yaml
new file mode 100644 (file)
index 0000000..f6a1d18
--- /dev/null
@@ -0,0 +1,73 @@
+--- !ELF
+FileHeader:      
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_EXEC
+  Machine:         EM_X86_64
+Sections:        
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x0000000000000010
+    Content:         554889E58B0425A80000005DC30F1F00
+  - Name:            .anothertext
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x0000000000000010
+    AddressAlign:    0x0000000000000010
+    Content:         554889E54883EC20488D0425A8000000C745FC00000000488945F0488B45F08B08894DECE8C7FFFFFF8B4DEC01C189C84883C4205D746573742073747200C3
+  - Name:            .eh_frame
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x0000000000000050
+    AddressAlign:    0x0000000000000008
+    Content:         1400000000000000017A5200017810011B0C0708900100001C0000001C00000090FFFFFF0D00000000410E108602430D06000000000000001C0000003C00000080FFFFFF3F00000000410E108602430D0600000000000000
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    Address:         0x00000000000000A8
+    AddressAlign:    0x0000000000000004
+    Content:         '01000000'
+  - Name:            .comment
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_MERGE, SHF_STRINGS ]
+    AddressAlign:    0x0000000000000001
+    Content:         5562756E747520636C616E672076657273696F6E20332E352D317562756E74753120287472756E6B2920286261736564206F6E204C4C564D20332E352900
+Symbols:         
+  Local:           
+    - Type:            STT_SECTION
+      Section:         .text
+    - Type:            STT_SECTION
+      Section:         .anothertext
+      Value:           0x0000000000000010
+    - Type:            STT_SECTION
+      Section:         .eh_frame
+      Value:           0x0000000000000050
+    - Type:            STT_SECTION
+      Section:         .data
+      Value:           0x00000000000000A8
+    - Type:            STT_SECTION
+      Section:         .comment
+    - Name:            /tmp/a.c
+      Type:            STT_FILE
+    - Type:            STT_FILE
+  Global:          
+    - Name:            somedata
+      Type:            STT_OBJECT
+      Section:         .anothertext
+      Value:           0x0000000000000045
+    - Name:            main
+      Type:            STT_FUNC
+      Section:         .anothertext
+      Value:           0x0000000000000010
+      Size:            0x000000000000003F
+    - Name:            foo
+      Type:            STT_FUNC
+      Section:         .text
+      Size:            0x000000000000000D
+    - Name:            a
+      Type:            STT_OBJECT
+      Section:         .data
+      Value:           0x00000000000000A8
+      Size:            0x0000000000000004
+...
diff --git a/llvm/test/tools/llvm-objdump/start-stop-address.test b/llvm/test/tools/llvm-objdump/start-stop-address.test
new file mode 100644 (file)
index 0000000..97c1f45
--- /dev/null
@@ -0,0 +1,29 @@
+// RUN: yaml2obj -o %t.out %p/Inputs/simple-executable-x86_64.yaml 
+// RUN: llvm-objdump -d %t.out --start-address=0x18 --stop-address=0x2f | FileCheck %s 
+// RUN: llvm-objdump -d %t.out --start-address=0xc --stop-address=0x11 | FileCheck %s --check-prefix "CROSSSECTION"
+// RUN: llvm-objdump -d %t.out --start-address=0x40 --stop-address=0x47 | FileCheck %s --check-prefix "CROSSDATA"
+
+// CHECK:              Disassembly of section .anothertext:
+// CHECK-NEXT:         main:
+// CHECK-NEXT:         18:     48 8d 04 25 a8 00 00 00         leaq    168, %rax
+// CHECK-NEXT:         20:     c7 45 fc 00 00 00 00    movl    $0, -4(%rbp)
+// CHECK-NEXT:         27:     48 89 45 f0     movq    %rax, -16(%rbp)
+// CHECK-NEXT:         2b:     48 8b 45 f0     movq    -16(%rbp), %rax
+// CHECK-NOT:          2f:
+
+// CROSSSECTION:       Disassembly of section .text:
+// CROSSSECTION-NEXT:  foo:
+// CROSSSECTION-NEXT:  c:      c3      retq
+// CROSSSECTION-NEXT:  d:      0f 1f 00        nopl    (%rax)
+// CROSSSECTION-NEXT:  Disassembly of section .anothertext:
+// CROSSSECTION-NEXT:  main:
+// CROSSSECTION-NEXT:  10:     55      pushq   %rbp
+// CROSSSECTION-NOT:   11:
+
+// CROSSDATA:          Disassembly of section .anothertext:
+// CROSSDATA:          main:
+// CROSSDATA:          40:     48 83 c4 20     addq    $32, %rsp
+// CROSSDATA:          44:     5d      popq    %rbp
+// CROSSDATA-DAG:      somedata:
+// CROSSDATA-NEXT:     45:      74 65                           te
+
index 0cf42e3..56d3559 100644 (file)
@@ -205,6 +205,13 @@ cl::opt<bool> PrintLines("line-numbers",
 
 cl::alias PrintLinesShort("l", cl::desc("Alias for -line-numbers"),
                           cl::aliasopt(PrintLines));
+
+cl::opt<unsigned long long>
+    StartAddress("start-address", cl::desc("Disassemble beginning at address"),
+                 cl::value_desc("address"), cl::init(0));
+cl::opt<unsigned long long>
+    StopAddress("stop-address", cl::desc("Stop disassembly at address"),
+                cl::value_desc("address"), cl::init(UINT64_MAX));
 static StringRef ToolName;
 
 namespace {
@@ -1060,6 +1067,9 @@ static uint8_t getElfSymbolType(const ObjectFile *Obj, const SymbolRef &Sym) {
 }
 
 static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
+  if (StartAddress > StopAddress)
+    error("Start address should be less than stop address");
+
   const Target *TheTarget = getTarget(Obj);
 
   // Package up features to be passed to target/subtarget
@@ -1238,10 +1248,14 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
     }
     StringRef name;
     error(Section.getName(name));
+
+    if ((SectionAddr <= StopAddress) &&
+        (SectionAddr + SectSize) >= StartAddress) {
     outs() << "Disassembly of section ";
     if (!SegmentName.empty())
       outs() << SegmentName << ",";
     outs() << name << ':';
+    }
 
     // If the section has no symbol at the start, just insert a dummy one.
     if (Symbols.empty() || std::get<0>(Symbols[0]) != 0) {
@@ -1278,6 +1292,17 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
       if (Start >= End)
         continue;
 
+      // Check if we need to skip symbol
+      // Skip if the symbol's data is not between StartAddress and StopAddress
+      if (End + SectionAddr < StartAddress ||
+          Start + SectionAddr > StopAddress) {
+        continue;
+      }
+
+      // Stop disassembly at the stop address specified
+      if (End + SectionAddr > StopAddress)
+        End = StopAddress - SectionAddr;
+
       if (Obj->isELF() && Obj->getArch() == Triple::amdgcn) {
         // make size 4 bytes folded
         End = Start + ((End - Start) & ~0x3ull);
@@ -1308,6 +1333,12 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
       for (Index = Start; Index < End; Index += Size) {
         MCInst Inst;
 
+        if (Index + SectionAddr < StartAddress ||
+            Index + SectionAddr > StopAddress) {
+          // skip byte by byte till StartAddress is reached
+          Size = 1;
+          continue;
+        }
         // 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 the data marker is within a
@@ -1384,6 +1415,9 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
           int NumBytes = 0;
 
           for (Index = Start; Index < End; Index += 1) {
+            if (((SectionAddr + Index) < StartAddress) ||
+                ((SectionAddr + Index) > StopAddress))
+              continue;
             if (NumBytes == 0) {
               outs() << format("%8" PRIx64 ":", SectionAddr + Index);
               outs() << "\t";
@@ -1489,7 +1523,10 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
           SmallString<32> val;
 
           // If this relocation is hidden, skip it.
-          if (hidden) goto skip_print_rel;
+          if (hidden || ((SectionAddr + addr) < StartAddress)) {
+            ++rel_cur;
+            continue;
+          }
 
           // Stop when rel_cur's address is past the current instruction.
           if (addr >= Index + Size) break;
@@ -1497,8 +1534,6 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
           error(getRelocationValueString(*rel_cur, val));
           outs() << format(Fmt.data(), SectionAddr + addr) << name
                  << "\t" << val << "\n";
-
-        skip_print_rel:
           ++rel_cur;
         }
       }
@@ -1525,7 +1560,7 @@ void llvm::PrintRelocations(const ObjectFile *Obj) {
       uint64_t address = Reloc.getOffset();
       SmallString<32> relocname;
       SmallString<32> valuestr;
-      if (hidden)
+      if (address < StartAddress || address > StopAddress || hidden)
         continue;
       Reloc.getTypeName(relocname);
       error(getRelocationValueString(Reloc, valuestr));
@@ -1616,6 +1651,8 @@ void llvm::PrintSymbolTable(const ObjectFile *o, StringRef ArchiveName,
     if (!AddressOrError)
       report_error(ArchiveName, o->getFileName(), AddressOrError.takeError());
     uint64_t Address = *AddressOrError;
+    if ((Address < StartAddress) || (Address > StopAddress))
+      continue;
     Expected<SymbolRef::Type> TypeOrError = Symbol.getType();
     if (!TypeOrError)
       report_error(ArchiveName, o->getFileName(), TypeOrError.takeError());