diff options
Diffstat (limited to 'contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp')
-rw-r--r-- | contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp | 172 |
1 files changed, 113 insertions, 59 deletions
diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp index 01a3fd9..5b92867 100644 --- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp +++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp @@ -55,35 +55,80 @@ static intptr_t computeDelta(SectionEntry *A, SectionEntry *B) { return ObjDistance - MemDistance; } -StringRef RuntimeDyldMachO::getEHFrameSection() { - SectionEntry *Text = NULL; - SectionEntry *EHFrame = NULL; - SectionEntry *ExceptTab = NULL; - for (int i = 0, e = Sections.size(); i != e; ++i) { - if (Sections[i].Name == "__eh_frame") - EHFrame = &Sections[i]; - else if (Sections[i].Name == "__text") - Text = &Sections[i]; - else if (Sections[i].Name == "__gcc_except_tab") - ExceptTab = &Sections[i]; +void RuntimeDyldMachO::registerEHFrames() { + + if (!MemMgr) + return; + for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) { + EHFrameRelatedSections &SectionInfo = UnregisteredEHFrameSections[i]; + if (SectionInfo.EHFrameSID == RTDYLD_INVALID_SECTION_ID || + SectionInfo.TextSID == RTDYLD_INVALID_SECTION_ID) + continue; + SectionEntry *Text = &Sections[SectionInfo.TextSID]; + SectionEntry *EHFrame = &Sections[SectionInfo.EHFrameSID]; + SectionEntry *ExceptTab = NULL; + if (SectionInfo.ExceptTabSID != RTDYLD_INVALID_SECTION_ID) + ExceptTab = &Sections[SectionInfo.ExceptTabSID]; + + intptr_t DeltaForText = computeDelta(Text, EHFrame); + intptr_t DeltaForEH = 0; + if (ExceptTab) + DeltaForEH = computeDelta(ExceptTab, EHFrame); + + unsigned char *P = EHFrame->Address; + unsigned char *End = P + EHFrame->Size; + do { + P = processFDE(P, DeltaForText, DeltaForEH); + } while(P != End); + + MemMgr->registerEHFrames(EHFrame->Address, + EHFrame->LoadAddress, + EHFrame->Size); } - if (Text == NULL || EHFrame == NULL) - return StringRef(); - - intptr_t DeltaForText = computeDelta(Text, EHFrame); - intptr_t DeltaForEH = 0; - if (ExceptTab) - DeltaForEH = computeDelta(ExceptTab, EHFrame); - - unsigned char *P = EHFrame->Address; - unsigned char *End = P + EHFrame->Size; - do { - P = processFDE(P, DeltaForText, DeltaForEH); - } while(P != End); + UnregisteredEHFrameSections.clear(); +} - return StringRef((char*)EHFrame->Address, EHFrame->Size); +void RuntimeDyldMachO::finalizeLoad(ObjSectionToIDMap &SectionMap) { + unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID; + unsigned TextSID = RTDYLD_INVALID_SECTION_ID; + unsigned ExceptTabSID = RTDYLD_INVALID_SECTION_ID; + ObjSectionToIDMap::iterator i, e; + for (i = SectionMap.begin(), e = SectionMap.end(); i != e; ++i) { + const SectionRef &Section = i->first; + StringRef Name; + Section.getName(Name); + if (Name == "__eh_frame") + EHFrameSID = i->second; + else if (Name == "__text") + TextSID = i->second; + else if (Name == "__gcc_except_tab") + ExceptTabSID = i->second; + } + UnregisteredEHFrameSections.push_back(EHFrameRelatedSections(EHFrameSID, + TextSID, + ExceptTabSID)); } +// The target location for the relocation is described by RE.SectionID and +// RE.Offset. RE.SectionID can be used to find the SectionEntry. Each +// SectionEntry has three members describing its location. +// SectionEntry::Address is the address at which the section has been loaded +// into memory in the current (host) process. SectionEntry::LoadAddress is the +// address that the section will have in the target process. +// SectionEntry::ObjAddress is the address of the bits for this section in the +// original emitted object image (also in the current address space). +// +// Relocations will be applied as if the section were loaded at +// SectionEntry::LoadAddress, but they will be applied at an address based +// on SectionEntry::Address. SectionEntry::ObjAddress will be used to refer to +// Target memory contents if they are required for value calculations. +// +// The Value parameter here is the load address of the symbol for the +// relocation to be applied. For relocations which refer to symbols in the +// current object Value will be the LoadAddress of the section in which +// the symbol resides (RE.Addend provides additional information about the +// symbol location). For external symbols, Value will be the address of the +// symbol in the target address space. void RuntimeDyldMachO::resolveRelocation(const RelocationEntry &RE, uint64_t Value) { const SectionEntry &Section = Sections[RE.SectionID]; @@ -160,7 +205,7 @@ bool RuntimeDyldMachO::resolveI386Relocation(uint8_t *LocalAddress, switch (Type) { default: llvm_unreachable("Invalid relocation type!"); - case macho::RIT_Vanilla: { + case MachO::GENERIC_RELOC_VANILLA: { uint8_t *p = LocalAddress; uint64_t ValueToWrite = Value + Addend; for (unsigned i = 0; i < Size; ++i) { @@ -169,9 +214,9 @@ bool RuntimeDyldMachO::resolveI386Relocation(uint8_t *LocalAddress, } return false; } - case macho::RIT_Difference: - case macho::RIT_Generic_LocalDifference: - case macho::RIT_Generic_PreboundLazyPointer: + case MachO::GENERIC_RELOC_SECTDIFF: + case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: + case MachO::GENERIC_RELOC_PB_LA_PTR: return Error("Relocation type not implemented yet!"); } } @@ -193,12 +238,12 @@ bool RuntimeDyldMachO::resolveX86_64Relocation(uint8_t *LocalAddress, switch(Type) { default: llvm_unreachable("Invalid relocation type!"); - case macho::RIT_X86_64_Signed1: - case macho::RIT_X86_64_Signed2: - case macho::RIT_X86_64_Signed4: - case macho::RIT_X86_64_Signed: - case macho::RIT_X86_64_Unsigned: - case macho::RIT_X86_64_Branch: { + case MachO::X86_64_RELOC_SIGNED_1: + case MachO::X86_64_RELOC_SIGNED_2: + case MachO::X86_64_RELOC_SIGNED_4: + case MachO::X86_64_RELOC_SIGNED: + case MachO::X86_64_RELOC_UNSIGNED: + case MachO::X86_64_RELOC_BRANCH: { Value += Addend; // Mask in the target value a byte at a time (we don't have an alignment // guarantee for the target address, so this is safest). @@ -209,10 +254,10 @@ bool RuntimeDyldMachO::resolveX86_64Relocation(uint8_t *LocalAddress, } return false; } - case macho::RIT_X86_64_GOTLoad: - case macho::RIT_X86_64_GOT: - case macho::RIT_X86_64_Subtractor: - case macho::RIT_X86_64_TLV: + case MachO::X86_64_RELOC_GOT_LOAD: + case MachO::X86_64_RELOC_GOT: + case MachO::X86_64_RELOC_SUBTRACTOR: + case MachO::X86_64_RELOC_TLV: return Error("Relocation type not implemented yet!"); } } @@ -237,7 +282,7 @@ bool RuntimeDyldMachO::resolveARMRelocation(uint8_t *LocalAddress, switch(Type) { default: llvm_unreachable("Invalid relocation type!"); - case macho::RIT_Vanilla: { + case MachO::ARM_RELOC_VANILLA: { // Mask in the target value a byte at a time (we don't have an alignment // guarantee for the target address, so this is safest). uint8_t *p = (uint8_t*)LocalAddress; @@ -247,7 +292,7 @@ bool RuntimeDyldMachO::resolveARMRelocation(uint8_t *LocalAddress, } break; } - case macho::RIT_ARM_Branch24Bit: { + case MachO::ARM_RELOC_BR24: { // Mask the value into the target address. We know instructions are // 32-bit aligned, so we can do it all at once. uint32_t *p = (uint32_t*)LocalAddress; @@ -263,14 +308,14 @@ bool RuntimeDyldMachO::resolveARMRelocation(uint8_t *LocalAddress, *p = (*p & ~0xffffff) | Value; break; } - case macho::RIT_ARM_ThumbBranch22Bit: - case macho::RIT_ARM_ThumbBranch32Bit: - case macho::RIT_ARM_Half: - case macho::RIT_ARM_HalfDifference: - case macho::RIT_Pair: - case macho::RIT_Difference: - case macho::RIT_ARM_LocalDifference: - case macho::RIT_ARM_PreboundLazyPointer: + case MachO::ARM_THUMB_RELOC_BR22: + case MachO::ARM_THUMB_32BIT_BRANCH: + case MachO::ARM_RELOC_HALF: + case MachO::ARM_RELOC_HALF_SECTDIFF: + case MachO::ARM_RELOC_PAIR: + case MachO::ARM_RELOC_SECTDIFF: + case MachO::ARM_RELOC_LOCAL_SECTDIFF: + case MachO::ARM_RELOC_PB_LA_PTR: return Error("Relocation type not implemented yet!"); } return false; @@ -284,9 +329,19 @@ void RuntimeDyldMachO::processRelocationRef(unsigned SectionID, StubMap &Stubs) { const ObjectFile *OF = Obj.getObjectFile(); const MachOObjectFile *MachO = static_cast<const MachOObjectFile*>(OF); - macho::RelocationEntry RE = MachO->getRelocation(RelI.getRawDataRefImpl()); + MachO::any_relocation_info RE= MachO->getRelocation(RelI.getRawDataRefImpl()); uint32_t RelType = MachO->getAnyRelocationType(RE); + + // FIXME: Properly handle scattered relocations. + // For now, optimistically skip these: they can often be ignored, as + // the static linker will already have applied the relocation, and it + // only needs to be reapplied if symbols move relative to one another. + // Note: This will fail horribly where the relocations *do* need to be + // applied, but that was already the case. + if (MachO->isRelocationScattered(RE)) + return; + RelocationValueRef Value; SectionEntry &Section = Sections[SectionID]; @@ -302,10 +357,9 @@ void RuntimeDyldMachO::processRelocationRef(unsigned SectionID, if (isExtern) { // Obtain the symbol name which is referenced in the relocation - SymbolRef Symbol; - RelI.getSymbol(Symbol); + symbol_iterator Symbol = RelI.getSymbol(); StringRef TargetName; - Symbol.getName(TargetName); + Symbol->getName(TargetName); // First search for the symbol in the local symbol table SymbolTableMap::const_iterator lsi = Symbols.find(TargetName.data()); if (lsi != Symbols.end()) { @@ -330,7 +384,8 @@ void RuntimeDyldMachO::processRelocationRef(unsigned SectionID, Value.Addend = Addend - Addr; } - if (Arch == Triple::x86_64 && RelType == macho::RIT_X86_64_GOT) { + if (Arch == Triple::x86_64 && (RelType == MachO::X86_64_RELOC_GOT || + RelType == MachO::X86_64_RELOC_GOT_LOAD)) { assert(IsPCRel); assert(Size == 2); StubMap::const_iterator i = Stubs.find(Value); @@ -341,8 +396,7 @@ void RuntimeDyldMachO::processRelocationRef(unsigned SectionID, Stubs[Value] = Section.StubOffset; uint8_t *GOTEntry = Section.Address + Section.StubOffset; RelocationEntry RE(SectionID, Section.StubOffset, - macho::RIT_X86_64_Unsigned, Value.Addend - 4, false, - 3); + MachO::X86_64_RELOC_UNSIGNED, 0, false, 3); if (Value.SymbolName) addRelocationForSymbol(RE, Value.SymbolName); else @@ -351,9 +405,9 @@ void RuntimeDyldMachO::processRelocationRef(unsigned SectionID, Addr = GOTEntry; } resolveRelocation(Section, Offset, (uint64_t)Addr, - macho::RIT_X86_64_Unsigned, 4, true, 2); + MachO::X86_64_RELOC_UNSIGNED, Value.Addend, true, 2); } else if (Arch == Triple::arm && - (RelType & 0xf) == macho::RIT_ARM_Branch24Bit) { + (RelType & 0xf) == MachO::ARM_RELOC_BR24) { // This is an ARM branch relocation, need to use a stub function. // Look up for existing stub. @@ -368,7 +422,7 @@ void RuntimeDyldMachO::processRelocationRef(unsigned SectionID, uint8_t *StubTargetAddr = createStubFunction(Section.Address + Section.StubOffset); RelocationEntry RE(SectionID, StubTargetAddr - Section.Address, - macho::RIT_Vanilla, Value.Addend); + MachO::GENERIC_RELOC_VANILLA, Value.Addend); if (Value.SymbolName) addRelocationForSymbol(RE, Value.SymbolName); else |