[llvm-readobj] MachO: Dump segment command.
authorDavide Italiano <davide@freebsd.org>
Wed, 2 Sep 2015 16:24:24 +0000 (16:24 +0000)
committerDavide Italiano <davide@freebsd.org>
Wed, 2 Sep 2015 16:24:24 +0000 (16:24 +0000)
Example output:

File: <stdin>
Format: Mach-O arm
Arch: arm
AddressSize: 32bit
Segment {
  Cmd: LC_SEGMENT
  Name:
  Size: 260
  vmaddr: 0x0
  vmsize: 0x10
  fileoff: 408
  filesize: 408
  maxprot: rwx
  initprot: rwx
  nsects: 3
  flags: 0x0
}

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

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

tools/llvm-readobj/MachODumper.cpp
tools/llvm-readobj/ObjDumper.h
tools/llvm-readobj/llvm-readobj.cpp

index 7b99a1ac90ee2e0e30964fff0abdbfc4d2fecfd3..a7c5d23b7e4c379f274bbaa90bcb511db97b8ae9 100644 (file)
@@ -44,6 +44,7 @@ public:
   void printMachODataInCode() override;
   void printMachOVersionMin() override;
   void printMachODysymtab() override;
+  void printMachOSegment() override;
 
 private:
   template<class MachHeader>
@@ -263,6 +264,20 @@ namespace {
     uint32_t Reserved3;
   };
 
+  struct MachOSegment {
+    StringRef CmdName;
+    StringRef SegName;
+    uint64_t cmdsize;
+    uint64_t vmaddr;
+    uint64_t vmsize;
+    uint64_t fileoff;
+    uint64_t filesize;
+    uint32_t maxprot;
+    uint32_t initprot;
+    uint32_t nsects;
+    uint32_t flags;
+  };
+
   struct MachOSymbol {
     uint32_t StringIndex;
     uint8_t Type;
@@ -272,6 +287,18 @@ namespace {
   };
 }
 
+static std::string getMask(uint32_t prot)
+{
+  // TODO (davide): This always assumes prot is valid.
+  // Catch mistakes and report if needed.
+  std::string Prot;
+  Prot = "";
+  Prot += (prot & MachO::VM_PROT_READ) ? "r" : "-";
+  Prot += (prot & MachO::VM_PROT_WRITE) ? "w" : "-";
+  Prot += (prot & MachO::VM_PROT_EXECUTE) ? "x" : "-";
+  return Prot;
+}
+
 static void getSection(const MachOObjectFile *Obj,
                        DataRefImpl Sec,
                        MachOSection &Section) {
@@ -301,6 +328,37 @@ static void getSection(const MachOObjectFile *Obj,
   Section.Reserved3   = Sect.reserved3;
 }
 
+static void getSegment(const MachOObjectFile *Obj,
+                       const MachOObjectFile::LoadCommandInfo &L,
+                       MachOSegment &Segment) {
+  if (!Obj->is64Bit()) {
+    MachO::segment_command SC = Obj->getSegmentLoadCommand(L);
+    Segment.CmdName = "LC_SEGMENT";
+    Segment.SegName = SC.segname;
+    Segment.cmdsize = SC.cmdsize;
+    Segment.vmaddr = SC.vmaddr;
+    Segment.vmsize = SC.vmsize;
+    Segment.fileoff = SC.fileoff;
+    Segment.filesize = SC.filesize;
+    Segment.maxprot = SC.maxprot;
+    Segment.initprot = SC.initprot;
+    Segment.nsects = SC.nsects;
+    Segment.flags = SC.flags;
+    return;
+  }
+  MachO::segment_command_64 SC = Obj->getSegment64LoadCommand(L);
+  Segment.CmdName = "LC_SEGMENT_64";
+  Segment.SegName = SC.segname;
+  Segment.cmdsize = SC.cmdsize;
+  Segment.vmaddr = SC.vmaddr;
+  Segment.vmsize = SC.vmsize;
+  Segment.fileoff = SC.fileoff;
+  Segment.filesize = SC.filesize;
+  Segment.maxprot = SC.maxprot;
+  Segment.initprot = SC.initprot;
+  Segment.nsects = SC.nsects;
+  Segment.flags = SC.flags;
+}
 
 static void getSymbol(const MachOObjectFile *Obj,
                       DataRefImpl DRI,
@@ -695,3 +753,24 @@ void MachODumper::printMachODysymtab() {
     }
   }
 }
+
+void MachODumper::printMachOSegment() {
+  for (const auto &Load : Obj->load_commands()) {
+    if (Load.C.cmd == MachO::LC_SEGMENT || Load.C.cmd == MachO::LC_SEGMENT_64) {
+      MachOSegment MOSegment;
+      getSegment(Obj, Load, MOSegment);
+      DictScope Group(W, "Segment");
+      W.printString("Cmd", MOSegment.CmdName);
+      W.printString("Name", MOSegment.SegName);
+      W.printNumber("Size", MOSegment.cmdsize);
+      W.printHex("vmaddr", MOSegment.vmaddr);
+      W.printHex("vmsize", MOSegment.vmsize);
+      W.printNumber("fileoff", MOSegment.fileoff);
+      W.printNumber("filesize", MOSegment.fileoff);
+      W.printString("maxprot", getMask(MOSegment.maxprot));
+      W.printString("initprot", getMask(MOSegment.initprot));
+      W.printNumber("nsects", MOSegment.nsects);
+      W.printHex("flags", MOSegment.flags);
+    }
+  }
+}
index 22051708efaf6da1debb62b5bf03b2fc6b6b74f4..5fea403322d67d53a94a1fa06cb9ab35e4aa4284 100644 (file)
@@ -59,6 +59,7 @@ public:
   virtual void printMachODataInCode() { }
   virtual void printMachOVersionMin() { }
   virtual void printMachODysymtab() { }
+  virtual void printMachOSegment() { }
 
   virtual void printStackMap() const = 0;
 
index c0e6add4f2cde446881d62cf19c8e63892cf1731..f63bc81002f9f43f768ca64a7233cea6de98dd03 100644 (file)
@@ -187,6 +187,11 @@ namespace opts {
   MachODataInCode("macho-data-in-code",
                   cl::desc("Display MachO Data in Code command"));
 
+  // -macho-segment
+  cl::opt<bool>
+  MachOSegment("macho-segment",
+                  cl::desc("Display MachO Segment command"));
+
   // -macho-version-min
   cl::opt<bool>
   MachOVersionMin("macho-version-min",
@@ -331,6 +336,8 @@ static void dumpObject(const ObjectFile *Obj) {
   if (Obj->isMachO()) {
     if (opts::MachODataInCode)
       Dumper->printMachODataInCode();
+    if (opts::MachOSegment)
+      Dumper->printMachOSegment();
     if (opts::MachOVersionMin)
       Dumper->printMachOVersionMin();
     if (opts::MachODysymtab)