[PATCH 3 07/16] MIPS: Add user-defined sdata sections

Jovan Dmitrovic jovan.dmitrovic@htecgroup.com
Thu Feb 5 16:23:56 GMT 2026


From: Matthew Fortune <matthew.fortune@imgtec.com>

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.
---
 bfd/elfxx-mips.c        | 59 ++++++++++++++++++++++++++++++++++++++++-
 bfd/elfxx-mips.h        |  2 ++
 ld/emultempl/mipself.em | 23 ++++++++++++++++
 ld/ldlex.h              |  2 ++
 4 files changed, 85 insertions(+), 1 deletion(-)

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
+     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.  */
+  bool user_def_sdata_sections;
+
   /* True if we already reported the small-data section overflow.  */
   bool small_data_overflow_reported;
 
@@ -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;
+  bfd_signed_vma sdata_section[1000];
 };
 
 /* Get MIPS ELF private object data from BFD's tdata.  */
@@ -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;
 
   dynobj = elf_hash_table (info)->dynobj;
   htab = mips_elf_hash_table (info);
@@ -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]);
+
+      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);
+	      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
      to R_MIPS_GOT_DISP/R_MICROMIPS_GOT_DISP.  The addend is applied by the
      corresponding R_MIPS_GOT_OFST/R_MICROMIPS_GOT_OFST.  */
@@ -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)
 	hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
       else if (strcmp (name, ".srdata") == 0)
 	hdr->sh_flags |= SHF_ALLOC | SHF_MIPS_GPREL;
@@ -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
 	   || strcmp (name, ".lit4") == 0
 	   || strcmp (name, ".lit8") == 0)
     hdr->sh_flags |= SHF_MIPS_GPREL;
@@ -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;
+}
+
 

 /* Structure for saying that BFD machine EXTENSION extends BASE.  */
 
@@ -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++)
+    {
+      struct bfd_link_hash_entry *h;
+      char gp_name[8];
+      bfd_signed_vma gp_vma = -1;
+
+      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;
+    }
+
   /* Get a value for the GP register.  */
   if (elf_gp (abfd) == 0)
     {
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);
 extern bool _bfd_mips_elf_init_stubs
   (struct bfd_link_info *,
    asection *(*) (const char *, asection *, asection *));
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;
 
 struct hook_stub_info
 {
@@ -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);
       _bfd_mips_elf_init_stubs (&link_info, mips_add_stub_section);
     }
 }
@@ -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 },
 '
 
 PARSE_AND_LIST_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"));
 '
 
 PARSE_AND_LIST_ARGS_CASES='
@@ -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;
 '
 
 LDEMUL_BEFORE_ALLOCATION=mips_before_allocation
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,
   /* Used by emultempl/msp430.em.  */
   OPTION_CODE_REGION,
   OPTION_DATA_REGION,
-- 
2.34.1


More information about the Binutils mailing list