[2/2] riscv: Let compiler handle unaligned access when fixing R_RISCV_RELATIVE
Checks
Context |
Check |
Description |
dj/TryBot-apply_patch |
success
|
Patch applied to master at the time it was sent
|
dj/TryBot-32bit |
success
|
Build for i686
|
Commit Message
Explicitly say that might be unaligned, so that the compiler will generate
appropriate code sequence for this relocation fix-up.
Although RISC-V Linux will enable the unaligned memory access handler by
default, that is quite expensive in general, letting the compiler solve this
will be much cheaper - just break down that into several store byte
instructions.
ARM and MIPS has similar issue:
ARM: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51456
MIPS: https://gcc.gnu.org/legacy-ml/gcc-help/2005-07/msg00325.html
---
sysdeps/riscv/dl-machine.h | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
Comments
> On 23 Jun 2022, at 12:47, Kito Cheng <kito.cheng@sifive.com> wrote:
>
> Explicitly say that might be unaligned, so that the compiler will generate
> appropriate code sequence for this relocation fix-up.
>
> Although RISC-V Linux will enable the unaligned memory access handler by
> default, that is quite expensive in general, letting the compiler solve this
> will be much cheaper - just break down that into several store byte
> instructions.
>
> ARM and MIPS has similar issue:
>
> ARM: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51456
> MIPS: https://gcc.gnu.org/legacy-ml/gcc-help/2005-07/msg00325.html
> ---
> sysdeps/riscv/dl-machine.h | 9 ++++++++-
> 1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/sysdeps/riscv/dl-machine.h b/sysdeps/riscv/dl-machine.h
> index 4bb858adaa..c83513e5b8 100644
> --- a/sysdeps/riscv/dl-machine.h
> +++ b/sysdeps/riscv/dl-machine.h
> @@ -157,7 +157,14 @@ __attribute__ ((always_inline))
> elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
> void *const reloc_addr)
> {
> - *(ElfW(Addr) *) reloc_addr = l_addr + reloc->r_addend;
> + /* R_RISCV_RELATIVE might located in debug info section which might not
> + aligned to XLEN bytes. */
> + struct unaligned
> + {
> + ElfW(Addr) x;
> + } __attribute__ ((packed, may_alias));
> + /* Support relocations on unaligned offsets. */
> + ((struct unaligned *) reloc_addr)->x = l_addr + reloc->r_addend;
> }
Although the same strategy on arm dl-machine.h, I think the most usual way
is to use a a memcpy since it avoid the type cast (which strictly is a UB):
/* R_RISCV_RELATIVE might located in debug info section which might not
aligned to XLEN bytes. Also support relocations on unaligned offsets. */
ElfW(Addr) value = l_addr + relic->r_addend;
memcpy (reloc_addr, &value, sizeof value);
>
> /* Perform a relocation described by R_INFO at the location pointed to
> --
> 2.34.0
>
On Thu, 23 Jun 2022 09:47:20 PDT (-0700), adhemerval.zanella@linaro.org wrote:
>
>
>> On 23 Jun 2022, at 12:47, Kito Cheng <kito.cheng@sifive.com> wrote:
>>
>> Explicitly say that might be unaligned, so that the compiler will generate
>> appropriate code sequence for this relocation fix-up.
>>
>> Although RISC-V Linux will enable the unaligned memory access handler by
>> default, that is quite expensive in general, letting the compiler solve this
>> will be much cheaper - just break down that into several store byte
>> instructions.
>>
>> ARM and MIPS has similar issue:
>>
>> ARM: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51456
>> MIPS: https://gcc.gnu.org/legacy-ml/gcc-help/2005-07/msg00325.html
>> ---
>> sysdeps/riscv/dl-machine.h | 9 ++++++++-
>> 1 file changed, 8 insertions(+), 1 deletion(-)
>>
>> diff --git a/sysdeps/riscv/dl-machine.h b/sysdeps/riscv/dl-machine.h
>> index 4bb858adaa..c83513e5b8 100644
>> --- a/sysdeps/riscv/dl-machine.h
>> +++ b/sysdeps/riscv/dl-machine.h
>> @@ -157,7 +157,14 @@ __attribute__ ((always_inline))
>> elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
>> void *const reloc_addr)
>> {
>> - *(ElfW(Addr) *) reloc_addr = l_addr + reloc->r_addend;
>> + /* R_RISCV_RELATIVE might located in debug info section which might not
>> + aligned to XLEN bytes. */
>> + struct unaligned
>> + {
>> + ElfW(Addr) x;
>> + } __attribute__ ((packed, may_alias));
>> + /* Support relocations on unaligned offsets. */
>> + ((struct unaligned *) reloc_addr)->x = l_addr + reloc->r_addend;
>> }
>
> Although the same strategy on arm dl-machine.h, I think the most usual way
> is to use a a memcpy since it avoid the type cast (which strictly is a UB):
>
> /* R_RISCV_RELATIVE might located in debug info section which might not
> aligned to XLEN bytes. Also support relocations on unaligned offsets. */
> ElfW(Addr) value = l_addr + relic->r_addend;
> memcpy (reloc_addr, &value, sizeof value);
Presumably we should fix the other ports as well? I just see
$ git grep '((struct unaligned \*) reloc_addr)' | cat
sysdeps/arm/dl-machine.h: ((struct unaligned *) reloc_addr)->x += value;
I'm not super partial to either behavior, but your suggestion is shorter
and avoiding UB is always a good bet so that sounds better to me as
well. With that
Acked-by: Palmer Dabbelt <palmer@rivosinc.com>
I just sent along the arm version of this, figured that's easier than
waiting.
Thanks!
>
>
>>
>> /* Perform a relocation described by R_INFO at the location pointed to
>> --
>> 2.34.0
>>
@@ -157,7 +157,14 @@ __attribute__ ((always_inline))
elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
void *const reloc_addr)
{
- *(ElfW(Addr) *) reloc_addr = l_addr + reloc->r_addend;
+ /* R_RISCV_RELATIVE might located in debug info section which might not
+ aligned to XLEN bytes. */
+ struct unaligned
+ {
+ ElfW(Addr) x;
+ } __attribute__ ((packed, may_alias));
+ /* Support relocations on unaligned offsets. */
+ ((struct unaligned *) reloc_addr)->x = l_addr + reloc->r_addend;
}
/* Perform a relocation described by R_INFO at the location pointed to