[Bug dynamic-link/26643] New: register x8 and quad sized NEON registers are not properly saved when using ld_audit on aarch64
woodard at redhat dot com
sourceware-bugzilla@sourceware.org
Tue Sep 22 06:09:30 GMT 2020
https://sourceware.org/bugzilla/show_bug.cgi?id=26643
Bug ID: 26643
Summary: register x8 and quad sized NEON registers are not
properly saved when using ld_audit on aarch64
Product: glibc
Version: unspecified
Status: NEW
Severity: normal
Priority: P2
Component: dynamic-link
Assignee: unassigned at sourceware dot org
Reporter: woodard at redhat dot com
Target Milestone: ---
Created attachment 12853
--> https://sourceware.org/bugzilla/attachment.cgi?id=12853&action=edit
reproducer that demonstrates that x8 is not being saved.
Description of problem:
According to the Arm Cortex-A Series Programmers Guide for ARMv8-A It is part
of the ABI for the architecture.
See Section 9.1.1 Parameters in general-purpose registers on page 9-3 where it
states:
Registers with a special purpose (X8, X16-X18, X29, X30)
• X8 is the indirect result register. This is used to pass the address
location of an indirect result, for example, where a function returns a large
structure.gister should be preserved.
You can see that this register is saved in the normal code path which is what
is normally run. See sysdeps/aarch64/dl-trampoline.S:48 :
/* Save arguments. */
stp x8, x9, [sp, #-(80+8*16)]!
cfi_adjust_cfa_offset (80+8*16)
cfi_rel_offset (x8, 0)
cfi_rel_offset (x9, 8)
However, when you use LD_AUDIT the rtld shifts into what it calls profiling
mode. In that profiling mode x8 is not properly saved. See there is no x8 being
saved around line 185 in _dl_runtime_profile:
stp x0, x1, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*0]
cfi_rel_offset (x0, OFFSET_RG + DL_OFFSET_RG_X0 + 16*0 + 0)
cfi_rel_offset (x1, OFFSET_RG + DL_OFFSET_RG_X0 + 16*0 + 8)
stp x2, x3, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*1]
cfi_rel_offset (x2, OFFSET_RG + DL_OFFSET_RG_X0 + 16*1 + 0)
cfi_rel_offset (x3, OFFSET_RG + DL_OFFSET_RG_X0 + 16*1 + 8)
stp x4, x5, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*2]
cfi_rel_offset (x4, OFFSET_RG + DL_OFFSET_RG_X0 + 16*2 + 0)
cfi_rel_offset (x5, OFFSET_RG + DL_OFFSET_RG_X0 + 16*2 + 8)
stp x6, x7, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*3]
cfi_rel_offset (x6, OFFSET_RG + DL_OFFSET_RG_X0 + 16*3 + 0)
cfi_rel_offset (x7, OFFSET_RG + DL_OFFSET_RG_X0 + 16*3 + 8)
Yeah you got the Parameter and result registers but where is the Indirect
result location register? After that block of code, you immediately start
saving the d registers.
When you start looking at the code in _dl_runtime_profile it looks like it has
been copied from a previous version of the processor where there were no Q
registers in the V register group. In other words the V registers were only
uint64_t's not uint128_t's.
x29 ends up being loaded with a pointer to a struct of type la_aarch64_regs
/* Registers for entry into PLT on AArch64. */
typedef struct La_aarch64_regs
{
uint64_t lr_xreg[8];
uint64_t lr_dreg[8];
uint64_t lr_sp;
uint64_t lr_lr;
} La_aarch64_regs;
This doesn't include space for x8 the indirect result register. Nor does it
have space for the full sized v registers. Furthermore when you look at line
136 where it describes the stack frame layout
Stack frame layout:
[sp, #...] lr
[sp, #...] &PLTGOT[n]
[sp, #96] La_aarch64_regs
[sp, #48] La_aarch64_retval
[sp, #40] frame size return from pltenter
[sp, #32] dl_profile_call saved x1
[sp, #24] dl_profile_call saved x0
[sp, #16] t1
[sp, #0] x29, lr <- x29
what _dl_runtime_resolve actually pushes on the stack the La_aarch64_regs part
doesn't match the what _dl_runtime_profile is expecting. The size of the
structure is quite different.
To be able to support those the structure would have to be:
/* Registers for entry into PLT on AArch64. */
typedef struct La_aarch64_regs
{
uint64_t lr_xreg[10];
__uint128_t lr_vreg[8]; /* or uint64_t lr_vreg[16]; */
uint64_t lr_sp;
uint64_t lr_lr;
} La_aarch64_regs;
Version-Release number of selected component (if applicable):
All - this bug has been there since the beginning of the aarch64 port
How reproducible:
Always
Steps to Reproduce:
There are two reproducers in the uploaded tar.gz which I got for the original
reporter. One is very simple and should work but variations in the compiler can
change how the structure is returned and cause that reproducer not to work. The
other reproducer is a much bigger bit of code which always forces the use of x8
but it is much more code.
Additional info:
This bug report was provided by developers at Rice University Jonathon
Anderson, John Mellor-Crummey, Xiaozhu Meng, Mark Krentel working on behalf of
LLNL
--
You are receiving this mail because:
You are on the CC list for the bug.
More information about the Glibc-bugs
mailing list