Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

RuntimeDyldCOFFI386 error on IMAGE_REL_I386_REL32 for global function address mapping #26115

Open Quuxplusone opened 8 years ago

Quuxplusone commented 8 years ago
Bugzilla Link PR26116
Status NEW
Importance P release blocker
Reported by Vivien MILLET (vivien.millet@gmail.com)
Reported on 2016-01-11 13:17:03 -0800
Last modified on 2016-02-24 05:53:03 -0800
Version trunk
Hardware PC All
CC listhex@gmail.com, llvm-bugs@lists.llvm.org, vivien.millet@gmail.com
Fixed by commit(s)
Attachments
Blocks
Blocked by
See also
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<uint32_t>(-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<int32_t>(Result) <= INT32_MAX &&
             "relocation overflow");
      assert(static_cast<int32_t>(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;
Quuxplusone 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.
Quuxplusone 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     }