Avoid printing absolute addresses in oatdump

- Added printing of OatClass offsets.
- Added printing of OatMethod offsets.
- Added bounds checks for code size size, code size, mapping table, gc map, vmap table.
- Added sanity check of 100k for code size.
- Added partial disassembly of questionable code.
- Added --no-disassemble to disable disassembly.
- Added --no-dump:vmap to disable vmap dumping.
- Reordered OatMethod info to be in file order.

Bug: 15567083

(cherry picked from commit 34fa79ece5b3a1940d412cd94dbdcc4225aae72f)

Change-Id: I2c368f3b81af53b735149a866f3e491c9ac33fb8
diff --git a/disassembler/disassembler.cc b/disassembler/disassembler.cc
index 41ee213..c97bf64 100644
--- a/disassembler/disassembler.cc
+++ b/disassembler/disassembler.cc
@@ -19,6 +19,7 @@
 #include <iostream>
 
 #include "base/logging.h"
+#include "base/stringprintf.h"
 #include "disassembler_arm.h"
 #include "disassembler_arm64.h"
 #include "disassembler_mips.h"
@@ -26,21 +27,30 @@
 
 namespace art {
 
-Disassembler* Disassembler::Create(InstructionSet instruction_set) {
+Disassembler* Disassembler::Create(InstructionSet instruction_set, DisassemblerOptions* options) {
   if (instruction_set == kArm || instruction_set == kThumb2) {
-    return new arm::DisassemblerArm();
+    return new arm::DisassemblerArm(options);
   } else if (instruction_set == kArm64) {
-    return new arm64::DisassemblerArm64();
+    return new arm64::DisassemblerArm64(options);
   } else if (instruction_set == kMips) {
-    return new mips::DisassemblerMips();
+    return new mips::DisassemblerMips(options);
   } else if (instruction_set == kX86) {
-    return new x86::DisassemblerX86(false);
+    return new x86::DisassemblerX86(options, false);
   } else if (instruction_set == kX86_64) {
-    return new x86::DisassemblerX86(true);
+    return new x86::DisassemblerX86(options, true);
   } else {
     UNIMPLEMENTED(FATAL) << "no disassembler for " << instruction_set;
     return NULL;
   }
 }
 
+std::string Disassembler::FormatInstructionPointer(const uint8_t* begin) {
+  if (disassembler_options_->absolute_addresses_) {
+    return StringPrintf("%p", begin);
+  } else {
+    size_t offset = begin - disassembler_options_->base_address_;
+    return StringPrintf("0x%08zx", offset);
+  }
+}
+
 }  // namespace art
diff --git a/disassembler/disassembler.h b/disassembler/disassembler.h
index 183e692..487f433 100644
--- a/disassembler/disassembler.h
+++ b/disassembler/disassembler.h
@@ -26,10 +26,31 @@
 
 namespace art {
 
+class DisassemblerOptions {
+ public:
+  // Should the disassembler print absolute or relative addresses.
+  const bool absolute_addresses_;
+
+  // Base addess for calculating relative code offsets when absolute_addresses_ is false.
+  const uint8_t* const base_address_;
+
+  DisassemblerOptions(bool absolute_addresses, const uint8_t* base_address)
+      : absolute_addresses_(absolute_addresses), base_address_(base_address) {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DisassemblerOptions);
+};
+
 class Disassembler {
  public:
-  static Disassembler* Create(InstructionSet instruction_set);
-  virtual ~Disassembler() {}
+  // Creates a Disassembler for the given InstructionSet with the
+  // non-null DisassemblerOptions which become owned by the
+  // Disassembler.
+  static Disassembler* Create(InstructionSet instruction_set, DisassemblerOptions* options);
+
+  virtual ~Disassembler() {
+    delete disassembler_options_;
+  }
 
   // Dump a single instruction returning the length of that instruction.
   virtual size_t Dump(std::ostream& os, const uint8_t* begin) = 0;
@@ -37,9 +58,15 @@
   virtual void Dump(std::ostream& os, const uint8_t* begin, const uint8_t* end) = 0;
 
  protected:
-  Disassembler() {}
+  explicit Disassembler(DisassemblerOptions* disassembler_options)
+      : disassembler_options_(disassembler_options) {
+    CHECK(disassembler_options_ != nullptr);
+  }
+
+  std::string FormatInstructionPointer(const uint8_t* begin);
 
  private:
+  DisassemblerOptions* disassembler_options_;
   DISALLOW_COPY_AND_ASSIGN(Disassembler);
 };
 
diff --git a/disassembler/disassembler_arm.cc b/disassembler/disassembler_arm.cc
index 56023c1..54e7761 100644
--- a/disassembler/disassembler_arm.cc
+++ b/disassembler/disassembler_arm.cc
@@ -94,7 +94,7 @@
 }
 
 void DisassemblerArm::DumpBranchTarget(std::ostream& os, const uint8_t* instr_ptr, int32_t imm32) {
-  os << StringPrintf("%+d (%p)", imm32, instr_ptr + imm32);
+  os << StringPrintf("%+d (", imm32) << FormatInstructionPointer(instr_ptr + imm32) << ")";
 }
 
 static uint32_t ReadU16(const uint8_t* ptr) {
@@ -356,7 +356,9 @@
     opcode += kConditionCodeNames[cond];
     opcode += suffixes;
     // TODO: a more complete ARM disassembler could generate wider opcodes.
-    os << StringPrintf("%p: %08x\t%-7s ", instr_ptr, instruction, opcode.c_str()) << args.str() << '\n';
+    os << FormatInstructionPointer(instr_ptr)
+       << StringPrintf(": %08x\t%-7s ", instruction, opcode.c_str())
+       << args.str() << '\n';
 }
 
 int32_t ThumbExpand(int32_t imm12) {
@@ -1608,7 +1610,9 @@
     opcode << "UNKNOWN " << op2;
   }
 
-  os << StringPrintf("%p: %08x\t%-7s ", instr_ptr, instr, opcode.str().c_str()) << args.str() << '\n';
+  os << FormatInstructionPointer(instr_ptr)
+     << StringPrintf(": %08x\t%-7s ", instr, opcode.str().c_str())
+     << args.str() << '\n';
   return 4;
 }  // NOLINT(readability/fn_size)
 
