[PATCH v2 1/3] RISC-V: Add support for vendor-specific relocations
Kito Cheng
kito.cheng@gmail.com
Wed Sep 23 08:24:08 GMT 2026
Hi Ethan:
Thanks for your patch, inline comment below :)
> diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
> index 8263be49d56..adb35aa342d 100644
> --- a/bfd/elfnn-riscv.c
> +++ b/bfd/elfnn-riscv.c
> @@ -279,7 +279,28 @@ riscv_info_to_howto_rela (bfd *abfd,
> arelent *cache_ptr,
> Elf_Internal_Rela *dst)
> {
> - cache_ptr->howto = riscv_elf_rtype_to_howto (abfd, ELFNN_R_TYPE (dst->r_info));
> + static enum elf_riscv_vendor_id vendor_id = RISCV_VENDOR_ID_NONE;
Put this into global var rather than static local, also plz record the addr
of the R_RISCV_VENDOR to make sure the next relocation is the expected
vendor-specific relocation.
And testcase for this commit, e.g.
https://github.com/llvm/llvm-project/tree/main/lld/test/ELF/riscv-vendor-relocations.s
> + unsigned int r_type = ELFNN_R_TYPE (dst->r_info);
> +
> + cache_ptr->howto
> + = riscv_elf_rtype_to_howto (abfd, ELFNN_R_TYPE (dst->r_info), vendor_id);
> + vendor_id = RISCV_VENDOR_ID_NONE;
> +
> + /* Record the vendor id for use by the next relocation. */
> + if (r_type == R_RISCV_VENDOR)
> + {
> + const char *vendor_str = bfd_asymbol_name (*cache_ptr->sym_ptr_ptr);
> + vendor_id = riscv_vendor_str_to_id (vendor_str);
> + if (vendor_id == RISCV_VENDOR_ID_NONE)
> + {
> + _bfd_error_handler (_("error: %pB: vendor-specific (%s) "
> + "relocations are not supported"),
> + abfd, vendor_str);
> + bfd_set_error (bfd_error_bad_value);
> + return false;
> + }
> + }
> +
> return cache_ptr->howto != NULL;
> }
>
...
> reloc_howto_type *
> -riscv_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
> +riscv_elf_rtype_to_howto (bfd *abfd, unsigned int r_type,
> + enum elf_riscv_vendor_id vendor_id)
Plz add riscv_elf_rtype_to_howto_vid and keep riscv_elf_rtype_to_howto
unchanged, so that we don't need to pass RISCV_VENDOR_ID_NONE in many place.
> {
> - if (r_type < ARRAY_SIZE (howto_table))
> - return &howto_table[r_type];
> - else if (r_type < R_RISCV_max + ARRAY_SIZE (howto_table_internal))
> - return &howto_table_internal[r_type - R_RISCV_max];
> + if (vendor_id == RISCV_VENDOR_ID_NONE)
> + {
> + if (r_type >= R_RISCV_internal_first
> + && r_type < (R_RISCV_internal_first
> + + ARRAY_SIZE (howto_table_internal)))
> + return &howto_table_internal[r_type - R_RISCV_internal_first];
> + else if (r_type < ARRAY_SIZE (howto_table))
> + return &howto_table[r_type];
> + }
> else
> {
> - (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
> - abfd, r_type);
> - bfd_set_error (bfd_error_bad_value);
> - return NULL;
> + if (vendor_id > RISCV_VENDOR_ID_NONE
> + && vendor_id < RISCV_VENDOR_ID_COUNT
> + && r_type > R_RISCV_VENDOR
> + && r_type <= R_RISCV_VENDOR + howto_table_vendor_sizes[vendor_id])
Plz also check the address of this reloc is same as R_RISCV_VENDOR.
> + return &howto_table_vendors[vendor_id][r_type - R_RISCV_VENDOR - 1];
> }
> +
> + if (vendor_id == RISCV_VENDOR_ID_NONE)
> + (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"), abfd,
> + r_type);
> + else
> + (*_bfd_error_handler) (
> + _("%pB: unsupported relocation type %#x for vendor id %d"), abfd,
> + r_type, (int)vendor_id);
> +
> + bfd_set_error (bfd_error_bad_value);
> + return NULL;
> +}
> +
> diff --git a/include/elf/riscv.h b/include/elf/riscv.h
> index f6ca3d4acd8..2dbafb0a0c0 100644
> --- a/include/elf/riscv.h
> +++ b/include/elf/riscv.h
> @@ -95,16 +95,63 @@ START_RELOC_NUMBERS (elf_riscv_reloc_type)
> RELOC_NUMBER (R_RISCV_TLSDESC_LOAD_LO12, 63)
> RELOC_NUMBER (R_RISCV_TLSDESC_ADD_LO12, 64)
> RELOC_NUMBER (R_RISCV_TLSDESC_CALL, 65)
> -END_RELOC_NUMBERS (R_RISCV_max)
> + EMPTY_RELOC (R_RISCV_internal_first)
Deinfe R_RISCV_internal_first as 256, that could prevent internal relocation
conflict with R_RISCV_VENDOR and all further reolcation in future.
> +/* Given a vendor string and a relocation number, return a relocation name
> + string. */
> +static const char *
> +elf_riscv_vendor_reloc_type (const char *vendor_str, unsigned long rtype)
Could you convert vendor_str to vendor_id first.
> +{
> + unsigned int i;
> +
> + /* Choose a vendor-defined function according to the vendor string. */
> + for (i = 0; i < ARRAY_SIZE (elf_riscv_vendor_str_table); i++)
> + if (elf_riscv_vendor_str_table[i] && vendor_str
> + && strcmp (elf_riscv_vendor_str_table[i], vendor_str) == 0)
Then we could prevent compare the string again and again?
> + return elf_riscv_vendor_reloc_type_funcs[i](rtype);
> +
> + return NULL;
> +}
> +#endif
More information about the Binutils
mailing list