<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Jul 3, 2016 at 10:34 PM, Jay K via llvm-dev <span dir="ltr"><<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">> Message: 3<br>
> Date: Sun, 3 Jul 2016 17:49:50 -0700<br>
> From: Michael Lewis via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a>><br>
> To: Hayden Livingston <<a href="mailto:halivingston@gmail.com">halivingston@gmail.com</a>><br>
> Cc: llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a>><br>
> Subject: Re: [llvm-dev] Status of stack walking in LLVM on Win64?<br>
> Message-ID:<br>
> <<a href="mailto:CAEm7p3svyOi6JU6r_RCCtRfGhTgTHeRw-SR0iD%2B9Edv2pi71Dw@mail.gmail.com">CAEm7p3svyOi6JU6r_RCCtRfGhTgTHeRw-SR0iD+9Edv2pi71Dw@mail.gmail.com</a>><br>
> Content-Type: text/plain; charset="utf-8"<br>
<span class="">><br>
> On Sun, Jul 3, 2016 at 2:17 PM, Hayden Livingston <<a href="mailto:halivingston@gmail.com">halivingston@gmail.com</a>><br>
> wrote:<br>
><br>
>> For JITs it would appear that there is a patch needed for some kind of<br>
>> relocations.<br>
>><br>
>> <a href="https://llvm.org/bugs/show_bug.cgi?id=24233" rel="noreferrer" target="_blank">https://llvm.org/bugs/show_bug.cgi?id=24233</a><br>
>><br>
>> Is the patch really needed? What does it do? I'm not an expert here so<br>
>> asking.<br>
>><br>
><br>
><br>
> I'm not really interested in the JIT case as I said originally, so I can't<br>
> answer that question.<br>
><br>
><br>
><br>
>><br>
>> On Sun, Jul 3, 2016 at 2:48 AM, David Majnemer via llvm-dev<br>
>> <<a href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a>> wrote:<br>
>>> I can confirm that LLVM emits correct data when used in an AoT<br>
>> configuration<br>
>>> for x64, exception handling would be totally broken without it.<br>
>>><br>
>><br>
><br>
><br>
> Two points of clarification:<br>
><br>
> - Are you talking about Win64 or just x64 in general (i.e. *nix/MacOS)?<br>
</span><span class="">> Again given the presence of bugs going back to 2015 (including one linked<br>
</span>> in this thread) and other scant data from the list, I really can't tell<br>
<span class="">> what the expected state of this functionality is on Win64.<br>
><br>
> - Are you referring to data generated by LLVM that is embedded in COFF<br>
</span>> object files and then placed in the binary image by the linker? This data<br>
<span class="">> is at a minimum relocated by link.exe on Windows as near as I can tell. I<br>
> do not want a dependency on link.exe. I can handle doing my own relocations<br>
> prior to emitting the final image, but I want to know if there's a turnkey<br>
> implementation of this already or if I have to roll my own here.<br>
><br>
</span>> Thanks,<br>
><br>
><br>
><br>
> - Mike<br>
<br>
<br>
<br>
 Windows/x64 ABI is pretty well documented. <br>
<br>
<br>
 - The parameter passing is probably not the same as any other system.<br>
   (Unless people are using LLVM for UEFI development?) <br>
   Ignoring floating point, the first four integer parameters<br>
   are in rcx, rdx, r8, r9. The rest are on the stack. <br>
   <br>
<br>
 - The exception handling might *resemble* other systems, but<br>
   surely has unique details.<br>
   <br>
 - Ghere is absolutely an unremovable dependency on a linker;<br>
   it doesn't have to be the Microsoft linker, I believe GNU ld<br>
   already implements this.<br>
   <br>
   The documentation should be used.<br>
   <br>
   I can summarize and such, but it is documented.<br>
   <br>
   Roughly, ignoring parameter passing and focusing only on exception handling,<br>
   it goes like this:<br>
   <br>
  <br>
   - At any point in any program, "the stack" must be "unwindable".<br>
       I've never seen this clearly described.<br>
       It boils down to really "non volatile registers must be restorable"<br>
       by "a runtime" via a documented/standardized metadata, such as to<br>
       appear as if control was returned to any function on the call stack,<br>
       w/o running any generated code in any of the functions between<br>
       the current stack location and the resumed-to location.<br>
       <br>
       <br>
       The stack pointer is often called out specially, but in fact<br>
       it is just another non volatile register and not really a special case.<br>
       <br>
