> On Sep 25, 2017, at 09:24, Joe Groff via swift-dev <swift-dev@swift.org> > wrote: > > > >> On Sep 24, 2017, at 10:30 PM, John McCall <rjmcc...@apple.com> wrote: >> >> >>> On Sep 22, 2017, at 8:39 PM, Saleem Abdulrasool <compn...@compnerd.org> >>> wrote: >>> >>> On Thu, Sep 21, 2017 at 10:28 PM, John McCall <rjmcc...@apple.com> wrote: >>> >>>> On Sep 21, 2017, at 10:10 PM, Saleem Abdulrasool <compn...@compnerd.org> >>>> wrote: >>>> >>>> On Thu, Sep 21, 2017 at 5:18 PM, John McCall <rjmcc...@apple.com> wrote: >>>>> On Sep 21, 2017, at 1:26 PM, Saleem Abdulrasool via swift-dev >>>>> <swift-dev@swift.org> wrote: >>>>> On Thu, Sep 21, 2017 at 12:04 PM, Joe Groff <jgr...@apple.com> wrote: >>>>> >>>>> >>>>>> On Sep 21, 2017, at 11:49 AM, Saleem Abdulrasool <compn...@compnerd.org> >>>>>> wrote: >>>>>> >>>>>> On Thu, Sep 21, 2017 at 10:53 AM, Joe Groff <jgr...@apple.com> wrote: >>>>>> >>>>>> >>>>>>> On Sep 21, 2017, at 9:32 AM, Saleem Abdulrasool via swift-dev >>>>>>> <swift-dev@swift.org> wrote: >>>>>>> >>>>>>> Hello, >>>>>>> >>>>>>> The current layout for the swift metadata for structure types, as >>>>>>> emitted, seems to be unrepresentable in PE/COFF (at least for x86_64). >>>>>>> There is a partial listing of the generated code following the message >>>>>>> for reference. >>>>>>> >>>>>>> When building the standard library, LLVM encounters a relocation which >>>>>>> cannot be represented. Tracking down the relocation led to the type >>>>>>> metadata for SwiftNSOperatingSystemVersion. The metadata here is >>>>>>> _T0SC30_SwiftNSOperatingSystemVersionVN. At +32-bytes we find the Kind >>>>>>> (1). So, this is a struct metadata type. Thus at Offset 1 (+40 bytes) >>>>>>> we have the nominal type descriptor reference. This is the relocation >>>>>>> which we fail to represent correctly. If I'm not mistaken, it seems >>>>>>> that the field is supposed to be a relative offset to the nominal type >>>>>>> descriptor. However, currently, the nominal type descriptor is emitted >>>>>>> in a different section (.rodata) as opposed to the type descriptor >>>>>>> (.data). This cross-section relocation cannot be represented in the >>>>>>> file format. >>>>>>> >>>>>>> My understanding is that the type metadata will be adjusted during the >>>>>>> load for the field offsets. Furthermore, my guess is that the relative >>>>>>> offset is used to encode the location to avoid a relocation for the >>>>>>> load address base. In the case of windows, the based relocations are a >>>>>>> given, and I'm not sure if there is a better approach to be taken. >>>>>>> There are a couple of solutions which immediately spring to mind: >>>>>>> moving the nominal type descriptor into the (RW) data segment and the >>>>>>> other is to adjust the ABI to use an absolute relocation which would be >>>>>>> rebased. Given that the type metadata may be adjusted means that we >>>>>>> cannot emit it into the RO data segment. Is there another solution >>>>>>> that I am overlooking which may be simpler or better? >>>>>> >>>>>> IIRC, this came up when someone was trying to port Swift to Windows on >>>>>> ARM as well, and they were able to conditionalize the code so that we >>>>>> used absolute pointers on Windows/ARM, and we may have to do the same on >>>>>> Windows in general. It may be somewhat more complicated on Win64 since >>>>>> we generally assume that relative references can be 32-bit, whereas an >>>>>> absolute reference will be 64-bit, so some formats may have to change >>>>>> layout to make this work too. I believe Windows' executable loader still >>>>>> ultimately maps the final PE image contiguously, so alternatively, you >>>>>> could conceivably build a Swift toolchain that used ELF or Mach-O or >>>>>> some other format with better support for PIC as the intermediate object >>>>>> format and still linked a final PE executable. Using relative references >>>>>> should still be a win on Windows both because of the size benefit of >>>>>> being 32-bit and the fact that they don't need to be slid when running >>>>>> under ASLR or when a DLL needs to be rebased. >>>>>> >>>>>> >>>>>> Yeah, I tracked down the relativePointer thing. There is a nice subtle >>>>>> little warning that it is not fully portable :-). Would you happen to >>>>>> have a pointer to where the adjustment for the absolute pointers on WoA >>>>>> is? >>>>>> >>>>>> You are correct that the image should be contiugously mapped on Windows. >>>>>> The idea of MachO as an intermediatary is rather intriguing. Thinking >>>>>> longer term, maybe we want to use that as a global solution? It would >>>>>> also provide a nicer autolinking mechanism for ELF which is the one >>>>>> target which currently is missing this functionality. However, if Im >>>>>> not mistaken, this would require a MachO linker (and the only current >>>>>> viable MachO linker would be ld64). The MachO binary would then need to >>>>>> be converted into ELF or COFF. This seems like it could take a while to >>>>>> implement though, but would not really break ABI, so pushing that off to >>>>>> later may be wise. >>>>> >>>>> Intriguingly, LLVM does support `*-*-win32-macho` as a target triple >>>>> already, though I don't know what Mach-O to PE linker (if any) that's >>>>> intended to be used with. We implemented relative references using >>>>> current-position-relative offsets for Darwin and Linux both because that >>>>> still allows for a fairly convenient pointer-like C++ API for working >>>>> with relative offsets, and because the established toolchains on those >>>>> platforms already have to support PIC so had most of the relocations we >>>>> needed to make them work already; is there another base we could use for >>>>> relative offsets on Windows that would fit in the set of relocations >>>>> supported by standard COFF linkers? >>>>> >>>>> >>>>> Yes, the `-windows-macho` target is used for UEFI :-). The MachO binary >>>>> is translated later to PE/COFF as required by the UEFI specification. >>>>> >>>>> There are only two relocation types which can be used for relative >>>>> displacements: __ImageBase relative (IMAGE_REL_*_ADDR32NB) and section >>>>> relative (IMAGE_REL_*_SECREL) which are relative to the beginning of the >>>>> section. The latter is why I mentioned that moving them into the same >>>>> section could be a solution as that would allow the relative distance to >>>>> be encoded. Unfortunately, the section relative relocation is relative >>>>> to the section within which the symbol is. >>>> >>>> What's wrong with IMAGE_REL_AMD64_REL32? We'd have to adjust the >>>> relative-pointer logic to store an offset from the end of the relative >>>> pointer instead of the beginning, but it doesn't seem to have a section >>>> requirement. >>>> >>>> Hmm, is it possible to use RIP relative addressing in data? If so, yes, >>>> that could work. >>> >>> There's no inherent reason, but I wouldn't put it past the linker to fall >>> over and die. But it should at least be section-agnostic about the target, >>> since this is likely to be used for all sorts of PC-relative addressing. >>> >>> >>> At least MC doesnt seem to like it. Something like this for example: >>> >>> ``` >>> .data >>> data: >>> .long 0 >>> >>> .section .rodata >>> rodata: >>> .quad data(%rip) >>> ``` >>> >>> Bails out due to the unexpected modifier. Now, theoretically, we could >>> support that modififer, but it does seem pretty odd. >>> >>> Now, as it so happens, both PE and PE+ have limitations on the file size at >>> 4GiB. This means that we are guaranteed that the relative difference is >>> guaranteed to fit within 32-bits. This is where things get really >>> interesting! >>> >>> We cannot generate the relocation because we are emitting the values at >>> pointer width. However, the value that we are emitting is a relative >>> offset, which we just determined to be limited to 32-bits in width. The >>> thing is, the IMAGE_REL_AMD64_REL32 doesn't actually seem to care about the >>> cross-setionness as you pointed out. So, rather than emitting a >>> pointer-width value (`.quad`), we could emit a pad (`.long 0`) and follow >>> that with the relative displacement (`.long <expr>`). This would be >>> representable in the PE/COFF model. >>> >>> If I understand the layout correctly, the type metadata fields are supposed >>> to be pointer sized. I assume that we would like to maintain that across >>> the formats. It may be possible to alter the emission to change the >>> relative pointer emission to emit a pair of longs instead for PE/COFF with >>> a 64-bit pointer value. Basically, we cannot truncate the relocation to a >>> IMAGE_REL_AMD64_REL32 but we could generate the appropriate relocation and >>> pad to the desired width. >>> >>> Are there any pitfalls that I should be aware of trying to adjust the >>> emission to do this? The only downsides that I can see is that the >>> emission would need to be taret dependent (that is check the output object >>> format and the target pointer width). >>> >>> Thanks for the hint John! It seems that was spot on :-). >> >> Honestly, I don't know that there's a great reason for this pointer to be >> relative in the first place. The struct metadata will already have an >> absolute pointer to the value witness table which requires load-time >> relocation, so maybe we should just make this an absolute pointer, too, >> unless we're seriously considering making that a relative pointer before >> allocation. >> >> In practice this will just be a rebase, not a full relocation, so it should >> be relatively cheap. > > At one point we discussed the possibility of also making the value witness > table pointer relative, which would allow concrete value type metadata to be > fully read-only, and since code invoking a value witness is almost certainly > going to have the base type metadata pointer live, probably not an undue > burden on code size. It's a fair question though whether we'll ever get > around to that analysis, and I think the nominal type descriptor reference is > the only place we statically emit a pointer-sized rather than 32-bit relative > offset, which has caused problems for ports to other platforms that only > support 32-bit relative offsets.
That seems at odds with having standard VWTs in the runtime, though, or having a single-element struct share a VWT with its lone member. Jordan
_______________________________________________ swift-dev mailing list swift-dev@swift.org https://lists.swift.org/mailman/listinfo/swift-dev