DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj)
    : IsLittleEndian(Obj->isLittleEndian()),
      AddressSize(Obj->getBytesInAddress()) {
  for (const SectionRef &Section : Obj->sections()) {
    StringRef name;
    Section.getName(name);
    StringRef data;
    Section.getContents(data);

    name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes.

    // Check if debug info section is compressed with zlib.
    if (name.startswith("zdebug_")) {
      uint64_t OriginalSize;
      if (!zlib::isAvailable() ||
          !consumeCompressedDebugSectionHeader(data, OriginalSize))
        continue;
      UncompressedSections.resize(UncompressedSections.size() + 1);
      if (zlib::uncompress(data, UncompressedSections.back(), OriginalSize) !=
          zlib::StatusOK) {
        UncompressedSections.pop_back();
        continue;
      }
      // Make data point to uncompressed section contents and save its contents.
      name = name.substr(1);
      data = UncompressedSections.back();
    }

    StringRef *SectionData =
        StringSwitch<StringRef *>(name)
            .Case("debug_info", &InfoSection.Data)
            .Case("debug_abbrev", &AbbrevSection)
            .Case("debug_loc", &LocSection.Data)
            .Case("debug_line", &LineSection.Data)
            .Case("debug_aranges", &ARangeSection)
            .Case("debug_frame", &DebugFrameSection)
            .Case("debug_str", &StringSection)
            .Case("debug_ranges", &RangeSection)
            .Case("debug_pubnames", &PubNamesSection)
            .Case("debug_pubtypes", &PubTypesSection)
            .Case("debug_gnu_pubnames", &GnuPubNamesSection)
            .Case("debug_gnu_pubtypes", &GnuPubTypesSection)
            .Case("debug_info.dwo", &InfoDWOSection.Data)
            .Case("debug_abbrev.dwo", &AbbrevDWOSection)
            .Case("debug_loc.dwo", &LocDWOSection.Data)
            .Case("debug_line.dwo", &LineDWOSection.Data)
            .Case("debug_str.dwo", &StringDWOSection)
            .Case("debug_str_offsets.dwo", &StringOffsetDWOSection)
            .Case("debug_addr", &AddrSection)
            // Any more debug info sections go here.
            .Default(nullptr);
    if (SectionData) {
      *SectionData = data;
      if (name == "debug_ranges") {
        // FIXME: Use the other dwo range section when we emit it.
        RangeDWOSection = data;
      }
    } else if (name == "debug_types") {
      // Find debug_types data by section rather than name as there are
      // multiple, comdat grouped, debug_types sections.
      TypesSections[Section].Data = data;
    } else if (name == "debug_types.dwo") {
      TypesDWOSections[Section].Data = data;
    }

    section_iterator RelocatedSection = Section.getRelocatedSection();
    if (RelocatedSection == Obj->section_end())
      continue;

    StringRef RelSecName;
    RelocatedSection->getName(RelSecName);
    RelSecName = RelSecName.substr(
        RelSecName.find_first_not_of("._")); // Skip . and _ prefixes.

    // TODO: Add support for relocations in other sections as needed.
    // Record relocations for the debug_info and debug_line sections.
    RelocAddrMap *Map = StringSwitch<RelocAddrMap*>(RelSecName)
        .Case("debug_info", &InfoSection.Relocs)
        .Case("debug_loc", &LocSection.Relocs)
        .Case("debug_info.dwo", &InfoDWOSection.Relocs)
        .Case("debug_line", &LineSection.Relocs)
        .Default(nullptr);
    if (!Map) {
      // Find debug_types relocs by section rather than name as there are
      // multiple, comdat grouped, debug_types sections.
      if (RelSecName == "debug_types")
        Map = &TypesSections[*RelocatedSection].Relocs;
      else if (RelSecName == "debug_types.dwo")
        Map = &TypesDWOSections[*RelocatedSection].Relocs;
      else
        continue;
    }

    if (Section.relocation_begin() != Section.relocation_end()) {
      uint64_t SectionSize;
      RelocatedSection->getSize(SectionSize);
      for (const RelocationRef &Reloc : Section.relocations()) {
        uint64_t Address;
        Reloc.getOffset(Address);
        uint64_t Type;
        Reloc.getType(Type);
        uint64_t SymAddr = 0;
        // ELF relocations may need the symbol address
        if (Obj->isELF()) {
          object::symbol_iterator Sym = Reloc.getSymbol();
          Sym->getAddress(SymAddr);
        }

        object::RelocVisitor V(Obj->getFileFormatName());
        // The section address is always 0 for debug sections.
        object::RelocToApply R(V.visit(Type, Reloc, 0, SymAddr));
        if (V.error()) {
          SmallString<32> Name;
          error_code ec(Reloc.getTypeName(Name));
          if (ec) {
            errs() << "Aaaaaa! Nameless relocation! Aaaaaa!\n";
          }
          errs() << "error: failed to compute relocation: "
                 << Name << "\n";
          continue;
        }

        if (Address + R.Width > SectionSize) {
          errs() << "error: " << R.Width << "-byte relocation starting "
                 << Address << " bytes into section " << name << " which is "
                 << SectionSize << " bytes long.\n";
          continue;
        }
        if (R.Width > 8) {
          errs() << "error: can't handle a relocation of more than 8 bytes at "
                    "a time.\n";
          continue;
        }
        DEBUG(dbgs() << "Writing " << format("%p", R.Value)
                     << " at " << format("%p", Address)
                     << " with width " << format("%d", R.Width)
                     << "\n");
        Map->insert(std::make_pair(Address, std::make_pair(R.Width, R.Value)));
      }
    }
  }
}
示例#2
0
DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) :
  IsLittleEndian(Obj->isLittleEndian()),
  AddressSize(Obj->getBytesInAddress()) {
  error_code ec;
  for (object::section_iterator i = Obj->begin_sections(),
         e = Obj->end_sections();
       i != e; i.increment(ec)) {
    StringRef name;
    i->getName(name);
    StringRef data;
    i->getContents(data);

    name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes.

    // Check if debug info section is compressed with zlib.
    if (name.startswith("zdebug_")) {
      uint64_t OriginalSize;
      if (!zlib::isAvailable() ||
          !consumeCompressedDebugSectionHeader(data, OriginalSize))
        continue;
      OwningPtr<MemoryBuffer> UncompressedSection;
      if (zlib::uncompress(data, UncompressedSection, OriginalSize) !=
          zlib::StatusOK)
        continue;
      // Make data point to uncompressed section contents and save its contents.
      name = name.substr(1);
      data = UncompressedSection->getBuffer();
      UncompressedSections.push_back(UncompressedSection.take());
    }

    StringRef *Section = StringSwitch<StringRef*>(name)
        .Case("debug_info", &InfoSection)
        .Case("debug_abbrev", &AbbrevSection)
        .Case("debug_line", &LineSection)
        .Case("debug_aranges", &ARangeSection)
        .Case("debug_frame", &DebugFrameSection)
        .Case("debug_str", &StringSection)
        .Case("debug_ranges", &RangeSection)
        .Case("debug_pubnames", &PubNamesSection)
        .Case("debug_info.dwo", &InfoDWOSection)
        .Case("debug_abbrev.dwo", &AbbrevDWOSection)
        .Case("debug_str.dwo", &StringDWOSection)
        .Case("debug_str_offsets.dwo", &StringOffsetDWOSection)
        .Case("debug_addr", &AddrSection)
        // Any more debug info sections go here.
        .Default(0);
    if (!Section)
      continue;
    *Section = data;
    if (name == "debug_ranges") {
      // FIXME: Use the other dwo range section when we emit it.
      RangeDWOSection = data;
    }

    // TODO: Add support for relocations in other sections as needed.
    // Record relocations for the debug_info and debug_line sections.
    RelocAddrMap *Map = StringSwitch<RelocAddrMap*>(name)
        .Case("debug_info", &InfoRelocMap)
        .Case("debug_info.dwo", &InfoDWORelocMap)
        .Case("debug_line", &LineRelocMap)
        .Default(0);
    if (!Map)
      continue;

    if (i->begin_relocations() != i->end_relocations()) {
      uint64_t SectionSize;
      i->getSize(SectionSize);
      for (object::relocation_iterator reloc_i = i->begin_relocations(),
             reloc_e = i->end_relocations();
           reloc_i != reloc_e; reloc_i.increment(ec)) {
        uint64_t Address;
        reloc_i->getOffset(Address);
        uint64_t Type;
        reloc_i->getType(Type);
        uint64_t SymAddr = 0;
        // ELF relocations may need the symbol address
        if (Obj->isELF()) {
          object::SymbolRef Sym;
          reloc_i->getSymbol(Sym);
          Sym.getAddress(SymAddr);
        }

        object::RelocVisitor V(Obj->getFileFormatName());
        // The section address is always 0 for debug sections.
        object::RelocToApply R(V.visit(Type, *reloc_i, 0, SymAddr));
        if (V.error()) {
          SmallString<32> Name;
          error_code ec(reloc_i->getTypeName(Name));
          if (ec) {
            errs() << "Aaaaaa! Nameless relocation! Aaaaaa!\n";
          }
          errs() << "error: failed to compute relocation: "
                 << Name << "\n";
          continue;
        }

        if (Address + R.Width > SectionSize) {
          errs() << "error: " << R.Width << "-byte relocation starting "
                 << Address << " bytes into section " << name << " which is "
                 << SectionSize << " bytes long.\n";
          continue;
        }
        if (R.Width > 8) {
          errs() << "error: can't handle a relocation of more than 8 bytes at "
                    "a time.\n";
          continue;
        }
        DEBUG(dbgs() << "Writing " << format("%p", R.Value)
                     << " at " << format("%p", Address)
                     << " with width " << format("%d", R.Width)
                     << "\n");
        Map->insert(std::make_pair(Address, std::make_pair(R.Width, R.Value)));
      }
    }
  }
}
示例#3
0
DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
    const LoadedObjectInfo *L)
    : IsLittleEndian(Obj.isLittleEndian()),
      AddressSize(Obj.getBytesInAddress()) {
  for (const SectionRef &Section : Obj.sections()) {
    StringRef name;
    Section.getName(name);
    // Skip BSS and Virtual sections, they aren't interesting.
    bool IsBSS = Section.isBSS();
    if (IsBSS)
      continue;
    bool IsVirtual = Section.isVirtual();
    if (IsVirtual)
      continue;
    StringRef data;

    // Try to obtain an already relocated version of this section.
    // Else use the unrelocated section from the object file. We'll have to
    // apply relocations ourselves later.
    if (!L || !L->getLoadedSectionContents(name,data))
      Section.getContents(data);

    name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes.

    // Check if debug info section is compressed with zlib.
    if (name.startswith("zdebug_")) {
      uint64_t OriginalSize;
      if (!zlib::isAvailable() ||
          !consumeCompressedDebugSectionHeader(data, OriginalSize))
        continue;
      UncompressedSections.resize(UncompressedSections.size() + 1);
      if (zlib::uncompress(data, UncompressedSections.back(), OriginalSize) !=
          zlib::StatusOK) {
        UncompressedSections.pop_back();
        continue;
      }
      // Make data point to uncompressed section contents and save its contents.
      name = name.substr(1);
      data = UncompressedSections.back();
    }

    StringRef *SectionData =
        StringSwitch<StringRef *>(name)
            .Case("debug_info", &InfoSection.Data)
            .Case("debug_abbrev", &AbbrevSection)
            .Case("debug_loc", &LocSection.Data)
            .Case("debug_line", &LineSection.Data)
            .Case("debug_aranges", &ARangeSection)
            .Case("debug_frame", &DebugFrameSection)
            .Case("debug_str", &StringSection)
            .Case("debug_ranges", &RangeSection)
            .Case("debug_pubnames", &PubNamesSection)
            .Case("debug_pubtypes", &PubTypesSection)
            .Case("debug_gnu_pubnames", &GnuPubNamesSection)
            .Case("debug_gnu_pubtypes", &GnuPubTypesSection)
            .Case("debug_info.dwo", &InfoDWOSection.Data)
            .Case("debug_abbrev.dwo", &AbbrevDWOSection)
            .Case("debug_loc.dwo", &LocDWOSection.Data)
            .Case("debug_line.dwo", &LineDWOSection.Data)
            .Case("debug_str.dwo", &StringDWOSection)
            .Case("debug_str_offsets.dwo", &StringOffsetDWOSection)
            .Case("debug_addr", &AddrSection)
            .Case("apple_names", &AppleNamesSection.Data)
            .Case("apple_types", &AppleTypesSection.Data)
            .Case("apple_namespaces", &AppleNamespacesSection.Data)
            .Case("apple_namespac", &AppleNamespacesSection.Data)
            .Case("apple_objc", &AppleObjCSection.Data)
            // Any more debug info sections go here.
            .Default(nullptr);
    if (SectionData) {
      *SectionData = data;
      if (name == "debug_ranges") {
        // FIXME: Use the other dwo range section when we emit it.
        RangeDWOSection = data;
      }
    } else if (name == "debug_types") {
      // Find debug_types data by section rather than name as there are
      // multiple, comdat grouped, debug_types sections.
      TypesSections[Section].Data = data;
    } else if (name == "debug_types.dwo") {
      TypesDWOSections[Section].Data = data;
    }

    section_iterator RelocatedSection = Section.getRelocatedSection();
    if (RelocatedSection == Obj.section_end())
      continue;

    StringRef RelSecName;
    StringRef RelSecData;
    RelocatedSection->getName(RelSecName);

    // If the section we're relocating was relocated already by the JIT,
    // then we used the relocated version above, so we do not need to process
    // relocations for it now.
    if (L && L->getLoadedSectionContents(RelSecName,RelSecData))
      continue;

    RelSecName = RelSecName.substr(
        RelSecName.find_first_not_of("._")); // Skip . and _ prefixes.

    // TODO: Add support for relocations in other sections as needed.
    // Record relocations for the debug_info and debug_line sections.
    RelocAddrMap *Map = StringSwitch<RelocAddrMap*>(RelSecName)
        .Case("debug_info", &InfoSection.Relocs)
        .Case("debug_loc", &LocSection.Relocs)
        .Case("debug_info.dwo", &InfoDWOSection.Relocs)
        .Case("debug_line", &LineSection.Relocs)
        .Case("apple_names", &AppleNamesSection.Relocs)
        .Case("apple_types", &AppleTypesSection.Relocs)
        .Case("apple_namespaces", &AppleNamespacesSection.Relocs)
        .Case("apple_namespac", &AppleNamespacesSection.Relocs)
        .Case("apple_objc", &AppleObjCSection.Relocs)
        .Default(nullptr);
    if (!Map) {
      // Find debug_types relocs by section rather than name as there are
      // multiple, comdat grouped, debug_types sections.
      if (RelSecName == "debug_types")
        Map = &TypesSections[*RelocatedSection].Relocs;
      else if (RelSecName == "debug_types.dwo")
        Map = &TypesDWOSections[*RelocatedSection].Relocs;
      else
        continue;
    }

    if (Section.relocation_begin() != Section.relocation_end()) {
      uint64_t SectionSize = RelocatedSection->getSize();
      for (const RelocationRef &Reloc : Section.relocations()) {
        uint64_t Address;
        Reloc.getOffset(Address);
        uint64_t Type;
        Reloc.getType(Type);
        uint64_t SymAddr = 0;
        uint64_t SectionLoadAddress = 0;
        object::symbol_iterator Sym = Reloc.getSymbol();
        object::section_iterator RSec = Obj.section_end();

        // First calculate the address of the symbol or section as it appears
        // in the objct file
        if (Sym != Obj.symbol_end()) {
          Sym->getAddress(SymAddr);
          // Also remember what section this symbol is in for later
          Sym->getSection(RSec);
        } else if (auto *MObj = dyn_cast<MachOObjectFile>(&Obj)) {
          // MachO also has relocations that point to sections and
          // scattered relocations.
          // FIXME: We are not handling scattered relocations, do we have to?
          RSec = MObj->getRelocationSection(Reloc.getRawDataRefImpl());
          SymAddr = RSec->getAddress();
        }

        // If we are given load addresses for the sections, we need to adjust:
        // SymAddr = (Address of Symbol Or Section in File) -
        //           (Address of Section in File) +
        //           (Load Address of Section)
        if (L != nullptr && RSec != Obj.section_end()) {
          // RSec is now either the section being targetted or the section
          // containing the symbol being targetted. In either case,
          // we need to perform the same computation.
          StringRef SecName;
          RSec->getName(SecName);
          SectionLoadAddress = L->getSectionLoadAddress(SecName);
          if (SectionLoadAddress != 0)
            SymAddr += SectionLoadAddress - RSec->getAddress();
        }

        object::RelocVisitor V(Obj);
        object::RelocToApply R(V.visit(Type, Reloc, SymAddr));
        if (V.error()) {
          SmallString<32> Name;
          std::error_code ec(Reloc.getTypeName(Name));
          if (ec) {
            errs() << "Aaaaaa! Nameless relocation! Aaaaaa!\n";
          }
          errs() << "error: failed to compute relocation: "
                 << Name << "\n";
          continue;
        }

        if (Address + R.Width > SectionSize) {
          errs() << "error: " << R.Width << "-byte relocation starting "
                 << Address << " bytes into section " << name << " which is "
                 << SectionSize << " bytes long.\n";
          continue;
        }
        if (R.Width > 8) {
          errs() << "error: can't handle a relocation of more than 8 bytes at "
                    "a time.\n";
          continue;
        }
        DEBUG(dbgs() << "Writing " << format("%p", R.Value)
                     << " at " << format("%p", Address)
                     << " with width " << format("%d", R.Width)
                     << "\n");
        Map->insert(std::make_pair(Address, std::make_pair(R.Width, R.Value)));
      }
    }
  }
}
示例#4
0
DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) :
  IsLittleEndian(Obj->isLittleEndian()) {
  error_code ec;
  for (object::section_iterator i = Obj->begin_sections(),
         e = Obj->end_sections();
       i != e; i.increment(ec)) {
    StringRef name;
    i->getName(name);
    StringRef data;
    i->getContents(data);

    name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes.
    if (name == "debug_info")
      InfoSection = data;
    else if (name == "debug_abbrev")
      AbbrevSection = data;
    else if (name == "debug_line")
      LineSection = data;
    else if (name == "debug_aranges")
      ARangeSection = data;
    else if (name == "debug_str")
      StringSection = data;
    else if (name == "debug_ranges") {
      // FIXME: Use the other dwo range section when we emit it.
      RangeDWOSection = data;
      RangeSection = data;
    }
    else if (name == "debug_info.dwo")
      InfoDWOSection = data;
    else if (name == "debug_abbrev.dwo")
      AbbrevDWOSection = data;
    else if (name == "debug_str.dwo")
      StringDWOSection = data;
    else if (name == "debug_str_offsets.dwo")
      StringOffsetDWOSection = data;
    // Any more debug info sections go here.
    else
      continue;

    // TODO: For now only handle relocations for the debug_info section.
    RelocAddrMap *Map;
    if (name == "debug_info")
      Map = &InfoRelocMap;
    else if (name == "debug_info.dwo")
      Map = &InfoDWORelocMap;
    else
      continue;

    if (i->begin_relocations() != i->end_relocations()) {
      uint64_t SectionSize;
      i->getSize(SectionSize);
      for (object::relocation_iterator reloc_i = i->begin_relocations(),
             reloc_e = i->end_relocations();
           reloc_i != reloc_e; reloc_i.increment(ec)) {
        uint64_t Address;
        reloc_i->getAddress(Address);
        uint64_t Type;
        reloc_i->getType(Type);

        object::RelocVisitor V(Obj->getFileFormatName());
        // The section address is always 0 for debug sections.
        object::RelocToApply R(V.visit(Type, *reloc_i));
        if (V.error()) {
          SmallString<32> Name;
          error_code ec(reloc_i->getTypeName(Name));
          if (ec) {
            errs() << "Aaaaaa! Nameless relocation! Aaaaaa!\n";
          }
          errs() << "error: failed to compute relocation: "
                 << Name << "\n";
          continue;
        }

        if (Address + R.Width > SectionSize) {
          errs() << "error: " << R.Width << "-byte relocation starting "
                 << Address << " bytes into section " << name << " which is "
                 << SectionSize << " bytes long.\n";
          continue;
        }
        if (R.Width > 8) {
          errs() << "error: can't handle a relocation of more than 8 bytes at "
                    "a time.\n";
          continue;
        }
        DEBUG(dbgs() << "Writing " << format("%p", R.Value)
                     << " at " << format("%p", Address)
                     << " with width " << format("%d", R.Width)
                     << "\n");
        Map->insert(std::make_pair(Address, std::make_pair(R.Width, R.Value)));
      }
    }
  }
}
示例#5
0
DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
        const LoadedObjectInfo *L)
    : IsLittleEndian(Obj.isLittleEndian()),
      AddressSize(Obj.getBytesInAddress()) {
    for (const SectionRef &Section : Obj.sections()) {
        StringRef name;
        Section.getName(name);
        // Skip BSS and Virtual sections, they aren't interesting.
        bool IsBSS = Section.isBSS();
        if (IsBSS)
            continue;
        bool IsVirtual = Section.isVirtual();
        if (IsVirtual)
            continue;
        StringRef data;

        section_iterator RelocatedSection = Section.getRelocatedSection();
        // Try to obtain an already relocated version of this section.
        // Else use the unrelocated section from the object file. We'll have to
        // apply relocations ourselves later.
        if (!L || !L->getLoadedSectionContents(*RelocatedSection,data))
            Section.getContents(data);

        name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes.

        bool ZLibStyleCompressed = Section.isCompressed();
        if (ZLibStyleCompressed || name.startswith("zdebug_")) {
            SmallString<32> Out;
            if (!tryDecompress(name, data, Out, ZLibStyleCompressed, IsLittleEndian,
                               AddressSize == 8))
                continue;
            UncompressedSections.emplace_back(std::move(Out));
            data = UncompressedSections.back();
        }

        StringRef *SectionData =
            StringSwitch<StringRef *>(name)
            .Case("debug_info", &InfoSection.Data)
            .Case("debug_abbrev", &AbbrevSection)
            .Case("debug_loc", &LocSection.Data)
            .Case("debug_line", &LineSection.Data)
            .Case("debug_aranges", &ARangeSection)
            .Case("debug_frame", &DebugFrameSection)
            .Case("eh_frame", &EHFrameSection)
            .Case("debug_str", &StringSection)
            .Case("debug_ranges", &RangeSection)
            .Case("debug_macinfo", &MacinfoSection)
            .Case("debug_pubnames", &PubNamesSection)
            .Case("debug_pubtypes", &PubTypesSection)
            .Case("debug_gnu_pubnames", &GnuPubNamesSection)
            .Case("debug_gnu_pubtypes", &GnuPubTypesSection)
            .Case("debug_info.dwo", &InfoDWOSection.Data)
            .Case("debug_abbrev.dwo", &AbbrevDWOSection)
            .Case("debug_loc.dwo", &LocDWOSection.Data)
            .Case("debug_line.dwo", &LineDWOSection.Data)
            .Case("debug_str.dwo", &StringDWOSection)
            .Case("debug_str_offsets.dwo", &StringOffsetDWOSection)
            .Case("debug_addr", &AddrSection)
            .Case("apple_names", &AppleNamesSection.Data)
            .Case("apple_types", &AppleTypesSection.Data)
            .Case("apple_namespaces", &AppleNamespacesSection.Data)
            .Case("apple_namespac", &AppleNamespacesSection.Data)
            .Case("apple_objc", &AppleObjCSection.Data)
            .Case("debug_cu_index", &CUIndexSection)
            .Case("debug_tu_index", &TUIndexSection)
            // Any more debug info sections go here.
            .Default(nullptr);
        if (SectionData) {
            *SectionData = data;
            if (name == "debug_ranges") {
                // FIXME: Use the other dwo range section when we emit it.
                RangeDWOSection = data;
            }
        } else if (name == "debug_types") {
            // Find debug_types data by section rather than name as there are
            // multiple, comdat grouped, debug_types sections.
            TypesSections[Section].Data = data;
        } else if (name == "debug_types.dwo") {
            TypesDWOSections[Section].Data = data;
        }

        if (RelocatedSection == Obj.section_end())
            continue;

        StringRef RelSecName;
        StringRef RelSecData;
        RelocatedSection->getName(RelSecName);

        // If the section we're relocating was relocated already by the JIT,
        // then we used the relocated version above, so we do not need to process
        // relocations for it now.
        if (L && L->getLoadedSectionContents(*RelocatedSection,RelSecData))
            continue;

        // In Mach-o files, the relocations do not need to be applied if
        // there is no load offset to apply. The value read at the
        // relocation point already factors in the section address
        // (actually applying the relocations will produce wrong results
        // as the section address will be added twice).
        if (!L && isa<MachOObjectFile>(&Obj))
            continue;

        RelSecName = RelSecName.substr(
                         RelSecName.find_first_not_of("._")); // Skip . and _ prefixes.

        // TODO: Add support for relocations in other sections as needed.
        // Record relocations for the debug_info and debug_line sections.
        RelocAddrMap *Map = StringSwitch<RelocAddrMap*>(RelSecName)
                            .Case("debug_info", &InfoSection.Relocs)
                            .Case("debug_loc", &LocSection.Relocs)
                            .Case("debug_info.dwo", &InfoDWOSection.Relocs)
                            .Case("debug_line", &LineSection.Relocs)
                            .Case("apple_names", &AppleNamesSection.Relocs)
                            .Case("apple_types", &AppleTypesSection.Relocs)
                            .Case("apple_namespaces", &AppleNamespacesSection.Relocs)
                            .Case("apple_namespac", &AppleNamespacesSection.Relocs)
                            .Case("apple_objc", &AppleObjCSection.Relocs)
                            .Default(nullptr);
        if (!Map) {
            // Find debug_types relocs by section rather than name as there are
            // multiple, comdat grouped, debug_types sections.
            if (RelSecName == "debug_types")
                Map = &TypesSections[*RelocatedSection].Relocs;
            else if (RelSecName == "debug_types.dwo")
                Map = &TypesDWOSections[*RelocatedSection].Relocs;
            else
                continue;
        }

        if (Section.relocation_begin() != Section.relocation_end()) {
            uint64_t SectionSize = RelocatedSection->getSize();
            for (const RelocationRef &Reloc : Section.relocations()) {
                uint64_t Address = Reloc.getOffset();
                uint64_t Type = Reloc.getType();
                uint64_t SymAddr = 0;
                uint64_t SectionLoadAddress = 0;
                object::symbol_iterator Sym = Reloc.getSymbol();
                object::section_iterator RSec = Obj.section_end();

                // First calculate the address of the symbol or section as it appears
                // in the objct file
                if (Sym != Obj.symbol_end()) {
                    ErrorOr<uint64_t> SymAddrOrErr = Sym->getAddress();
                    if (std::error_code EC = SymAddrOrErr.getError()) {
                        errs() << "error: failed to compute symbol address: "
                               << EC.message() << '\n';
                        continue;
                    }
                    SymAddr = *SymAddrOrErr;
                    // Also remember what section this symbol is in for later
                    auto SectOrErr = Sym->getSection();
                    if (!SectOrErr) {
                        std::string Buf;
                        raw_string_ostream OS(Buf);
                        logAllUnhandledErrors(SectOrErr.takeError(), OS, "");
                        OS.flush();
                        errs() << "error: failed to get symbol section: "
                               << Buf << '\n';
                        continue;
                    }
                    RSec = *SectOrErr;
                } else if (auto *MObj = dyn_cast<MachOObjectFile>(&Obj)) {
                    // MachO also has relocations that point to sections and
                    // scattered relocations.
                    auto RelocInfo = MObj->getRelocation(Reloc.getRawDataRefImpl());
                    if (MObj->isRelocationScattered(RelocInfo)) {
                        // FIXME: it's not clear how to correctly handle scattered
                        // relocations.
                        continue;
                    } else {
                        RSec = MObj->getRelocationSection(Reloc.getRawDataRefImpl());
                        SymAddr = RSec->getAddress();
                    }
                }

                // If we are given load addresses for the sections, we need to adjust:
                // SymAddr = (Address of Symbol Or Section in File) -
                //           (Address of Section in File) +
                //           (Load Address of Section)
                if (L != nullptr && RSec != Obj.section_end()) {
                    // RSec is now either the section being targeted or the section
                    // containing the symbol being targeted. In either case,
                    // we need to perform the same computation.
                    StringRef SecName;
                    RSec->getName(SecName);
//           llvm::dbgs() << "Name: '" << SecName
//                        << "', RSec: " << RSec->getRawDataRefImpl()
//                        << ", Section: " << Section.getRawDataRefImpl() << "\n";
                    SectionLoadAddress = L->getSectionLoadAddress(*RSec);
                    if (SectionLoadAddress != 0)
                        SymAddr += SectionLoadAddress - RSec->getAddress();
                }

                object::RelocVisitor V(Obj);
                object::RelocToApply R(V.visit(Type, Reloc, SymAddr));
                if (V.error()) {
                    SmallString<32> Name;
                    Reloc.getTypeName(Name);
                    errs() << "error: failed to compute relocation: "
                           << Name << "\n";
                    continue;
                }

                if (Address + R.Width > SectionSize) {
                    errs() << "error: " << R.Width << "-byte relocation starting "
                           << Address << " bytes into section " << name << " which is "
                           << SectionSize << " bytes long.\n";
                    continue;
                }
                if (R.Width > 8) {
                    errs() << "error: can't handle a relocation of more than 8 bytes at "
                           "a time.\n";
                    continue;
                }
                DEBUG(dbgs() << "Writing " << format("%p", R.Value)
                      << " at " << format("%p", Address)
                      << " with width " << format("%d", R.Width)
                      << "\n");
                Map->insert(std::make_pair(Address, std::make_pair(R.Width, R.Value)));
            }
        }
    }
}