<br>
     So then some details:<br>
       a "leaf function" is a function that does not change any non volatile registers,<br>
       including the stack pointer. Leaf functions can do pretty much anything,<br>
       but they must not change any non volatile registers -- which is a severe<br>
       restriction. Have locals essentially makes you non-leaf -- even if you<br>
       don't call anything. A leaf function is *not* a function that makes no calls,<br>
       but calls do make a function a non-leaf, as it changes the stack pointer.<br>
<br>
<br>
       The slight exception here is that all functions, including leaves, do have<br>
       4*8 bytes of scratch space in the stack available to them -- so local<br>
       variables can be had, in that space and in volatile registers.<br>
<br>
      <br>
      The stack is walked from a leaf function merely by reading from rsp. <br>
      A leaf function can make a syscall, so they aren't necessarily at the bottom of the stack. <br>
<br>
       <br>
      non-leaf functions are the interesting ones.<br>
      They can change rsp, including such as via a call, and can change non-volatile<br>
      registers, but all such changes (or rather, the saving of said registers) must<br>
      be described by metadata, and the metadata<br>
      must be findable -- via looking up a code address on the stack.<br>
<br>
      <br>
      Roughly speaking, all dlls have "pdata" -- procedure data.<br>
      There are 3 UINT32s per non-leaf function.<br>
      These are offsets into the image. Images are limited to 4GB in size.<br>
      They are to the start of the function, end of the function, and to additional metadata.<br>
      The additional metadata is called "xdata" or exception data.<br>
      The offset to the metadata be be absent or 0, but that should be rare/nonexistant<br>
      in practise -- it is for revealing leaf functions to static analysis for example.<br>
      <br>
<br>
      The "xdata" is then what describes how to restore non volatile registers,<br>
      such as the order to pop them, or what offset they were saved at to the<br>
      frame pointer or stack pointer (and which register if any is the frame pointer -- it doesn't have to be rbp,<br>
      and most functions don't have one.)<br>
      <br>
<br>
      There are restrictions on code generation -- rsp changes and non volatile saves<br>
      must be describable with this metadata. There is a notion of the end of the prologue,<br>
      at this point all non volatiles that will be changed have been saved, and rsp changes<br>
      are done. This is misleading though in that almost arbitrary code can be interleaved<br>
      within the prologue, i.e. changes to volatile registers.<br>
     <br>
 <br>
      As well, as a background, generally Windows/x64 functions don't change rsp,<br>
      except in their prologue and the call instruction.<br>
      They are not "pushy/poppp". However if a function uses _alloca, that<br>
      is a contradiction. Such functions must have a frame pointer, such as rbp,<br>
      though it doesn't have to be rbp and often is not.<br>
      <br>
<br>
      There is also a notion of chaining the data. This is useful when<br>
      a function has "early out" paths that only change some non volatiles.<br>
      <br>
<br>
      Also there is allowance for discontiguous functions.<br>
      <br>
<br>
      Also there is no metadata for epilogues. If an exception occurs in an epilogue,<br>
      the runtime actually look at the code being run, detects it is an epilogue<br>
      and simulates it. As such, epilogue code generation is constrained.<br>
      (and breakpoints within epilogues mess things up!)<br></blockquote><div><br></div><div>These is metadata for epilogues (UWOP_EPILOG) but it is only available on Windows 8.1 and newer.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">
      <br>
<br>
      To repeat -- the unwindability is from any single instruction, be in the<br>
      middle of a prologue, middle of an epilogue, or in the body of a function<br>
      outside of prologue/epilogue.<br>
      <br>
<br>
      This unwindabilty serves both exception dispatch and debugger stack walking,<br>
      and other things, like sampling profiler stack walking, or "leak tracking<br>
      stack walking" -- stack walking is always possible, modulo bugs.<br>
      The most common bugs are probably in hand written assemble, since<br>
      assembly programmers have to do basically the work themselves.<br>
<br>
      <br>
      There is provision for providing the pdata at runtime for JITed code.<br>
<br>
      <br>
      The linker has to combine all the pdata and place a pointer (offset) to it<br>
      in a documented place in the PE, similar to how imports and exports and base<br>
      relocations are recorded.<br>
      <br>
      <br>
      Anyway, see the documentation.<br>
      <br>
      <br>
      - Jay<br>
<div class=""><div class="h5">_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</div></div></blockquote></div><br></div></div>