llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.06k stars 11.59k forks source link

RuntimeDyldCOFFI386 error on IMAGE_REL_I386_REL32 for global function address mapping #26490

Open llvmbot opened 8 years ago

llvmbot commented 8 years ago
Bugzilla Link 26116
Version trunk
OS All
Reporter LLVM Bugzilla Contributor

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;

llvmbot commented 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 }

llvmbot commented 8 years ago

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.

Endilll commented 1 year ago

CC @phoebewang @MaskRay