[PATCH 2/4] strip: Pull relocate() info file scope

tbaeder@redhat.com tbaeder@redhat.com
Fri Jan 8 08:04:47 GMT 2021


From: Timm Bäder <tbaeder@redhat.com>

Pull relocate() info file scope and get rid of a nested function this
way. Refactor remove_debug_relocations() to minimize the parameters we
need to pass to relocate().

Signed-off-by: Timm Bäder <tbaeder@redhat.com>
---
 src/strip.c | 347 ++++++++++++++++++++++++++++------------------------
 1 file changed, 184 insertions(+), 163 deletions(-)

diff --git a/src/strip.c b/src/strip.c
index c971b6c2..71913fac 100644
--- a/src/strip.c
+++ b/src/strip.c
@@ -442,6 +442,127 @@ update_shdrstrndx (Elf *elf, size_t shdrstrndx)
   return 0;
 }
 
+
+/* Apply one relocation.  Returns true when trivial
+   relocation actually done.  */
+static bool
+relocate (Elf *elf, GElf_Addr offset, const GElf_Sxword addend,
+	  Elf_Data *tdata, unsigned int ei_data, const char *fname,
+	  bool is_rela, GElf_Sym *sym, int addsub, Elf_Type type)
+{
+  /* These are the types we can relocate.  */
+#define TYPES   DO_TYPE (BYTE, Byte); DO_TYPE (HALF, Half);		\
+      DO_TYPE (WORD, Word); DO_TYPE (SWORD, Sword);		\
+      DO_TYPE (XWORD, Xword); DO_TYPE (SXWORD, Sxword)
+
+  size_t size;
+
+#define DO_TYPE(NAME, Name) GElf_##Name Name;
+  union { TYPES; } tmpbuf;
+#undef DO_TYPE
+
+  switch (type)
+    {
+#define DO_TYPE(NAME, Name)				\
+      case ELF_T_##NAME:			\
+	size = sizeof (GElf_##Name);	\
+	tmpbuf.Name = 0;			\
+	break;
+      TYPES;
+#undef DO_TYPE
+    default:
+      return false;
+    }
+
+  if (offset > tdata->d_size
+      || tdata->d_size - offset < size)
+    {
+      cleanup_debug ();
+      error (EXIT_FAILURE, 0, _("bad relocation"));
+    }
+
+  /* When the symbol value is zero then for SHT_REL
+     sections this is all that needs to be checked.
+     The addend is contained in the original data at
+     the offset already.  So if the (section) symbol
+     address is zero and the given addend is zero
+     just remove the relocation, it isn't needed
+     anymore.  */
+  if (addend == 0 && sym->st_value == 0)
+    return true;
+
+  Elf_Data tmpdata =
+    {
+      .d_type = type,
+      .d_buf = &tmpbuf,
+      .d_size = size,
+      .d_version = EV_CURRENT,
+    };
+  Elf_Data rdata =
+    {
+      .d_type = type,
+      .d_buf = tdata->d_buf + offset,
+      .d_size = size,
+      .d_version = EV_CURRENT,
+    };
+
+  GElf_Addr value = sym->st_value;
+  if (is_rela)
+    {
+      /* For SHT_RELA sections we just take the
+	 given addend and add it to the value.  */
+      value += addend;
+      /* For ADD/SUB relocations we need to fetch the
+	 current section contents.  */
+      if (addsub != 0)
+	{
+	  Elf_Data *d = gelf_xlatetom (elf, &tmpdata,
+				       &rdata,
+				       ei_data);
+	  if (d == NULL)
+	    INTERNAL_ERROR (fname);
+	  assert (d == &tmpdata);
+	}
+    }
+  else
+    {
+      /* For SHT_REL sections we have to peek at
+	 what is already in the section at the given
+	 offset to get the addend.  */
+      Elf_Data *d = gelf_xlatetom (elf, &tmpdata,
+				   &rdata,
+				   ei_data);
+      if (d == NULL)
+	INTERNAL_ERROR (fname);
+      assert (d == &tmpdata);
+    }
+
+  switch (type)
+    {
+#define DO_TYPE(NAME, Name)					 \
+      case ELF_T_##NAME:				 \
+	if (addsub < 0)				 \
+	  tmpbuf.Name -= (GElf_##Name) value;	 \
+	else					 \
+	  tmpbuf.Name += (GElf_##Name) value;	 \
+	break;
+      TYPES;
+#undef DO_TYPE
+    default:
+      abort ();
+    }
+
+  /* Now finally put in the new value.  */
+  Elf_Data *s = gelf_xlatetof (elf, &rdata,
+			       &tmpdata,
+			       ei_data);
+  if (s == NULL)
+    INTERNAL_ERROR (fname);
+  assert (s == &rdata);
+
+  return true;
+}
+
 /* Remove any relocations between debug sections in ET_REL
    for the debug file when requested.  These relocations are always
    zero based between the unallocated sections.  */
@@ -517,180 +638,80 @@ remove_debug_relocations (Ebl *ebl, Elf *elf, GElf_Ehdr *ehdr,
 	  if (symdata == NULL)
 	    INTERNAL_ERROR (fname);
 
-	  /* Apply one relocation.  Returns true when trivial
-	     relocation actually done.  */
-	  bool relocate (GElf_Addr offset, const GElf_Sxword addend,
-			 bool is_rela, int rtype, int symndx)
-	  {
-	    /* R_*_NONE relocs can always just be removed.  */
-	    if (rtype == 0)
-	      return true;
+	  if (shdr->sh_entsize == 0)
+	    INTERNAL_ERROR (fname);
 
-	    /* We only do simple absolute relocations.  */
-	    int addsub = 0;
-	    Elf_Type type = ebl_reloc_simple_type (ebl, rtype, &addsub);
-	    if (type == ELF_T_NUM)
-	      return false;
+	  size_t nrels = shdr->sh_size / shdr->sh_entsize;
+	  size_t next = 0;
+	  const bool is_rela = (shdr->sh_type == SHT_RELA);
+	  const unsigned int ei_data = ehdr->e_ident[EI_DATA];
 
-	    /* These are the types we can relocate.  */
-#define TYPES   DO_TYPE (BYTE, Byte); DO_TYPE (HALF, Half);		\
-		DO_TYPE (WORD, Word); DO_TYPE (SWORD, Sword);		\
-		DO_TYPE (XWORD, Xword); DO_TYPE (SXWORD, Sxword)
-
-	    /* And only for relocations against other debug sections.  */
-	    GElf_Sym sym_mem;
-	    Elf32_Word xndx;
-	    GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
-					      symndx, &sym_mem,
-					      &xndx);
-	    Elf32_Word sec = (sym->st_shndx == SHN_XINDEX
-			      ? xndx : sym->st_shndx);
-
-	    if (ebl_debugscn_p (ebl, secndx_name (elf, sec)))
-	      {
-		size_t size;
+	  for (size_t relidx = 0; relidx < nrels; ++relidx)
+	    {
+	      int rtype, symndx, offset, addend;
+	      union { GElf_Rela rela; GElf_Rel rel; } mem;
+	      void *rel_p; /* Pointer to either rela or rel above */
 
-#define DO_TYPE(NAME, Name) GElf_##Name Name;
-		union { TYPES; } tmpbuf;
-#undef DO_TYPE
+	      if (is_rela)
+		{
+		  GElf_Rela *r = gelf_getrela (reldata, relidx, &mem.rela);
+		  offset = r->r_offset;
+		  addend = r->r_addend;
+		  rtype = GELF_R_TYPE (r->r_info);
+		  symndx = GELF_R_SYM (r->r_info);
+		  rel_p = r;
+		}
+	      else
+		{
+		  GElf_Rel *r = gelf_getrel (reldata, relidx, &mem.rel);
+		  offset = r->r_offset;
+		  addend = 0;
+		  rtype = GELF_R_TYPE (r->r_info);
+		  symndx = GELF_R_SYM (r->r_info);
+		  rel_p = r;
+		}
 
-		switch (type)
-		  {
-#define DO_TYPE(NAME, Name)				\
-		    case ELF_T_##NAME:			\
-		      size = sizeof (GElf_##Name);	\
-		      tmpbuf.Name = 0;			\
-		      break;
-		    TYPES;
-#undef DO_TYPE
-		  default:
-		    return false;
-		  }
+	      /* R_*_NONE relocs can always just be removed.  */
+	      if (rtype == 0)
+		continue;
 
-		if (offset > tdata->d_size
-		    || tdata->d_size - offset < size)
-		  {
-		    cleanup_debug ();
-		    error (EXIT_FAILURE, 0, _("bad relocation"));
-		  }
+	      /* We only do simple absolute relocations.  */
+	      int addsub = 0;
+	      Elf_Type type = ebl_reloc_simple_type (ebl, rtype, &addsub);
+	      if (type == ELF_T_NUM)
+		goto relocate_failed;
 
-		/* When the symbol value is zero then for SHT_REL
-		   sections this is all that needs to be checked.
-		   The addend is contained in the original data at
-		   the offset already.  So if the (section) symbol
-		   address is zero and the given addend is zero
-		   just remove the relocation, it isn't needed
-		   anymore.  */
-		if (addend == 0 && sym->st_value == 0)
-		  return true;
-
-		Elf_Data tmpdata =
-		  {
-		    .d_type = type,
-		    .d_buf = &tmpbuf,
-		    .d_size = size,
-		    .d_version = EV_CURRENT,
-		  };
-		Elf_Data rdata =
-		  {
-		    .d_type = type,
-		    .d_buf = tdata->d_buf + offset,
-		    .d_size = size,
-		    .d_version = EV_CURRENT,
-		  };
-
-		GElf_Addr value = sym->st_value;
-		if (is_rela)
-		  {
-		    /* For SHT_RELA sections we just take the
-		       given addend and add it to the value.  */
-		    value += addend;
-		    /* For ADD/SUB relocations we need to fetch the
-		       current section contents.  */
-		    if (addsub != 0)
-		      {
-			Elf_Data *d = gelf_xlatetom (elf, &tmpdata,
-						     &rdata,
-						     ehdr->e_ident[EI_DATA]);
-			if (d == NULL)
-			  INTERNAL_ERROR (fname);
-			assert (d == &tmpdata);
-		      }
-		  }
-		else
-		  {
-		    /* For SHT_REL sections we have to peek at
-		       what is already in the section at the given
-		       offset to get the addend.  */
-		    Elf_Data *d = gelf_xlatetom (elf, &tmpdata,
-						 &rdata,
-						 ehdr->e_ident[EI_DATA]);
-		    if (d == NULL)
-		      INTERNAL_ERROR (fname);
-		    assert (d == &tmpdata);
-		  }
+	      /* And only for relocations against other debug sections.  */
+	      GElf_Sym sym_mem;
+	      Elf32_Word xndx;
+	      GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
+						symndx, &sym_mem,
+						  &xndx);
+	      Elf32_Word sec = (sym->st_shndx == SHN_XINDEX
+				? xndx : sym->st_shndx);
 
-		switch (type)
-		  {
-#define DO_TYPE(NAME, Name)					 \
-		    case ELF_T_##NAME:				 \
-		      if (addsub < 0)				 \
-			tmpbuf.Name -= (GElf_##Name) value;	 \
-		      else					 \
-			tmpbuf.Name += (GElf_##Name) value;	 \
-		      break;
-		    TYPES;
-#undef DO_TYPE
-		  default:
-		    abort ();
-		  }
+	      bool dbg_scn = ebl_debugscn_p (ebl, secndx_name (elf, sec));
 
-		/* Now finally put in the new value.  */
-		Elf_Data *s = gelf_xlatetof (elf, &rdata,
-					     &tmpdata,
-					     ehdr->e_ident[EI_DATA]);
-		if (s == NULL)
-		  INTERNAL_ERROR (fname);
-		assert (s == &rdata);
+	      if (!dbg_scn)
+		goto relocate_failed;
 
-		return true;
-	      }
-	    return false;
-	  }
+	      if (! relocate (elf, offset, addend,
+			    tdata, ei_data, fname, is_rela,
+			    sym, addsub, type))
+	      goto relocate_failed;
 
-	  if (shdr->sh_entsize == 0)
-	    INTERNAL_ERROR (fname);
+	      continue; /* Next */
 
-	  size_t nrels = shdr->sh_size / shdr->sh_entsize;
-	  size_t next = 0;
-	  if (shdr->sh_type == SHT_REL)
-	    for (size_t relidx = 0; relidx < nrels; ++relidx)
-	      {
-		GElf_Rel rel_mem;
-		GElf_Rel *r = gelf_getrel (reldata, relidx, &rel_mem);
-		if (! relocate (r->r_offset, 0, false,
-				GELF_R_TYPE (r->r_info),
-				GELF_R_SYM (r->r_info)))
-		  {
-		    if (relidx != next)
-		      gelf_update_rel (reldata, next, r);
-		    ++next;
-		  }
-	      }
-	  else
-	    for (size_t relidx = 0; relidx < nrels; ++relidx)
-	      {
-		GElf_Rela rela_mem;
-		GElf_Rela *r = gelf_getrela (reldata, relidx, &rela_mem);
-		if (! relocate (r->r_offset, r->r_addend, true,
-				GELF_R_TYPE (r->r_info),
-				GELF_R_SYM (r->r_info)))
-		  {
-		    if (relidx != next)
-		      gelf_update_rela (reldata, next, r);
-		    ++next;
-		  }
-	      }
+relocate_failed:
+	      if (relidx != next)
+		{
+		  if (is_rela)
+		    gelf_update_rela (reldata, next, rel_p);
+		  else
+		    gelf_update_rel (reldata, next, rel_p);
+		}
+	      ++next;
+	    }
 
 	  nrels = next;
 	  shdr->sh_size = reldata->d_size = nrels * shdr->sh_entsize;
-- 
2.26.2



More information about the Elfutils-devel mailing list