Open llvmbot opened 8 years ago
Hi, I agree on that point, REL32 shouldn't be used to locate absolute addresses of external symbols. About the Value -= FinalAddress + 4; I've just adapted the x64 version of the same code section in RuntimeDyldCOFFX86_64.h :
00069 case COFF::IMAGE_REL_AMD64_REL32: 00070 case COFF::IMAGE_REL_AMD64_REL32_1: 00071 case COFF::IMAGE_REL_AMD64_REL32_2: 00072 case COFF::IMAGE_REL_AMD64_REL32_3: 00073 case COFF::IMAGE_REL_AMD64_REL32_4: 00074 case COFF::IMAGE_REL_AMD64_REL32_5: { 00075 uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset); 00076 // Delta is the distance from the start of the reloc to the end of the 00077 // instruction with the reloc. 00078 uint64_t Delta = 4 + (RE.RelType - COFF::IMAGE_REL_AMD64_REL32); 00079 Value -= FinalAddress + Delta; // <------- HERE 00080 uint64_t Result = Value + RE.Addend; 00081 assert(((int64_t)Result <= INT32_MAX) && "Relocation overflow"); 00082 assert(((int64_t)Result >= INT32_MIN) && "Relocation underflow"); 00083 writeBytesUnaligned(Result, Target, 4); 00084 break; 00085 }
Hi, I've got the same assertion but in my case the external symbol is an address of external function which is linked during RtDyld. So your instruction
Value -= FinalAddress + 4;
may give negative result if FinalAddress > Value and will get relocation overflow. I think the problem is in using of REL32 relocation for externals.
CC @phoebewang @MaskRay
Extended Description
In RuntimeDyldCOFFI386.h After Line: 151 We have : uint64_t Result = Sections[RE.Sections.SectionA].getLoadAddress() - Section.getLoadAddress() + RE.Addend - 4 - RE.Offset;
BUT In case of global native C++ function mapping (ExecutionEngine::addGlobalMapping(...)), RE.Sections.SectionA equals -1 (0xffffffff) which triggers a bad index assertion.
Analysing and comparing to the In RuntimeDyldCOFFX86_64, we should treat a special case when SectionA == -1
I propose that code which works fine for me and retrieves on code generation the good global address (i put the whole switch case)
case COFF::IMAGE_REL_I386_REL32: { // 32-bit relative displacement to the target. uint64_t Result; if(RE.Sections.SectionA == static_cast(-1))
{
uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset);
Value -= FinalAddress + 4;
Result = Value + RE.Addend;
}
else
{
Result = Sections[RE.Sections.SectionA].getLoadAddress() -
Section.getLoadAddress() + RE.Addend - 4 - RE.Offset;
}
assert(static_cast(Result) <= INT32_MAX &&
"relocation overflow");
assert(static_cast(Result) >= INT32_MIN &&
"relocation underflow");
DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
<< " RelType: IMAGE_REL_I386_REL32"
<< " TargetSection: " << RE.Sections.SectionA
<< " Value: " << format("0x%08" PRIx32, Result) << '\n');
writeBytesUnaligned(Result, Target, 4);
break;