@@ -1936,7 +1940,9 @@
       it_conditions_.pop_back();
     }
 
-    os << StringPrintf("%p: %04x    \t%-7s ", instr_ptr, instr, opcode.str().c_str()) << args.str() << '\n';
+    os << FormatInstructionPointer(instr_ptr)
+       << StringPrintf(": %04x    \t%-7s ", instr, opcode.str().c_str())
+       << args.str() << '\n';
   }
   return 2;
 }
diff --git a/disassembler/disassembler_arm.h b/disassembler/disassembler_arm.h
index f6d7fda..f870e8e 100644
--- a/disassembler/disassembler_arm.h
+++ b/disassembler/disassembler_arm.h
@@ -26,8 +26,7 @@
 
 class DisassemblerArm FINAL : public Disassembler {
  public:
-  DisassemblerArm() {
-  }
+  explicit DisassemblerArm(DisassemblerOptions* options) : Disassembler(options) {}
 
   size_t Dump(std::ostream& os, const uint8_t* begin) OVERRIDE;
   void Dump(std::ostream& os, const uint8_t* begin, const uint8_t* end) OVERRIDE;
diff --git a/disassembler/disassembler_arm64.cc b/disassembler/disassembler_arm64.cc
index 864d22d..5d0c218 100644
--- a/disassembler/disassembler_arm64.cc
+++ b/disassembler/disassembler_arm64.cc
@@ -34,7 +34,8 @@
 size_t DisassemblerArm64::Dump(std::ostream& os, const uint8_t* begin) {
   uint32_t instruction = ReadU32(begin);
   decoder.Decode(reinterpret_cast<vixl::Instruction*>(&instruction));
-  os << StringPrintf("%p: %08x\t%s\n", begin, instruction, disasm.GetOutput());
+  os << FormatInstructionPointer(begin)
+     << StringPrintf(": %08x\t%s\n", instruction, disasm.GetOutput());
   return vixl::kInstructionSize;
 }
 
diff --git a/disassembler/disassembler_arm64.h b/disassembler/disassembler_arm64.h
index 28c0fa7..ad20c70 100644
--- a/disassembler/disassembler_arm64.h
+++ b/disassembler/disassembler_arm64.h
@@ -27,7 +27,7 @@
 
 class DisassemblerArm64 FINAL : public Disassembler {
  public:
-  DisassemblerArm64() {
+  explicit DisassemblerArm64(DisassemblerOptions* options) : Disassembler(options) {
     decoder.AppendVisitor(&disasm);
   }
 
diff --git a/disassembler/disassembler_mips.cc b/disassembler/disassembler_mips.cc
index 5e89f6f..bd5fac7 100644
--- a/disassembler/disassembler_mips.cc
+++ b/disassembler/disassembler_mips.cc
@@ -168,7 +168,7 @@
   return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
 }
 
-static void DumpMips(std::ostream& os, const uint8_t* instr_ptr) {
+size_t DisassemblerMips::Dump(std::ostream& os, const uint8_t* instr_ptr) {
   uint32_t instruction = ReadU32(instr_ptr);
 
   uint32_t rs = (instruction >> 21) & 0x1f;  // I-type, R-type.
@@ -197,7 +197,8 @@
               int32_t offset = static_cast<int16_t>(instruction & 0xffff);
               offset <<= 2;
               offset += 4;  // Delay slot.
-              args << StringPrintf("%p  ; %+d", instr_ptr + offset, offset);
+              args << FormatInstructionPointer(instr_ptr + offset)
+                   << StringPrintf("  ; %+d", offset);
             }
             break;
           case 'D': args << 'r' << rd; break;
@@ -254,17 +255,15 @@
     }
   }
 
-  os << StringPrintf("%p: %08x\t%-7s ", instr_ptr, instruction, opcode.c_str()) << args.str() << '\n';
-}
-
-size_t DisassemblerMips::Dump(std::ostream& os, const uint8_t* begin) {
-  DumpMips(os, begin);
+  os << FormatInstructionPointer(instr_ptr)
+     << StringPrintf(": %08x\t%-7s ", instruction, opcode.c_str())
+     << args.str() << '\n';
   return 4;
 }
 
 void DisassemblerMips::Dump(std::ostream& os, const uint8_t* begin, const uint8_t* end) {
   for (const uint8_t* cur = begin; cur < end; cur += 4) {
-    DumpMips(os, cur);
+    Dump(os, cur);
   }
 }
 
