-bool RuntimeDyldMachO::
-resolveARMRelocation(uint8_t *LocalAddress,
- uint64_t FinalAddress,
- uint64_t Value,
- bool isPCRel,
- unsigned Type,
- unsigned Size,
- int64_t Addend) {
- // If the relocation is PC-relative, the value to be encoded is the
- // pointer difference.
- if (isPCRel) {
- Value -= FinalAddress;
- // ARM PCRel relocations have an effective-PC offset of two instructions
- // (four bytes in Thumb mode, 8 bytes in ARM mode).
- // FIXME: For now, assume ARM mode.
- Value -= 8;
- }
-
- switch(Type) {
- default:
- llvm_unreachable("Invalid relocation type!");
- case macho::RIT_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;
- for (unsigned i = 0; i < Size; ++i) {
- *p++ = (uint8_t)Value;
- Value >>= 8;
- }
- break;
- }
- case macho::RIT_ARM_Branch24Bit: {
- // 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;
- // The low two bits of the value are not encoded.
- Value >>= 2;
- // Mask the value to 24 bits.
- Value &= 0xffffff;
- // FIXME: If the destination is a Thumb function (and the instruction
- // is a non-predicated BL instruction), we need to change it to a BLX
- // instruction instead.
-
- // Insert the value into the instruction.
- *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:
- return Error("Relocation type not implemented yet!");
- }
- return false;
-}
-
-bool RuntimeDyldMachO::
-loadSegment32(const MachOObject *Obj,
- const MachOObject::LoadCommandInfo *SegmentLCI,
- const InMemoryStruct<macho::SymtabLoadCommand> &SymtabLC) {
- // FIXME: This should really be combined w/ loadSegment64. Templatized
- // function on the 32/64 datatypes maybe?
- InMemoryStruct<macho::SegmentLoadCommand> SegmentLC;
- Obj->ReadSegmentLoadCommand(*SegmentLCI, SegmentLC);
- if (!SegmentLC)
- return Error("unable to load segment load command");
-
-
- SmallVector<unsigned, 16> SectionMap;
- for (unsigned SectNum = 0; SectNum != SegmentLC->NumSections; ++SectNum) {
- InMemoryStruct<macho::Section> Sect;
- Obj->ReadSection(*SegmentLCI, SectNum, Sect);
- if (!Sect)
- return Error("unable to load section: '" + Twine(SectNum) + "'");
-
- // Allocate memory via the MM for the section.
- uint8_t *Buffer;
- uint32_t SectionID = Sections.size();
- if (Sect->Flags == 0x80000400)
- Buffer = MemMgr->allocateCodeSection(Sect->Size, Sect->Align, SectionID);
- else
- Buffer = MemMgr->allocateDataSection(Sect->Size, Sect->Align, SectionID);
-
- DEBUG(dbgs() << "Loading "
- << ((Sect->Flags == 0x80000400) ? "text" : "data")
- << " (ID #" << SectionID << ")"
- << " '" << Sect->SegmentName << ","
- << Sect->Name << "' of size " << Sect->Size
- << " to address " << Buffer << ".\n");
-
- // Copy the payload from the object file into the allocated buffer.
- uint8_t *Base = (uint8_t*)Obj->getData(SegmentLC->FileOffset,
- SegmentLC->FileSize).data();
- memcpy(Buffer, Base + Sect->Address, Sect->Size);
-
- // Remember what got allocated for this SectionID.
- Sections.push_back(sys::MemoryBlock(Buffer, Sect->Size));
- SectionLocalMemToID[Buffer] = SectionID;
-
- // By default, the load address of a section is its memory buffer.
- SectionLoadAddress.push_back((uint64_t)Buffer);
-
- // Keep a map of object file section numbers to corresponding SectionIDs
- // while processing the file.
- SectionMap.push_back(SectionID);
- }
-
- // Process the symbol table.
- SmallVector<StringRef, 64> SymbolNames;
- processSymbols32(Obj, SectionMap, SymbolNames, SymtabLC);
-
- // Process the relocations for each section we're loading.
- Relocations.grow(Relocations.size() + SegmentLC->NumSections);
- Referrers.grow(Referrers.size() + SegmentLC->NumSections);
- for (unsigned SectNum = 0; SectNum != SegmentLC->NumSections; ++SectNum) {
- InMemoryStruct<macho::Section> Sect;
- Obj->ReadSection(*SegmentLCI, SectNum, Sect);
- if (!Sect)
- return Error("unable to load section: '" + Twine(SectNum) + "'");
- for (unsigned j = 0; j != Sect->NumRelocationTableEntries; ++j) {
- InMemoryStruct<macho::RelocationEntry> RE;
- Obj->ReadRelocationEntry(Sect->RelocationTableOffset, j, RE);
- if (RE->Word0 & macho::RF_Scattered)
- return Error("NOT YET IMPLEMENTED: scattered relocations.");
- // Word0 of the relocation is the offset into the section where the
- // relocation should be applied. We need to translate that into an
- // offset into a function since that's our atom.
- uint32_t Offset = RE->Word0;
- bool isExtern = (RE->Word1 >> 27) & 1;
-
- // FIXME: Get the relocation addend from the target address.
- // FIXME: VERY imporant for internal relocations.
-
- // Figure out the source symbol of the relocation. If isExtern is true,
- // this relocation references the symbol table, otherwise it references
- // a section in the same object, numbered from 1 through NumSections
- // (SectionBases is [0, NumSections-1]).
- uint32_t SourceNum = RE->Word1 & 0xffffff; // 24-bit value
- if (!isExtern) {
- assert(SourceNum > 0 && "Invalid relocation section number!");
- unsigned SectionID = SectionMap[SourceNum - 1];
- unsigned TargetID = SectionMap[SectNum];
- DEBUG(dbgs() << "Internal relocation at Section #"
- << TargetID << " + " << Offset
- << " from Section #"
- << SectionID << " (Word1: "
- << format("0x%x", RE->Word1) << ")\n");
-
- // Store the relocation information. It will get resolved when
- // the section addresses are assigned.
- uint32_t RelocationIndex = Relocations[SectionID].size();
- Relocations[SectionID].push_back(RelocationEntry(TargetID,
- Offset,
- RE->Word1,
- 0 /*Addend*/));
- Referrers[TargetID].push_back(Referrer(SectionID, RelocationIndex));