On Thu, Sep 28, 2017 at 10:59 AM, John McCall <rjmcc...@apple.com> wrote:
> > On Sep 28, 2017, at 1:01 PM, Saleem Abdulrasool <compn...@compnerd.org> > wrote: > > On Mon, Sep 25, 2017 at 10:18 PM, John McCall <rjmcc...@apple.com> wrote: > >> On Sep 26, 2017, at 12:35 AM, Saleem Abdulrasool <compn...@compnerd.org> >> wrote: >> On Mon, Sep 25, 2017 at 11:47 AM, John McCall <rjmcc...@apple.com> wrote: >> >>> > On Sep 25, 2017, at 12:24 PM, Joe Groff <jgr...@apple.com> 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. >>> >>> Yes, that's true. It would make the base of the load (metadata + >>> loaded-offset + immediate-offset), which I think would require an extra >>> instruction even on x86, but maybe that's not so bad. >>> >>> On the other hand, yes, it would not be possible to refer to prebuilt >>> vwtables from the runtime, and it would need to be a 64-bit relative offset >>> in order to handle dynamic instantiation correctly, which as you say is >>> problematic on some platforms. >> >> >> Hmm, Im not sure I understand the desired approach. Would we want to >> switch to a rebased pointer? >> >> >> That's what we're discussing. Switching to an absolute pointer (i.e. a >> normal pointer, which would need to be rebased) has proven to be generally >> more portable because many linkers do not support 64-bit relative >> pointers. Also, since this is adjacent to another absolute pointer, the >> benefits of a relative pointer seem pretty weak: it would eliminate a very >> small amount of work at load time and (probably) some binary-size overhead, >> but that's relatively minor compared to, say, whether the loader has to >> dirty any memory. Now, maybe we can avoid it being adjacent to another >> absolute pointer by making the vwtable relative, and that would have some >> significant upsides, but it would also have some significant drawbacks, and >> it's not clear that anybody actually wants to put any time into that >> investigation before we reach ABI stability. >> >> I'm personally leaning towards saying that vwtables should just stay >> absolute, and thus that nominal-type-descriptor pointers should just become >> absolute to make things easier. I'm not worried about the binary-size >> impact; it's just a rebase, and Mach-O encodes rebases pretty efficiently. >> It's a little unfortunate for ELF, which has wastefully large loader >> encodings, but we could address that specifically if we felt the urge (or >> maybe just do ELF infrastructure work on more efficient encodings). >> >> Would this be for all of the metadata or just the struct type? >> >> >> Only structs, enums, and classes have nominal type metadata, and classes >> use an absolute pointer. >> > > I thought that I would take a stab at this since this is the penultimate > issue preventing the Windows x86_64 stdlib build. Maybe I'm misreading > something, but the compiler seems to indicate that the class metadata has a > relative pointer? > > template <class Impl> > class ClassMetadataBuilderBase : public ClassMetadataVisitor<Impl> { > ... > void addNominalTypeDescriptor() { > auto descriptor = ClassNominalTypeDescriptorBuilder(IGM, > Target).emit(); > B.addFarRelativeAddress(descriptor); > } > ... > } > > The addFarRelativeAddress would handle this the same way as the other > cases AFAICT. > > > I'm not sure what you're getting at here. The compiler is using a > relative pointer because that's the current ABI. Implementing a structural > change in metadata emitted by the compiler and interpreted by the runtime > will obviously require changing both the compiler and the runtime. > I misunderstood your previous statement as saying that classes already used absolute pointers for the nominal type metadata. Just wanted to make sure that I wasn't looking at the wrong area of the code. > John. > > > Are there no other instances of the same pattern? >> >> >> At the very least, none of the other instances have the 64-bit problem. >> They're also just generally more likely to be internal to a section. >> >> John. >> >> >> >> >>> >>> John. >>> >>> > 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. >>> >>> >>> > >>> > -Joe >>> >>> >> >> >> -- >> Saleem Abdulrasool >> compnerd (at) compnerd (dot) org >> >> >> > > > -- > Saleem Abdulrasool > compnerd (at) compnerd (dot) org > > > -- Saleem Abdulrasool compnerd (at) compnerd (dot) org
_______________________________________________ swift-dev mailing list swift-dev@swift.org https://lists.swift.org/mailman/listinfo/swift-dev