Index: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp =================================================================== --- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -522,6 +522,9 @@ Offset += Size; Addr += Size; } + + if (Checker) + Checker->registerSection(Obj.getFileName(), SectionID); } unsigned RuntimeDyldImpl::emitSection(const ObjectFile &Obj, Index: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h =================================================================== --- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h +++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h @@ -123,6 +123,10 @@ // no particular advanced processing. void processSimpleRelocation(unsigned SectionID, uint64_t Offset, unsigned RelType, RelocationValueRef Value); + // Return matching *LO16 relocation (Mips specific) + uint32_t getMatchingLoRelocation(uint32_t RelType, + bool IsLocal = false) const; + // The tentative ID for the GOT section unsigned GOTSectionID; @@ -138,6 +142,10 @@ // A map to avoid duplicate got entries (Mips64 specific) StringMap GOTSymbolOffsets; + // *HI16 relocations will be added for resolving when we find matching + // *LO16 part. (Mips specific) + SmallVector, 8> PendingRelocs; + // When a module is loaded we save the SectionID of the EH frame section // in a table until we receive a request to register all unregistered // EH frame sections with the memory manager. Index: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp =================================================================== --- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -1123,6 +1123,29 @@ addRelocationForSection(RE, Value.SectionID); } +uint32_t RuntimeDyldELF::getMatchingLoRelocation(uint32_t RelType, + bool IsLocal) const { + switch (RelType) { + case ELF::R_MICROMIPS_GOT16: + if (IsLocal) + return ELF::R_MICROMIPS_LO16; + break; + case ELF::R_MICROMIPS_HI16: + return ELF::R_MICROMIPS_LO16; + case ELF::R_MIPS_GOT16: + if (IsLocal) + return ELF::R_MIPS_LO16; + break; + case ELF::R_MIPS_HI16: + return ELF::R_MIPS_LO16; + case ELF::R_MIPS_PCHI16: + return ELF::R_MIPS_PCLO16; + default: + break; + } + return ELF::R_MIPS_NONE; +} + relocation_iterator RuntimeDyldELF::processRelocationRef( unsigned SectionID, relocation_iterator RelI, const ObjectFile &O, ObjSectionToIDMap &ObjSectionToID, StubMap &Stubs) { @@ -1331,17 +1354,35 @@ addRelocationForSection(RE, SectionID); Section.StubOffset += getMaxStubSize(); } + } else if (RelType == ELF::R_MIPS_HI16 || RelType == ELF::R_MIPS_PCHI16) { + int64_t Addend = (Opcode & 0x0000ffff) << 16; + RelocationEntry RE(SectionID, Offset, RelType, Addend); + PendingRelocs.push_back(std::make_pair(Value, RE)); + } else if (RelType == ELF::R_MIPS_LO16 || RelType == ELF::R_MIPS_PCLO16) { + int64_t Addend = Value.Addend + SignExtend32<16>(Opcode & 0x0000ffff); + for (auto I = PendingRelocs.begin(); I != PendingRelocs.end();) { + const RelocationValueRef &MatchingValue = I->first; + RelocationEntry &Reloc = I->second; + if (MatchingValue == Value && + RelType == getMatchingLoRelocation(Reloc.RelType) && + SectionID == Reloc.SectionID) { + Reloc.Addend += Addend; + if (Value.SymbolName) + addRelocationForSymbol(Reloc, Value.SymbolName); + else + addRelocationForSection(Reloc, Value.SectionID); + I = PendingRelocs.erase(I); + } else + ++I; + } + RelocationEntry RE(SectionID, Offset, RelType, Addend); + if (Value.SymbolName) + addRelocationForSymbol(RE, Value.SymbolName); + else + addRelocationForSection(RE, Value.SectionID); } else { - // FIXME: Calculate correct addends for R_MIPS_HI16, R_MIPS_LO16, - // R_MIPS_PCHI16 and R_MIPS_PCLO16 relocations. - if (RelType == ELF::R_MIPS_HI16 || RelType == ELF::R_MIPS_PCHI16) - Value.Addend += (Opcode & 0x0000ffff) << 16; - else if (RelType == ELF::R_MIPS_LO16) - Value.Addend += (Opcode & 0x0000ffff); - else if (RelType == ELF::R_MIPS_32) + if (RelType == ELF::R_MIPS_32) Value.Addend += Opcode; - else if (RelType == ELF::R_MIPS_PCLO16) - Value.Addend += SignExtend32<16>((Opcode & 0x0000ffff)); else if (RelType == ELF::R_MIPS_PC16) Value.Addend += SignExtend32<18>((Opcode & 0x0000ffff) << 2); else if (RelType == ELF::R_MIPS_PC19_S2) @@ -1719,6 +1760,10 @@ void RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj, ObjSectionToIDMap &SectionMap) { + if (IsMipsO32ABI) + if (!PendingRelocs.empty()) + report_fatal_error("Can't find matching LO16 reloc"); + // If necessary, allocate the global offset table if (GOTSectionID != 0) { // Allocate memory for the section Index: llvm/trunk/test/ExecutionEngine/RuntimeDyld/Mips/ELF_O32_PIC_relocations.s =================================================================== --- llvm/trunk/test/ExecutionEngine/RuntimeDyld/Mips/ELF_O32_PIC_relocations.s +++ llvm/trunk/test/ExecutionEngine/RuntimeDyld/Mips/ELF_O32_PIC_relocations.s @@ -1,10 +1,10 @@ # RUN: llvm-mc -triple=mipsel-unknown-linux -relocation-model=pic -code-model=small -filetype=obj -o %T/test_ELF_O32.o %s # RUN: llc -mtriple=mipsel-unknown-linux -relocation-model=pic -filetype=obj -o %T/test_ELF_ExternalFunction_O32.o %S/Inputs/ExternalFunction.ll -# RUN: llvm-rtdyld -triple=mipsel-unknown-linux -verify -map-section test_ELF_O32.o,.text=0x1000 -map-section test_ELF_ExternalFunction_O32.o,.text=0x10000 -check=%s %T/test_ELF_O32.o %T/test_ELF_ExternalFunction_O32.o +# RUN: llvm-rtdyld -triple=mipsel-unknown-linux -verify -map-section test_ELF_O32.o,""=0x7FF8 -map-section test_ELF_O32.o,.text=0x1000 -map-section test_ELF_ExternalFunction_O32.o,.text=0x10000 -check=%s %T/test_ELF_O32.o %T/test_ELF_ExternalFunction_O32.o # RUN: llvm-mc -triple=mips-unknown-linux -relocation-model=pic -code-model=small -filetype=obj -o %T/test_ELF_O32.o %s # RUN: llc -mtriple=mips-unknown-linux -relocation-model=pic -filetype=obj -o %/T/test_ELF_ExternalFunction_O32.o %S/Inputs/ExternalFunction.ll -# RUN: llvm-rtdyld -triple=mips-unknown-linux -verify -map-section test_ELF_O32.o,.text=0x1000 -map-section test_ELF_ExternalFunction_O32.o,.text=0x10000 -check=%s %T/test_ELF_O32.o %T/test_ELF_ExternalFunction_O32.o +# RUN: llvm-rtdyld -triple=mips-unknown-linux -verify -map-section test_ELF_O32.o,""=0x7FF8 -map-section test_ELF_O32.o,.text=0x1000 -map-section test_ELF_ExternalFunction_O32.o,.text=0x10000 -check=%s %T/test_ELF_O32.o %T/test_ELF_ExternalFunction_O32.o .data # rtdyld-check: *{4}R_MIPS_32 = foo[31:0] @@ -52,4 +52,13 @@ R_MIPS_LO16: lui $1, %lo(foo) +# rtdyld-check: decode_operand(R_MIPS_HI16_ADDEND, 1)[15:0] = (var+0x8008)[31:16] +R_MIPS_HI16_ADDEND: + lui $2, %hi(var+8) + +# rtdyld-check: decode_operand(R_MIPS_LO16_ADDEND, 2)[15:0] = (var+0x8)[15:0] +R_MIPS_LO16_ADDEND: + lb $2, %lo(var+8)($2) + .size bar, .-bar + .comm var,9,1