From: Timm Bäder <tbae...@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 <tbae...@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

Reply via email to