Add 179294 back, but don't use bit fields so that it works on big endian hosts.
authorRafael Espindola <rafael.espindola@gmail.com>
Fri, 12 Apr 2013 00:17:33 +0000 (00:17 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Fri, 12 Apr 2013 00:17:33 +0000 (00:17 +0000)
Original message:

Print more information about relocations.

With this patch llvm-readobj now prints if a relocation is pcrel, its length,
if it is extern and if it is scattered.

It also refactors the code a bit to use bit fields instead of shifts and
masks all over the place.

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

include/llvm/Object/MachO.h
lib/Object/MachOObjectFile.cpp
test/tools/llvm-readobj/relocations.test
test/tools/llvm-readobj/sections-ext.test
tools/llvm-readobj/MachODumper.cpp

index b02e1ac100761f7b58120ec6a60381699f475a75..9b7a07372da08b08c12d1c340dd2e69a9a38b173 100644 (file)
@@ -112,11 +112,53 @@ namespace MachOFormat {
     MachOInt32 Reserved3;
   };
 
+  struct MachOInt24 {
+    uint8_t bytes[3];
+    operator uint32_t() const {
+      return (bytes[2] << 24) | (bytes[1] << 16) | bytes[0];
+    }
+  };
+
   template<endianness TargetEndianness>
   struct RelocationEntry {
     LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
-    MachOInt32 Word0;
-    MachOInt32 Word1;
+    MachOInt32 Address;
+    MachOInt24 SymbolNum;
+    uint8_t Bits;
+
+    unsigned getPCRel() const {
+      return Bits & 0x1;
+    }
+    unsigned getLength() const {
+      return (Bits >> 1) & 0x3;
+    }
+    unsigned getExternal() const {
+      return (Bits >> 3) & 0x1;
+    }
+    unsigned getType() const {
+      return Bits >> 4;
+    }
+  };
+
+  template<endianness TargetEndianness>
+  struct ScatteredRelocationEntry {
+    LLVM_MACHOB_IMPORT_TYPES(TargetEndianness)
+    MachOInt24 Address;
+    uint8_t Bits;
+    MachOInt32 Value;
+
+    unsigned getType() const {
+      return Bits & 0xf;
+    }
+    unsigned getLength() const {
+      return (Bits >> 4) & 0x3;
+    }
+    unsigned getPCRel() const {
+      return (Bits >> 6) & 0x1;
+    }
+    unsigned getScattered() const {
+      return Bits >> 7;
+    }
   };
 
   template<endianness TargetEndianness>
@@ -206,6 +248,8 @@ public:
     SymbolTableEntryBase;
   typedef MachOFormat::SymtabLoadCommand<support::little> SymtabLoadCommand;
   typedef MachOFormat::RelocationEntry<support::little> RelocationEntry;
+  typedef MachOFormat::ScatteredRelocationEntry<support::little>
+    ScatteredRelocationEntry;
   typedef MachOFormat::SectionBase SectionBase;
   typedef MachOFormat::LoadCommand<support::little> LoadCommand;
   typedef MachOFormat::Header<support::little> Header;
@@ -243,6 +287,11 @@ public:
   const Header *getHeader() const;
   unsigned getHeaderSize() const;
   StringRef getData(size_t Offset, size_t Size) const;
+  const RelocationEntry *getRelocation(DataRefImpl Rel) const;
+  bool isScattered(const RelocationEntry *RE) const;
+  bool isPCRel(const RelocationEntry *RE) const;
+  unsigned getLength(const RelocationEntry *RE) const;
+  unsigned getType(const RelocationEntry *RE) const;
 
   static inline bool classof(const Binary *v) {
     return v->isMachO();
@@ -479,15 +528,12 @@ MachOObjectFile<MachOT>::getRelocationAddress(DataRefImpl Rel,
   const Section *Sect = getSection(Sections[Rel.d.b]);
   uint64_t SectAddress = Sect->Address;
   const RelocationEntry *RE = getRelocation(Rel);
-  unsigned Arch = getArch();
-  bool isScattered = (Arch != Triple::x86_64) &&
-                     (RE->Word0 & macho::RF_Scattered);
 
   uint64_t RelAddr;
-  if (isScattered)
-    RelAddr = RE->Word0 & 0xFFFFFF;
+  if (isScattered(RE))
+    RelAddr = RE->Address & 0xFFFFFF;
   else
-    RelAddr = RE->Word0;
+    RelAddr = RE->Address;
 
   Res = SectAddress + RelAddr;
   return object_error::success;
@@ -498,14 +544,10 @@ error_code
 MachOObjectFile<MachOT>::getRelocationOffset(DataRefImpl Rel,
                                              uint64_t &Res) const {
   const RelocationEntry *RE = getRelocation(Rel);
-
-  unsigned Arch = getArch();
-  bool isScattered = (Arch != Triple::x86_64) &&
-                     (RE->Word0 & macho::RF_Scattered);
-  if (isScattered)
-    Res = RE->Word0 & 0xFFFFFF;
+  if (isScattered(RE))
+    Res = RE->Address & 0xFFFFFF;
   else
-    Res = RE->Word0;
+    Res = RE->Address;
   return object_error::success;
 }
 
@@ -514,8 +556,8 @@ error_code
 MachOObjectFile<MachOT>::getRelocationSymbol(DataRefImpl Rel,
                                              SymbolRef &Res) const {
   const RelocationEntry *RE = getRelocation(Rel);
-  uint32_t SymbolIdx = RE->Word1 & 0xffffff;
-  bool isExtern = (RE->Word1 >> 27) & 1;
+  uint32_t SymbolIdx = RE->SymbolNum;
+  bool isExtern = RE->getExternal();
 
   DataRefImpl Sym;
   moveToNextSymbol(Sym);
@@ -535,9 +577,7 @@ template<class MachOT>
 error_code MachOObjectFile<MachOT>::getRelocationType(DataRefImpl Rel,
                                                       uint64_t &Res) const {
   const RelocationEntry *RE = getRelocation(Rel);
-  Res = RE->Word0;
-  Res <<= 32;
-  Res |= RE->Word1;
+  Res = getType(RE);
   return object_error::success;
 }
 
@@ -550,14 +590,8 @@ MachOObjectFile<MachOT>::getRelocationTypeName(DataRefImpl Rel,
   const RelocationEntry *RE = getRelocation(Rel);
 
   unsigned Arch = getArch();
-  bool isScattered = (Arch != Triple::x86_64) &&
-                     (RE->Word0 & macho::RF_Scattered);
 
-  unsigned r_type;
-  if (isScattered)
-    r_type = (RE->Word0 >> 24) & 0xF;
-  else
-    r_type = (RE->Word1 >> 28) & 0xF;
+  unsigned r_type = getType(RE);
 
   switch (Arch) {
     case Triple::x86: {
@@ -650,30 +684,20 @@ MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel,
   const RelocationEntry *RE = getRelocation(Rel);
 
   unsigned Arch = getArch();
-  bool isScattered = (Arch != Triple::x86_64) &&
-                     (RE->Word0 & macho::RF_Scattered);
+  bool IsScattered = isScattered(RE);
 
   std::string fmtbuf;
   raw_string_ostream fmt(fmtbuf);
 
-  unsigned Type;
-  if (isScattered)
-    Type = (RE->Word0 >> 24) & 0xF;
-  else
-    Type = (RE->Word1 >> 28) & 0xF;
-
-  bool isPCRel;
-  if (isScattered)
-    isPCRel = ((RE->Word0 >> 30) & 1);
-  else
-    isPCRel = ((RE->Word1 >> 24) & 1);
+  unsigned Type = getType(RE);
+  bool IsPCRel = isPCRel(RE);
 
   // Determine any addends that should be displayed with the relocation.
   // These require decoding the relocation type, which is triple-specific.
 
   // X86_64 has entirely custom relocation types.
   if (Arch == Triple::x86_64) {
-    bool isPCRel = ((RE->Word1 >> 24) & 1);
+    bool isPCRel = RE->getPCRel();
 
     switch (Type) {
       case macho::RIT_X86_64_GOTLoad:   // X86_64_RELOC_GOT_LOAD
@@ -691,7 +715,7 @@ MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel,
         // X86_64_SUBTRACTOR must be followed by a relocation of type
         // X86_64_RELOC_UNSIGNED.
         // NOTE: Scattered relocations don't exist on x86_64.
-        unsigned RType = (RENext->Word1 >> 28) & 0xF;
+        unsigned RType = RENext->getType();
         if (RType != 0)
           report_fatal_error("Expected X86_64_RELOC_UNSIGNED after "
                              "X86_64_RELOC_SUBTRACTOR.");
@@ -738,12 +762,12 @@ MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel,
         // X86 sect diff's must be followed by a relocation of type
         // GENERIC_RELOC_PAIR.
         bool isNextScattered = (Arch != Triple::x86_64) &&
-                               (RENext->Word0 & macho::RF_Scattered);
+                               (RENext->Address & macho::RF_Scattered);
         unsigned RType;
         if (isNextScattered)
-          RType = (RENext->Word0 >> 24) & 0xF;
+          RType = (RENext->Address >> 24) & 0xF;
         else
-          RType = (RENext->Word1 >> 28) & 0xF;
+          RType = RENext->getType();
         if (RType != 1)
           report_fatal_error("Expected GENERIC_RELOC_PAIR after "
                              "GENERIC_RELOC_SECTDIFF.");
@@ -767,12 +791,12 @@ MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel,
           // X86 sect diff's must be followed by a relocation of type
           // GENERIC_RELOC_PAIR.
           bool isNextScattered = (Arch != Triple::x86_64) &&
-                               (RENext->Word0 & macho::RF_Scattered);
+                               (RENext->Address & macho::RF_Scattered);
           unsigned RType;
           if (isNextScattered)
-            RType = (RENext->Word0 >> 24) & 0xF;
+            RType = (RENext->Address >> 24) & 0xF;
           else
-            RType = (RENext->Word1 >> 28) & 0xF;
+            RType = RENext->getType();
           if (RType != 1)
             report_fatal_error("Expected GENERIC_RELOC_PAIR after "
                                "GENERIC_RELOC_LOCAL_SECTDIFF.");
@@ -785,7 +809,7 @@ MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel,
         case macho::RIT_Generic_TLV: {
           printRelocationTargetName(RE, fmt);
           fmt << "@TLV";
-          if (isPCRel) fmt << "P";
+          if (IsPCRel) fmt << "P";
           break;
         }
         default:
@@ -798,10 +822,10 @@ MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel,
           // Half relocations steal a bit from the length field to encode
           // whether this is an upper16 or a lower16 relocation.
           bool isUpper;
-          if (isScattered)
-            isUpper = (RE->Word0 >> 28) & 1;
+          if (IsScattered)
+            isUpper = (RE->Address >> 28) & 1;
           else
-            isUpper = (RE->Word1 >> 25) & 1;
+            isUpper = (RE->getLength() >> 1) & 1;
 
           if (isUpper)
             fmt << ":upper16:(";
@@ -816,12 +840,12 @@ MachOObjectFile<MachOT>::getRelocationValueString(DataRefImpl Rel,
           // ARM half relocs must be followed by a relocation of type
           // ARM_RELOC_PAIR.
           bool isNextScattered = (Arch != Triple::x86_64) &&
-                                 (RENext->Word0 & macho::RF_Scattered);
+                                 (RENext->Address & macho::RF_Scattered);
           unsigned RType;
           if (isNextScattered)
-            RType = (RENext->Word0 >> 24) & 0xF;
+            RType = (RENext->Address >> 24) & 0xF;
           else
-            RType = (RENext->Word1 >> 28) & 0xF;
+            RType = RENext->getType();
 
           if (RType != 1)
             report_fatal_error("Expected ARM_RELOC_PAIR after "
@@ -860,15 +884,8 @@ error_code
 MachOObjectFile<MachOT>::getRelocationHidden(DataRefImpl Rel,
                                              bool &Result) const {
   const RelocationEntry *RE = getRelocation(Rel);
-
   unsigned Arch = getArch();
-  bool isScattered = (Arch != Triple::x86_64) &&
-                     (RE->Word0 & macho::RF_Scattered);
-  unsigned Type;
-  if (isScattered)
-    Type = (RE->Word0 >> 24) & 0xF;
-  else
-    Type = (RE->Word1 >> 28) & 0xF;
+  unsigned Type = getType(RE);
 
   Result = false;
 
@@ -884,7 +901,7 @@ MachOObjectFile<MachOT>::getRelocationHidden(DataRefImpl Rel,
       RelPrev.d.a--;
       const RelocationEntry *REPrev = getRelocation(RelPrev);
 
-      unsigned PrevType = (REPrev->Word1 >> 28) & 0xF;
+      unsigned PrevType = REPrev->getType();
 
       if (PrevType == macho::RIT_X86_64_Subtractor) Result = true;
     }
index c846206e6e4b099c142f951deef9866a15c67bb3..627e7485a6bb15e48c9bd8e0cda005113681fbaf 100644 (file)
@@ -80,6 +80,46 @@ StringRef MachOObjectFileBase::getData(size_t Offset, size_t Size) const {
   return ObjectFile::getData().substr(Offset, Size);
 }
 
+const MachOObjectFileBase::RelocationEntry *
+MachOObjectFileBase::getRelocation(DataRefImpl Rel) const {
+  if (const MachOObjectFile32Le *O = dyn_cast<MachOObjectFile32Le>(this))
+    return O->getRelocation(Rel);
+  const MachOObjectFile64Le *O = dyn_cast<MachOObjectFile64Le>(this);
+  return O->getRelocation(Rel);
+}
+
+bool MachOObjectFileBase::isScattered(const RelocationEntry *RE) const {
+  unsigned Arch = getArch();
+  return (Arch != Triple::x86_64) && (RE->Address & macho::RF_Scattered);
+}
+
+bool MachOObjectFileBase::isPCRel(const RelocationEntry *RE) const {
+  if (isScattered(RE)) {
+    const ScatteredRelocationEntry *SRE =
+      reinterpret_cast<const ScatteredRelocationEntry *>(RE);
+    return SRE->getPCRel();
+  }
+  return RE->getPCRel();
+}
+
+unsigned MachOObjectFileBase::getLength(const RelocationEntry *RE) const {
+  if (isScattered(RE)) {
+    const ScatteredRelocationEntry *SRE =
+      reinterpret_cast<const ScatteredRelocationEntry *>(RE);
+    return SRE->getLength();
+  }
+  return RE->getLength();
+}
+
+unsigned MachOObjectFileBase::getType(const RelocationEntry *RE) const {
+  if (isScattered(RE)) {
+    const ScatteredRelocationEntry *SRE =
+      reinterpret_cast<const ScatteredRelocationEntry *>(RE);
+    return SRE->getType();
+  }
+  return RE->getType();
+}
+
 ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
   StringRef Magic = Buffer->getBuffer().slice(0, 4);
   error_code ec;
@@ -435,16 +475,12 @@ void advanceTo(T &it, size_t Val) {
 void
 MachOObjectFileBase::printRelocationTargetName(const RelocationEntry *RE,
                                                raw_string_ostream &fmt) const {
-  unsigned Arch = getArch();
-  bool isScattered = (Arch != Triple::x86_64) &&
-                     (RE->Word0 & macho::RF_Scattered);
-
   // Target of a scattered relocation is an address.  In the interest of
   // generating pretty output, scan through the symbol table looking for a
   // symbol that aligns with that address.  If we find one, print it.
   // Otherwise, we just print the hex address of the target.
-  if (isScattered) {
-    uint32_t Val = RE->Word1;
+  if (isScattered(RE)) {
+    uint32_t Val = RE->SymbolNum;
 
     error_code ec;
     for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE;
@@ -486,8 +522,8 @@ MachOObjectFileBase::printRelocationTargetName(const RelocationEntry *RE,
   }
 
   StringRef S;
-  bool isExtern = (RE->Word1 >> 27) & 1;
-  uint32_t Val = RE->Word1 & 0xFFFFFF;
+  bool isExtern = RE->getExternal();
+  uint32_t Val = RE->Address;
 
   if (isExtern) {
     symbol_iterator SI = begin_symbols();
index b4b876a70b09f2733c33a54d209a6c625deee8e4..96aac231dba92ef170c41cee2a22b9ef74e5e67b 100644 (file)
@@ -26,17 +26,17 @@ ELF-NEXT: ]
 
 MACHO-I386:      Relocations [
 MACHO-I386-NEXT:   Section __text {
-MACHO-I386-NEXT:     0x18 GENERIC_RELOC_VANILLA _SomeOtherFunction 0x0
-MACHO-I386-NEXT:     0x13 GENERIC_RELOC_VANILLA _puts 0x0
-MACHO-I386-NEXT:     0xB GENERIC_RELOC_LOCAL_SECTDIFF _main 0x{{[0-9A-F]+}}
-MACHO-I386-NEXT:     0x0 GENERIC_RELOC_PAIR _main 0x{{[0-9A-F]+}}
+MACHO-I386-NEXT:     0x18 1 2 1 GENERIC_RELOC_VANILLA 0 _SomeOtherFunction
+MACHO-I386-NEXT:     0x13 1 2 1 GENERIC_RELOC_VANILLA 0 _puts
+MACHO-I386-NEXT:     0xB 0 2 n/a GENERIC_RELOC_LOCAL_SECTDIFF 1 _main
+MACHO-I386-NEXT:     0x0 0 2 n/a GENERIC_RELOC_PAIR 1 _main
 MACHO-I386-NEXT:   }
 MACHO-I386-NEXT: ]
 
 MACHO-X86-64: Relocations [
 MACHO-X86-64-NEXT:  Section __text {
-MACHO-X86-64-NEXT:    0xE X86_64_RELOC_BRANCH _SomeOtherFunction 0x0
-MACHO-X86-64-NEXT:    0x9 X86_64_RELOC_BRANCH _puts 0x0
-MACHO-X86-64-NEXT:    0x4 X86_64_RELOC_SIGNED L_.str 0x0
+MACHO-X86-64-NEXT:    0xE 1 2 1 X86_64_RELOC_BRANCH 0 _SomeOtherFunction
+MACHO-X86-64-NEXT:    0x9 1 2 1 X86_64_RELOC_BRANCH 0 _puts
+MACHO-X86-64-NEXT:    0x4 1 2 1 X86_64_RELOC_SIGNED 0 L_.str
 MACHO-X86-64-NEXT:  }
 MACHO-X86-64-NEXT:]
index a16bca2b19d1f7878f7b6653c1780703c67507ac..a12d9e4646624d3b7c33c443667bb4ec524b4166 100644 (file)
@@ -153,10 +153,10 @@ MACHO-I386-NEXT:     ]
 MACHO-I386-NEXT:     Reserved1: 0x0
 MACHO-I386-NEXT:     Reserved2: 0x0
 MACHO-I386-NEXT:     Relocations [
-MACHO-I386-NEXT:       0x18 GENERIC_RELOC_VANILLA _SomeOtherFunction 0x0
-MACHO-I386-NEXT:       0x13 GENERIC_RELOC_VANILLA _puts 0x0
-MACHO-I386-NEXT:       0xB GENERIC_RELOC_LOCAL_SECTDIFF _main 0x{{[0-9A-F]+}}
-MACHO-I386-NEXT:       0x0 GENERIC_RELOC_PAIR _main 0x{{[0-9A-F]+}}
+MACHO-I386-NEXT:       0x18 1 2 1 GENERIC_RELOC_VANILLA 0 _SomeOtherFunction
+MACHO-I386-NEXT:       0x13 1 2 1 GENERIC_RELOC_VANILLA 0 _puts
+MACHO-I386-NEXT:       0xB 0 2 n/a GENERIC_RELOC_LOCAL_SECTDIFF 1 _main
+MACHO-I386-NEXT:       0x0 0 2 n/a GENERIC_RELOC_PAIR 1 _main
 MACHO-I386-NEXT:     ]
 MACHO-I386-NEXT:     Symbols [
 MACHO-I386-NEXT:       Symbol {
@@ -196,9 +196,9 @@ MACHO-X86-64-NEXT:    ]
 MACHO-X86-64-NEXT:    Reserved1: 0x0
 MACHO-X86-64-NEXT:    Reserved2: 0x0
 MACHO-X86-64-NEXT:    Relocations [
-MACHO-X86-64-NEXT:      0xE X86_64_RELOC_BRANCH _SomeOtherFunction 0x0
-MACHO-X86-64-NEXT:      0x9 X86_64_RELOC_BRANCH _puts 0x0
-MACHO-X86-64-NEXT:      0x4 X86_64_RELOC_SIGNED L_.str 0x0
+MACHO-X86-64-NEXT:      0xE 1 2 1 X86_64_RELOC_BRANCH 0 _SomeOtherFunction
+MACHO-X86-64-NEXT:      0x9 1 2 1 X86_64_RELOC_BRANCH 0 _puts
+MACHO-X86-64-NEXT:      0x4 1 2 1 X86_64_RELOC_SIGNED 0 L_.str
 MACHO-X86-64-NEXT:    ]
 MACHO-X86-64-NEXT:    Symbols [
 MACHO-X86-64-NEXT:      Symbol {
index 2073ddf46390ae76c43d405fa5886a9d911c92b3..a13593b44836803db45adeb33e92fbfd4af57ccc 100644 (file)
@@ -330,20 +330,28 @@ void MachODumper::printRelocation(section_iterator SecI,
                                   relocation_iterator RelI) {
   uint64_t Offset;
   SmallString<32> RelocName;
-  int64_t Info;
   StringRef SymbolName;
   SymbolRef Symbol;
   if (error(RelI->getOffset(Offset))) return;
   if (error(RelI->getTypeName(RelocName))) return;
-  if (error(RelI->getAdditionalInfo(Info))) return;
   if (error(RelI->getSymbol(Symbol))) return;
   if (error(Symbol.getName(SymbolName))) return;
 
+  DataRefImpl DR = RelI->getRawDataRefImpl();
+  const MachOObjectFileBase::RelocationEntry *RE = Obj->getRelocation(DR);
+  bool IsScattered = Obj->isScattered(RE);
+
   raw_ostream& OS = W.startLine();
   OS << W.hex(Offset)
-     << " " << RelocName
+     << " " << Obj->isPCRel(RE)
+     << " " << Obj->getLength(RE);
+  if (IsScattered)
+    OS << " n/a";
+  else
+    OS << " " << RE->getExternal();
+  OS << " " << RelocName
+     << " " << IsScattered
      << " " << (SymbolName.size() > 0 ? SymbolName : "-")
-     << " " << W.hex(Info)
      << "\n";
 }