[llvm] r251761 - RuntimeDyld: add COFF i386 support

Aaron Ballman via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 4 08:01:11 PST 2015


On Sat, Oct 31, 2015 at 9:26 PM, Saleem Abdulrasool via llvm-commits
<llvm-commits at lists.llvm.org> wrote:
> Author: compnerd
> Date: Sat Oct 31 20:26:15 2015
> New Revision: 251761
>
> URL: http://llvm.org/viewvc/llvm-project?rev=251761&view=rev
> Log:
> RuntimeDyld: add COFF i386 support
>
> This adds support for COFF I386.  This is sufficient for code execution in a
> 32-bit JIT, though, imported symbols need to custom lowered for the redirection.
>
> Added:
>     llvm/trunk/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h
>     llvm/trunk/test/ExecutionEngine/RuntimeDyld/X86/COFF_i386.s
> Modified:
>     llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp
>
> Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp?rev=251761&r1=251760&r2=251761&view=diff
> ==============================================================================
> --- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp (original)
> +++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp Sat Oct 31 20:26:15 2015
> @@ -12,6 +12,7 @@
>  //===----------------------------------------------------------------------===//
>
>  #include "RuntimeDyldCOFF.h"
> +#include "Targets/RuntimeDyldCOFFI386.h"
>  #include "Targets/RuntimeDyldCOFFX86_64.h"
>  #include "llvm/ADT/STLExtras.h"
>  #include "llvm/ADT/Triple.h"
> @@ -47,6 +48,8 @@ llvm::RuntimeDyldCOFF::create(Triple::Ar
>    default:
>      llvm_unreachable("Unsupported target for RuntimeDyldCOFF.");
>      break;
> +  case Triple::x86:
> +    return make_unique<RuntimeDyldCOFFI386>(MemMgr, Resolver);
>    case Triple::x86_64:
>      return make_unique<RuntimeDyldCOFFX86_64>(MemMgr, Resolver);
>    }
>
> Added: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h?rev=251761&view=auto
> ==============================================================================
> --- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h (added)
> +++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h Sat Oct 31 20:26:15 2015
> @@ -0,0 +1,199 @@
> +//===--- RuntimeDyldCOFFI386.h --- COFF/X86_64 specific code ---*- C++ --*-===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// COFF x86 support for MC-JIT runtime dynamic linker.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFI386_H
> +#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFI386_H
> +
> +#include "llvm/Object/COFF.h"
> +#include "llvm/Support/COFF.h"
> +#include "../RuntimeDyldCOFF.h"
> +
> +#define DEBUG_TYPE "dyld"
> +
> +namespace llvm {
> +
> +class RuntimeDyldCOFFI386 : public RuntimeDyldCOFF {
> +public:
> +  RuntimeDyldCOFFI386(RuntimeDyld::MemoryManager &MM,
> +                      RuntimeDyld::SymbolResolver &Resolver)
> +      : RuntimeDyldCOFF(MM, Resolver) {}
> +
> +  unsigned getMaxStubSize() override {
> +    return 8; // 2-byte jmp instruction + 32-bit relative address + 2 byte pad
> +  }
> +
> +  unsigned getStubAlignment() override { return 1; }
> +
> +  relocation_iterator processRelocationRef(unsigned SectionID,
> +                                           relocation_iterator RelI,
> +                                           const ObjectFile &Obj,
> +                                           ObjSectionToIDMap &ObjSectionToID,
> +                                           StubMap &Stubs) override {
> +    auto Symbol = RelI->getSymbol();
> +    if (Symbol == Obj.symbol_end())
> +      report_fatal_error("Unknown symbol in relocation");
> +
> +    ErrorOr<StringRef> TargetNameOrErr = Symbol->getName();
> +    if (auto EC = TargetNameOrErr.getError())
> +      report_fatal_error(EC.message());
> +    StringRef TargetName = *TargetNameOrErr;
> +
> +    auto Section = *Symbol->getSection();
> +
> +    uint64_t RelType = RelI->getType();
> +    uint64_t Offset = RelI->getOffset();
> +
> +#if !defined(NDEBUG)
> +    SmallString<32> RelTypeName;
> +    RelI->getTypeName(RelTypeName);
> +#endif
> +    DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset
> +                 << " RelType: " << RelTypeName << " TargetName: " << TargetName
> +                 << "\n");
> +
> +    unsigned TargetSectionID = -1;
> +    if (Section == Obj.section_end()) {
> +      RelocationEntry RE(SectionID, Offset, RelType, 0, -1, 0, 0, 0, false, 0);
> +      addRelocationForSymbol(RE, TargetName);
> +    } else {
> +      TargetSectionID =
> +          findOrEmitSection(Obj, *Section, Section->isText(), ObjSectionToID);
> +
> +      switch (RelType) {
> +      case COFF::IMAGE_REL_I386_ABSOLUTE:
> +        // This relocation is ignored.
> +        break;
> +      case COFF::IMAGE_REL_I386_DIR32:
> +      case COFF::IMAGE_REL_I386_DIR32NB:
> +      case COFF::IMAGE_REL_I386_REL32: {
> +        RelocationEntry RE =
> +            RelocationEntry(SectionID, Offset, RelType, 0, TargetSectionID,
> +                            getSymbolOffset(*Symbol), 0, 0, false, 0);
> +        addRelocationForSection(RE, TargetSectionID);
> +        break;
> +      }
> +      case COFF::IMAGE_REL_I386_SECTION: {
> +        RelocationEntry RE =
> +            RelocationEntry(TargetSectionID, Offset, RelType, 0);
> +        addRelocationForSection(RE, TargetSectionID);
> +        break;
> +      }
> +      case COFF::IMAGE_REL_I386_SECREL: {
> +        RelocationEntry RE = RelocationEntry(SectionID, Offset, RelType,
> +                                             getSymbolOffset(*Symbol));
> +        addRelocationForSection(RE, TargetSectionID);
> +        break;
> +      }
> +      default:
> +        llvm_unreachable("unsupported relocation type");
> +      }
> +
> +    }
> +
> +    return ++RelI;
> +  }
> +
> +  void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
> +    const auto Section = Sections[RE.SectionID];
> +    uint8_t *Target = Section.Address + RE.Offset;
> +
> +    switch (RE.RelType) {
> +    case COFF::IMAGE_REL_I386_ABSOLUTE:
> +      // This relocation is ignored.
> +      break;
> +    case COFF::IMAGE_REL_I386_DIR32: {
> +      // The target's 32-bit VA.
> +      uint64_t Result =
> +          RE.Sections.SectionA == static_cast<uint32_t>(-1)
> +              ? Value
> +              : Sections[RE.Sections.SectionA].LoadAddress + RE.Addend;
> +      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_DIR32"
> +                   << " TargetSection: " << RE.Sections.SectionA
> +                   << " Value: " << format("0x%08" PRIx32, Result) << '\n');
> +      writeBytesUnaligned(Result, Target, 4);
> +      break;
> +    }
> +    case COFF::IMAGE_REL_I386_DIR32NB: {
> +      // The target's 32-bit RVA.
> +      // NOTE: use Section[0].LoadAddress as an approximation of ImageBase
> +      uint64_t Result = Sections[RE.Sections.SectionA].LoadAddress + RE.Addend -
> +                        Sections[0].LoadAddress;
> +      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_DIR32NB"
> +                   << " TargetSection: " << RE.Sections.SectionA
> +                   << " Value: " << format("0x%08" PRIx32, Result) << '\n');
> +      writeBytesUnaligned(Result, Target, 4);
> +      break;
> +    }
> +    case COFF::IMAGE_REL_I386_REL32: {
> +      // 32-bit relative displacement to the target.
> +      uint64_t Result = Sections[RE.Sections.SectionA].LoadAddress -
> +                        Section.LoadAddress + 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;
> +    }
> +    case COFF::IMAGE_REL_I386_SECTION:
> +      // 16-bit section index of the section that contains the target.
> +      assert(static_cast<int16_t>(RE.SectionID) <= INT16_MAX &&
> +             "relocation overflow");
> +      assert(static_cast<int16_t>(RE.SectionID) >= INT16_MIN &&
> +             "relocation underflow");

