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