[PATCH 3 07/16] MIPS: Add user-defined sdata sections
Maciej W. Rozycki
macro@orcam.me.uk
Mon Sep 21 13:43:54 GMT 2026
On Thu, 5 Feb 2026, Jovan Dmitrovic via Binutils wrote:
> Adds functionality to allow user to use different small data areas for
> each data item. When turned on, gp relative relocation against a symbol
> in the .sdata_<num> or .sbss_<num> use the gp value based on _gp_<num>
> symbol.
This is a psABI extension. Is there a document available that describes
it? I've gone through this change based on lone code at this time, but
I'd like to verify it against the spec too.
> diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
> index 701ac76cd33..e44cea87740 100644
> --- a/bfd/elfxx-mips.c
> +++ b/bfd/elfxx-mips.c
> @@ -482,6 +482,12 @@ struct mips_elf_link_hash_table
> /* True if we are targetting R6 compact branches. */
> bool compact_branches;
>
> + /* When True and processing a gp relative relocation against a symbol
s/True/TRUE/
> + in a .sdata_<num>/.sbss_<num> section use the gp value
> + based on the address of the _gp_<num> symbol where <num> is
> + the number of the .sbss/.sdata section the symbol is in. */
Please rejustify the comment as it's weirdly formatted.
> + bool user_def_sdata_sections;
> +
OK, a flag tracking whether the feature has been enabled.
> @@ -602,6 +608,9 @@ struct mips_elf_obj_tdata
> text/data symbols defined in dynamic objects. */
> asection *elf_data_section;
> asection *elf_text_section;
> +
> + struct mips_hi16 *mips_hi16_list;
Where is this new member of the struct used?
> + bfd_signed_vma sdata_section[1000];
Missing member description. Use plural. Presumably the fixed size of
the array comes from the psABI spec?
> @@ -5657,6 +5666,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
> struct mips_elf_link_hash_table *htab;
> bfd *dynobj;
> bool resolved_to_zero;
> + int gp_sec_num = 0;
This is not used outside the block below, so move it there.
> @@ -6053,6 +6063,27 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
> if (gnu_local_gp_p)
> symbol = gp;
>
> + if (mips_elf_hash_table (info)->user_def_sdata_sections && sec != NULL)
> + {
> + if (strncmp (".sdata_", sec->name, 7) == 0)
> + gp_sec_num = atoi (&sec->name[7]);
> + else if (strncmp (".sbss_", sec->name, 6) == 0)
> + gp_sec_num = atoi (&sec->name[6]);
So how about sections called `.sdata_', `.sdata_foo', or`.sdata_001foo'?
Or say `.sdata_0' vs `.sdata_000'? It seems to me this would best be
factored out to a helper returning the section number or -1 if not a
matching section name. Then all the individual checks can be done there.
> +
> + if (gp_sec_num)
> + {
> + if (gp_sec_num < 0 || gp_sec_num > 999
> + || mips_elf_tdata(abfd)->sdata_section[gp_sec_num] == -1)
> + {
> + (*_bfd_error_handler)
> + (_("%pB: Error: Unable to apply gp relocation to section `%s'"),
> + abfd, sec->name);
Use `%pA'; s/Error: Unable/error: unable/.
> + bfd_set_error (bfd_error_bad_value);
> + }
> + }
> +
> + gp = mips_elf_tdata(abfd)->sdata_section[gp_sec_num];
> + }
> /* Global R_MIPS_GOT_PAGE/R_MICROMIPS_GOT_PAGE relocations are equivalent
New line above the comment please.
> @@ -7649,7 +7680,8 @@ _bfd_mips_elf_section_processing (bfd *abfd, Elf_Internal_Shdr *hdr)
> on it in an input file will be followed. */
> if (strcmp (name, ".sdata") == 0
> || strcmp (name, ".lit8") == 0
> - || strcmp (name, ".lit4") == 0)
> + || strcmp (name, ".lit4") == 0
> + || strncmp (name, ".sdata_", 7) == 0)
Again can this section name be properly validated?
> @@ -7941,7 +7973,9 @@ _bfd_mips_elf_fake_sections (bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec)
> else if (strcmp (name, ".got") == 0
> || strcmp (name, ".srdata") == 0
> || strcmp (name, ".sdata") == 0
> + || strncmp (name, ".sdata_", 7) == 0
> || strcmp (name, ".sbss") == 0
> + || strncmp (name, ".sbss_", 6) == 0
Likewise?
> @@ -14948,6 +14982,12 @@ _bfd_mips_elf_compact_branches (struct bfd_link_info *info, bool on)
> mips_elf_hash_table (info)->compact_branches = on;
> }
>
> +void
> +_bfd_mips_elf_user_def_sdata_sections (struct bfd_link_info *info, bool on)
> +{
> + mips_elf_hash_table (info)->user_def_sdata_sections = on;
> +}
> +
Document a new function.
> @@ -15298,6 +15338,23 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
> if (hti.error)
> return false;
>
> + unsigned int gp_num;
> + for (gp_num = 0 ; gp_num < 1000 ; gp_num++)
Move the declaration into the statement. Fix formatting.
> + {
> + struct bfd_link_hash_entry *h;
> + char gp_name[8];
> + bfd_signed_vma gp_vma = -1;
Reorder for reverse Xmas tree.
> +
> + sprintf (gp_name, "_gp_%d", gp_num);
> + h = bfd_link_hash_lookup (info->hash, gp_name, false, false, true);
> + if (h != NULL && h->type == bfd_link_hash_defined)
> + gp_vma = (h->u.def.value
> + + h->u.def.section->output_section->vma
> + + h->u.def.section->output_offset);
> +
> + mips_elf_tdata(abfd)->sdata_section[gp_num] = gp_vma;
> + }
> +
OK, gathering `_gp_*' definitions.
> diff --git a/bfd/elfxx-mips.h b/bfd/elfxx-mips.h
> index fedc21ed3d9..528929e7c31 100644
> --- a/bfd/elfxx-mips.h
> +++ b/bfd/elfxx-mips.h
> @@ -182,6 +182,8 @@ extern void _bfd_mips_elf_linker_flags
> (struct bfd_link_info *, bool, bool, bool);
> extern void _bfd_mips_elf_compact_branches
> (struct bfd_link_info *, bool);
> +extern void _bfd_mips_elf_user_def_sdata_sections
> + (struct bfd_link_info *, bool);
OK, used externally.
> diff --git a/ld/emultempl/mipself.em b/ld/emultempl/mipself.em
> index f84ad1c6de9..7414a948ad4 100644
> --- a/ld/emultempl/mipself.em
> +++ b/ld/emultempl/mipself.em
> @@ -45,6 +45,7 @@ static bfd *stub_bfd;
> static bool insn32;
> static bool ignore_branch_isa;
> static bool compact_branches;
> +static bool user_def_sdata_sections;
OK, hold the setting of `--user-defined-sdata-sections'.
> @@ -204,6 +205,7 @@ mips_create_output_section_statements (void)
> if (is_mips_elf (link_info.output_bfd))
> {
> _bfd_mips_elf_compact_branches (&link_info, compact_branches);
> + _bfd_mips_elf_user_def_sdata_sections (&link_info, user_def_sdata_sections);
OK, propagate the setting to BFD.
> @@ -239,6 +241,8 @@ PARSE_AND_LIST_LONGOPTS='
> { "no-ignore-branch-isa", no_argument, NULL, OPTION_NO_IGNORE_BRANCH_ISA },
> { "compact-branches", no_argument, NULL, OPTION_COMPACT_BRANCHES },
> { "no-compact-branches", no_argument, NULL, OPTION_NO_COMPACT_BRANCHES },
> + { "user-defined-sdata-sections", no_argument, NULL, OPTION_USER_DEF_SDATA_SECTIONS },
> + { "no-user-defined-sdata-sections", no_argument, NULL, OPTION_NO_USER_DEF_SDATA_SECTIONS },
> '
OK, the user options.
> @@ -262,6 +266,17 @@ PARSE_AND_LIST_OPTIONS='
> fprintf (file, _("\
> --no-compact-branches Generate delay slot branches/jumps for MIPS R6\n"
> ));
> + fprintf (file, _("\
> + --user-defined-sdata-sections\n\
> + When processing a gp relative relocation against a symbol\n\
> + in a .sdata_<num>/.sbss_<num> section use the gp value\n\
> + based on the address of the _gp_<num> symbol where <num> is\n\
> + the number of the .sbss/.sdata section the symbol is in\n"));
> + fprintf (file, _("\
> + --no-user-defined-sdata-sections\n\
> + When processing a gp relative relocation against a symbol\n\
> + in a .sdata_<num>/.sbss_<num> section use the gp value\n\
> + based on the address of the _gp symbol\n"));
> '
I find this way too verbose. It seems to me like almost an entry for the
manual rather than a terse reminder for the forgetful, which the `--help'
option summary is supposed to be. Have a look at the other descriptions
and make these two similarly brief as well.
Conversely a manual update is missing altogether and these descriptions
will be a good starting point.
> @@ -288,6 +303,14 @@ PARSE_AND_LIST_ARGS_CASES='
> case OPTION_NO_COMPACT_BRANCHES:
> compact_branches = false;
> break;
> +
> + case OPTION_USER_DEF_SDATA_SECTIONS:
> + user_def_sdata_sections = true;
> + break;
> +
> + case OPTION_NO_USER_DEF_SDATA_SECTIONS:
> + user_def_sdata_sections = false;
> + break;
> '
OK, record the options supplied.
> diff --git a/ld/ldlex.h b/ld/ldlex.h
> index 85e06b6fcc4..52d5352de56 100644
> --- a/ld/ldlex.h
> +++ b/ld/ldlex.h
> @@ -306,6 +306,8 @@ enum option_values
> OPTION_NO_IGNORE_BRANCH_ISA,
> OPTION_COMPACT_BRANCHES,
> OPTION_NO_COMPACT_BRANCHES,
> + OPTION_USER_DEF_SDATA_SECTIONS,
> + OPTION_NO_USER_DEF_SDATA_SECTIONS,
OK, new enumeration constants corresponding to the new options.
Thank you for your submission. Please update and repost.
Maciej
More information about the Binutils
mailing list