+
+// SortedSections implementation.
+
+static bool SectionStartsBefore(const SectionRef &S, uint64_t Addr) {
+ uint64_t SAddr; S.getAddress(SAddr);
+ return SAddr < Addr;
+}
+
+const SectionRef *MCObjectSymbolizer::findSectionContaining(uint64_t Addr) {
+ if (SortedSections.empty())
+ buildSectionList();
+
+ SortedSectionList::iterator
+ EndIt = SortedSections.end(),
+ It = std::lower_bound(SortedSections.begin(), EndIt,
+ Addr, SectionStartsBefore);
+ if (It == EndIt)
+ return 0;
+ uint64_t SAddr; It->getAddress(SAddr);
+ uint64_t SSize; It->getSize(SSize);
+ if (Addr >= SAddr + SSize)
+ return 0;
+ return &*It;
+}
+
+const RelocationRef *MCObjectSymbolizer::findRelocationAt(uint64_t Addr) {
+ if (AddrToReloc.empty())
+ buildRelocationByAddrMap();
+
+ AddrToRelocMap::const_iterator RI = AddrToReloc.find(Addr);
+ if (RI == AddrToReloc.end())
+ return 0;
+ return &RI->second;
+}
+
+void MCObjectSymbolizer::buildSectionList() {
+ error_code ec;
+ for (section_iterator SI = Obj->begin_sections(), SE = Obj->end_sections();
+ SI != SE; SI.increment(ec)) {
+ if (ec) break;
+
+ bool RequiredForExec; SI->isRequiredForExecution(RequiredForExec);
+ if (RequiredForExec == false)
+ continue;
+ uint64_t SAddr; SI->getAddress(SAddr);
+ uint64_t SSize; SI->getSize(SSize);
+ SortedSectionList::iterator It = std::lower_bound(SortedSections.begin(),
+ SortedSections.end(),
+ SAddr,
+ SectionStartsBefore);
+ if (It != SortedSections.end()) {
+ uint64_t FoundSAddr; It->getAddress(FoundSAddr);
+ if (FoundSAddr < SAddr + SSize)
+ llvm_unreachable("Inserting overlapping sections");
+ }
+ SortedSections.insert(It, *SI);
+ }
+}
+
+void MCObjectSymbolizer::buildRelocationByAddrMap() {
+ error_code ec;
+ for (section_iterator SI = Obj->begin_sections(), SE = Obj->end_sections();
+ SI != SE; SI.increment(ec)) {
+ if (ec) break;
+
+ section_iterator RelSecI = SI->getRelocatedSection();
+ if (RelSecI == Obj->end_sections())
+ continue;
+
+ uint64_t StartAddr; RelSecI->getAddress(StartAddr);
+ uint64_t Size; RelSecI->getSize(Size);
+ bool RequiredForExec; RelSecI->isRequiredForExecution(RequiredForExec);
+ if (RequiredForExec == false || Size == 0)
+ continue;
+ for (relocation_iterator RI = SI->begin_relocations(),
+ RE = SI->end_relocations();
+ RI != RE;
+ RI.increment(ec)) {
+ if (ec) break;
+ // FIXME: libObject is inconsistent regarding error handling. The
+ // overwhelming majority of methods always return object_error::success,
+ // and assert for simple errors.. Here, ELFObjectFile::getRelocationOffset
+ // asserts when the file type isn't ET_REL.
+ // This workaround handles x86-64 elf, the only one that has a relocinfo.
+ uint64_t Offset;
+ if (Obj->isELF()) {
+ const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj);
+ if (ELFObj == 0)
+ break;
+ if (ELFObj->getELFFile()->getHeader()->e_type == ELF::ET_REL) {
+ RI->getOffset(Offset);
+ Offset += StartAddr;
+ } else {
+ RI->getAddress(Offset);
+ }
+ } else {
+ RI->getOffset(Offset);
+ Offset += StartAddr;
+ }
+ // At a specific address, only keep the first relocation.
+ if (AddrToReloc.find(Offset) == AddrToReloc.end())
+ AddrToReloc[Offset] = *RI;
+ }
+ }
+}