On 26/03/2025 9:00 am, Jan Beulich wrote:
> On 25.03.2025 19:00, Andrew Cooper wrote:
>> I was mistaken about when ASM_CALL_CONSTRAINT is applicable.  It is not
>> applicable for plain pushes/pops, so remove it from the flags logic.
>>
>> Clarify the description of ASM_CALL_CONSTRAINT to be explicit about unwinding
>> using framepointers.
>>
>> Fixes: 0754534b8a38 ("x86/elf: Improve code generation in 
>> elf_core_save_regs()")
>> Signed-off-by: Andrew Cooper <andrew.coop...@citrix.com>
>> ---
>> CC: Jan Beulich <jbeul...@suse.com>
>> CC: Roger Pau Monné <roger....@citrix.com>
>> ---
>>  xen/arch/x86/include/asm/asm_defns.h  | 5 +++--
>>  xen/arch/x86/include/asm/x86_64/elf.h | 2 +-
>>  2 files changed, 4 insertions(+), 3 deletions(-)
>>
>> diff --git a/xen/arch/x86/include/asm/asm_defns.h 
>> b/xen/arch/x86/include/asm/asm_defns.h
>> index 92b4116a1564..689d1dcbf754 100644
>> --- a/xen/arch/x86/include/asm/asm_defns.h
>> +++ b/xen/arch/x86/include/asm/asm_defns.h
>> @@ -28,8 +28,9 @@ asm ( "\t.equ CONFIG_INDIRECT_THUNK, "
>>  
>>  /*
>>   * This output constraint should be used for any inline asm which has a 
>> "call"
>> - * instruction.  Otherwise the asm may be inserted before the frame pointer
>> - * gets set up by the containing function.
>> + * instruction, which forces the stack frame to be set up prior to the asm
>> + * block.  This matters when unwinding using framepointers, where the asm's
>> + * function can get skipped over.
> Does "forces the stack frame to be set up" really mean the stack frame, or the
> frame pointer (if one is in use)?

What do you consider to be the difference, given how frame pointers work
in our ABI?

It is the frame pointer which needs setting up, which at a minimum
involves spilling registers to the stack and getting %rsp into it's
eventual position.

>  In the latter case I can see how the asm()
> being moved ahead of that point could cause problems. In the former case I
> apparently still don't understand (yet) what the issue is that
> ASM_CALL_CONSTRAINT ultimately is to help with.

The specific bug is from a sequence of functions a, b and c, where b
uses an asm() to call c.

a() pushes old %rbp sets up new %rbp, b() fails to do so early enough,
and c() pushes a()'s frame pointer, not b()'s.  Then unwinding via frame
pointer skips b() in the backtrace.

I don't know what the precise effects of the constraint are.  The
compiler maintainers can't agree either, and say it's fragile and can't
be relied upon, but it seems to be the only way to have the desired
effect on emitted code.

~Andrew

Reply via email to