diff --git a/disassembler/disassembler_mips.h b/disassembler/disassembler_mips.h
index e1fb034..00b2f8d 100644
--- a/disassembler/disassembler_mips.h
+++ b/disassembler/disassembler_mips.h
@@ -26,8 +26,7 @@
 
 class DisassemblerMips FINAL : public Disassembler {
  public:
-  DisassemblerMips() {
-  }
+  explicit DisassemblerMips(DisassemblerOptions* options) : Disassembler(options) {}
 
   size_t Dump(std::ostream& os, const uint8_t* begin) OVERRIDE;
   void Dump(std::ostream& os, const uint8_t* begin, const uint8_t* end) OVERRIDE;
diff --git a/disassembler/disassembler_x86.cc b/disassembler/disassembler_x86.cc
index 1848abe..1d29765 100644
--- a/disassembler/disassembler_x86.cc
+++ b/disassembler/disassembler_x86.cc
@@ -1215,7 +1215,9 @@
       displacement = *reinterpret_cast<const int32_t*>(instr);
       instr += 4;
     }
-    args << StringPrintf("%+d (%p)", displacement, instr + displacement);
+    args << StringPrintf("%+d (", displacement)
+         << FormatInstructionPointer(instr + displacement)
+         << ")";
   }
   if (prefix[1] == kFs && !supports_rex_) {
     args << "  ; ";
@@ -1238,8 +1240,8 @@
     default: LOG(FATAL) << "Unreachable";
   }
   prefixed_opcode << opcode.str();
-  os << StringPrintf("%p: %22s    \t%-7s ", begin_instr, hex.str().c_str(),
-                     prefixed_opcode.str().c_str())
+  os << FormatInstructionPointer(begin_instr)
+     << StringPrintf(": %22s    \t%-7s ", hex.str().c_str(), prefixed_opcode.str().c_str())
      << args.str() << '\n';
   return instr - begin_instr;
 }  // NOLINT(readability/fn_size)
diff --git a/disassembler/disassembler_x86.h b/disassembler/disassembler_x86.h
index 2565bb1..f448662 100644
--- a/disassembler/disassembler_x86.h
+++ b/disassembler/disassembler_x86.h
@@ -24,8 +24,8 @@
 
 class DisassemblerX86 FINAL : public Disassembler {
  public:
-  explicit DisassemblerX86(bool supports_rex) : supports_rex_(supports_rex) {
-  }
+  DisassemblerX86(DisassemblerOptions* options, bool supports_rex)
+      : Disassembler(options), supports_rex_(supports_rex) {}
 
   size_t Dump(std::ostream& os, const uint8_t* begin) OVERRIDE;
   void Dump(std::ostream& os, const uint8_t* begin, const uint8_t* end) OVERRIDE;