[llvm-objdump] - Implement the --adjust-vma option.

GNU objdump's help says: "--adjust-vma: Add OFFSET to all displayed section addresses"
In real life what it does is a bit more complicated
(and IMO not always reasonable. For example, GNU objdump prints not only VMA, but also LMA
for sections. And with --adjust-vma it adjusts LMA, but only when a section has relocations.
llvm-objsump does not seem to support printing LMAs yet, but GNU's logic anyways does not
make sense for me here).

This patch tries to adjust VMA. I tried to implement a reasonable approach.
I am not adjusting sections that are not allocatable. As, for example, adjusting debug sections
VA's and rel[a] sections VA's should not make sense. This behavior seems to be GNU compatible.

Differential revision: https://reviews.llvm.org/D57051

llvm-svn: 352347
diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp
index 9ac5266..8241765 100644
--- a/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -70,6 +70,11 @@
 using namespace llvm;
 using namespace object;
 
+cl::opt<unsigned long long> AdjustVMA(
+    "adjust-vma",
+    cl::desc("Increase the displayed address by the specified offset"),
+    cl::value_desc("offset"), cl::init(0));
+
 cl::opt<bool>
     llvm::AllHeaders("all-headers",
                      cl::desc("Display all available header information"));
@@ -890,6 +895,18 @@
   return Ret;
 }
 
+// Used for --adjust-vma to check if address should be adjusted by the
+// specified value for a given section.
+// For ELF we do not adjust non-allocatable sections like debug ones,
+// because they are not loadable.
+// TODO: implement for other file formats.
+static bool shouldAdjustVA(const SectionRef &Section) {
+  const ObjectFile *Obj = Section.getObject();
+  if (isa<object::ELFObjectFileBase>(Obj))
+    return ELFSectionRef(Section).getFlags() & ELF::SHF_ALLOC;
+  return false;
+}
+
 static void disassembleObject(const Target *TheTarget, const ObjectFile *Obj,
                               MCContext &Ctx, MCDisassembler *DisAsm,
                               const MCInstrAnalysis *MIA, MCInstPrinter *IP,
@@ -1046,6 +1063,10 @@
     ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(BytesStr.data()),
                             BytesStr.size());
 
+    uint64_t VMAAdjustment = 0;
+    if (shouldAdjustVA(Section))
+      VMAAdjustment = AdjustVMA;
+
     uint64_t Size;
     uint64_t Index;
     bool PrintedSection = false;
@@ -1110,7 +1131,8 @@
 
       outs() << '\n';
       if (!NoLeadingAddr)
-        outs() << format("%016" PRIx64 " ", SectionAddr + Start);
+        outs() << format("%016" PRIx64 " ",
+                         SectionAddr + Start + VMAAdjustment);
 
       StringRef SymbolName = std::get<1>(Symbols[SI]);
       if (Demangle)
@@ -1271,9 +1293,9 @@
         if (Size == 0)
           Size = 1;
 
-        PIP.printInst(*IP, Disassembled ? &Inst : nullptr,
-                      Bytes.slice(Index, Size), SectionAddr + Index, outs(), "",
-                      *STI, &SP, &Rels);
+        PIP.printInst(
+            *IP, Disassembled ? &Inst : nullptr, Bytes.slice(Index, Size),
+            SectionAddr + Index + VMAAdjustment, outs(), "", *STI, &SP, &Rels);
         outs() << CommentStream.str();
         Comments.clear();
 
@@ -1353,6 +1375,15 @@
             if (Offset >= Index + Size)
               break;
 
+            // When --adjust-vma is used, update the address printed.
+            if (RelCur->getSymbol() != Obj->symbol_end()) {
+              Expected<section_iterator> SymSI =
+                  RelCur->getSymbol()->getSection();
+              if (SymSI && *SymSI != Obj->section_end() &&
+                  (shouldAdjustVA(**SymSI)))
+                Offset += AdjustVMA;
+            }
+
             printRelocation(*RelCur, SectionAddr + Offset,
                             Obj->getBytesInAddress());
             ++RelCur;
@@ -1493,6 +1524,9 @@
     StringRef Name;
     error(Section.getName(Name));
     uint64_t Address = Section.getAddress();
+    if (shouldAdjustVA(Section))
+      Address += AdjustVMA;
+
     uint64_t Size = Section.getSize();
     bool Text = Section.isText();
     bool Data = Section.isData();