These asserts are triggering a -Wtype-limits warning.

In file included from
/opt/llvm/build-llvm/src/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp:15:0:
/opt/llvm/build-llvm/src/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h:
In member function ‘virtual void
llvm::RuntimeDyldCOFFI386::resolveRelocation(const
llvm::RelocationEntry&, uint64_t)’:
/opt/llvm/build-llvm/src/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h:164:7:
warning: comparison is always true due to limited range of data type
[-Wtype-limits]
/opt/llvm/build-llvm/src/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h:166:7:
warning: comparison is always true due to limited range of data type
[-Wtype-limits]

~Aaron

> +      DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
> +                   << " RelType: IMAGE_REL_I386_SECTION Value: " << RE.SectionID
> +                   << '\n');
> +      writeBytesUnaligned(RE.SectionID, Target, 2);
> +      break;
> +    case COFF::IMAGE_REL_I386_SECREL:
> +      // 32-bit offset of the target from the beginning of its section.
> +      assert(static_cast<int32_t>(RE.Addend) <= INT32_MAX &&
> +             "relocation overflow");
> +      assert(static_cast<int32_t>(RE.Addend) >= INT32_MIN &&
> +             "relocation underflow");
> +      DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
> +                   << " RelType: IMAGE_REL_I386_SECREL Value: " << RE.Addend
> +                   << '\n');
> +      writeBytesUnaligned(RE.Addend, Target, 2);
> +      break;
> +    default:
> +      llvm_unreachable("unsupported relocation type");
> +    }
> +  }
> +
> +  void registerEHFrames() override {}
> +  void deregisterEHFrames() override {}
> +
> +  void finalizeLoad(const ObjectFile &Obj,
> +                    ObjSectionToIDMap &SectionMap) override {}
> +};
> +
> +}
> +
> +#endif
> +
>
> Added: llvm/trunk/test/ExecutionEngine/RuntimeDyld/X86/COFF_i386.s
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/RuntimeDyld/X86/COFF_i386.s?rev=251761&view=auto
> ==============================================================================
> --- llvm/trunk/test/ExecutionEngine/RuntimeDyld/X86/COFF_i386.s (added)
> +++ llvm/trunk/test/ExecutionEngine/RuntimeDyld/X86/COFF_i386.s Sat Oct 31 20:26:15 2015
> @@ -0,0 +1,66 @@
> +// RUN: llvm-mc -triple i686-windows -filetype obj -o %t.obj %s
> +// RUN: llvm-rtdyld -triple i686-windows -dummy-extern _OutputDebugStringA at 4=0xfffffffe -dummy-extern _ExitProcess at 4=0xffffffff -verify -check=%s %t.obj
> +
> +       .text
> +
> +       .def _main
> +               .scl 2
> +               .type 32
> +       .endef
> +       .global _main
> +_main:
> +rel1:
> +       call _function                          // IMAGE_REL_I386_REL32
> +# rtdyld-check: decode_operand(rel1, 0) = (_function-_main-4-1)
> +       xorl %eax, %eax
> +       retl
> +
> +       .def _function
> +               .scl 2
> +               .type 32
> +       .endef
> +_function:
> +rel2:
> +       pushl string
> +rel3:
> +       calll *__imp__OutputDebugStringA        // IMAGE_REL_I386_DIR32
> +# rtdyld-check: decode_operand(rel3, 3) = __imp__OutputDebugStringA
> +       addl  $4, %esp
> +       pushl $0
> +rel4:
> +       calll *__imp__ExitProcess               // IMAGE_REL_I386_DIR32
> +# rtdyld-check: decode_operand(rel4, 3) = __imp__ExitProcess
> +       addl  $4, %esp
> +       retl
> +
> +       .data
> +
> +       .global __imp__OutputDebugStringA
> +       .align 4
> +__imp__OutputDebugStringA:
> +       .long "_OutputDebugStringA at 4"           // IMAGE_REL_I386_DIR32
> +# rtdyld-check: *{4}__imp__OutputDebugStringA = 0xfffffffe
> +
> +       .global __imp__ExitProcess
> +       .align 4
> +__imp__ExitProcess:
> +       .long "_ExitProcess at 4"                  // IMAGE_REL_I386_DIR32
> +# rtdyld-check: *{4}__imp__ExitProcess = 0xffffffff
> +
> +       .global string
> +       .align 1
> +string:
> +       .asciz "Hello World!\n"
> +
> +       .global relocations
> +relocations:
> +rel5:
> +       .long _function at imgrel                  // IMAGE_REL_I386_DIR32NB
> +# rtdyld-check: *{4}rel5 = _function - section_addr(COFF_i386.s.tmp.obj, .text)
> +rel6:
> +# rtdyld-check: *{2}rel6 = 1
> +       .secidx __imp__OutputDebugStringA       // IMAGE_REL_I386_SECTION
> +rel7:
> +# rtdyld-check: *{4}rel7 = relocations - section_addr(COFF_i386.s.tmp.obj, .data)
> +       .secrel32 relocations                   // IMAGE_REL_I386_SECREL
> +
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits


More information about the llvm-commits mailing list