public inbox for elfutils@sourceware.org
 help / color / mirror / Atom feed
* Removing gnu99 constructs from elfutils
@ 2020-11-12 15:03 Timm Bäder
  2020-11-12 15:03 ` [PATCH 01/14] segment_report_module: Get rid of variable-length arrays Timm Bäder
                   ` (14 more replies)
  0 siblings, 15 replies; 25+ messages in thread
From: Timm Bäder @ 2020-11-12 15:03 UTC (permalink / raw)
  To: elfutils-devel

Hi,

I'm looking into removing both the nested functions as well as
variable-length arrays in the elfutils source code, so it can be built
using clang. This is a continuation of
https://sourceware.org/bugzilla/show_bug.cgi?id=24964 basically.

I did try to incorporate some cleanup commits as well so the result does
not get too ugly. Some of the nested functions have quite a few hidden
dependencies on the surrounding code.

I started with libdwfl/dwfl_segment_report_module.c but am planning on
converting everything else as well of course.

What do you think?


Thanks,
Timm




^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 01/14] segment_report_module: Get rid of variable-length arrays
  2020-11-12 15:03 Removing gnu99 constructs from elfutils Timm Bäder
@ 2020-11-12 15:03 ` Timm Bäder
  2020-11-18 23:04   ` Mark Wielaard
  2020-11-12 15:04 ` [PATCH 02/14] segment_report_module: Pull segment_read into file scope Timm Bäder
                   ` (13 subsequent siblings)
  14 siblings, 1 reply; 25+ messages in thread
From: Timm Bäder @ 2020-11-12 15:03 UTC (permalink / raw)
  To: elfutils-devel

This prevents a jump which is needed in a later patch.

Signed-off-by: Timm Bäder <tbaeder@redhat.com>
---
 libdwfl/dwfl_segment_report_module.c | 36 ++++++++++++++--------------
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c
index 430e13d5..dd3fdb9e 100644
--- a/libdwfl/dwfl_segment_report_module.c
+++ b/libdwfl/dwfl_segment_report_module.c
@@ -606,18 +606,18 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
       }
   }
 
-  Elf32_Phdr (*p32)[phnum] = phdrsp;
-  Elf64_Phdr (*p64)[phnum] = phdrsp;
+  Elf32_Phdr *p32 = phdrsp;
+  Elf64_Phdr *p64 = phdrsp;
   if (ei_class == ELFCLASS32)
     {
       if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
 	found_bias = false;	/* Trigger error check.  */
       else
 	for (uint_fast16_t i = 0; i < phnum; ++i)
-	  consider_phdr ((*p32)[i].p_type,
-			 (*p32)[i].p_vaddr, (*p32)[i].p_memsz,
-			 (*p32)[i].p_offset, (*p32)[i].p_filesz,
-			 (*p32)[i].p_align);
+	  consider_phdr (p32[i].p_type,
+			 p32[i].p_vaddr, p32[i].p_memsz,
+			 p32[i].p_offset, p32[i].p_filesz,
+			 p32[i].p_align);
     }
   else
     {
@@ -625,10 +625,10 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 	found_bias = false;	/* Trigger error check.  */
       else
 	for (uint_fast16_t i = 0; i < phnum; ++i)
-	  consider_phdr ((*p64)[i].p_type,
-			 (*p64)[i].p_vaddr, (*p64)[i].p_memsz,
-			 (*p64)[i].p_offset, (*p64)[i].p_filesz,
-			 (*p64)[i].p_align);
+	  consider_phdr (p64[i].p_type,
+			 p64[i].p_vaddr, p64[i].p_memsz,
+			 p64[i].p_offset, p64[i].p_filesz,
+			 p64[i].p_align);
     }
 
   finish_portion (&ph_buffer, &ph_buffer_size);
@@ -796,8 +796,8 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 	dyn_filesz = dyn_data_size;
 
       void *dyns = malloc (dyn_filesz);
-      Elf32_Dyn (*d32)[dyn_filesz / sizeof (Elf32_Dyn)] = dyns;
-      Elf64_Dyn (*d64)[dyn_filesz / sizeof (Elf64_Dyn)] = dyns;
+      Elf32_Dyn *d32 = dyns;
+      Elf64_Dyn *d64 = dyns;
       if (unlikely (dyns == NULL))
 	return finish ();
 
@@ -811,14 +811,14 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 	{
 	  if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL)
 	    for (size_t i = 0; i < dyn_filesz / sizeof (Elf32_Dyn); ++i)
-	      if (consider_dyn ((*d32)[i].d_tag, (*d32)[i].d_un.d_val))
+	      if (consider_dyn (d32[i].d_tag, d32[i].d_un.d_val))
 		break;
 	}
       else
 	{
 	  if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL)
 	    for (size_t i = 0; i < dyn_filesz / sizeof (Elf64_Dyn); ++i)
-	      if (consider_dyn ((*d64)[i].d_tag, (*d64)[i].d_un.d_val))
+	      if (consider_dyn (d64[i].d_tag, d64[i].d_un.d_val))
 		break;
 	}
       free (dyns);
@@ -937,12 +937,12 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 
 	  if (ei_class == ELFCLASS32)
 	    for (uint_fast16_t i = 0; i < phnum; ++i)
-	      read_phdr ((*p32)[i].p_type, (*p32)[i].p_vaddr,
-			 (*p32)[i].p_offset, (*p32)[i].p_filesz);
+	      read_phdr (p32[i].p_type, p32[i].p_vaddr,
+			 p32[i].p_offset, p32[i].p_filesz);
 	  else
 	    for (uint_fast16_t i = 0; i < phnum; ++i)
-	      read_phdr ((*p64)[i].p_type, (*p64)[i].p_vaddr,
-			 (*p64)[i].p_offset, (*p64)[i].p_filesz);
+	      read_phdr (p64[i].p_type, p64[i].p_vaddr,
+			 p64[i].p_offset, p64[i].p_filesz);
 	}
       else
 	{
-- 
2.26.2


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 02/14] segment_report_module: Pull segment_read into file scope
  2020-11-12 15:03 Removing gnu99 constructs from elfutils Timm Bäder
  2020-11-12 15:03 ` [PATCH 01/14] segment_report_module: Get rid of variable-length arrays Timm Bäder
@ 2020-11-12 15:04 ` Timm Bäder
  2020-11-18 23:18   ` Mark Wielaard
  2020-11-12 15:04 ` [PATCH 03/14] segment_report_module: Remove nested finish() function Timm Bäder
                   ` (12 subsequent siblings)
  14 siblings, 1 reply; 25+ messages in thread
From: Timm Bäder @ 2020-11-12 15:04 UTC (permalink / raw)
  To: elfutils-devel

In preparation of getting rid of nested functions

Signed-off-by: Timm Bäder <tbaeder@redhat.com>
---
 libdwfl/dwfl_segment_report_module.c | 30 +++++++++++++++++-----------
 1 file changed, 18 insertions(+), 12 deletions(-)

diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c
index dd3fdb9e..9f06672a 100644
--- a/libdwfl/dwfl_segment_report_module.c
+++ b/libdwfl/dwfl_segment_report_module.c
@@ -232,6 +232,16 @@ invalid_elf (Elf *elf, bool disk_file_has_build_id,
   return false;
 }
 
+static inline bool
+segment_read (Dwfl *dwfl,
+              Dwfl_Memory_Callback *memory_callback, void *memory_callback_arg,
+              int segndx, void **buffer, size_t *buffer_available,
+              GElf_Addr addr, size_t minread)
+{
+  return ! (*memory_callback) (dwfl, segndx, buffer, buffer_available,
+                               addr, minread, memory_callback_arg);
+}
+
 int
 dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 			    Dwfl_Memory_Callback *memory_callback,
@@ -257,18 +267,11 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 
   GElf_Addr start = dwfl->lookup_addr[segment];
 
-  inline bool segment_read (int segndx,
-			    void **buffer, size_t *buffer_available,
-			    GElf_Addr addr, size_t minread)
-  {
-    return ! (*memory_callback) (dwfl, segndx, buffer, buffer_available,
-				 addr, minread, memory_callback_arg);
-  }
-
   inline void release_buffer (void **buffer, size_t *buffer_available)
   {
     if (*buffer != NULL)
-      (void) segment_read (-1, buffer, buffer_available, 0, 0);
+      (void) segment_read (dwfl, memory_callback, memory_callback_arg,
+                           -1, buffer, buffer_available, 0, 0);
   }
 
   /* First read in the file header and check its sanity.  */
@@ -293,7 +296,8 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
     return ndx;
   }
 
-  if (segment_read (ndx, &buffer, &buffer_available,
+  if (segment_read (dwfl, memory_callback, memory_callback_arg,
+                    ndx, &buffer, &buffer_available,
 		    start, sizeof (Elf64_Ehdr))
       || memcmp (buffer, ELFMAG, SELFMAG) != 0)
     return finish ();
@@ -312,7 +316,8 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
       {
 	*data = NULL;
 	*data_size = filesz;
-	return segment_read (addr_segndx (dwfl, segment, vaddr, false),
+	return segment_read (dwfl, memory_callback, memory_callback_arg,
+                             addr_segndx (dwfl, segment, vaddr, false),
 			     data, data_size, vaddr, filesz);
       }
 
@@ -919,7 +924,8 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
       {
 	void *into = contents + offset;
 	size_t read_size = size;
-	(void) segment_read (addr_segndx (dwfl, segment, vaddr, false),
+	(void) segment_read (dwfl, memory_callback, memory_callback_arg,
+                             addr_segndx (dwfl, segment, vaddr, false),
 			     &into, &read_size, vaddr, size);
       }
 
-- 
2.26.2


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 03/14] segment_report_module: Remove nested finish() function
  2020-11-12 15:03 Removing gnu99 constructs from elfutils Timm Bäder
  2020-11-12 15:03 ` [PATCH 01/14] segment_report_module: Get rid of variable-length arrays Timm Bäder
  2020-11-12 15:04 ` [PATCH 02/14] segment_report_module: Pull segment_read into file scope Timm Bäder
@ 2020-11-12 15:04 ` Timm Bäder
  2020-11-19 11:18   ` Mark Wielaard
  2020-11-12 15:04 ` [PATCH 04/14] segment_report_module: Remove nested release_buffer() function Timm Bäder
                   ` (11 subsequent siblings)
  14 siblings, 1 reply; 25+ messages in thread
From: Timm Bäder @ 2020-11-12 15:04 UTC (permalink / raw)
  To: elfutils-devel

This works just as well with a goto-out style label.

Signed-off-by: Timm Bäder <tbaeder@redhat.com>
---
 libdwfl/dwfl_segment_report_module.c | 50 +++++++++++++---------------
 1 file changed, 23 insertions(+), 27 deletions(-)

diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c
index 9f06672a..d06d0ba0 100644
--- a/libdwfl/dwfl_segment_report_module.c
+++ b/libdwfl/dwfl_segment_report_module.c
@@ -285,22 +285,11 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
      here so we can always safely free it.  */
   void *phdrsp = NULL;
 
-  inline int finish (void)
-  {
-    free (phdrsp);
-    release_buffer (&buffer, &buffer_available);
-    if (elf != NULL)
-      elf_end (elf);
-    if (fd != -1)
-      close (fd);
-    return ndx;
-  }
-
   if (segment_read (dwfl, memory_callback, memory_callback_arg,
                     ndx, &buffer, &buffer_available,
 		    start, sizeof (Elf64_Ehdr))
       || memcmp (buffer, ELFMAG, SELFMAG) != 0)
-    return finish ();
+    goto out;
 
   inline bool read_portion (void **data, size_t *data_size,
 			    GElf_Addr vaddr, size_t filesz)
@@ -368,13 +357,13 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
     case ELFCLASS32:
       xlatefrom.d_size = sizeof (Elf32_Ehdr);
       if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
-	return finish ();
+	goto out;
       e_type = ehdr.e32.e_type;
       phoff = ehdr.e32.e_phoff;
       phnum = ehdr.e32.e_phnum;
       phentsize = ehdr.e32.e_phentsize;
       if (phentsize != sizeof (Elf32_Phdr))
-	return finish ();
+	goto out;
       /* NOTE if the number of sections is > 0xff00 then e_shnum
 	 is zero and the actual number would come from the section
 	 zero sh_size field. We ignore this here because getting shdrs
@@ -386,19 +375,19 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
     case ELFCLASS64:
       xlatefrom.d_size = sizeof (Elf64_Ehdr);
       if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
-	return finish ();
+	goto out;
       e_type = ehdr.e64.e_type;
       phoff = ehdr.e64.e_phoff;
       phnum = ehdr.e64.e_phnum;
       phentsize = ehdr.e64.e_phentsize;
       if (phentsize != sizeof (Elf64_Phdr))
-	return finish ();
+	goto out;
       /* See the NOTE above for shdrs_end and ehdr.e32.e_shnum.  */
       shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * ehdr.e64.e_shentsize;
       break;
 
     default:
-      return finish ();
+      goto out;
     }
 
   /* The file header tells where to find the program headers.
@@ -406,7 +395,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
      Without them, we don't have a module to report.  */
 
   if (phnum == 0)
-    return finish ();
+    goto out;
 
   xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR;
   xlatefrom.d_size = phnum * phentsize;
@@ -415,7 +404,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
   size_t ph_buffer_size = 0;
   if (read_portion (&ph_buffer, &ph_buffer_size,
 		    start + phoff, xlatefrom.d_size))
-    return finish ();
+    goto out;
 
   /* ph_buffer_size will be zero if we got everything from the initial
      buffer, otherwise it will be the size of the new buffer that
@@ -428,11 +417,11 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
   bool class32 = ei_class == ELFCLASS32;
   size_t phdr_size = class32 ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr);
   if (unlikely (phnum > SIZE_MAX / phdr_size))
-    return finish ();
+    goto out;
   const size_t phdrsp_bytes = phnum * phdr_size;
   phdrsp = malloc (phdrsp_bytes);
   if (unlikely (phdrsp == NULL))
-    return finish ();
+    goto out;
 
   xlateto.d_buf = phdrsp;
   xlateto.d_size = phdrsp_bytes;
@@ -643,7 +632,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
   if (unlikely (!found_bias))
     {
       free (build_id);
-      return finish ();
+      goto out;
     }
 
   /* Now we know enough to report a module for sure: its bounds.  */
@@ -714,7 +703,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
       if (skip_this_module)
 	{
 	  free (build_id);
-	  return finish ();
+	  goto out;
 	}
     }
 
@@ -804,7 +793,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
       Elf32_Dyn *d32 = dyns;
       Elf64_Dyn *d64 = dyns;
       if (unlikely (dyns == NULL))
-	return finish ();
+	goto out;
 
       xlatefrom.d_type = xlateto.d_type = ELF_T_DYN;
       xlatefrom.d_buf = (void *) dyn_data;
@@ -894,7 +883,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
   if (unlikely (mod == NULL))
     {
       ndx = -1;
-      return finish ();
+      goto out;
     }
 
   /* We have reported the module.  Now let the caller decide whether we
@@ -918,7 +907,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 
       void *contents = calloc (1, file_trimmed_end);
       if (unlikely (contents == NULL))
-	return finish ();
+	goto out;
 
       inline void final_read (size_t offset, GElf_Addr vaddr, size_t size)
       {
@@ -981,5 +970,12 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
       mod->main_bias = bias;
     }
 
-  return finish ();
+out:
+  free (phdrsp);
+  release_buffer (&buffer, &buffer_available);
+  if (elf != NULL)
+    elf_end (elf);
+  if (fd != -1)
+    close (fd);
+  return ndx;
 }
-- 
2.26.2


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 04/14] segment_report_module: Remove nested release_buffer() function
  2020-11-12 15:03 Removing gnu99 constructs from elfutils Timm Bäder
                   ` (2 preceding siblings ...)
  2020-11-12 15:04 ` [PATCH 03/14] segment_report_module: Remove nested finish() function Timm Bäder
@ 2020-11-12 15:04 ` Timm Bäder
  2020-11-19 11:24   ` Mark Wielaard
  2020-11-12 15:04 ` [PATCH 05/14] segment_report_module: Pull finish_portion() info file scope Timm Bäder
                   ` (10 subsequent siblings)
  14 siblings, 1 reply; 25+ messages in thread
From: Timm Bäder @ 2020-11-12 15:04 UTC (permalink / raw)
  To: elfutils-devel

Signed-off-by: Timm Bäder <tbaeder@redhat.com>
---
 libdwfl/dwfl_segment_report_module.c | 16 ++++++----------
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c
index d06d0ba0..ba11b60a 100644
--- a/libdwfl/dwfl_segment_report_module.c
+++ b/libdwfl/dwfl_segment_report_module.c
@@ -267,13 +267,6 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 
   GElf_Addr start = dwfl->lookup_addr[segment];
 
-  inline void release_buffer (void **buffer, size_t *buffer_available)
-  {
-    if (*buffer != NULL)
-      (void) segment_read (dwfl, memory_callback, memory_callback_arg,
-                           -1, buffer, buffer_available, 0, 0);
-  }
-
   /* First read in the file header and check its sanity.  */
 
   void *buffer = NULL;
@@ -318,8 +311,9 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 
   inline void finish_portion (void **data, size_t *data_size)
   {
-    if (*data_size != 0)
-      release_buffer (data, data_size);
+    if (*data_size != 0 && *data != NULL)
+      (void) segment_read (dwfl, memory_callback, memory_callback_arg,
+                           -1, data, data_size, 0, 0);
   }
 
   /* Extract the information we need from the file header.  */
@@ -972,7 +966,9 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 
 out:
   free (phdrsp);
-  release_buffer (&buffer, &buffer_available);
+  if (buffer != NULL)
+    (void) segment_read (dwfl, memory_callback, memory_callback_arg,
+                         -1, &buffer, &buffer_available, 0, 0);
   if (elf != NULL)
     elf_end (elf);
   if (fd != -1)
-- 
2.26.2


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 05/14] segment_report_module: Pull finish_portion() info file scope
  2020-11-12 15:03 Removing gnu99 constructs from elfutils Timm Bäder
                   ` (3 preceding siblings ...)
  2020-11-12 15:04 ` [PATCH 04/14] segment_report_module: Remove nested release_buffer() function Timm Bäder
@ 2020-11-12 15:04 ` Timm Bäder
  2020-11-19 11:48   ` Mark Wielaard
  2020-11-12 15:04 ` [PATCH 06/14] segment_report_module: Pull read_portion() into " Timm Bäder
                   ` (9 subsequent siblings)
  14 siblings, 1 reply; 25+ messages in thread
From: Timm Bäder @ 2020-11-12 15:04 UTC (permalink / raw)
  To: elfutils-devel

Signed-off-by: Timm Bäder <tbaeder@redhat.com>
---
 libdwfl/dwfl_segment_report_module.c | 27 ++++++++++++++++-----------
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c
index ba11b60a..751a96f1 100644
--- a/libdwfl/dwfl_segment_report_module.c
+++ b/libdwfl/dwfl_segment_report_module.c
@@ -242,6 +242,18 @@ segment_read (Dwfl *dwfl,
                                addr, minread, memory_callback_arg);
 }
 
+
+static inline void
+finish_portion (Dwfl *dwfl,
+                Dwfl_Memory_Callback *memory_callback,
+                void *memory_callback_arg,
+                void **data, size_t *data_size)
+{
+  if (*data_size != 0 && *data != NULL)
+    (void) segment_read (dwfl, memory_callback, memory_callback_arg,
+                         -1, data, data_size, 0, 0);
+}
+
 int
 dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 			    Dwfl_Memory_Callback *memory_callback,
@@ -309,13 +321,6 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
     return false;
   }
 
-  inline void finish_portion (void **data, size_t *data_size)
-  {
-    if (*data_size != 0 && *data != NULL)
-      (void) segment_read (dwfl, memory_callback, memory_callback_arg,
-                           -1, data, data_size, 0, 0);
-  }
-
   /* Extract the information we need from the file header.  */
   const unsigned char *e_ident;
   unsigned char ei_class;
@@ -522,7 +527,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
   done:
     if (notes != data)
       free (notes);
-    finish_portion (&data, &data_size);
+    finish_portion (dwfl, memory_callback, memory_callback_arg, &data, &data_size);
   }
 
   /* Consider each of the program headers we've read from the image.  */
@@ -619,7 +624,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 			 p64[i].p_align);
     }
 
-  finish_portion (&ph_buffer, &ph_buffer_size);
+  finish_portion (dwfl, memory_callback, memory_callback_arg, &ph_buffer, &ph_buffer_size);
 
   /* We must have seen the segment covering offset 0, or else the ELF
      header we read at START was not produced by these program headers.  */
@@ -811,7 +816,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 	}
       free (dyns);
     }
-  finish_portion (&dyn_data, &dyn_data_size);
+  finish_portion (dwfl, memory_callback, memory_callback_arg, &dyn_data, &dyn_data_size);
 
   /* We'll use the name passed in or a stupid default if not DT_SONAME.  */
   if (name == NULL)
@@ -872,7 +877,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
   /* At this point we do not need BUILD_ID or NAME any more.
      They have been copied.  */
   free (build_id);
-  finish_portion (&soname, &soname_size);
+  finish_portion (dwfl, memory_callback, memory_callback_arg, &soname, &soname_size);
 
   if (unlikely (mod == NULL))
     {
-- 
2.26.2


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 06/14] segment_report_module: Pull read_portion() into file scope
  2020-11-12 15:03 Removing gnu99 constructs from elfutils Timm Bäder
                   ` (4 preceding siblings ...)
  2020-11-12 15:04 ` [PATCH 05/14] segment_report_module: Pull finish_portion() info file scope Timm Bäder
@ 2020-11-12 15:04 ` Timm Bäder
  2020-11-12 15:04 ` [PATCH 07/14] segment_report_module: Use a struct for build id information Timm Bäder
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 25+ messages in thread
From: Timm Bäder @ 2020-11-12 15:04 UTC (permalink / raw)
  To: elfutils-devel

Signed-off-by: Timm Bäder <tbaeder@redhat.com>
---
 libdwfl/dwfl_segment_report_module.c | 79 +++++++++++++++++-----------
 1 file changed, 48 insertions(+), 31 deletions(-)

diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c
index 751a96f1..00455aa4 100644
--- a/libdwfl/dwfl_segment_report_module.c
+++ b/libdwfl/dwfl_segment_report_module.c
@@ -254,6 +254,40 @@ finish_portion (Dwfl *dwfl,
                          -1, data, data_size, 0, 0);
 }
 
+
+static inline bool
+read_portion (Dwfl *dwfl,
+              Dwfl_Memory_Callback *memory_callback,
+              void *memory_callback_arg,
+              void **data, size_t *data_size,
+              GElf_Addr vaddr, size_t filesz,
+              void *buffer,
+              size_t buffer_available,
+              GElf_Addr start,
+              size_t segment)
+{
+  /* Check whether we will have to read the segment data, or if it
+     can be returned from the existing buffer.  */
+  if (filesz > buffer_available
+      || vaddr - start > buffer_available - filesz
+      /* If we're in string mode, then don't consider the buffer we have
+         sufficient unless it contains the terminator of the string.  */
+      || (filesz == 0 && memchr (vaddr - start + buffer, '\0',
+                                 buffer_available - (vaddr - start)) == NULL))
+    {
+      *data = NULL;
+      *data_size = filesz;
+      return segment_read (dwfl, memory_callback, memory_callback_arg,
+                           addr_segndx (dwfl, segment, vaddr, false),
+                           data, data_size, vaddr, filesz);
+    }
+
+  /* We already have this whole note segment from our initial read.  */
+  *data = vaddr - start + buffer;
+  *data_size = 0;
+  return false;
+}
+
 int
 dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 			    Dwfl_Memory_Callback *memory_callback,
@@ -296,31 +330,6 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
       || memcmp (buffer, ELFMAG, SELFMAG) != 0)
     goto out;
 
-  inline bool read_portion (void **data, size_t *data_size,
-			    GElf_Addr vaddr, size_t filesz)
-  {
-    /* Check whether we will have to read the segment data, or if it
-       can be returned from the existing buffer.  */
-    if (filesz > buffer_available
-	|| vaddr - start > buffer_available - filesz
-	/* If we're in string mode, then don't consider the buffer we have
-	   sufficient unless it contains the terminator of the string.  */
-	|| (filesz == 0 && memchr (vaddr - start + buffer, '\0',
-				   buffer_available - (vaddr - start)) == NULL))
-      {
-	*data = NULL;
-	*data_size = filesz;
-	return segment_read (dwfl, memory_callback, memory_callback_arg,
-                             addr_segndx (dwfl, segment, vaddr, false),
-			     data, data_size, vaddr, filesz);
-      }
-
-    /* We already have this whole note segment from our initial read.  */
-    *data = vaddr - start + buffer;
-    *data_size = 0;
-    return false;
-  }
-
   /* Extract the information we need from the file header.  */
   const unsigned char *e_ident;
   unsigned char ei_class;
@@ -401,8 +410,10 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 
   void *ph_buffer = NULL;
   size_t ph_buffer_size = 0;
-  if (read_portion (&ph_buffer, &ph_buffer_size,
-		    start + phoff, xlatefrom.d_size))
+  if (read_portion (dwfl, memory_callback, memory_callback_arg,
+                    &ph_buffer, &ph_buffer_size,
+                    start + phoff, xlatefrom.d_size,
+                    buffer, buffer_available, start, segment))
     goto out;
 
   /* ph_buffer_size will be zero if we got everything from the initial
@@ -459,7 +470,9 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 
     void *data;
     size_t data_size;
-    if (read_portion (&data, &data_size, vaddr, filesz))
+    if (read_portion (dwfl, memory_callback, memory_callback_arg,
+                      &data, &data_size, vaddr, filesz,
+                      buffer, buffer_available, start, segment))
       return;
 
     /* data_size will be zero if we got everything from the initial
@@ -780,7 +793,9 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
   void *dyn_data = NULL;
   size_t dyn_data_size = 0;
   if (dyn_filesz != 0 && dyn_filesz % dyn_entsize == 0
-      && ! read_portion (&dyn_data, &dyn_data_size, dyn_vaddr, dyn_filesz))
+      && ! read_portion (dwfl, memory_callback, memory_callback_arg,
+                         &dyn_data, &dyn_data_size, dyn_vaddr, dyn_filesz,
+                         buffer, buffer_available, start, segment))
     {
       /* dyn_data_size will be zero if we got everything from the initial
          buffer, otherwise it will be the size of the new buffer that
@@ -848,8 +863,10 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 
       /* Try to get the DT_SONAME string.  */
       if (soname_stroff != 0 && soname_stroff + 1 < dynstrsz
-	  && ! read_portion (&soname, &soname_size,
-			     dynstr_vaddr + soname_stroff, 0))
+	  && ! read_portion (dwfl, memory_callback, memory_callback_arg,
+                             &soname, &soname_size,
+                             dynstr_vaddr + soname_stroff, 0,
+                             buffer, buffer_available, start, segment))
 	name = soname;
     }
 
-- 
2.26.2


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 07/14] segment_report_module: Use a struct for build id information
  2020-11-12 15:03 Removing gnu99 constructs from elfutils Timm Bäder
                   ` (5 preceding siblings ...)
  2020-11-12 15:04 ` [PATCH 06/14] segment_report_module: Pull read_portion() into " Timm Bäder
@ 2020-11-12 15:04 ` Timm Bäder
  2020-11-12 15:04 ` [PATCH 08/14] segment_report_module: Pull consider_notes() into file scope Timm Bäder
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 25+ messages in thread
From: Timm Bäder @ 2020-11-12 15:04 UTC (permalink / raw)
  To: elfutils-devel

Keep the three build id fields in a struct. This will be an important
clean up later.

Signed-off-by: Timm Bäder <tbaeder@redhat.com>
---
 libdwfl/dwfl_segment_report_module.c | 54 ++++++++++++++++------------
 1 file changed, 31 insertions(+), 23 deletions(-)

diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c
index 00455aa4..44743fab 100644
--- a/libdwfl/dwfl_segment_report_module.c
+++ b/libdwfl/dwfl_segment_report_module.c
@@ -54,6 +54,13 @@
 # define MY_ELFDATA	ELFDATA2MSB
 #endif
 
+struct elf_build_id
+{
+  void *memory;
+  size_t len;
+  GElf_Addr vaddr;
+};
+
 
 /* Return user segment index closest to ADDR but not above it.
    If NEXT, return the closest to ADDR but not below it.  */
@@ -206,16 +213,16 @@ handle_file_note (GElf_Addr module_start, GElf_Addr module_end,
 
 static bool
 invalid_elf (Elf *elf, bool disk_file_has_build_id,
-	     const void *build_id, size_t build_id_len)
+             struct elf_build_id *build_id)
 {
-  if (! disk_file_has_build_id && build_id_len > 0)
+  if (! disk_file_has_build_id && build_id->len > 0)
     {
       /* Module found in segments with build-id is more reliable
 	 than a module found via DT_DEBUG on disk without any
 	 build-id.   */
       return true;
     }
-  if (disk_file_has_build_id && build_id_len > 0)
+  if (disk_file_has_build_id && build_id->len > 0)
     {
       const void *elf_build_id;
       ssize_t elf_build_id_len;
@@ -224,8 +231,8 @@ invalid_elf (Elf *elf, bool disk_file_has_build_id,
       elf_build_id_len = INTUSE(dwelf_elf_gnu_build_id) (elf, &elf_build_id);
       if (elf_build_id_len > 0)
 	{
-	  if (build_id_len != (size_t) elf_build_id_len
-	      || memcmp (build_id, elf_build_id, build_id_len) != 0)
+	  if (build_id->len != (size_t) elf_build_id_len
+	      || memcmp (build_id->memory, elf_build_id, build_id->len) != 0)
 	    return true;
 	}
     }
@@ -456,16 +463,17 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
   GElf_Xword dyn_filesz = 0;
 
   /* Collect the build ID bits here.  */
-  void *build_id = NULL;
-  size_t build_id_len = 0;
-  GElf_Addr build_id_vaddr = 0;
+  struct elf_build_id build_id;
+  build_id.memory = NULL;
+  build_id.len = 0;
+  build_id.vaddr =0;
 
   /* Consider a PT_NOTE we've found in the image.  */
   inline void consider_notes (GElf_Addr vaddr, GElf_Xword filesz,
 			      GElf_Xword align)
   {
     /* If we have already seen a build ID, we don't care any more.  */
-    if (build_id != NULL || filesz == 0)
+    if (build_id.memory != NULL || filesz == 0)
       return;
 
     void *data;
@@ -524,11 +532,11 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 	    && nh->n_namesz == sizeof "GNU"
 	    && !memcmp (note_name, "GNU", sizeof "GNU"))
 	  {
-	    build_id_vaddr = note_desc - (const void *) notes + vaddr;
-	    build_id_len = nh->n_descsz;
-	    build_id = malloc (nh->n_descsz);
-	    if (likely (build_id != NULL))
-	      memcpy (build_id, note_desc, build_id_len);
+            build_id.vaddr = note_desc - (const void *) notes + vaddr;
+            build_id.len = nh->n_descsz;
+            build_id.memory = malloc (build_id.len);
+            if (likely (build_id.memory != NULL))
+              memcpy (build_id.memory, note_desc, build_id.len);
 	    break;
 	  }
 
@@ -643,7 +651,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
      header we read at START was not produced by these program headers.  */
   if (unlikely (!found_bias))
     {
-      free (build_id);
+      free (build_id.memory);
       goto out;
     }
 
@@ -698,7 +706,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 	  {
 	    if (module->elf != NULL
 	        && invalid_elf (module->elf, module->disk_file_has_build_id,
-				build_id, build_id_len))
+                                &build_id))
 	      {
 		elf_end (module->elf);
 		close (module->fd);
@@ -714,7 +722,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 	  }
       if (skip_this_module)
 	{
-	  free (build_id);
+	  free (build_id.memory);
 	  goto out;
 	}
     }
@@ -733,7 +741,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 	  Dwfl_Error error = __libdw_open_file (&fd, &elf, true, false);
 	  if (error == DWFL_E_NOERROR)
 	    invalid = invalid_elf (elf, true /* disk_file_has_build_id */,
-				   build_id, build_id_len);
+                                   &build_id);
 	}
       if (invalid)
 	{
@@ -881,11 +889,11 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
   if (mod != NULL && (execlike || ehdr.e32.e_type == ET_EXEC))
     mod->is_executable = true;
 
-  if (likely (mod != NULL) && build_id != NULL
+  if (likely (mod != NULL) && build_id.memory != NULL
       && unlikely (INTUSE(dwfl_module_report_build_id) (mod,
-							build_id,
-							build_id_len,
-							build_id_vaddr)))
+							build_id.memory,
+							build_id.len,
+							build_id.vaddr)))
     {
       mod->gc = true;
       mod = NULL;
@@ -893,7 +901,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 
   /* At this point we do not need BUILD_ID or NAME any more.
      They have been copied.  */
-  free (build_id);
+  free (build_id.memory);
   finish_portion (dwfl, memory_callback, memory_callback_arg, &soname, &soname_size);
 
   if (unlikely (mod == NULL))
-- 
2.26.2


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 08/14] segment_report_module: Pull consider_notes() into file scope
  2020-11-12 15:03 Removing gnu99 constructs from elfutils Timm Bäder
                   ` (6 preceding siblings ...)
  2020-11-12 15:04 ` [PATCH 07/14] segment_report_module: Use a struct for build id information Timm Bäder
@ 2020-11-12 15:04 ` Timm Bäder
  2020-11-12 15:04 ` [PATCH 09/14] segment_report_module: Get rid of nested final_read() function Timm Bäder
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 25+ messages in thread
From: Timm Bäder @ 2020-11-12 15:04 UTC (permalink / raw)
  To: elfutils-devel

Signed-off-by: Timm Bäder <tbaeder@redhat.com>
---
 libdwfl/dwfl_segment_report_module.c | 187 +++++++++++++++------------
 1 file changed, 101 insertions(+), 86 deletions(-)

diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c
index 44743fab..76686a72 100644
--- a/libdwfl/dwfl_segment_report_module.c
+++ b/libdwfl/dwfl_segment_report_module.c
@@ -295,6 +295,99 @@ read_portion (Dwfl *dwfl,
   return false;
 }
 
+
+/* Consider a PT_NOTE we've found in the image.  */
+static inline void
+consider_notes (Dwfl *dwfl,
+                Dwfl_Memory_Callback *memory_callback, void *memory_callback_arg,
+                GElf_Addr vaddr, GElf_Xword filesz,
+                GElf_Xword align,
+                void *buffer, size_t buffer_available,
+                GElf_Addr start,
+                size_t segment,
+                unsigned char ei_data,
+                struct elf_build_id *build_id,
+                Elf_Data *xlatefrom,
+                Elf_Data *xlateto,
+                unsigned int xencoding)
+{
+  if (build_id->memory != NULL || filesz == 0)
+    return;
+
+  void *data;
+  size_t data_size;
+  if (read_portion (dwfl, memory_callback, memory_callback_arg,
+                    &data, &data_size, vaddr, filesz,
+                    buffer, buffer_available, start, segment))
+    return;
+
+  /* data_size will be zero if we got everything from the initial
+     buffer, otherwise it will be the size of the new buffer that
+     could be read.  */
+  if (data_size != 0)
+    filesz = data_size;
+
+  assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr));
+
+  void *notes;
+  if (ei_data == MY_ELFDATA)
+    notes = data;
+  else
+    {
+      notes = malloc (filesz);
+      if (unlikely (notes == NULL))
+        return;
+      xlatefrom->d_type = xlateto->d_type = (align == 8
+                                             ? ELF_T_NHDR8 : ELF_T_NHDR);
+      xlatefrom->d_buf = (void *) data;
+      xlatefrom->d_size = filesz;
+      xlateto->d_buf = notes;
+      xlateto->d_size = filesz;
+      if (elf32_xlatetom (xlateto, xlatefrom, xencoding) == NULL)
+        goto done;
+    }
+
+  const GElf_Nhdr *nh = notes;
+  size_t len = 0;
+  while (filesz > len + sizeof (*nh))
+    {
+      const void *note_name;
+      const void *note_desc;
+
+      len += sizeof (*nh);
+      note_name = notes + len;
+
+      len += nh->n_namesz;
+      len = align == 8 ? NOTE_ALIGN8 (len) : NOTE_ALIGN4 (len);
+      note_desc = notes + len;
+
+      if (unlikely (filesz < len + nh->n_descsz))
+        break;
+
+      if (nh->n_type == NT_GNU_BUILD_ID
+          && nh->n_descsz > 0
+          && nh->n_namesz == sizeof "GNU"
+          && !memcmp (note_name, "GNU", sizeof "GNU"))
+        {
+          build_id->vaddr = note_desc - (const void *) notes + vaddr;
+          build_id->len = nh->n_descsz;
+          build_id->memory = malloc (build_id->len);
+          if (likely (build_id->memory != NULL))
+            memcpy (build_id->memory, note_desc, build_id->len);
+          break;
+        }
+
+      len += nh->n_descsz;
+      len = align == 8 ? NOTE_ALIGN8 (len) : NOTE_ALIGN4 (len);
+      nh = (void *) notes + len;
+    }
+
+done:
+  if (notes != data)
+    free (notes);
+  finish_portion (dwfl, memory_callback, memory_callback_arg, &data, &data_size);
+}
+
 int
 dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 			    Dwfl_Memory_Callback *memory_callback,
@@ -468,89 +561,6 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
   build_id.len = 0;
   build_id.vaddr =0;
 
-  /* Consider a PT_NOTE we've found in the image.  */
-  inline void consider_notes (GElf_Addr vaddr, GElf_Xword filesz,
-			      GElf_Xword align)
-  {
-    /* If we have already seen a build ID, we don't care any more.  */
-    if (build_id.memory != NULL || filesz == 0)
-      return;
-
-    void *data;
-    size_t data_size;
-    if (read_portion (dwfl, memory_callback, memory_callback_arg,
-                      &data, &data_size, vaddr, filesz,
-                      buffer, buffer_available, start, segment))
-      return;
-
-    /* data_size will be zero if we got everything from the initial
-       buffer, otherwise it will be the size of the new buffer that
-       could be read.  */
-    if (data_size != 0)
-      filesz = data_size;
-
-    assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr));
-
-    void *notes;
-    if (ei_data == MY_ELFDATA)
-      notes = data;
-    else
-      {
-	notes = malloc (filesz);
-	if (unlikely (notes == NULL))
-	  return;
-	xlatefrom.d_type = xlateto.d_type = (align == 8
-					     ? ELF_T_NHDR8 : ELF_T_NHDR);
-	xlatefrom.d_buf = (void *) data;
-	xlatefrom.d_size = filesz;
-	xlateto.d_buf = notes;
-	xlateto.d_size = filesz;
-	if (elf32_xlatetom (&xlateto, &xlatefrom,
-			    ehdr.e32.e_ident[EI_DATA]) == NULL)
-	  goto done;
-      }
-
-    const GElf_Nhdr *nh = notes;
-    size_t len = 0;
-    while (filesz > len + sizeof (*nh))
-      {
-	const void *note_name;
-	const void *note_desc;
-
-	len += sizeof (*nh);
-	note_name = notes + len;
-
-	len += nh->n_namesz;
-	len = align == 8 ? NOTE_ALIGN8 (len) : NOTE_ALIGN4 (len);
-	note_desc = notes + len;
-
-	if (unlikely (filesz < len + nh->n_descsz))
-	  break;
-
-        if (nh->n_type == NT_GNU_BUILD_ID
-	    && nh->n_descsz > 0
-	    && nh->n_namesz == sizeof "GNU"
-	    && !memcmp (note_name, "GNU", sizeof "GNU"))
-	  {
-            build_id.vaddr = note_desc - (const void *) notes + vaddr;
-            build_id.len = nh->n_descsz;
-            build_id.memory = malloc (build_id.len);
-            if (likely (build_id.memory != NULL))
-              memcpy (build_id.memory, note_desc, build_id.len);
-	    break;
-	  }
-
-	len += nh->n_descsz;
-	len = align == 8 ? NOTE_ALIGN8 (len) : NOTE_ALIGN4 (len);
-	nh = (void *) notes + len;
-      }
-
-  done:
-    if (notes != data)
-      free (notes);
-    finish_portion (dwfl, memory_callback, memory_callback_arg, &data, &data_size);
-  }
-
   /* Consider each of the program headers we've read from the image.  */
   inline void consider_phdr (GElf_Word type,
 			     GElf_Addr vaddr, GElf_Xword memsz,
@@ -565,9 +575,14 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 	break;
 
       case PT_NOTE:
-	/* We calculate from the p_offset of the note segment,
-	   because we don't yet know the bias for its p_vaddr.  */
-	consider_notes (start + offset, filesz, align);
+          /* We calculate from the p_offset of the note segment,
+           because we don't yet know the bias for its p_vaddr.  */
+          consider_notes (dwfl, memory_callback, memory_callback_arg,
+                          start + offset, filesz, align,
+                          buffer, buffer_available, start, segment,
+                          ei_data, &build_id,
+                          &xlatefrom, &xlateto,
+                          ehdr.e32.e_ident[EI_DATA]);
 	break;
 
       case PT_LOAD:
-- 
2.26.2


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 09/14] segment_report_module: Get rid of nested final_read() function
  2020-11-12 15:03 Removing gnu99 constructs from elfutils Timm Bäder
                   ` (7 preceding siblings ...)
  2020-11-12 15:04 ` [PATCH 08/14] segment_report_module: Pull consider_notes() into file scope Timm Bäder
@ 2020-11-12 15:04 ` Timm Bäder
  2020-11-12 15:04 ` [PATCH 10/14] segment_report_module: Use one loop for p32/p64 arrays Timm Bäder
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 25+ messages in thread
From: Timm Bäder @ 2020-11-12 15:04 UTC (permalink / raw)
  To: elfutils-devel

Signed-off-by: Timm Bäder <tbaeder@redhat.com>
---
 libdwfl/dwfl_segment_report_module.c | 26 +++++++++++++++-----------
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c
index 76686a72..80f97cfd 100644
--- a/libdwfl/dwfl_segment_report_module.c
+++ b/libdwfl/dwfl_segment_report_module.c
@@ -948,15 +948,6 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
       if (unlikely (contents == NULL))
 	goto out;
 
-      inline void final_read (size_t offset, GElf_Addr vaddr, size_t size)
-      {
-	void *into = contents + offset;
-	size_t read_size = size;
-	(void) segment_read (dwfl, memory_callback, memory_callback_arg,
-                             addr_segndx (dwfl, segment, vaddr, false),
-			     &into, &read_size, vaddr, size);
-      }
-
       if (contiguous < file_trimmed_end)
 	{
 	  /* We can't use the memory image verbatim as the file image.
@@ -966,7 +957,14 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 				 GElf_Off offset, GElf_Xword filesz)
 	  {
 	    if (type == PT_LOAD)
-	      final_read (offset, vaddr + bias, filesz);
+              {
+                void *into = contents + offset;
+                size_t read_size = filesz;
+                (void)segment_read (dwfl, memory_callback, memory_callback_arg,
+                                    addr_segndx (dwfl, segment, vaddr + bias, false),
+                                    &into, &read_size, vaddr + bias, read_size);
+
+              }
 	  }
 
 	  if (ei_class == ELFCLASS32)
@@ -987,7 +985,13 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 	  memcpy (contents, buffer, have);
 
 	  if (have < file_trimmed_end)
-	    final_read (have, start + have, file_trimmed_end - have);
+            {
+              void *into = contents + have;
+              size_t read_size = file_trimmed_end - have;
+              (void)segment_read (dwfl, memory_callback, memory_callback_arg,
+                                  addr_segndx (dwfl, segment, start + have, false),
+                                  &into, &read_size, start + have, read_size);
+            }
 	}
 
       elf = elf_memory (contents, file_trimmed_end);
-- 
2.26.2


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 10/14] segment_report_module: Use one loop for p32/p64 arrays
  2020-11-12 15:03 Removing gnu99 constructs from elfutils Timm Bäder
                   ` (8 preceding siblings ...)
  2020-11-12 15:04 ` [PATCH 09/14] segment_report_module: Get rid of nested final_read() function Timm Bäder
@ 2020-11-12 15:04 ` Timm Bäder
  2020-11-12 15:04 ` [PATCH 11/14] segment_report_module: Inline read_phdr() into only caller Timm Bäder
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 25+ messages in thread
From: Timm Bäder @ 2020-11-12 15:04 UTC (permalink / raw)
  To: elfutils-devel

Do one loop check for 32/64 bit inside the loop, instead of outside.
This way we have only one call site for the function called in the loop
body.

Signed-off-by: Timm Bäder <tbaeder@redhat.com>
---
 libdwfl/dwfl_segment_report_module.c | 52 +++++++++++++++-------------
 1 file changed, 27 insertions(+), 25 deletions(-)

diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c
index 80f97cfd..2535f9e3 100644
--- a/libdwfl/dwfl_segment_report_module.c
+++ b/libdwfl/dwfl_segment_report_module.c
@@ -637,27 +637,27 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 
   Elf32_Phdr *p32 = phdrsp;
   Elf64_Phdr *p64 = phdrsp;
-  if (ei_class == ELFCLASS32)
+  if ((ei_class == ELFCLASS32 &&
+      elf32_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL) ||
+      (ei_class == ELFCLASS64 &&
+      elf64_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL))
     {
-      if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
-	found_bias = false;	/* Trigger error check.  */
-      else
-	for (uint_fast16_t i = 0; i < phnum; ++i)
-	  consider_phdr (p32[i].p_type,
-			 p32[i].p_vaddr, p32[i].p_memsz,
-			 p32[i].p_offset, p32[i].p_filesz,
-			 p32[i].p_align);
+      found_bias = false; /* Trigger error check */
     }
   else
     {
-      if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
-	found_bias = false;	/* Trigger error check.  */
-      else
-	for (uint_fast16_t i = 0; i < phnum; ++i)
-	  consider_phdr (p64[i].p_type,
-			 p64[i].p_vaddr, p64[i].p_memsz,
-			 p64[i].p_offset, p64[i].p_filesz,
-			 p64[i].p_align);
+      for (uint_fast16_t i = 0; i < phnum; ++i)
+        {
+          bool is32 = (ei_class == ELFCLASS32);
+          GElf_Word type = is32 ? p32[i].p_type : p64[i].p_type;
+          GElf_Addr vaddr = is32 ? p32[i].p_vaddr : p64[i].p_vaddr;
+          GElf_Xword memsz = is32 ? p32[i].p_memsz : p64[i].p_memsz;
+          GElf_Off offset = is32 ? p32[i].p_offset : p64[i].p_offset;
+          GElf_Xword filesz = is32 ? p32[i].p_filesz : p64[i].p_filesz;
+          GElf_Xword align = is32 ? p32[i].p_align : p64[i].p_align;
+
+          consider_phdr (type, vaddr, memsz, offset, filesz, align);
+        }
     }
 
   finish_portion (dwfl, memory_callback, memory_callback_arg, &ph_buffer, &ph_buffer_size);
@@ -967,14 +967,16 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
               }
 	  }
 
-	  if (ei_class == ELFCLASS32)
-	    for (uint_fast16_t i = 0; i < phnum; ++i)
-	      read_phdr (p32[i].p_type, p32[i].p_vaddr,
-			 p32[i].p_offset, p32[i].p_filesz);
-	  else
-	    for (uint_fast16_t i = 0; i < phnum; ++i)
-	      read_phdr (p64[i].p_type, p64[i].p_vaddr,
-			 p64[i].p_offset, p64[i].p_filesz);
+          for (uint_fast16_t i = 0; i < phnum; ++i)
+            {
+              bool is32 = (ei_class == ELFCLASS32);
+              GElf_Word type = is32 ? p32[i].p_type : p64[i].p_type;
+              GElf_Addr vaddr = is32 ? p32[i].p_vaddr : p64[i].p_vaddr;
+              GElf_Off offset = is32 ? p32[i].p_offset : p64[i].p_offset;
+              GElf_Xword filesz = is32 ? p32[i].p_filesz : p64[i].p_filesz;
+
+              read_phdr (type, vaddr, offset, filesz);
+            }
 	}
       else
 	{
-- 
2.26.2


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 11/14] segment_report_module: Inline read_phdr() into only caller
  2020-11-12 15:03 Removing gnu99 constructs from elfutils Timm Bäder
                   ` (9 preceding siblings ...)
  2020-11-12 15:04 ` [PATCH 10/14] segment_report_module: Use one loop for p32/p64 arrays Timm Bäder
@ 2020-11-12 15:04 ` Timm Bäder
  2020-11-12 15:04 ` [PATCH 12/14] segment_report_module: Unify d32/d64 loops Timm Bäder
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 25+ messages in thread
From: Timm Bäder @ 2020-11-12 15:04 UTC (permalink / raw)
  To: elfutils-devel

There is now only one caller for this nested function, so get rid of it
by just inlining it there.

Signed-off-by: Timm Bäder <tbaeder@redhat.com>
---
 libdwfl/dwfl_segment_report_module.c | 25 +++++++++----------------
 1 file changed, 9 insertions(+), 16 deletions(-)

diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c
index 2535f9e3..bcf69fe7 100644
--- a/libdwfl/dwfl_segment_report_module.c
+++ b/libdwfl/dwfl_segment_report_module.c
@@ -952,30 +952,23 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 	{
 	  /* We can't use the memory image verbatim as the file image.
 	     So we'll be reading into a local image of the virtual file.  */
-
-	  inline void read_phdr (GElf_Word type, GElf_Addr vaddr,
-				 GElf_Off offset, GElf_Xword filesz)
-	  {
-	    if (type == PT_LOAD)
-              {
-                void *into = contents + offset;
-                size_t read_size = filesz;
-                (void)segment_read (dwfl, memory_callback, memory_callback_arg,
-                                    addr_segndx (dwfl, segment, vaddr + bias, false),
-                                    &into, &read_size, vaddr + bias, read_size);
-
-              }
-	  }
-
           for (uint_fast16_t i = 0; i < phnum; ++i)
             {
               bool is32 = (ei_class == ELFCLASS32);
               GElf_Word type = is32 ? p32[i].p_type : p64[i].p_type;
+
+              if (type != PT_LOAD)
+                continue;
+
               GElf_Addr vaddr = is32 ? p32[i].p_vaddr : p64[i].p_vaddr;
               GElf_Off offset = is32 ? p32[i].p_offset : p64[i].p_offset;
               GElf_Xword filesz = is32 ? p32[i].p_filesz : p64[i].p_filesz;
 
-              read_phdr (type, vaddr, offset, filesz);
+              void *into = contents + offset;
+              size_t read_size = filesz;
+              (void)segment_read (dwfl, memory_callback, memory_callback_arg,
+                                  addr_segndx (dwfl, segment, vaddr + bias, false),
+                                  &into, &read_size, vaddr + bias, read_size);
             }
 	}
       else
-- 
2.26.2


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 12/14] segment_report_module: Unify d32/d64 loops
  2020-11-12 15:03 Removing gnu99 constructs from elfutils Timm Bäder
                   ` (10 preceding siblings ...)
  2020-11-12 15:04 ` [PATCH 11/14] segment_report_module: Inline read_phdr() into only caller Timm Bäder
@ 2020-11-12 15:04 ` Timm Bäder
  2020-11-12 15:04 ` [PATCH 13/14] segment_report_module: Inline consider_dyn() into only caller Timm Bäder
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 25+ messages in thread
From: Timm Bäder @ 2020-11-12 15:04 UTC (permalink / raw)
  To: elfutils-devel

Just like we did before, use only one loop here and check for 32/64 bit
in the loop body. This way we only have one call site for consider_dyn

Signed-off-by: Timm Bäder <tbaeder@redhat.com>
---
 libdwfl/dwfl_segment_report_module.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c
index bcf69fe7..7c97784f 100644
--- a/libdwfl/dwfl_segment_report_module.c
+++ b/libdwfl/dwfl_segment_report_module.c
@@ -838,20 +838,20 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
       xlateto.d_buf = dyns;
       xlateto.d_size = dyn_filesz;
 
-      if (ei_class == ELFCLASS32)
-	{
-	  if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL)
-	    for (size_t i = 0; i < dyn_filesz / sizeof (Elf32_Dyn); ++i)
-	      if (consider_dyn (d32[i].d_tag, d32[i].d_un.d_val))
-		break;
-	}
-      else
-	{
-	  if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL)
-	    for (size_t i = 0; i < dyn_filesz / sizeof (Elf64_Dyn); ++i)
-	      if (consider_dyn (d64[i].d_tag, d64[i].d_un.d_val))
-		break;
-	}
+      bool is32 = (ei_class == ELFCLASS32);
+      if ((is32 && elf32_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL)
+          || (!is32 && elf64_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL))
+        {
+          size_t n = is32 ? (dyn_filesz / sizeof (Elf32_Dyn)) : (dyn_filesz / sizeof (Elf64_Dyn));
+          for (size_t i = 0; i < n; ++i)
+            {
+              GElf_Sxword tag = is32 ? d32[i].d_tag : d64[i].d_tag;
+              GElf_Xword val = is32 ? d32[i].d_un.d_val : d64[i].d_un.d_val;
+
+              if (consider_dyn (tag, val))
+                break;
+            }
+        }
       free (dyns);
     }
   finish_portion (dwfl, memory_callback, memory_callback_arg, &dyn_data, &dyn_data_size);
-- 
2.26.2


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 13/14] segment_report_module: Inline consider_dyn() into only caller
  2020-11-12 15:03 Removing gnu99 constructs from elfutils Timm Bäder
                   ` (11 preceding siblings ...)
  2020-11-12 15:04 ` [PATCH 12/14] segment_report_module: Unify d32/d64 loops Timm Bäder
@ 2020-11-12 15:04 ` Timm Bäder
  2020-11-12 15:04 ` [PATCH 14/14] segment_report_module: Inline consider_phdr() " Timm Bäder
  2020-11-13 12:38 ` Removing gnu99 constructs from elfutils Mark Wielaard
  14 siblings, 0 replies; 25+ messages in thread
From: Timm Bäder @ 2020-11-12 15:04 UTC (permalink / raw)
  To: elfutils-devel

Signed-off-by: Timm Bäder <tbaeder@redhat.com>
---
 libdwfl/dwfl_segment_report_module.c | 40 +++++++++-------------------
 1 file changed, 12 insertions(+), 28 deletions(-)

diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c
index 7c97784f..0679453e 100644
--- a/libdwfl/dwfl_segment_report_module.c
+++ b/libdwfl/dwfl_segment_report_module.c
@@ -784,33 +784,6 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
   GElf_Addr dynstr_vaddr = 0;
   GElf_Xword dynstrsz = 0;
   bool execlike = false;
-  inline bool consider_dyn (GElf_Sxword tag, GElf_Xword val)
-  {
-    switch (tag)
-      {
-      default:
-	return false;
-
-      case DT_DEBUG:
-	execlike = true;
-	break;
-
-      case DT_SONAME:
-	soname_stroff = val;
-	break;
-
-      case DT_STRTAB:
-	dynstr_vaddr = val;
-	break;
-
-      case DT_STRSZ:
-	dynstrsz = val;
-	break;
-      }
-
-    return soname_stroff != 0 && dynstr_vaddr != 0 && dynstrsz != 0;
-  }
-
   const size_t dyn_entsize = (ei_class == ELFCLASS32
 			      ? sizeof (Elf32_Dyn) : sizeof (Elf64_Dyn));
   void *dyn_data = NULL;
@@ -848,7 +821,18 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
               GElf_Sxword tag = is32 ? d32[i].d_tag : d64[i].d_tag;
               GElf_Xword val = is32 ? d32[i].d_un.d_val : d64[i].d_un.d_val;
 
-              if (consider_dyn (tag, val))
+              if (tag == DT_DEBUG)
+                execlike = true;
+              else if (tag == DT_SONAME)
+                soname_stroff = val;
+              else if (tag == DT_STRTAB)
+                dynstr_vaddr = val;
+              else if (tag == DT_STRSZ)
+                dynstrsz = val;
+              else
+                continue;
+
+              if (soname_stroff != 0 && dynstr_vaddr != 0 && dynstrsz != 0)
                 break;
             }
         }
-- 
2.26.2


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 14/14] segment_report_module: Inline consider_phdr() into only caller
  2020-11-12 15:03 Removing gnu99 constructs from elfutils Timm Bäder
                   ` (12 preceding siblings ...)
  2020-11-12 15:04 ` [PATCH 13/14] segment_report_module: Inline consider_dyn() into only caller Timm Bäder
@ 2020-11-12 15:04 ` Timm Bäder
  2020-11-12 16:52   ` Navin P
  2020-11-13 12:38 ` Removing gnu99 constructs from elfutils Mark Wielaard
  14 siblings, 1 reply; 25+ messages in thread
From: Timm Bäder @ 2020-11-12 15:04 UTC (permalink / raw)
  To: elfutils-devel

Get rid of the nested function this way

Signed-off-by: Timm Bäder <tbaeder@redhat.com>
---
 libdwfl/dwfl_segment_report_module.c | 142 +++++++++++++--------------
 1 file changed, 66 insertions(+), 76 deletions(-)

diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c
index 0679453e..f93c60e2 100644
--- a/libdwfl/dwfl_segment_report_module.c
+++ b/libdwfl/dwfl_segment_report_module.c
@@ -475,7 +475,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
       /* NOTE if the number of sections is > 0xff00 then e_shnum
 	 is zero and the actual number would come from the section
 	 zero sh_size field. We ignore this here because getting shdrs
-	 is just a nice bonus (see below in consider_phdr PT_LOAD
+	 is just a nice bonus (see below in the type == PT_LOAD case
 	 where we trim the last segment).  */
       shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * ehdr.e32.e_shentsize;
       break;
@@ -561,80 +561,6 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
   build_id.len = 0;
   build_id.vaddr =0;
 
-  /* Consider each of the program headers we've read from the image.  */
-  inline void consider_phdr (GElf_Word type,
-			     GElf_Addr vaddr, GElf_Xword memsz,
-			     GElf_Off offset, GElf_Xword filesz,
-			     GElf_Xword align)
-  {
-    switch (type)
-      {
-      case PT_DYNAMIC:
-	dyn_vaddr = vaddr;
-	dyn_filesz = filesz;
-	break;
-
-      case PT_NOTE:
-          /* We calculate from the p_offset of the note segment,
-           because we don't yet know the bias for its p_vaddr.  */
-          consider_notes (dwfl, memory_callback, memory_callback_arg,
-                          start + offset, filesz, align,
-                          buffer, buffer_available, start, segment,
-                          ei_data, &build_id,
-                          &xlatefrom, &xlateto,
-                          ehdr.e32.e_ident[EI_DATA]);
-	break;
-
-      case PT_LOAD:
-	align = dwfl->segment_align > 1 ? dwfl->segment_align : align ?: 1;
-
-	GElf_Addr vaddr_end = (vaddr + memsz + align - 1) & -align;
-	GElf_Addr filesz_vaddr = filesz < memsz ? vaddr + filesz : vaddr_end;
-	GElf_Off filesz_offset = filesz_vaddr - vaddr + offset;
-
-	if (file_trimmed_end < offset + filesz)
-	  {
-	    file_trimmed_end = offset + filesz;
-
-	    /* Trim the last segment so we don't bother with zeros
-	       in the last page that are off the end of the file.
-	       However, if the extra bit in that page includes the
-	       section headers, keep them.  */
-	    if (shdrs_end <= filesz_offset && shdrs_end > file_trimmed_end)
-	      {
-		filesz += shdrs_end - file_trimmed_end;
-		file_trimmed_end = shdrs_end;
-	      }
-	  }
-
-	total_filesz += filesz;
-
-	if (file_end < filesz_offset)
-	  {
-	    file_end = filesz_offset;
-	    if (filesz_vaddr - start == filesz_offset)
-	      contiguous = file_end;
-	  }
-
-	if (!found_bias && (offset & -align) == 0
-	    && likely (filesz_offset >= phoff + phnum * phentsize))
-	  {
-	    bias = start - vaddr;
-	    found_bias = true;
-	  }
-
-	if ((vaddr & -align) < module_start)
-	  {
-	    module_start = vaddr & -align;
-	    module_address_sync = vaddr + memsz;
-	  }
-
-	if (module_end < vaddr_end)
-	  module_end = vaddr_end;
-	break;
-      }
-  }
-
   Elf32_Phdr *p32 = phdrsp;
   Elf64_Phdr *p64 = phdrsp;
   if ((ei_class == ELFCLASS32 &&
@@ -646,6 +572,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
     }
   else
     {
+      /* Consider each of the program headers we've read from the image.  */
       for (uint_fast16_t i = 0; i < phnum; ++i)
         {
           bool is32 = (ei_class == ELFCLASS32);
@@ -656,7 +583,70 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
           GElf_Xword filesz = is32 ? p32[i].p_filesz : p64[i].p_filesz;
           GElf_Xword align = is32 ? p32[i].p_align : p64[i].p_align;
 
-          consider_phdr (type, vaddr, memsz, offset, filesz, align);
+          if (type == PT_DYNAMIC)
+            {
+              dyn_vaddr = vaddr;
+              dyn_filesz = filesz;
+            }
+          else if (type == PT_NOTE)
+            {
+              /* We calculate from the p_offset of the note segment,
+               because we don't yet know the bias for its p_vaddr.  */
+              consider_notes (dwfl, memory_callback, memory_callback_arg,
+                              start + offset, filesz, align,
+                              buffer, buffer_available, start, segment,
+                              ei_data, &build_id,
+                              &xlatefrom, &xlateto,
+                              ehdr.e32.e_ident[EI_DATA]);
+            }
+          else if (type == PT_LOAD)
+            {
+              align = dwfl->segment_align > 1 ? dwfl->segment_align : align ?: 1;
+
+              GElf_Addr vaddr_end = (vaddr + memsz + align - 1) & -align;
+              GElf_Addr filesz_vaddr = filesz < memsz ? vaddr + filesz : vaddr_end;
+              GElf_Off filesz_offset = filesz_vaddr - vaddr + offset;
+
+              if (file_trimmed_end < offset + filesz)
+                {
+                  file_trimmed_end = offset + filesz;
+
+                  /* Trim the last segment so we don't bother with zeros
+                     in the last page that are off the end of the file.
+                     However, if the extra bit in that page includes the
+                     section headers, keep them.  */
+                  if (shdrs_end <= filesz_offset && shdrs_end > file_trimmed_end)
+                    {
+                      filesz += shdrs_end - file_trimmed_end;
+                      file_trimmed_end = shdrs_end;
+                    }
+                }
+
+              total_filesz += filesz;
+
+              if (file_end < filesz_offset)
+                {
+                  file_end = filesz_offset;
+                  if (filesz_vaddr - start == filesz_offset)
+                    contiguous = file_end;
+                }
+
+              if (!found_bias && (offset & -align) == 0
+                  && likely (filesz_offset >= phoff + phnum * phentsize))
+                {
+                  bias = start - vaddr;
+                  found_bias = true;
+                }
+
+              if ((vaddr & -align) < module_start)
+                {
+                  module_start = vaddr & -align;
+                  module_address_sync = vaddr + memsz;
+                }
+
+              if (module_end < vaddr_end)
+                module_end = vaddr_end;
+            }
         }
     }
 
-- 
2.26.2


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 14/14] segment_report_module: Inline consider_phdr() into only caller
  2020-11-12 15:04 ` [PATCH 14/14] segment_report_module: Inline consider_phdr() " Timm Bäder
@ 2020-11-12 16:52   ` Navin P
  2020-11-13  7:41     ` Timm Bäder
  0 siblings, 1 reply; 25+ messages in thread
From: Navin P @ 2020-11-12 16:52 UTC (permalink / raw)
  To: Timm Bäder; +Cc: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 8486 bytes --]

Hi,
 I already have a patch that makes elfutils compile with clang. Since
you are working
this will be of use to you. I've attached the patch since it is big.

 Here are some of the changes
 1. All functions at file scope have static qualifier so that no
collison with other files.
 2. Non global variables declared in the outer function should be
passed as pointer variable
    in the new outer file scope function whenever they are assigned in
the nested  function. The
    argument  addition in new functions are at the end.

3.  With the applied patch above , gcc passes all 220 tests where
clang fails 3 tests which
   is due to llvm_addrsig (change in libelf/elf.h ) and other 2 tests
are error related to
.rela.eh_frame.

clang test suite
=========
# TOTAL: 222
# PASS:  217
# SKIP:  2
# XFAIL: 0
# FAIL:  3
# XPASS: 0
# ERROR: 0

On Thu, Nov 12, 2020 at 8:36 PM Timm Bäder via Elfutils-devel
<elfutils-devel@sourceware.org> wrote:
>
> Get rid of the nested function this way
>
> Signed-off-by: Timm Bäder <tbaeder@redhat.com>
> ---
>  libdwfl/dwfl_segment_report_module.c | 142 +++++++++++++--------------
>  1 file changed, 66 insertions(+), 76 deletions(-)
>
> diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c
> index 0679453e..f93c60e2 100644
> --- a/libdwfl/dwfl_segment_report_module.c
> +++ b/libdwfl/dwfl_segment_report_module.c
> @@ -475,7 +475,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
>        /* NOTE if the number of sections is > 0xff00 then e_shnum
>          is zero and the actual number would come from the section
>          zero sh_size field. We ignore this here because getting shdrs
> -        is just a nice bonus (see below in consider_phdr PT_LOAD
> +        is just a nice bonus (see below in the type == PT_LOAD case
>          where we trim the last segment).  */
>        shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * ehdr.e32.e_shentsize;
>        break;
> @@ -561,80 +561,6 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
>    build_id.len = 0;
>    build_id.vaddr =0;
>
> -  /* Consider each of the program headers we've read from the image.  */
> -  inline void consider_phdr (GElf_Word type,
> -                            GElf_Addr vaddr, GElf_Xword memsz,
> -                            GElf_Off offset, GElf_Xword filesz,
> -                            GElf_Xword align)
> -  {
> -    switch (type)
> -      {
> -      case PT_DYNAMIC:
> -       dyn_vaddr = vaddr;
> -       dyn_filesz = filesz;
> -       break;
> -
> -      case PT_NOTE:
> -          /* We calculate from the p_offset of the note segment,
> -           because we don't yet know the bias for its p_vaddr.  */
> -          consider_notes (dwfl, memory_callback, memory_callback_arg,
> -                          start + offset, filesz, align,
> -                          buffer, buffer_available, start, segment,
> -                          ei_data, &build_id,
> -                          &xlatefrom, &xlateto,
> -                          ehdr.e32.e_ident[EI_DATA]);
> -       break;
> -
> -      case PT_LOAD:
> -       align = dwfl->segment_align > 1 ? dwfl->segment_align : align ?: 1;
> -
> -       GElf_Addr vaddr_end = (vaddr + memsz + align - 1) & -align;
> -       GElf_Addr filesz_vaddr = filesz < memsz ? vaddr + filesz : vaddr_end;
> -       GElf_Off filesz_offset = filesz_vaddr - vaddr + offset;
> -
> -       if (file_trimmed_end < offset + filesz)
> -         {
> -           file_trimmed_end = offset + filesz;
> -
> -           /* Trim the last segment so we don't bother with zeros
> -              in the last page that are off the end of the file.
> -              However, if the extra bit in that page includes the
> -              section headers, keep them.  */
> -           if (shdrs_end <= filesz_offset && shdrs_end > file_trimmed_end)
> -             {
> -               filesz += shdrs_end - file_trimmed_end;
> -               file_trimmed_end = shdrs_end;
> -             }
> -         }
> -
> -       total_filesz += filesz;
> -
> -       if (file_end < filesz_offset)
> -         {
> -           file_end = filesz_offset;
> -           if (filesz_vaddr - start == filesz_offset)
> -             contiguous = file_end;
> -         }
> -
> -       if (!found_bias && (offset & -align) == 0
> -           && likely (filesz_offset >= phoff + phnum * phentsize))
> -         {
> -           bias = start - vaddr;
> -           found_bias = true;
> -         }
> -
> -       if ((vaddr & -align) < module_start)
> -         {
> -           module_start = vaddr & -align;
> -           module_address_sync = vaddr + memsz;
> -         }
> -
> -       if (module_end < vaddr_end)
> -         module_end = vaddr_end;
> -       break;
> -      }
> -  }
> -
>    Elf32_Phdr *p32 = phdrsp;
>    Elf64_Phdr *p64 = phdrsp;
>    if ((ei_class == ELFCLASS32 &&
> @@ -646,6 +572,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
>      }
>    else
>      {
> +      /* Consider each of the program headers we've read from the image.  */
>        for (uint_fast16_t i = 0; i < phnum; ++i)
>          {
>            bool is32 = (ei_class == ELFCLASS32);
> @@ -656,7 +583,70 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
>            GElf_Xword filesz = is32 ? p32[i].p_filesz : p64[i].p_filesz;
>            GElf_Xword align = is32 ? p32[i].p_align : p64[i].p_align;
>
> -          consider_phdr (type, vaddr, memsz, offset, filesz, align);
> +          if (type == PT_DYNAMIC)
> +            {
> +              dyn_vaddr = vaddr;
> +              dyn_filesz = filesz;
> +            }
> +          else if (type == PT_NOTE)
> +            {
> +              /* We calculate from the p_offset of the note segment,
> +               because we don't yet know the bias for its p_vaddr.  */
> +              consider_notes (dwfl, memory_callback, memory_callback_arg,
> +                              start + offset, filesz, align,
> +                              buffer, buffer_available, start, segment,
> +                              ei_data, &build_id,
> +                              &xlatefrom, &xlateto,
> +                              ehdr.e32.e_ident[EI_DATA]);
> +            }
> +          else if (type == PT_LOAD)
> +            {
> +              align = dwfl->segment_align > 1 ? dwfl->segment_align : align ?: 1;
> +
> +              GElf_Addr vaddr_end = (vaddr + memsz + align - 1) & -align;
> +              GElf_Addr filesz_vaddr = filesz < memsz ? vaddr + filesz : vaddr_end;
> +              GElf_Off filesz_offset = filesz_vaddr - vaddr + offset;
> +
> +              if (file_trimmed_end < offset + filesz)
> +                {
> +                  file_trimmed_end = offset + filesz;
> +
> +                  /* Trim the last segment so we don't bother with zeros
> +                     in the last page that are off the end of the file.
> +                     However, if the extra bit in that page includes the
> +                     section headers, keep them.  */
> +                  if (shdrs_end <= filesz_offset && shdrs_end > file_trimmed_end)
> +                    {
> +                      filesz += shdrs_end - file_trimmed_end;
> +                      file_trimmed_end = shdrs_end;
> +                    }
> +                }
> +
> +              total_filesz += filesz;
> +
> +              if (file_end < filesz_offset)
> +                {
> +                  file_end = filesz_offset;
> +                  if (filesz_vaddr - start == filesz_offset)
> +                    contiguous = file_end;
> +                }
> +
> +              if (!found_bias && (offset & -align) == 0
> +                  && likely (filesz_offset >= phoff + phnum * phentsize))
> +                {
> +                  bias = start - vaddr;
> +                  found_bias = true;
> +                }
> +
> +              if ((vaddr & -align) < module_start)
> +                {
> +                  module_start = vaddr & -align;
> +                  module_address_sync = vaddr + memsz;
> +                }
> +
> +              if (module_end < vaddr_end)
> +                module_end = vaddr_end;
> +            }
>          }
>      }
>
> --
> 2.26.2
>

[-- Attachment #2: 0001-Make-elfutils-compile-with-clang.patch --]
[-- Type: text/x-patch, Size: 141806 bytes --]

From 934a437c9a607c25bfa5ee6e678ca9b74d7f9ff6 Mon Sep 17 00:00:00 2001
From: Navin P <navinp0304@gmail.com>
Date: Thu, 12 Nov 2020 22:12:36 +0530
Subject: [PATCH] Make elfutils compile with clang

Signed-off-by: Navin P <navinp0304@gmail.com>
---
 backends/Makefile.am                 |  10 +-
 config/eu.am                         |  33 +-
 configure.ac                         |  15 +-
 debuginfod/debuginfod-client.c       |   4 +-
 libasm/asm_newscn.c                  |   6 +-
 libdwfl/dwfl_segment_report_module.c | 713 ++++++++++++++++-----------
 libdwfl/elf-from-memory.c            | 122 +++--
 libdwfl/link_map.c                   | 171 ++++---
 libelf/elf.h                         |   1 +
 src/addr2line.c                      |  43 +-
 src/ar.c                             |  31 +-
 src/arlib-argp.c                     |  13 +-
 src/elfcompress.c                    | 350 ++++++++-----
 src/elflint.c                        |  56 +--
 src/readelf.c                        | 152 +++---
 src/strip.c                          | 333 +++++++------
 src/unstrip.c                        | 150 +++---
 tests/elfstrmerge.c                  | 108 ++--
 tests/zstrptr.c                      |  44 +-
 19 files changed, 1385 insertions(+), 970 deletions(-)

diff --git a/backends/Makefile.am b/backends/Makefile.am
index 62916c9c..1e3cbffd 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -34,6 +34,8 @@ endif
 AM_CPPFLAGS += -I$(top_srcdir)/libebl -I$(top_srcdir)/libasm \
 	   -I$(top_srcdir)/libelf -I$(top_srcdir)/libdw
 
+
+
 noinst_LIBRARIES = libebl_backends.a libebl_backends_pic.a
 
 modules = i386 sh x86_64 ia64 alpha arm aarch64 sparc ppc ppc64 s390 \
@@ -80,12 +82,7 @@ s390_SRCS = s390_init.c s390_symbol.c s390_regs.c s390_retval.c \
 m68k_SRCS = m68k_init.c m68k_symbol.c m68k_regs.c \
 	    m68k_retval.c m68k_corenote.c m68k_cfi.c m68k_initreg.c
 
-# m68k prstatus core notes are described by a packed structure
-# which has not naturally aligned fields. Since we don't access
-# these fields directly, but take their offset to be used later
-# to extract the data through elfxx_xlatetom/memmove, this isn't
-# an issue.
-m68k_corenote_no_Wpacked_not_aligned = yes
+
 
 bpf_SRCS = bpf_init.c bpf_regs.c bpf_symbol.c
 
@@ -108,3 +105,4 @@ noinst_HEADERS = libebl_CPU.h common-reloc.c linux-core-note.c x86_corenote.c
 EXTRA_DIST = $(modules:=_reloc.def)
 
 MOSTLYCLEANFILES = $(am_libebl_backends_pic_a_OBJECTS)
+
diff --git a/config/eu.am b/config/eu.am
index 6c3c444f..0ed87125 100644
--- a/config/eu.am
+++ b/config/eu.am
@@ -29,6 +29,8 @@
 ## not, see <http://www.gnu.org/licenses/>.
 ##
 
+
+
 DEFS = -D_GNU_SOURCE -DHAVE_CONFIG_H -DLOCALEDIR='"${localedir}"'
 AM_CPPFLAGS = -I. -I$(srcdir) -I$(top_srcdir)/lib -I..
 
@@ -64,30 +66,51 @@ endif
 if HAVE_IMPLICIT_FALLTHROUGH_WARNING
 # Use strict fallthrough. Only __attribute__((fallthrough)) will prevent the
 # warning
-IMPLICIT_FALLTHROUGH_WARNING=-Wimplicit-fallthrough=5
+	if IS_CLANG_COMPILER
+	    IMPLICIT_FALLTHROUGH_WARNING=-Wimplicit-fallthrough
+	else
+	    IMPLICIT_FALLTHROUGH_WARNING=-Wimplicit-fallthrough=5
+	endif
 else
 IMPLICIT_FALLTHROUGH_WARNING=
 endif
 
+# m68k prstatus core notes are described by a packed structure
+# which has not naturally aligned fields. Since we don't access
+# these fields directly, but take their offset to be used later
+# to extract the data through elfxx_xlatetom/memmove, this isn't
+# an issue.
+# 
+
+if IS_CLANG_COMPILER
+    TRAMPOLINES_WARNING=
+    NO_XOR_USED_AS_POW=-Wno-xor-used-as-pow
+    m68k_corenote_no_Wpacked_not_aligned =
+else
+    TRAMPOLINES_WARNING=-Wtrampolines
+    NO_XOR_USED_AS_POW=
+    m68k_corenote_no_Wpacked_not_aligned = yes
+endif
+
 AM_CFLAGS = -std=gnu99 -Wall -Wshadow -Wformat=2 \
-	    -Wold-style-definition -Wstrict-prototypes -Wtrampolines \
+	    -Wold-style-definition -Wstrict-prototypes $(TRAMPOLINES_WARNING) \
 	    $(LOGICAL_OP_WARNING) $(DUPLICATED_COND_WARNING) \
 	    $(NULL_DEREFERENCE_WARNING) $(IMPLICIT_FALLTHROUGH_WARNING) \
 	    $(if $($(*F)_no_Werror),,-Werror) \
 	    $(if $($(*F)_no_Wunused),,-Wunused -Wextra) \
 	    $(if $($(*F)_no_Wstack_usage),,$(STACK_USAGE_WARNING)) \
 	    $(if $($(*F)_no_Wpacked_not_aligned),-Wno-packed-not-aligned,) \
-	    $($(*F)_CFLAGS)
+	    $($(*F)_CFLAGS) $(NO_XOR_USED_AS_POW)
 
 AM_CXXFLAGS = -std=c++11 -Wall -Wshadow \
-	   -Wtrampolines \
+	   $(TRAMPOLINES_WARNING) \
 	   $(LOGICAL_OP_WARNING) $(DUPLICATED_COND_WARNING) \
 	   $(NULL_DEREFERENCE_WARNING) $(IMPLICIT_FALLTHROUGH_WARNING) \
 	   $(if $($(*F)_no_Werror),,-Werror) \
 	   $(if $($(*F)_no_Wunused),,-Wunused -Wextra) \
 	   $(if $($(*F)_no_Wstack_usage),,$(STACK_USAGE_WARNING)) \
 	   $(if $($(*F)_no_Wpacked_not_aligned),-Wno-packed-not-aligned,) \
-	   $($(*F)_CXXFLAGS)
+	   $($(*F)_CXXFLAGS) $(NO_XOR_USED_AS_POW)
 
 COMPILE.os = $(filter-out -fprofile-arcs -ftest-coverage, $(COMPILE))
 
diff --git a/configure.ac b/configure.ac
index c1a6954d..eed93771 100644
--- a/configure.ac
+++ b/configure.ac
@@ -95,6 +95,16 @@ AM_PROG_LEX
 m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
 AC_CHECK_TOOL([READELF], [readelf])
 AC_CHECK_TOOL([NM], [nm])
+AS_CASE([$CC],[*clang*|*clang++*],
+       [is_clang_compiler=yes],
+       [is_clang_compiler=no]
+)
+
+AM_CONDITIONAL([IS_CLANG_COMPILER],[ test x$is_clang_compiler = xyes])
+if test "$is_clang_compiler" = "no"; then
+AC_DEFINE([NOT_CLANG_COMPILER],[1],[Not a clang compiler])
+fi
+
 
 # We use -std=gnu99 but have explicit checks for some language constructs
 # and GNU extensions since some compilers claim GNU99 support, but don't
@@ -114,6 +124,7 @@ int foo (int a)
   for (int i = 0; i < a; ++i) if (i % 4) break; int s = a; return s;
 }
 
+#ifdef NOT_CLANG_COMPILER
 double bar (double a, double b)
 {
   double square (double z) { return z * z; }
@@ -123,7 +134,9 @@ double bar (double a, double b)
 void baz (int n)
 {
   struct S { int x[[n]]; };
-}])],
+} 
+#endif
+])],
 		  ac_cv_c99=yes, ac_cv_c99=no)
 CFLAGS="$old_CFLAGS"])
 AS_IF([test "x$ac_cv_c99" != xyes],
diff --git a/debuginfod/debuginfod-client.c b/debuginfod/debuginfod-client.c
index ce1d819b..4bbca2a2 100644
--- a/debuginfod/debuginfod-client.c
+++ b/debuginfod/debuginfod-client.c
@@ -819,7 +819,7 @@ debuginfod_query_server (debuginfod_client *c,
               if (curl_res == 0 && dl >= 0)
                 pa = (dl > LONG_MAX ? LONG_MAX : (long)dl);
 #else
-              double dl;
+              long double dl;
               curl_res = curl_easy_getinfo(target_handle,
                                            CURLINFO_SIZE_DOWNLOAD,
                                            &dl);
@@ -837,7 +837,7 @@ debuginfod_query_server (debuginfod_client *c,
               if (curl_res == 0 && cl >= 0)
                 pb = (cl > LONG_MAX ? LONG_MAX : (long)cl);
 #else
-              double cl;
+              long double cl;
               curl_res = curl_easy_getinfo(target_handle,
                                            CURLINFO_CONTENT_LENGTH_DOWNLOAD,
                                            &cl);
diff --git a/libasm/asm_newscn.c b/libasm/asm_newscn.c
index 7cdf484f..778a1e59 100644
--- a/libasm/asm_newscn.c
+++ b/libasm/asm_newscn.c
@@ -46,15 +46,15 @@
    dirty tricks here.  */
 static const struct
 {
-  struct FillPattern pattern;
   char zero;
+  struct FillPattern pattern;
 } xdefault_pattern =
   {
+    .zero = '\0',
     .pattern =
     {
       .len = 1
-    },
-    .zero = '\0'
+    }
   };
 const struct FillPattern *__libasm_default_pattern = &xdefault_pattern.pattern;
 
diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c
index 430e13d5..85ac107c 100644
--- a/libdwfl/dwfl_segment_report_module.c
+++ b/libdwfl/dwfl_segment_report_module.c
@@ -232,60 +232,34 @@ invalid_elf (Elf *elf, bool disk_file_has_build_id,
   return false;
 }
 
-int
-dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
-			    Dwfl_Memory_Callback *memory_callback,
-			    void *memory_callback_arg,
-			    Dwfl_Module_Callback *read_eagerly,
-			    void *read_eagerly_arg,
-			    const void *note_file, size_t note_file_size,
-			    const struct r_debug_info *r_debug_info)
-{
-  size_t segment = ndx;
-
-  if (segment >= dwfl->lookup_elts)
-    segment = dwfl->lookup_elts - 1;
-
-  while (segment > 0
-	 && (dwfl->lookup_segndx[segment] > ndx
-	     || dwfl->lookup_segndx[segment] == -1))
-    --segment;
-
-  while (dwfl->lookup_segndx[segment] < ndx)
-    if (++segment == dwfl->lookup_elts)
-      return 0;
-
-  GElf_Addr start = dwfl->lookup_addr[segment];
-
-  inline bool segment_read (int segndx,
+inline static bool segment_read (int segndx,
 			    void **buffer, size_t *buffer_available,
-			    GElf_Addr addr, size_t minread)
+			    GElf_Addr addr, size_t minread,
+			    Dwfl *dwfl, Dwfl_Memory_Callback *memory_callback,
+			    void *memory_callback_arg)
   {
     return ! (*memory_callback) (dwfl, segndx, buffer, buffer_available,
 				 addr, minread, memory_callback_arg);
   }
 
-  inline void release_buffer (void **buffer, size_t *buffer_available)
+  inline static void release_buffer (void **buffer, size_t *buffer_available,
+			    Dwfl *dwfl, Dwfl_Memory_Callback *memory_callback,
+			    void *memory_callback_arg)
   {
     if (*buffer != NULL)
-      (void) segment_read (-1, buffer, buffer_available, 0, 0);
+      (void) segment_read (-1, buffer, buffer_available, 0, 0,dwfl,
+		      		memory_callback,memory_callback_arg);
   }
 
-  /* First read in the file header and check its sanity.  */
-
-  void *buffer = NULL;
-  size_t buffer_available = INITIAL_READ;
-  Elf *elf = NULL;
-  int fd = -1;
-
-  /* We might have to reserve some memory for the phdrs.  Set to NULL
-     here so we can always safely free it.  */
-  void *phdrsp = NULL;
-
-  inline int finish (void)
+  inline static int finish (void *phdrsp,Elf *elf,
+		     void **buffer,size_t *buffer_available,
+		     int fd,int ndx,
+		     Dwfl *dwfl, Dwfl_Memory_Callback *memory_callback,
+		     void *memory_callback_arg)
   {
     free (phdrsp);
-    release_buffer (&buffer, &buffer_available);
+    release_buffer (buffer, buffer_available,dwfl,memory_callback,
+		    memory_callback_arg);
     if (elf != NULL)
       elf_end (elf);
     if (fd != -1)
@@ -293,51 +267,358 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
     return ndx;
   }
 
-  if (segment_read (ndx, &buffer, &buffer_available,
-		    start, sizeof (Elf64_Ehdr))
-      || memcmp (buffer, ELFMAG, SELFMAG) != 0)
-    return finish ();
+ inline static bool read_portion (void **data, size_t *data_size,
+			    GElf_Addr vaddr, size_t filesz,
+			    size_t *buffer_available,GElf_Addr start,
+			    void **buffer,size_t segment, Dwfl *dwfl, 
+			    Dwfl_Memory_Callback *memory_callback,
+		     	    void *memory_callback_arg)
 
-  inline bool read_portion (void **data, size_t *data_size,
-			    GElf_Addr vaddr, size_t filesz)
   {
     /* Check whether we will have to read the segment data, or if it
        can be returned from the existing buffer.  */
-    if (filesz > buffer_available
-	|| vaddr - start > buffer_available - filesz
+    if (filesz > *buffer_available
+	|| vaddr - start > *buffer_available - filesz
 	/* If we're in string mode, then don't consider the buffer we have
 	   sufficient unless it contains the terminator of the string.  */
-	|| (filesz == 0 && memchr (vaddr - start + buffer, '\0',
-				   buffer_available - (vaddr - start)) == NULL))
+	|| (filesz == 0 && memchr (vaddr - start + *buffer, '\0',
+				   *buffer_available - (vaddr - start)) == NULL))
       {
 	*data = NULL;
 	*data_size = filesz;
 	return segment_read (addr_segndx (dwfl, segment, vaddr, false),
-			     data, data_size, vaddr, filesz);
+			     data, data_size, vaddr, filesz,dwfl,memory_callback,
+			     memory_callback_arg);
       }
 
     /* We already have this whole note segment from our initial read.  */
-    *data = vaddr - start + buffer;
+    *data = vaddr - start + *buffer;
     *data_size = 0;
     return false;
   }
 
-  inline void finish_portion (void **data, size_t *data_size)
+
+  inline static void finish_portion (void **data, size_t *data_size,
+		  	Dwfl *dwfl, Dwfl_Memory_Callback *memory_callback,
+			    void *memory_callback_arg)
+
   {
     if (*data_size != 0)
-      release_buffer (data, data_size);
+      release_buffer (data, data_size,dwfl,memory_callback,memory_callback_arg);
   }
 
+union
+  {
+    Elf32_Ehdr e32;
+    Elf64_Ehdr e64;
+  } ehdr;
+  
+
+
+  /* Consider a PT_NOTE we've found in the image.  */
+  inline static void consider_notes (GElf_Addr vaddr, GElf_Xword *filesz,
+			      GElf_Xword align,void **build_id,
+			      size_t *buffer_available,GElf_Addr start,
+			      void **buffer,size_t segment,
+			      Dwfl *dwfl,
+			      Dwfl_Memory_Callback *memory_callback,
+			      void *memory_callback_arg,
+			      unsigned char ei_data,Elf_Data *xlatefrom,
+			      Elf_Data *xlateto,size_t *build_id_len,
+			      GElf_Addr *build_id_vaddr
+			      )
+  {
+    /* If we have already seen a build ID, we don't care any more.  */
+    if ((*build_id) != NULL || *filesz == 0)
+      return;
+
+    void *data;
+    size_t data_size;
+    if (read_portion (&data, &data_size, vaddr, *filesz,
+		    buffer_available,start,buffer,segment,dwfl,
+		    memory_callback,memory_callback_arg))
+      return;
+
+    /* data_size will be zero if we got everything from the initial
+       buffer, otherwise it will be the size of the new buffer that
+       could be read.  */
+    if (data_size != 0)
+      *filesz = data_size;
+
+    assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr));
+
+    void *notes;
+    if (ei_data == MY_ELFDATA)
+      notes = data;
+    else
+      {
+	notes = malloc (*filesz);
+	if (unlikely (notes == NULL))
+	  return;
+	xlatefrom->d_type = xlateto->d_type = (align == 8
+					     ? ELF_T_NHDR8 : ELF_T_NHDR);
+	xlatefrom->d_buf = (void *) data;
+	xlatefrom->d_size = *filesz;
+	xlateto->d_buf = notes;
+	xlateto->d_size = *filesz;
+	if (elf32_xlatetom (xlateto, xlatefrom,
+			    ehdr.e32.e_ident[EI_DATA]) == NULL)
+	  goto done;
+      }
+
+    const GElf_Nhdr *nh = notes;
+    size_t len = 0;
+    while (*filesz > len + sizeof (*nh))
+      {
+	const void *note_name;
+	const void *note_desc;
+
+	len += sizeof (*nh);
+	note_name = notes + len;
+
+	len += nh->n_namesz;
+	len = align == 8 ? NOTE_ALIGN8 (len) : NOTE_ALIGN4 (len);
+	note_desc = notes + len;
+
+	if (unlikely (*filesz < len + nh->n_descsz))
+	  break;
+
+        if (nh->n_type == NT_GNU_BUILD_ID
+	    && nh->n_descsz > 0
+	    && nh->n_namesz == sizeof "GNU"
+	    && !memcmp (note_name, "GNU", sizeof "GNU"))
+	  {
+	    *build_id_vaddr = note_desc - (const void *) notes + vaddr;
+	    *build_id_len = nh->n_descsz;
+	    *build_id = malloc (nh->n_descsz);
+	    if (likely (*build_id != NULL))
+	      memcpy (*build_id, note_desc, *build_id_len);
+	    break;
+	  }
+
+	len += nh->n_descsz;
+	len = align == 8 ? NOTE_ALIGN8 (len) : NOTE_ALIGN4 (len);
+	nh = (void *) notes + len;
+      }
+
+  done:
+    if (notes != data)
+      free (notes);
+    finish_portion (&data, &data_size,dwfl,memory_callback,memory_callback_arg);
+  }
+
+
+/* Consider each of the program headers we've read from the image.  */
+//should have inline
+  inline static void consider_phdr (GElf_Word type,
+			     GElf_Addr vaddr, GElf_Xword memsz,
+			     GElf_Off offset, void *ptrfilesz,size_t ptrlen,
+			     GElf_Xword align, GElf_Addr *dyn_vaddr,
+			     GElf_Xword *dyn_filesz,GElf_Addr start, 
+			     Dwfl *dwfl, GElf_Off *file_trimmed_end,
+			     GElf_Off shdrs_end,GElf_Addr *module_start,
+			     GElf_Addr *module_end,
+			     GElf_Addr *module_address_sync,void **build_id,
+			     size_t *buffer_available,void **buffer,
+			     size_t segment,
+			     Dwfl_Memory_Callback *memory_callback,
+			     void *memory_callback_arg,unsigned char ei_data,
+			     Elf_Data *xlatefrom,Elf_Data *xlateto,
+			     size_t *build_id_len,GElf_Addr *build_id_vaddr,
+			     GElf_Off *total_filesz,GElf_Off *file_end,
+			     GElf_Off *contiguous , GElf_Off phoff, 
+			     uint_fast16_t phnum,uint_fast16_t phentsize,
+			     GElf_Addr *bias,bool *found_bias 
+			     )
+  {
+
+    unsigned long filesz = 0;
+    memcpy(&filesz,ptrfilesz,ptrlen);
+
+    switch (type)
+      {
+      case PT_DYNAMIC:
+	*dyn_vaddr = vaddr;
+	*dyn_filesz = filesz;
+	break;
+
+      case PT_NOTE:
+
+	/* We calculate from the p_offset of the note segment,
+	   because we don't yet know the bias for its p_vaddr.  */
+	consider_notes (start + offset, &filesz, align, build_id,
+			buffer_available,start,
+			buffer,segment,dwfl,
+			memory_callback,memory_callback_arg,ei_data,
+			xlatefrom,xlateto,build_id_len,build_id_vaddr);
+			
+	break;
+
+      case PT_LOAD:
+	align = dwfl->segment_align > 1 ? dwfl->segment_align : align ?: 1;
+
+	GElf_Addr vaddr_end = (vaddr + memsz + align - 1) & -align;
+	GElf_Addr filesz_vaddr = filesz < memsz ? vaddr + filesz : vaddr_end;
+	GElf_Off filesz_offset = filesz_vaddr - vaddr + offset;
+
+	if (*file_trimmed_end < offset + filesz)
+	  {
+	    *file_trimmed_end = offset + filesz;
+
+	    /* Trim the last segment so we don't bother with zeros
+	       in the last page that are off the end of the file.
+	       However, if the extra bit in that page includes the
+	       section headers, keep them.  */
+	    if (shdrs_end <= filesz_offset && shdrs_end > *file_trimmed_end)
+	      {
+		filesz += shdrs_end - *file_trimmed_end;
+		*file_trimmed_end = shdrs_end;
+	      }
+	  }
+
+	*total_filesz += filesz;
+
+	if (*file_end < filesz_offset)
+	  {
+	    *file_end = filesz_offset;
+	    if (filesz_vaddr - start == filesz_offset)
+	      *contiguous = *file_end;
+	  }
+
+	if (!*found_bias && (offset & -align) == 0
+	    && likely (filesz_offset >= phoff + phnum * phentsize))
+	  {
+	    *bias = start - vaddr;
+	    *found_bias = true;
+	  }
+
+	if ((vaddr & -align) < *module_start)
+	  {
+	    *module_start = vaddr & -align;
+	    *module_address_sync = vaddr + memsz;
+	  }
+
+	if (*module_end < vaddr_end)
+	  *module_end = vaddr_end;
+	break;
+      }
+    
+    memcpy(ptrfilesz,&filesz,ptrlen);
+  }
+
+
+inline static bool consider_dyn (GElf_Sxword tag, GElf_Xword val,
+		bool *execlike,GElf_Addr *soname_stroff,
+		GElf_Addr *dynstr_vaddr, GElf_Xword *dynstrsz)
+  {
+    switch (tag)
+      {
+      default:
+	return false;
+
+      case DT_DEBUG:
+	*execlike = true;
+	break;
+
+      case DT_SONAME:
+	*soname_stroff = val;
+	break;
+
+      case DT_STRTAB:
+	*dynstr_vaddr = val;
+	break;
+
+      case DT_STRSZ:
+	*dynstrsz = val;
+	break;
+      }
+
+    return *soname_stroff != 0 && *dynstr_vaddr != 0 && *dynstrsz != 0;
+  }
+
+inline static void final_read (size_t offset, GElf_Addr vaddr, size_t size,
+			void *contents,Dwfl *dwfl,size_t segment,
+			Dwfl_Memory_Callback *memory_callback,
+			void *memory_callback_arg)
+      {
+	void *into = contents + offset;
+	size_t read_size = size;
+	(void) segment_read (addr_segndx (dwfl, segment, vaddr, false),
+			     &into, &read_size, vaddr, size,dwfl,
+			     memory_callback,memory_callback_arg);
+
+      }
+
+
+	  /* We can't use the memory image verbatim as the file image.
+	     So we'll be reading into a local image of the virtual file.  */
+
+	  inline static void read_phdr (GElf_Word type, GElf_Addr vaddr,
+				 GElf_Off offset, GElf_Xword filesz,
+				 GElf_Addr bias,void *contents,Dwfl *dwfl,
+				 size_t segment,
+				 Dwfl_Memory_Callback *memory_callback,
+			         void *memory_callback_arg)
+	  {
+	    if (type == PT_LOAD)
+	      final_read (offset, vaddr + bias, filesz,contents,dwfl,
+			    segment,memory_callback,memory_callback_arg);
+	  }
+
+
+
+
+
+
+int
+dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
+			    Dwfl_Memory_Callback *memory_callback,
+			    void *memory_callback_arg,
+			    Dwfl_Module_Callback *read_eagerly,
+			    void *read_eagerly_arg,
+			    const void *note_file, size_t note_file_size,
+			    const struct r_debug_info *r_debug_info)
+{
+  size_t segment = ndx;
+
+  if (segment >= dwfl->lookup_elts)
+    segment = dwfl->lookup_elts - 1;
+
+  while (segment > 0
+	 && (dwfl->lookup_segndx[segment] > ndx
+	     || dwfl->lookup_segndx[segment] == -1))
+    --segment;
+
+  while (dwfl->lookup_segndx[segment] < ndx)
+    if (++segment == dwfl->lookup_elts)
+      return 0;
+
+  GElf_Addr start = dwfl->lookup_addr[segment];
+
+  /* First read in the file header and check its sanity.  */
+
+  void *buffer = NULL;
+  size_t buffer_available = INITIAL_READ;
+  Elf *elf = NULL;
+  int fd = -1;
+
+  /* We might have to reserve some memory for the phdrs.  Set to NULL
+     here so we can always safely free it.  */
+  void *phdrsp = NULL;
+
+  if (segment_read (ndx, &buffer, &buffer_available,start, sizeof (Elf64_Ehdr),
+			  dwfl,memory_callback,memory_callback_arg)
+      || memcmp (buffer, ELFMAG, SELFMAG) != 0)
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+		    memory_callback,memory_callback_arg);
+
+  
+ 
   /* Extract the information we need from the file header.  */
   const unsigned char *e_ident;
   unsigned char ei_class;
   unsigned char ei_data;
   uint16_t e_type;
-  union
-  {
-    Elf32_Ehdr e32;
-    Elf64_Ehdr e64;
-  } ehdr;
   GElf_Off phoff;
   uint_fast16_t phnum;
   uint_fast16_t phentsize;
@@ -363,13 +644,15 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
     case ELFCLASS32:
       xlatefrom.d_size = sizeof (Elf32_Ehdr);
       if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
-	return finish ();
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+		    memory_callback,memory_callback_arg);
       e_type = ehdr.e32.e_type;
       phoff = ehdr.e32.e_phoff;
       phnum = ehdr.e32.e_phnum;
       phentsize = ehdr.e32.e_phentsize;
       if (phentsize != sizeof (Elf32_Phdr))
-	return finish ();
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+		    memory_callback,memory_callback_arg);
       /* NOTE if the number of sections is > 0xff00 then e_shnum
 	 is zero and the actual number would come from the section
 	 zero sh_size field. We ignore this here because getting shdrs
@@ -381,19 +664,22 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
     case ELFCLASS64:
       xlatefrom.d_size = sizeof (Elf64_Ehdr);
       if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
-	return finish ();
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+		    memory_callback,memory_callback_arg);
       e_type = ehdr.e64.e_type;
       phoff = ehdr.e64.e_phoff;
       phnum = ehdr.e64.e_phnum;
       phentsize = ehdr.e64.e_phentsize;
       if (phentsize != sizeof (Elf64_Phdr))
-	return finish ();
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+		    memory_callback,memory_callback_arg);
       /* See the NOTE above for shdrs_end and ehdr.e32.e_shnum.  */
       shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * ehdr.e64.e_shentsize;
       break;
 
     default:
-      return finish ();
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+		    memory_callback,memory_callback_arg);
     }
 
   /* The file header tells where to find the program headers.
@@ -401,7 +687,8 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
      Without them, we don't have a module to report.  */
 
   if (phnum == 0)
-    return finish ();
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+		    memory_callback,memory_callback_arg);
 
   xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR;
   xlatefrom.d_size = phnum * phentsize;
@@ -409,8 +696,11 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
   void *ph_buffer = NULL;
   size_t ph_buffer_size = 0;
   if (read_portion (&ph_buffer, &ph_buffer_size,
-		    start + phoff, xlatefrom.d_size))
-    return finish ();
+		    start + phoff, xlatefrom.d_size,
+		    &buffer_available,start,&buffer,segment,dwfl,
+		    memory_callback,memory_callback_arg))
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+		    memory_callback,memory_callback_arg);
 
   /* ph_buffer_size will be zero if we got everything from the initial
      buffer, otherwise it will be the size of the new buffer that
@@ -423,11 +713,13 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
   bool class32 = ei_class == ELFCLASS32;
   size_t phdr_size = class32 ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr);
   if (unlikely (phnum > SIZE_MAX / phdr_size))
-    return finish ();
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+		    memory_callback,memory_callback_arg);
   const size_t phdrsp_bytes = phnum * phdr_size;
   phdrsp = malloc (phdrsp_bytes);
   if (unlikely (phdrsp == NULL))
-    return finish ();
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+		    memory_callback,memory_callback_arg);
 
   xlateto.d_buf = phdrsp;
   xlateto.d_size = phdrsp_bytes;
@@ -456,155 +748,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
   size_t build_id_len = 0;
   GElf_Addr build_id_vaddr = 0;
 
-  /* Consider a PT_NOTE we've found in the image.  */
-  inline void consider_notes (GElf_Addr vaddr, GElf_Xword filesz,
-			      GElf_Xword align)
-  {
-    /* If we have already seen a build ID, we don't care any more.  */
-    if (build_id != NULL || filesz == 0)
-      return;
-
-    void *data;
-    size_t data_size;
-    if (read_portion (&data, &data_size, vaddr, filesz))
-      return;
-
-    /* data_size will be zero if we got everything from the initial
-       buffer, otherwise it will be the size of the new buffer that
-       could be read.  */
-    if (data_size != 0)
-      filesz = data_size;
-
-    assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr));
-
-    void *notes;
-    if (ei_data == MY_ELFDATA)
-      notes = data;
-    else
-      {
-	notes = malloc (filesz);
-	if (unlikely (notes == NULL))
-	  return;
-	xlatefrom.d_type = xlateto.d_type = (align == 8
-					     ? ELF_T_NHDR8 : ELF_T_NHDR);
-	xlatefrom.d_buf = (void *) data;
-	xlatefrom.d_size = filesz;
-	xlateto.d_buf = notes;
-	xlateto.d_size = filesz;
-	if (elf32_xlatetom (&xlateto, &xlatefrom,
-			    ehdr.e32.e_ident[EI_DATA]) == NULL)
-	  goto done;
-      }
-
-    const GElf_Nhdr *nh = notes;
-    size_t len = 0;
-    while (filesz > len + sizeof (*nh))
-      {
-	const void *note_name;
-	const void *note_desc;
-
-	len += sizeof (*nh);
-	note_name = notes + len;
-
-	len += nh->n_namesz;
-	len = align == 8 ? NOTE_ALIGN8 (len) : NOTE_ALIGN4 (len);
-	note_desc = notes + len;
-
-	if (unlikely (filesz < len + nh->n_descsz))
-	  break;
-
-        if (nh->n_type == NT_GNU_BUILD_ID
-	    && nh->n_descsz > 0
-	    && nh->n_namesz == sizeof "GNU"
-	    && !memcmp (note_name, "GNU", sizeof "GNU"))
-	  {
-	    build_id_vaddr = note_desc - (const void *) notes + vaddr;
-	    build_id_len = nh->n_descsz;
-	    build_id = malloc (nh->n_descsz);
-	    if (likely (build_id != NULL))
-	      memcpy (build_id, note_desc, build_id_len);
-	    break;
-	  }
-
-	len += nh->n_descsz;
-	len = align == 8 ? NOTE_ALIGN8 (len) : NOTE_ALIGN4 (len);
-	nh = (void *) notes + len;
-      }
-
-  done:
-    if (notes != data)
-      free (notes);
-    finish_portion (&data, &data_size);
-  }
-
-  /* Consider each of the program headers we've read from the image.  */
-  inline void consider_phdr (GElf_Word type,
-			     GElf_Addr vaddr, GElf_Xword memsz,
-			     GElf_Off offset, GElf_Xword filesz,
-			     GElf_Xword align)
-  {
-    switch (type)
-      {
-      case PT_DYNAMIC:
-	dyn_vaddr = vaddr;
-	dyn_filesz = filesz;
-	break;
-
-      case PT_NOTE:
-	/* We calculate from the p_offset of the note segment,
-	   because we don't yet know the bias for its p_vaddr.  */
-	consider_notes (start + offset, filesz, align);
-	break;
-
-      case PT_LOAD:
-	align = dwfl->segment_align > 1 ? dwfl->segment_align : align ?: 1;
-
-	GElf_Addr vaddr_end = (vaddr + memsz + align - 1) & -align;
-	GElf_Addr filesz_vaddr = filesz < memsz ? vaddr + filesz : vaddr_end;
-	GElf_Off filesz_offset = filesz_vaddr - vaddr + offset;
-
-	if (file_trimmed_end < offset + filesz)
-	  {
-	    file_trimmed_end = offset + filesz;
-
-	    /* Trim the last segment so we don't bother with zeros
-	       in the last page that are off the end of the file.
-	       However, if the extra bit in that page includes the
-	       section headers, keep them.  */
-	    if (shdrs_end <= filesz_offset && shdrs_end > file_trimmed_end)
-	      {
-		filesz += shdrs_end - file_trimmed_end;
-		file_trimmed_end = shdrs_end;
-	      }
-	  }
-
-	total_filesz += filesz;
-
-	if (file_end < filesz_offset)
-	  {
-	    file_end = filesz_offset;
-	    if (filesz_vaddr - start == filesz_offset)
-	      contiguous = file_end;
-	  }
-
-	if (!found_bias && (offset & -align) == 0
-	    && likely (filesz_offset >= phoff + phnum * phentsize))
-	  {
-	    bias = start - vaddr;
-	    found_bias = true;
-	  }
-
-	if ((vaddr & -align) < module_start)
-	  {
-	    module_start = vaddr & -align;
-	    module_address_sync = vaddr + memsz;
-	  }
-
-	if (module_end < vaddr_end)
-	  module_end = vaddr_end;
-	break;
-      }
-  }
+  
 
   Elf32_Phdr (*p32)[phnum] = phdrsp;
   Elf64_Phdr (*p64)[phnum] = phdrsp;
@@ -616,8 +760,17 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 	for (uint_fast16_t i = 0; i < phnum; ++i)
 	  consider_phdr ((*p32)[i].p_type,
 			 (*p32)[i].p_vaddr, (*p32)[i].p_memsz,
-			 (*p32)[i].p_offset, (*p32)[i].p_filesz,
-			 (*p32)[i].p_align);
+			 (*p32)[i].p_offset, &((*p32)[i].p_filesz),
+			 sizeof((*p32)[i].p_filesz),
+			 (*p32)[i].p_align, &dyn_vaddr, &dyn_filesz,
+			 start,dwfl,&file_trimmed_end,
+			 shdrs_end,&module_start,&module_end,
+			 &module_address_sync,&build_id,&buffer_available,
+			 &buffer,segment,memory_callback,memory_callback_arg,
+			 ei_data,&xlatefrom,&xlateto,&build_id_len,
+			 &build_id_vaddr,&total_filesz,&file_end ,&contiguous,
+			 phoff,phnum,phentsize,&bias,&found_bias);
+
     }
   else
     {
@@ -627,18 +780,29 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 	for (uint_fast16_t i = 0; i < phnum; ++i)
 	  consider_phdr ((*p64)[i].p_type,
 			 (*p64)[i].p_vaddr, (*p64)[i].p_memsz,
-			 (*p64)[i].p_offset, (*p64)[i].p_filesz,
-			 (*p64)[i].p_align);
+			 (*p64)[i].p_offset, &((*p64)[i].p_filesz),
+			 sizeof((*p64)[i].p_filesz),
+			 (*p64)[i].p_align, &dyn_vaddr, &dyn_filesz,
+			 start,dwfl,&file_trimmed_end,
+			 shdrs_end,&module_start,&module_end,
+			 &module_address_sync,&build_id,&buffer_available,
+			 &buffer,segment,memory_callback,memory_callback_arg,
+			 ei_data,&xlatefrom,&xlateto,&build_id_len,
+			 &build_id_vaddr,&total_filesz,&file_end ,&contiguous,
+			 phoff,phnum,phentsize,&bias,&found_bias);
+
     }
 
-  finish_portion (&ph_buffer, &ph_buffer_size);
+  finish_portion (&ph_buffer, &ph_buffer_size,dwfl,memory_callback,
+		  memory_callback_arg);
 
   /* We must have seen the segment covering offset 0, or else the ELF
      header we read at START was not produced by these program headers.  */
   if (unlikely (!found_bias))
     {
       free (build_id);
-      return finish ();
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+		    memory_callback,memory_callback_arg);
     }
 
   /* Now we know enough to report a module for sure: its bounds.  */
@@ -709,7 +873,8 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
       if (skip_this_module)
 	{
 	  free (build_id);
-	  return finish ();
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+		    memory_callback,memory_callback_arg);
 	}
     }
 
@@ -755,39 +920,14 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
   GElf_Addr dynstr_vaddr = 0;
   GElf_Xword dynstrsz = 0;
   bool execlike = false;
-  inline bool consider_dyn (GElf_Sxword tag, GElf_Xword val)
-  {
-    switch (tag)
-      {
-      default:
-	return false;
-
-      case DT_DEBUG:
-	execlike = true;
-	break;
-
-      case DT_SONAME:
-	soname_stroff = val;
-	break;
-
-      case DT_STRTAB:
-	dynstr_vaddr = val;
-	break;
-
-      case DT_STRSZ:
-	dynstrsz = val;
-	break;
-      }
-
-    return soname_stroff != 0 && dynstr_vaddr != 0 && dynstrsz != 0;
-  }
-
   const size_t dyn_entsize = (ei_class == ELFCLASS32
 			      ? sizeof (Elf32_Dyn) : sizeof (Elf64_Dyn));
   void *dyn_data = NULL;
   size_t dyn_data_size = 0;
   if (dyn_filesz != 0 && dyn_filesz % dyn_entsize == 0
-      && ! read_portion (&dyn_data, &dyn_data_size, dyn_vaddr, dyn_filesz))
+      && ! read_portion (&dyn_data, &dyn_data_size, dyn_vaddr, dyn_filesz,
+	      &buffer_available,start,&buffer,segment,dwfl,memory_callback,
+	      memory_callback_arg))
     {
       /* dyn_data_size will be zero if we got everything from the initial
          buffer, otherwise it will be the size of the new buffer that
@@ -799,7 +939,8 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
       Elf32_Dyn (*d32)[dyn_filesz / sizeof (Elf32_Dyn)] = dyns;
       Elf64_Dyn (*d64)[dyn_filesz / sizeof (Elf64_Dyn)] = dyns;
       if (unlikely (dyns == NULL))
-	return finish ();
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+		    memory_callback,memory_callback_arg);
 
       xlatefrom.d_type = xlateto.d_type = ELF_T_DYN;
       xlatefrom.d_buf = (void *) dyn_data;
@@ -811,19 +952,24 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 	{
 	  if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL)
 	    for (size_t i = 0; i < dyn_filesz / sizeof (Elf32_Dyn); ++i)
-	      if (consider_dyn ((*d32)[i].d_tag, (*d32)[i].d_un.d_val))
+	      if (consider_dyn ((*d32)[i].d_tag, (*d32)[i].d_un.d_val,
+		                 &execlike,&soname_stroff,
+				 &dynstr_vaddr, &dynstrsz))
 		break;
 	}
       else
 	{
 	  if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL)
 	    for (size_t i = 0; i < dyn_filesz / sizeof (Elf64_Dyn); ++i)
-	      if (consider_dyn ((*d64)[i].d_tag, (*d64)[i].d_un.d_val))
+	      if (consider_dyn ((*d64)[i].d_tag, (*d64)[i].d_un.d_val,
+		                 &execlike,&soname_stroff,
+				 &dynstr_vaddr, &dynstrsz))
 		break;
 	}
       free (dyns);
     }
-  finish_portion (&dyn_data, &dyn_data_size);
+  finish_portion (&dyn_data, &dyn_data_size,dwfl,memory_callback,
+		  memory_callback_arg);
 
   /* We'll use the name passed in or a stupid default if not DT_SONAME.  */
   if (name == NULL)
@@ -856,7 +1002,10 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
       /* Try to get the DT_SONAME string.  */
       if (soname_stroff != 0 && soname_stroff + 1 < dynstrsz
 	  && ! read_portion (&soname, &soname_size,
-			     dynstr_vaddr + soname_stroff, 0))
+			     dynstr_vaddr + soname_stroff, 0,
+			     &buffer_available,start,&buffer,segment,
+			     dwfl,memory_callback,
+			     memory_callback_arg))
 	name = soname;
     }
 
@@ -884,12 +1033,14 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
   /* At this point we do not need BUILD_ID or NAME any more.
      They have been copied.  */
   free (build_id);
-  finish_portion (&soname, &soname_size);
+  finish_portion (&soname, &soname_size,dwfl,memory_callback,
+		  memory_callback_arg);
 
   if (unlikely (mod == NULL))
     {
       ndx = -1;
-      return finish ();
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+		    memory_callback,memory_callback_arg);
     }
 
   /* We have reported the module.  Now let the caller decide whether we
@@ -913,36 +1064,25 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 
       void *contents = calloc (1, file_trimmed_end);
       if (unlikely (contents == NULL))
-	return finish ();
-
-      inline void final_read (size_t offset, GElf_Addr vaddr, size_t size)
-      {
-	void *into = contents + offset;
-	size_t read_size = size;
-	(void) segment_read (addr_segndx (dwfl, segment, vaddr, false),
-			     &into, &read_size, vaddr, size);
-      }
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+		    memory_callback,memory_callback_arg);
 
-      if (contiguous < file_trimmed_end)
+            if (contiguous < file_trimmed_end)
 	{
-	  /* We can't use the memory image verbatim as the file image.
-	     So we'll be reading into a local image of the virtual file.  */
-
-	  inline void read_phdr (GElf_Word type, GElf_Addr vaddr,
-				 GElf_Off offset, GElf_Xword filesz)
-	  {
-	    if (type == PT_LOAD)
-	      final_read (offset, vaddr + bias, filesz);
-	  }
+	  
 
 	  if (ei_class == ELFCLASS32)
 	    for (uint_fast16_t i = 0; i < phnum; ++i)
 	      read_phdr ((*p32)[i].p_type, (*p32)[i].p_vaddr,
-			 (*p32)[i].p_offset, (*p32)[i].p_filesz);
+			 (*p32)[i].p_offset, (*p32)[i].p_filesz,
+			 bias,contents,dwfl,segment,memory_callback,
+			 memory_callback_arg);
 	  else
 	    for (uint_fast16_t i = 0; i < phnum; ++i)
 	      read_phdr ((*p64)[i].p_type, (*p64)[i].p_vaddr,
-			 (*p64)[i].p_offset, (*p64)[i].p_filesz);
+			 (*p64)[i].p_offset, (*p64)[i].p_filesz,
+			 bias,contents,dwfl,segment,memory_callback,
+			 memory_callback_arg);
 	}
       else
 	{
@@ -953,7 +1093,9 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 	  memcpy (contents, buffer, have);
 
 	  if (have < file_trimmed_end)
-	    final_read (have, start + have, file_trimmed_end - have);
+	    final_read (have, start + have, file_trimmed_end - have,
+			contents,dwfl,segment,
+			memory_callback,memory_callback_arg);
 	}
 
       elf = elf_memory (contents, file_trimmed_end);
@@ -975,5 +1117,6 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
       mod->main_bias = bias;
     }
 
-  return finish ();
+ return finish (phdrsp,elf,&buffer,&buffer_available,fd,ndx,dwfl,
+		    memory_callback,memory_callback_arg);
 }
diff --git a/libdwfl/elf-from-memory.c b/libdwfl/elf-from-memory.c
index c54c1b99..40aea896 100644
--- a/libdwfl/elf-from-memory.c
+++ b/libdwfl/elf-from-memory.c
@@ -38,6 +38,63 @@
 #include <stdlib.h>
 #include <string.h>
 
+/* Sanity checks segments and calculates segment_end,
+	 segments_end, segments_end_mem and loadbase (if not
+	 found_base yet).  Returns true if sanity checking failed,
+	 false otherwise.  */
+      inline static bool ehdr_memsz_handle_segment (GElf_Addr vaddr, GElf_Off offset,
+				  GElf_Xword filesz, GElf_Xword memsz,
+				  GElf_Xword pagesize, GElf_Addr ehdr_vma,
+				  size_t *contents_size,GElf_Addr *loadbase,
+				  bool *found_base,GElf_Off *segments_end,
+  				  GElf_Off *segments_end_mem)
+	{
+	  /* Sanity check the segment load aligns with the pagesize.  */
+	  if (((vaddr - offset) & (pagesize - 1)) != 0)
+	    return true;
+
+	  GElf_Off segment_end = ((offset + filesz + pagesize - 1)
+				  & -pagesize);
+
+	  if (segment_end > (GElf_Off) *contents_size)
+	    *contents_size = segment_end;
+
+	  if (!*found_base && (offset & -pagesize) == 0)
+	    {
+	      *loadbase = ehdr_vma - (vaddr & -pagesize);
+	      *found_base = true;
+	    }
+
+	  *segments_end = offset + filesz;
+	  *segments_end_mem = offset + memsz;
+	  return false;
+	}
+
+/* Reads the given segment.  Returns true if reading fails,
+	 false otherwise.  */
+      inline static bool ehdr_filesz_handle_segment (GElf_Addr vaddr, GElf_Off offset,
+				  GElf_Xword filesz,GElf_Xword pagesize,
+				  size_t contents_size, ssize_t *nread,
+				  unsigned char *buffer,GElf_Addr loadbase,
+				  ssize_t (*read_memory) (void *arg, void *data,
+						GElf_Addr address,
+						size_t minread,
+						size_t maxread),
+				  void *arg)
+		      
+	{
+	  GElf_Off start = offset & -pagesize;
+	  GElf_Off end = (offset + filesz + pagesize - 1) & -pagesize;
+	  if (end > (GElf_Off) contents_size)
+	    end = contents_size;
+	  *nread = (*read_memory) (arg, buffer + start,
+				  (loadbase + vaddr) & -pagesize,
+				  end - start, end - start);
+	  return *nread <= 0;
+	}
+
+
+
 /* Reconstruct an ELF file by reading the segments out of remote memory
    based on the ELF file header at EHDR_VMA and the ELF program headers it
    points to.  If not null, *LOADBASEP is filled in with the difference
@@ -225,42 +282,16 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
   Elf64_Phdr (*p64)[phnum] = phdrsp;
   switch (ehdr.e32.e_ident[EI_CLASS])
     {
-      /* Sanity checks segments and calculates segment_end,
-	 segments_end, segments_end_mem and loadbase (if not
-	 found_base yet).  Returns true if sanity checking failed,
-	 false otherwise.  */
-      inline bool handle_segment (GElf_Addr vaddr, GElf_Off offset,
-				  GElf_Xword filesz, GElf_Xword memsz)
-	{
-	  /* Sanity check the segment load aligns with the pagesize.  */
-	  if (((vaddr - offset) & (pagesize - 1)) != 0)
-	    return true;
-
-	  GElf_Off segment_end = ((offset + filesz + pagesize - 1)
-				  & -pagesize);
-
-	  if (segment_end > (GElf_Off) contents_size)
-	    contents_size = segment_end;
-
-	  if (!found_base && (offset & -pagesize) == 0)
-	    {
-	      loadbase = ehdr_vma - (vaddr & -pagesize);
-	      found_base = true;
-	    }
-
-	  segments_end = offset + filesz;
-	  segments_end_mem = offset + memsz;
-	  return false;
-	}
-
     case ELFCLASS32:
       if (elf32_xlatetom (&xlateto, &xlatefrom,
 			  ehdr.e32.e_ident[EI_DATA]) == NULL)
 	goto libelf_error;
       for (uint_fast16_t i = 0; i < phnum; ++i)
 	if ((*p32)[i].p_type == PT_LOAD)
-	  if (handle_segment ((*p32)[i].p_vaddr, (*p32)[i].p_offset,
-			      (*p32)[i].p_filesz, (*p32)[i].p_memsz))
+	  if (ehdr_memsz_handle_segment ((*p32)[i].p_vaddr, (*p32)[i].p_offset,
+			      (*p32)[i].p_filesz, (*p32)[i].p_memsz,pagesize,
+ 			      ehdr_vma,&contents_size, &loadbase,&found_base,
+			      &segments_end,&segments_end_mem))
 	    goto bad_elf;
       break;
 
@@ -270,8 +301,10 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
 	goto libelf_error;
       for (uint_fast16_t i = 0; i < phnum; ++i)
 	if ((*p64)[i].p_type == PT_LOAD)
-	  if (handle_segment ((*p64)[i].p_vaddr, (*p64)[i].p_offset,
-			      (*p64)[i].p_filesz, (*p64)[i].p_memsz))
+	  if (ehdr_memsz_handle_segment ((*p64)[i].p_vaddr, (*p64)[i].p_offset,
+			      (*p64)[i].p_filesz, (*p64)[i].p_memsz,pagesize,
+ 			      ehdr_vma,&contents_size, &loadbase,&found_base,
+			      &segments_end,&segments_end_mem))
 	    goto bad_elf;
       break;
 
@@ -307,26 +340,12 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
 
   switch (ehdr.e32.e_ident[EI_CLASS])
     {
-      /* Reads the given segment.  Returns true if reading fails,
-	 false otherwise.  */
-      inline bool handle_segment (GElf_Addr vaddr, GElf_Off offset,
-				  GElf_Xword filesz)
-	{
-	  GElf_Off start = offset & -pagesize;
-	  GElf_Off end = (offset + filesz + pagesize - 1) & -pagesize;
-	  if (end > (GElf_Off) contents_size)
-	    end = contents_size;
-	  nread = (*read_memory) (arg, buffer + start,
-				  (loadbase + vaddr) & -pagesize,
-				  end - start, end - start);
-	  return nread <= 0;
-	}
-
     case ELFCLASS32:
       for (uint_fast16_t i = 0; i < phnum; ++i)
 	if ((*p32)[i].p_type == PT_LOAD)
-	  if (handle_segment ((*p32)[i].p_vaddr, (*p32)[i].p_offset,
-			      (*p32)[i].p_filesz))
+	  if (ehdr_filesz_handle_segment ((*p32)[i].p_vaddr, (*p32)[i].p_offset,
+			      (*p32)[i].p_filesz,pagesize,contents_size,
+			  	&nread,buffer,loadbase,read_memory,arg))
 	    goto read_error;
 
       /* If the segments visible in memory didn't include the section
@@ -352,8 +371,9 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
     case ELFCLASS64:
       for (uint_fast16_t i = 0; i < phnum; ++i)
 	if ((*p64)[i].p_type == PT_LOAD)
-	  if (handle_segment ((*p64)[i].p_vaddr, (*p64)[i].p_offset,
-			      (*p64)[i].p_filesz))
+	  if (ehdr_filesz_handle_segment ((*p64)[i].p_vaddr, (*p64)[i].p_offset,
+			      (*p64)[i].p_filesz,pagesize,contents_size,
+			     &nread,buffer,loadbase,read_memory,arg))
 	    goto read_error;
 
       /* If the segments visible in memory didn't include the section
diff --git a/libdwfl/link_map.c b/libdwfl/link_map.c
index 29307c74..d7ca42ae 100644
--- a/libdwfl/link_map.c
+++ b/libdwfl/link_map.c
@@ -1,3 +1,4 @@
+
 /* Report modules by examining dynamic linker data structures.
    Copyright (C) 2008-2016 Red Hat, Inc.
    This file is part of elfutils.
@@ -224,61 +225,42 @@ addrsize (uint_fast8_t elfclass)
 {
   return elfclass * 4;
 }
-
-/* Report a module for each struct link_map in the linked list at r_map
-   in the struct r_debug at R_DEBUG_VADDR.  For r_debug_info description
-   see dwfl_link_map_report in libdwflP.h.  If R_DEBUG_INFO is not NULL then no
-   modules get added to DWFL, caller has to add them from filled in
-   R_DEBUG_INFO.
-
-   For each link_map entry, if an existing module resides at its address,
-   this just modifies that module's name and suggested file name.  If
-   no such module exists, this calls dwfl_report_elf on the l_name string.
-
-   Returns the number of modules found, or -1 for errors.  */
-
-static int
-report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
-		Dwfl *dwfl, GElf_Addr r_debug_vaddr,
-		Dwfl_Memory_Callback *memory_callback,
-		void *memory_callback_arg,
-		struct r_debug_info *r_debug_info)
-{
-  /* Skip r_version, to aligned r_map field.  */
-  GElf_Addr read_vaddr = r_debug_vaddr + addrsize (elfclass);
-
-  void *buffer = NULL;
-  size_t buffer_available = 0;
-  inline int release_buffer (int result)
+inline static int release_buffer (int result,void **buffer,size_t *buffer_available,
+		Dwfl *dwfl, Dwfl_Memory_Callback *memory_callback,
+		void *memory_callback_arg)
   {
     if (buffer != NULL)
-      (void) (*memory_callback) (dwfl, -1, &buffer, &buffer_available, 0, 0,
+      (void) (*memory_callback) (dwfl, -1, buffer, buffer_available, 0, 0,
 				 memory_callback_arg);
     return result;
   }
 
-  GElf_Addr addrs[4];
-  inline bool read_addrs (GElf_Addr vaddr, size_t n)
+  inline static bool read_addrs (GElf_Addr vaddr, size_t n,uint_fast8_t elfclass,
+		  void **buffer,GElf_Addr *read_vaddr,size_t *buffer_available,
+		  Dwfl *dwfl,Dwfl_Memory_Callback memory_callback, 
+		  void *memory_callback_arg,
+		  uint_fast8_t elfdata, GElf_Addr addrs[]
+		  )
   {
     size_t nb = n * addrsize (elfclass); /* Address words -> bytes to read.  */
 
     /* Read a new buffer if the old one doesn't cover these words.  */
-    if (buffer == NULL
-	|| vaddr < read_vaddr
-	|| vaddr - read_vaddr + nb > buffer_available)
+    if (*buffer == NULL
+	|| vaddr < *read_vaddr
+	|| vaddr - *read_vaddr + nb > *buffer_available)
       {
-	release_buffer (0);
+	release_buffer (0,buffer,buffer_available,dwfl,memory_callback,memory_callback_arg);
 
-	read_vaddr = vaddr;
+	*read_vaddr = vaddr;
 	int segndx = INTUSE(dwfl_addrsegment) (dwfl, vaddr, NULL);
 	if (unlikely (segndx < 0)
 	    || unlikely (! (*memory_callback) (dwfl, segndx,
-					       &buffer, &buffer_available,
+					       buffer, buffer_available,
 					       vaddr, nb, memory_callback_arg)))
 	  return true;
       }
 
-    Elf32_Addr (*a32)[n] = vaddr - read_vaddr + buffer;
+    Elf32_Addr (*a32)[n] = vaddr - *read_vaddr + *buffer;
     Elf64_Addr (*a64)[n] = (void *) a32;
 
     if (elfclass == ELFCLASS32)
@@ -303,8 +285,39 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
     return false;
   }
 
-  if (unlikely (read_addrs (read_vaddr, 1)))
-    return release_buffer (-1);
+
+/* Report a module for each struct link_map in the linked list at r_map
+   in the struct r_debug at R_DEBUG_VADDR.  For r_debug_info description
+   see dwfl_link_map_report in libdwflP.h.  If R_DEBUG_INFO is not NULL then no
+   modules get added to DWFL, caller has to add them from filled in
+   R_DEBUG_INFO.
+
+   For each link_map entry, if an existing module resides at its address,
+   this just modifies that module's name and suggested file name.  If
+   no such module exists, this calls dwfl_report_elf on the l_name string.
+
+   Returns the number of modules found, or -1 for errors.  */
+
+static int
+report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
+		Dwfl *dwfl, GElf_Addr r_debug_vaddr,
+		Dwfl_Memory_Callback *memory_callback,
+		void *memory_callback_arg,
+		struct r_debug_info *r_debug_info)
+{
+  /* Skip r_version, to aligned r_map field.  */
+  GElf_Addr read_vaddr = r_debug_vaddr + addrsize (elfclass);
+
+  void *buffer = NULL;
+  size_t buffer_available = 0;
+  GElf_Addr addrs[4];
+  if (unlikely (
+		  read_addrs(read_vaddr,1,elfclass,&buffer,&read_vaddr,
+		  &buffer_available,dwfl,memory_callback,memory_callback_arg,
+		   elfdata,addrs)
+		  )
+     )
+	return release_buffer (-1,&buffer,&buffer_available,dwfl,memory_callback,memory_callback_arg);
 
   GElf_Addr next = addrs[0];
 
@@ -317,9 +330,13 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
      there must be a loop in the pointers due to link_map clobberation.  */
   size_t iterations = 0;
   while (next != 0 && ++iterations < dwfl->lookup_elts)
-    {
-      if (read_addrs (next, 4))
-	return release_buffer (-1);
+  {
+      if (
+   	read_addrs(next,4,elfclass,&buffer,&read_vaddr,
+		  &buffer_available,dwfl,memory_callback,memory_callback_arg,
+		  elfdata,addrs)
+	      )
+		return release_buffer (-1,&buffer,&buffer_available,dwfl,memory_callback,memory_callback_arg);
 
       /* Unused: l_addr is the difference between the address in memory
          and the ELF file when the core was created. We need to
@@ -345,7 +362,7 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
 	name = l_name - read_vaddr + buffer;
       else
 	{
-	  release_buffer (0);
+	  release_buffer (0,&buffer,&buffer_available,dwfl,memory_callback,memory_callback_arg);
 	  read_vaddr = l_name;
 	  int segndx = INTUSE(dwfl_addrsegment) (dwfl, l_name, NULL);
 	  if (likely (segndx >= 0)
@@ -372,7 +389,7 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
 	  r_debug_info_module = malloc (sizeof (*r_debug_info_module)
 					+ strlen (name1) + 1);
 	  if (unlikely (r_debug_info_module == NULL))
-	    return release_buffer (result);
+	return        release_buffer (result,&buffer,&buffer_available,dwfl,memory_callback,memory_callback_arg);
 	  r_debug_info_module->fd = -1;
 	  r_debug_info_module->elf = NULL;
 	  r_debug_info_module->l_ld = l_ld;
@@ -413,7 +430,7 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
 		      GElf_Addr build_id_vaddr = (build_id_elfaddr
 						  - elf_dynamic_vaddr + l_ld);
 
-		      release_buffer (0);
+	  	      release_buffer (0,&buffer,&buffer_available,dwfl,memory_callback,memory_callback_arg);
 		      int segndx = INTUSE(dwfl_addrsegment) (dwfl,
 							     build_id_vaddr,
 							     NULL);
@@ -432,7 +449,7 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
 			    /* File has valid build-id which does not match
 			       the one in memory.  */
 			    valid = false;
-			  release_buffer (0);
+	  	      release_buffer (0,&buffer,&buffer_available,dwfl,memory_callback,memory_callback_arg);
 			}
 		    }
 
@@ -498,7 +515,7 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
 	}
     }
 
-  return release_buffer (result);
+	return  	      release_buffer (result,&buffer,&buffer_available,dwfl,memory_callback,memory_callback_arg);
 }
 \f
 static GElf_Addr
@@ -688,6 +705,34 @@ find_executable (Dwfl *dwfl, GElf_Addr at_phdr, GElf_Addr at_entry,
 }
 \f
 
+      inline static bool consider_phdr (GElf_Word type,
+				 GElf_Addr vaddr, GElf_Xword filesz,
+				 GElf_Addr *dyn_bias,Dwfl  *dwfl,
+				 GElf_Addr phdr, GElf_Addr *dyn_vaddr,
+				 GElf_Xword *dyn_filesz)
+      {
+	switch (type)
+	  {
+	  case PT_PHDR:
+	    if (*dyn_bias == (GElf_Addr) -1
+		/* Do a sanity check on the putative address.  */
+		&& ((vaddr & (dwfl->segment_align - 1))
+		    == (phdr & (dwfl->segment_align - 1))))
+	      {
+		*dyn_bias = phdr - vaddr;
+		return *dyn_vaddr != 0;
+	      }
+	    break;
+
+	  case PT_DYNAMIC:
+	    *dyn_vaddr = vaddr;
+	    *dyn_filesz = filesz;
+	    return *dyn_bias != (GElf_Addr) -1;
+	  }
+
+	return false;
+      }
+
 int
 dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
 		      Dwfl_Memory_Callback *memory_callback,
@@ -758,30 +803,6 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
       GElf_Xword dyn_filesz = 0;
       GElf_Addr dyn_bias = (GElf_Addr) -1;
 
-      inline bool consider_phdr (GElf_Word type,
-				 GElf_Addr vaddr, GElf_Xword filesz)
-      {
-	switch (type)
-	  {
-	  case PT_PHDR:
-	    if (dyn_bias == (GElf_Addr) -1
-		/* Do a sanity check on the putative address.  */
-		&& ((vaddr & (dwfl->segment_align - 1))
-		    == (phdr & (dwfl->segment_align - 1))))
-	      {
-		dyn_bias = phdr - vaddr;
-		return dyn_vaddr != 0;
-	      }
-	    break;
-
-	  case PT_DYNAMIC:
-	    dyn_vaddr = vaddr;
-	    dyn_filesz = filesz;
-	    return dyn_bias != (GElf_Addr) -1;
-	  }
-
-	return false;
-      }
 
       if (phdr != 0 && phnum != 0)
 	{
@@ -901,7 +922,10 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
 		      for (size_t i = 0; i < phnum; ++i)
 			if (consider_phdr ((*p32)[i].p_type,
 					   (*p32)[i].p_vaddr,
-					   (*p32)[i].p_filesz))
+					   (*p32)[i].p_filesz,
+					   &dyn_bias,dwfl,phdr,&dyn_vaddr,
+					   &dyn_filesz
+					   ))
 			  break;
 		    }
 		  else
@@ -909,7 +933,10 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
 		      for (size_t i = 0; i < phnum; ++i)
 			if (consider_phdr ((*p64)[i].p_type,
 					   (*p64)[i].p_vaddr,
-					   (*p64)[i].p_filesz))
+					   (*p64)[i].p_filesz,
+					   &dyn_bias,dwfl,phdr,&dyn_vaddr,
+					   &dyn_filesz
+					   ))
 			  break;
 		    }
 		}
diff --git a/libelf/elf.h b/libelf/elf.h
index 6439c1a4..26420b45 100644
--- a/libelf/elf.h
+++ b/libelf/elf.h
@@ -444,6 +444,7 @@ typedef struct
 #define SHT_SYMTAB_SHNDX  18		/* Extended section indeces */
 #define	SHT_NUM		  19		/* Number of defined types.  */
 #define SHT_LOOS	  0x60000000	/* Start OS-specific.  */
+#define SHT_LLVM_ADDRSIG  0x6FFF4C03    /* llvm address sig */
 #define SHT_GNU_ATTRIBUTES 0x6ffffff5	/* Object attributes.  */
 #define SHT_GNU_HASH	  0x6ffffff6	/* GNU-style hash table.  */
 #define SHT_GNU_LIBLIST	  0x6ffffff7	/* Prelink library list */
diff --git a/src/addr2line.c b/src/addr2line.c
index 69d8d995..038c8691 100644
--- a/src/addr2line.c
+++ b/src/addr2line.c
@@ -598,6 +598,21 @@ get_addr_width (Dwfl_Module *mod)
   return width;
 }
 
+inline static void show (int (*get) (Dwarf_Line *, bool *),
+	    const char *note,Dwarf_Line *info)
+{
+bool flag;
+if ((*get) (info, &flag) == 0 && flag)
+fputs (note, stdout);
+}
+inline static void show_int (int (*get) (Dwarf_Line *, unsigned int *),
+		const char *name,Dwarf_Line *info)
+{
+unsigned int val;
+if ((*get) (info, &val) == 0 && val != 0)
+printf (" (%s %u)", name, val);
+}
+
 static int
 handle_address (const char *string, Dwfl *dwfl)
 {
@@ -692,27 +707,13 @@ handle_address (const char *string, Dwfl *dwfl)
 	  Dwarf_Line *info = dwfl_dwarf_line (line, &bias);
 	  assert (info != NULL);
 
-	  inline void show (int (*get) (Dwarf_Line *, bool *),
-			    const char *note)
-	  {
-	    bool flag;
-	    if ((*get) (info, &flag) == 0 && flag)
-	      fputs (note, stdout);
-	  }
-	  inline void show_int (int (*get) (Dwarf_Line *, unsigned int *),
-				const char *name)
-	  {
-	    unsigned int val;
-	    if ((*get) (info, &val) == 0 && val != 0)
-	      printf (" (%s %u)", name, val);
-	  }
-
-	  show (&dwarf_linebeginstatement, " (is_stmt)");
-	  show (&dwarf_lineblock, " (basic_block)");
-	  show (&dwarf_lineprologueend, " (prologue_end)");
-	  show (&dwarf_lineepiloguebegin, " (epilogue_begin)");
-	  show_int (&dwarf_lineisa, "isa");
-	  show_int (&dwarf_linediscriminator, "discriminator");
+
+	  show (&dwarf_linebeginstatement, " (is_stmt)",info);
+	  show (&dwarf_lineblock, " (basic_block)",info);
+	  show (&dwarf_lineprologueend, " (prologue_end)",info);
+	  show (&dwarf_lineepiloguebegin, " (epilogue_begin)",info);
+	  show_int (&dwarf_lineisa, "isa",info);
+	  show_int (&dwarf_linediscriminator, "discriminator",info);
 	}
       putchar ('\n');
     }
diff --git a/src/ar.c b/src/ar.c
index 7d33d814..2beadffb 100644
--- a/src/ar.c
+++ b/src/ar.c
@@ -436,30 +436,31 @@ copy_content (Elf *elf, int newfd, off_t off, size_t n)
   return write_retry (newfd, rawfile + off, n) != (ssize_t) n;
 }
 
-
-static int
-do_oper_extract (int oper, const char *arfname, char **argv, int argc,
-		 long int instance)
-{
-  bool found[argc > 0 ? argc : 1];
-  memset (found, '\0', sizeof (found));
-
-  size_t name_max = 0;
-  inline bool should_truncate_fname (void)
+inline static bool should_truncate_fname (size_t *name_max)
   {
     if (errno == ENAMETOOLONG && allow_truncate_fname)
       {
-	if (name_max == 0)
+	if (*name_max == 0)
 	  {
 	    long int len = pathconf (".", _PC_NAME_MAX);
 	    if (len > 0)
-	      name_max = len;
+	      *name_max = len;
 	  }
-	return name_max != 0;
+	return *name_max != 0;
       }
     return false;
   }
 
+
+static int
+do_oper_extract (int oper, const char *arfname, char **argv, int argc,
+		 long int instance)
+{
+  bool found[argc > 0 ? argc : 1];
+  memset (found, '\0', sizeof (found));
+
+  size_t name_max = 0;
+  
   off_t index_off = -1;
   size_t index_size = 0;
   off_t cur_off = SARMAG;
@@ -615,7 +616,7 @@ do_oper_extract (int oper, const char *arfname, char **argv, int argc,
 		    {
 		      int printlen = INT_MAX;
 
-		      if (should_truncate_fname ())
+		      if (should_truncate_fname (&name_max))
 			{
 			  /* Try to truncate the name.  First find out by how
 			     much.  */
@@ -704,7 +705,7 @@ do_oper_extract (int oper, const char *arfname, char **argv, int argc,
 		    {
 		      int printlen = INT_MAX;
 
-		      if (should_truncate_fname ())
+		      if (should_truncate_fname (&name_max))
 			{
 			  /* Try to truncate the name.  First find out by how
 			     much.  */
diff --git a/src/arlib-argp.c b/src/arlib-argp.c
index 1bdd8d0b..8719ec10 100644
--- a/src/arlib-argp.c
+++ b/src/arlib-argp.c
@@ -56,10 +56,7 @@ parse_opt (int key, char *arg __attribute__ ((unused)),
   return 0;
 }
 
-static char *
-help_filter (int key, const char *text, void *input __attribute__ ((unused)))
-{
-  inline char *text_for_default (void)
+inline static char *text_for_default (const char *text)
   {
     char *new_text;
     if (unlikely (asprintf (&new_text, gettext ("%s (default)"), text) < 0))
@@ -67,15 +64,19 @@ help_filter (int key, const char *text, void *input __attribute__ ((unused)))
     return new_text;
   }
 
+static char *
+help_filter (int key, const char *text, void *input __attribute__ ((unused)))
+{
+  
   switch (key)
     {
     case 'D':
       if (DEFAULT_AR_DETERMINISTIC)
-        return text_for_default ();
+        return text_for_default (text);
       break;
     case 'U':
       if (! DEFAULT_AR_DETERMINISTIC)
-        return text_for_default ();
+        return text_for_default (text);
       break;
     }
 
diff --git a/src/elfcompress.c b/src/elfcompress.c
index 6ba6af41..0fa10299 100644
--- a/src/elfcompress.c
+++ b/src/elfcompress.c
@@ -242,52 +242,19 @@ compress_section (Elf_Scn *scn, size_t orig_size, const char *name,
   return res;
 }
 
-static int
-process_file (const char *fname)
-{
-  if (verbose > 0)
-    printf ("processing: %s\n", fname);
-
-  /* The input ELF.  */
-  int fd = -1;
-  Elf *elf = NULL;
-
-  /* The output ELF.  */
-  char *fnew = NULL;
-  int fdnew = -1;
-  Elf *elfnew = NULL;
-
-  /* Buffer for (one) new section name if necessary.  */
-  char *snamebuf = NULL;
-
-  /* String table (and symbol table), if section names need adjusting.  */
-  Dwelf_Strtab *names = NULL;
-  Dwelf_Strent **scnstrents = NULL;
-  Dwelf_Strent **symstrents = NULL;
-  char **scnnames = NULL;
-
-  /* Section data from names.  */
-  void *namesbuf = NULL;
-
-  /* Which sections match and need to be (un)compressed.  */
-  unsigned int *sections = NULL;
-
-  /* How many sections are we talking about?  */
-  size_t shnum = 0;
-
 #define WORD_BITS (8U * sizeof (unsigned int))
-  void set_section (size_t ndx)
+  static void set_section (size_t ndx,unsigned int *sections)
   {
     sections[ndx / WORD_BITS] |= (1U << (ndx % WORD_BITS));
   }
 
-  bool get_section (size_t ndx)
+  static bool get_section (size_t ndx,unsigned int *sections)
   {
     return (sections[ndx / WORD_BITS] & (1U << (ndx % WORD_BITS))) != 0;
   }
 
   /* How many sections are we going to change?  */
-  size_t get_sections (void)
+  static size_t get_sections (size_t shnum,unsigned int *sections)
   {
     size_t s = 0;
     for (size_t i = 0; i < shnum / WORD_BITS + 1; i++)
@@ -295,7 +262,10 @@ process_file (const char *fname)
     return s;
   }
 
-  int cleanup (int res)
+  static int cleanup (int res,Elf *elf,Elf *elfnew,int fd,int fdnew,char *fnew,
+  	char *snamebuf,Dwelf_Strtab *names,Dwelf_Strent **scnstrents,
+  	Dwelf_Strent **symstrents,char **scnnames,size_t shnum,void *namesbuf,
+	unsigned int *sections)
   {
     elf_end (elf);
     close (fd);
@@ -329,12 +299,46 @@ process_file (const char *fname)
 
     return res;
   }
+static int
+process_file (const char *fname)
+{
+  if (verbose > 0)
+    printf ("processing: %s\n", fname);
+
+  /* The input ELF.  */
+  int fd = -1;
+  Elf *elf = NULL;
+
+  /* The output ELF.  */
+  char *fnew = NULL;
+  int fdnew = -1;
+  Elf *elfnew = NULL;
+
+  /* Buffer for (one) new section name if necessary.  */
+  char *snamebuf = NULL;
+
+  /* String table (and symbol table), if section names need adjusting.  */
+  Dwelf_Strtab *names = NULL;
+  Dwelf_Strent **scnstrents = NULL;
+  Dwelf_Strent **symstrents = NULL;
+  char **scnnames = NULL;
+
+  /* Section data from names.  */
+  void *namesbuf = NULL;
+
+  /* Which sections match and need to be (un)compressed.  */
+  unsigned int *sections = NULL;
+
+  /* How many sections are we talking about?  */
+  size_t shnum = 0;
+
 
   fd = open (fname, O_RDONLY);
   if (fd < 0)
     {
       error (0, errno, "Couldn't open %s\n", fname);
-      return cleanup (-1);
+      return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,scnstrents,
+		      symstrents,scnnames,shnum,namesbuf,sections);
     }
 
   elf = elf_begin (fd, ELF_C_READ, NULL);
@@ -342,7 +346,8 @@ process_file (const char *fname)
     {
       error (0, 0, "Couldn't open ELF file %s for reading: %s",
 	     fname, elf_errmsg (-1));
-      return cleanup (-1);
+      return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,scnstrents,
+		      symstrents,scnnames,shnum,namesbuf,sections);
     }
 
   /* We dont' handle ar files (or anything else), we probably should.  */
@@ -353,21 +358,24 @@ process_file (const char *fname)
 	error (0, 0, "Cannot handle ar files: %s", fname);
       else
 	error (0, 0, "Unknown file type: %s", fname);
-      return cleanup (-1);
+      return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,scnstrents,
+		      symstrents,scnnames,shnum,namesbuf,sections);
     }
 
   struct stat st;
   if (fstat (fd, &st) != 0)
     {
       error (0, errno, "Couldn't fstat %s", fname);
-      return cleanup (-1);
+      return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,scnstrents,
+		      symstrents,scnnames,shnum,namesbuf,sections);
     }
 
   GElf_Ehdr ehdr;
   if (gelf_getehdr (elf, &ehdr) == NULL)
     {
       error (0, 0, "Couldn't get ehdr for %s: %s", fname, elf_errmsg (-1));
-      return cleanup (-1);
+      return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,scnstrents,
+		      symstrents,scnnames,shnum,namesbuf,sections);
     }
 
   /* Get the section header string table.  */
@@ -376,7 +384,8 @@ process_file (const char *fname)
     {
       error (0, 0, "Couldn't get section header string table index in %s: %s",
 	     fname, elf_errmsg (-1));
-      return cleanup (-1);
+      return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,scnstrents,
+		      symstrents,scnnames,shnum,namesbuf,sections);
     }
 
   /* How many sections are we talking about?  */
@@ -384,13 +393,15 @@ process_file (const char *fname)
     {
       error (0, 0, "Couldn't get number of sections in %s: %s",
 	     fname, elf_errmsg (1));
-      return cleanup (-1);
+      return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,scnstrents,
+		      symstrents,scnnames,shnum,namesbuf,sections);
     }
 
   if (shnum == 0)
     {
       error (0, 0, "ELF file %s has no sections", fname);
-      return cleanup (-1);
+      return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,scnstrents,
+		      symstrents,scnnames,shnum,namesbuf,sections);
     }
 
   sections = xcalloc (shnum / 8 + 1, sizeof (unsigned int));
@@ -398,8 +409,8 @@ process_file (const char *fname)
   size_t phnum;
   if (elf_getphdrnum (elf, &phnum) != 0)
     {
-      error (0, 0, "Couldn't get phdrnum: %s", elf_errmsg (-1));
-      return cleanup (-1);
+      return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,scnstrents,
+		      symstrents,scnnames,shnum,namesbuf,sections);
     }
 
   /* Whether we need to adjust any section names (going to/from GNU
@@ -456,7 +467,8 @@ process_file (const char *fname)
 	{
 	  error (0, 0, "Unexpected section number %zd, expected only %zd",
 		 ndx, shnum);
-	  cleanup (-1);
+          cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,scnstrents,
+		      symstrents,scnnames,shnum,namesbuf,sections);
 	}
 
       GElf_Shdr shdr_mem;
@@ -464,14 +476,18 @@ process_file (const char *fname)
       if (shdr == NULL)
 	{
 	  error (0, 0, "Couldn't get shdr for section %zd", ndx);
-	  return cleanup (-1);
+          return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+			  scnstrents,symstrents,scnnames,shnum,namesbuf,
+			  sections);
 	}
 
       const char *sname = elf_strptr (elf, shdrstrndx, shdr->sh_name);
       if (sname == NULL)
 	{
 	  error (0, 0, "Couldn't get name for section %zd", ndx);
-	  return cleanup (-1);
+          return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+			  scnstrents,symstrents,scnnames,shnum,namesbuf,
+			  sections);
 	}
 
       if (section_name_matches (sname))
@@ -498,7 +514,7 @@ process_file (const char *fname)
 	  else if (shdr->sh_type != SHT_NOBITS
 	      && (shdr->sh_flags & SHF_ALLOC) == 0)
 	    {
-	      set_section (ndx);
+	      set_section (ndx,sections);
 	      /* Check if we might want to change this section name.  */
 	      if (! adjust_names
 		  && ((type != T_COMPRESS_GNU
@@ -532,7 +548,9 @@ process_file (const char *fname)
 		{
 		  error (0, 0,
 			 "Multiple symbol tables (%zd, %zd) using the same string table unsupported", symtabndx, ndx);
-		  return cleanup (-1);
+                  return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+			  scnstrents,symstrents,scnnames,shnum,namesbuf,
+			  sections);
 		}
 	      symtabndx = ndx;
 	    }
@@ -549,12 +567,14 @@ process_file (const char *fname)
 	  }
     }
 
-  if (foutput == NULL && get_sections () == 0)
+  if (foutput == NULL && get_sections (shnum,sections) == 0)
     {
       if (verbose > 0)
 	printf ("Nothing to do.\n");
       fnew = NULL;
-      return cleanup (0);
+      return cleanup (0,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+			  scnstrents,symstrents,scnnames,shnum,namesbuf,
+			  sections);
     }
 
   if (adjust_names)
@@ -563,7 +583,9 @@ process_file (const char *fname)
       if (names == NULL)
 	{
 	  error (0, 0, "Not enough memory for new strtab");
-	  return cleanup (-1);
+          return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+			  scnstrents,symstrents,scnnames,shnum,namesbuf,
+			  sections);
 	}
       scnstrents = xmalloc (shnum
 			    * sizeof (Dwelf_Strent *));
@@ -590,7 +612,9 @@ process_file (const char *fname)
       /* Since we didn't create it we don't want to try to unlink it.  */
       free (fnew);
       fnew = NULL;
-      return cleanup (-1);
+      return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+			  scnstrents,symstrents,scnnames,shnum,namesbuf,
+			  sections);
     }
 
   elfnew = elf_begin (fdnew, ELF_C_WRITE, NULL);
@@ -598,21 +622,27 @@ process_file (const char *fname)
     {
       error (0, 0, "Couldn't open new ELF %s for writing: %s",
 	     fnew, elf_errmsg (-1));
-      return cleanup (-1);
+      return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+			  scnstrents,symstrents,scnnames,shnum,namesbuf,
+			  sections);
     }
 
   /* Create the new ELF header and copy over all the data.  */
   if (gelf_newehdr (elfnew, gelf_getclass (elf)) == 0)
     {
       error (0, 0, "Couldn't create new ehdr: %s", elf_errmsg (-1));
-      return cleanup (-1);
+      return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+			  scnstrents,symstrents,scnnames,shnum,namesbuf,
+			  sections);
     }
 
   GElf_Ehdr newehdr;
   if (gelf_getehdr (elfnew, &newehdr) == NULL)
     {
       error (0, 0, "Couldn't get new ehdr: %s", elf_errmsg (-1));
-      return cleanup (-1);
+      return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+			  scnstrents,symstrents,scnnames,shnum,namesbuf,
+			  sections);
     }
 
   newehdr.e_ident[EI_DATA] = ehdr.e_ident[EI_DATA];
@@ -625,7 +655,9 @@ process_file (const char *fname)
   if (gelf_update_ehdr (elfnew, &newehdr) == 0)
     {
       error (0, 0, "Couldn't update ehdr: %s", elf_errmsg (-1));
-      return cleanup (-1);
+      return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+			  scnstrents,symstrents,scnnames,shnum,namesbuf,
+			  sections);
     }
 
   /* Copy over the phdrs as is.  */
@@ -634,7 +666,9 @@ process_file (const char *fname)
       if (gelf_newphdr (elfnew, phnum) == 0)
 	{
 	  error (0, 0, "Couldn't create phdrs: %s", elf_errmsg (-1));
-	  return cleanup (-1);
+      	  return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+			  scnstrents,symstrents,scnnames,shnum,namesbuf,
+			  sections);
 	}
 
       for (size_t cnt = 0; cnt < phnum; ++cnt)
@@ -644,13 +678,17 @@ process_file (const char *fname)
 	  if (phdr == NULL)
 	    {
 	      error (0, 0, "Couldn't get phdr %zd: %s", cnt, elf_errmsg (-1));
-	      return cleanup (-1);
+      	      return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+			  scnstrents,symstrents,scnnames,shnum,namesbuf,
+			  sections);
 	    }
 	  if (gelf_update_phdr (elfnew, cnt, phdr) == 0)
 	    {
 	      error (0, 0, "Couldn't create phdr %zd: %s", cnt,
 		     elf_errmsg (-1));
-	      return cleanup (-1);
+      	      return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+			  scnstrents,symstrents,scnnames,shnum,namesbuf,
+			  sections);
 	    }
 	}
     }
@@ -687,14 +725,16 @@ process_file (const char *fname)
       /* (de)compress if section matched.  */
       char *sname = NULL;
       char *newname = NULL;
-      if (get_section (ndx))
+      if (get_section (ndx,sections))
 	{
 	  GElf_Shdr shdr_mem;
 	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
 	  if (shdr == NULL)
 	    {
 	      error (0, 0, "Couldn't get shdr for section %zd", ndx);
-	      return cleanup (-1);
+      	      return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+			  scnstrents,symstrents,scnnames,shnum,namesbuf,
+			  sections);
 	    }
 
 	  uint64_t size = shdr->sh_size;
@@ -702,7 +742,9 @@ process_file (const char *fname)
 	  if (sname == NULL)
 	    {
 	      error (0, 0, "Couldn't get name for section %zd", ndx);
-	      return cleanup (-1);
+      	      return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+			  scnstrents,symstrents,scnnames,shnum,namesbuf,
+			  sections);
 	    }
 
 	  /* strdup sname, the shdrstrndx section itself might be
@@ -724,7 +766,9 @@ process_file (const char *fname)
 		{
 		  if (compress_section (scn, size, sname, NULL, ndx,
 					false, false, verbose > 0) < 0)
-		    return cleanup (-1);
+      	      	    return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+			  scnstrents,symstrents,scnnames,shnum,namesbuf,
+			  sections);
 		}
 	      else if (strncmp (sname, ".zdebug", strlen (".zdebug")) == 0)
 		{
@@ -733,7 +777,9 @@ process_file (const char *fname)
 		  newname = snamebuf;
 		  if (compress_section (scn, size, sname, newname, ndx,
 					true, false, verbose > 0) < 0)
-		    return cleanup (-1);
+      	      	    return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,names,
+			  scnstrents,symstrents,scnnames,shnum,namesbuf,
+			  sections);
 		}
 	      else if (verbose > 0)
 		printf ("[%zd] %s already decompressed\n", ndx, sname);
@@ -748,7 +794,9 @@ process_file (const char *fname)
 			 Don't report even when verbose.  */
 		      if (compress_section (scn, size, sname, NULL, ndx,
 					    false, false, false) < 0)
-			return cleanup (-1);
+      	                return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 		    }
 
 		  snamebuf[0] = '.';
@@ -779,7 +827,9 @@ process_file (const char *fname)
 						  ndx, true, true,
 						  verbose > 0);
 		      if (res < 0)
-			return cleanup (-1);
+      	                return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 
 		      if (res == 0)
 			newname = NULL;
@@ -805,7 +855,9 @@ process_file (const char *fname)
 			 Don't report even when verbose.  */
 		      if (compress_section (scn, size, sname, NULL, ndx,
 					    true, false, false) < 0)
-			return cleanup (-1);
+      	                return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 
 		      snamebuf[0] = '.';
 		      strcpy (&snamebuf[1], &sname[2]);
@@ -833,7 +885,9 @@ process_file (const char *fname)
 		    }
 		  else if (compress_section (scn, size, sname, newname, ndx,
 					     false, true, verbose > 0) < 0)
-		    return cleanup (-1);
+      	                return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 		}
 	      else if (verbose > 0)
 		printf ("[%zd] %s already compressed\n", ndx, sname);
@@ -847,7 +901,9 @@ process_file (const char *fname)
       if (newscn == NULL)
 	{
 	  error (0, 0, "Couldn't create new section %zd", ndx);
-	  return cleanup (-1);
+      	                return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 	}
 
       GElf_Shdr shdr_mem;
@@ -855,13 +911,17 @@ process_file (const char *fname)
       if (shdr == NULL)
 	{
 	  error (0, 0, "Couldn't get shdr for section %zd", ndx);
-	  return cleanup (-1);
+      	                return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 	}
 
       if (gelf_update_shdr (newscn, shdr) == 0)
         {
 	  error (0, 0, "Couldn't update section header %zd", ndx);
-	  return cleanup (-1);
+      	                return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 	}
 
       /* Except for the section header string table all data can be
@@ -874,14 +934,18 @@ process_file (const char *fname)
 	  if (data == NULL)
 	    {
 	      error (0, 0, "Couldn't get data from section %zd", ndx);
-	      return cleanup (-1);
+      	                return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 	    }
 
 	  Elf_Data *newdata = elf_newdata (newscn);
 	  if (newdata == NULL)
 	    {
 	      error (0, 0, "Couldn't create new data for section %zd", ndx);
-	      return cleanup (-1);
+      	                return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 	    }
 
 	  *newdata = *data;
@@ -899,7 +963,9 @@ process_file (const char *fname)
 	      if (name == NULL)
 		{
 		  error (0, 0, "Couldn't get name for section [%zd]", ndx);
-		  return cleanup (-1);
+      	                return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 		}
 	    }
 
@@ -908,7 +974,9 @@ process_file (const char *fname)
 	  if ((scnstrents[ndx] = dwelf_strtab_add (names, name)) == NULL)
 	    {
 	      error (0, 0, "No memory to add section name string table");
-	      return cleanup (-1);
+      	                return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 	    }
 
 	  /* If the symtab shares strings then add those too.  */
@@ -925,7 +993,9 @@ process_file (const char *fname)
 		      /* Don't report the (internal) uncompression.  */
 		      if (compress_section (newscn, size, sname, NULL, ndx,
 					    false, false, false) < 0)
-			return cleanup (-1);
+      	                return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 
 		      symtab_size = size;
 		      symtab_compressed = T_COMPRESS_ZLIB;
@@ -935,7 +1005,9 @@ process_file (const char *fname)
 		      /* Don't report the (internal) uncompression.  */
 		      if (compress_section (newscn, size, sname, NULL, ndx,
 					    true, false, false) < 0)
-			return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 
 		      symtab_size = size;
 		      symtab_compressed = T_COMPRESS_GNU;
@@ -947,7 +1019,9 @@ process_file (const char *fname)
 		{
 		  error (0, 0, "Couldn't get symtab data for section [%zd] %s",
 			 ndx, name);
-		  return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 		}
 	      size_t elsize = gelf_fsize (elfnew, ELF_T_SYM, 1, EV_CURRENT);
 	      size_t syms = symd->d_size / elsize;
@@ -959,7 +1033,9 @@ process_file (const char *fname)
 		  if (sym == NULL)
 		    {
 		      error (0, 0, "Couldn't get symbol %zd", i);
-		      return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 		    }
 		  if (sym->st_name != 0)
 		    {
@@ -971,13 +1047,17 @@ process_file (const char *fname)
 		      if (symname == NULL)
 			{
 			  error (0, 0, "Couldn't get symbol %zd name", i);
-			  return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 			}
 		      symstrents[i] = dwelf_strtab_add (names, symname);
 		      if (symstrents[i] == NULL)
 			{
 			  error (0, 0, "No memory to add to symbol name");
-			  return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 			}
 		    }
 		}
@@ -996,19 +1076,25 @@ process_file (const char *fname)
 	{
 	  error (0, 0, "Couldn't get new section header string table [%zd]",
 		 shdrstrndx);
-	  return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 	}
 
       Elf_Data *data = elf_newdata (scn);
       if (data == NULL)
 	{
 	  error (0, 0, "Couldn't create new section header string table data");
-	  return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 	}
       if (dwelf_strtab_finalize (names, data) == NULL)
 	{
 	  error (0, 0, "Not enough memory to create string table");
-	  return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 	}
       namesbuf = data->d_buf;
 
@@ -1018,7 +1104,9 @@ process_file (const char *fname)
 	{
 	  error (0, 0, "Couldn't get shdr for new section strings %zd",
 		 shdrstrndx);
-	  return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 	}
 
       /* Note that we also might have to compress and possibly set
@@ -1038,7 +1126,9 @@ process_file (const char *fname)
 	{
 	  error (0, 0, "Couldn't update new section strings [%zd]",
 		 shdrstrndx);
-	  return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 	}
 
       /* We might have to compress the data if the user asked us to,
@@ -1054,7 +1144,9 @@ process_file (const char *fname)
 	    {
 	      error (0, 0, "Couldn't get section header string table [%zd]",
 		     shdrstrndx);
-	      return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 	    }
 
 	  shdr = gelf_getshdr (oldscn, &shdr_mem);
@@ -1062,7 +1154,9 @@ process_file (const char *fname)
 	    {
 	      error (0, 0, "Couldn't get shdr for old section strings [%zd]",
 		     shdrstrndx);
-	      return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 	    }
 
 	  shstrtab_name = elf_strptr (elf, shdrstrndx, shdr->sh_name);
@@ -1070,7 +1164,9 @@ process_file (const char *fname)
 	    {
 	      error (0, 0, "Couldn't get name for old section strings [%zd]",
 		     shdrstrndx);
-	      return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 	    }
 
 	  shstrtab_size = shdr->sh_size;
@@ -1087,7 +1183,9 @@ process_file (const char *fname)
 				shstrtab_newname, shdrstrndx,
 				shstrtab_compressed == T_COMPRESS_GNU,
 				true, verbose > 0) < 0)
-	    return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 	}
     }
 
@@ -1096,7 +1194,9 @@ process_file (const char *fname)
   if (gelf_getehdr (elfnew, &newehdr) == NULL)
     {
       error (0, 0, "Couldn't re-get new ehdr: %s", elf_errmsg (-1));
-      return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
     }
 
   /* Set this after the sections have been created, otherwise section
@@ -1104,7 +1204,9 @@ process_file (const char *fname)
   if (setshdrstrndx (elfnew, &newehdr, shdrstrndx) != 0)
     {
       error (0, 0, "Couldn't set new shdrstrndx: %s", elf_errmsg (-1));
-      return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
     }
 
   /* Fixup pass.  Adjust string table references, symbol table and
@@ -1121,7 +1223,9 @@ process_file (const char *fname)
 	  if (shdr == NULL)
 	    {
 	      error (0, 0, "Couldn't get shdr for section %zd", ndx);
-	      return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 	    }
 
 	  /* Keep the offset of allocated sections so they are at the
@@ -1143,7 +1247,9 @@ process_file (const char *fname)
 	  if (gelf_update_shdr (scn, shdr) == 0)
 	    {
 	      error (0, 0, "Couldn't update section header %zd", ndx);
-	      return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 	    }
 
 	  if (adjust_names && ndx == symtabndx)
@@ -1156,7 +1262,9 @@ process_file (const char *fname)
 		{
 		  error (0, 0, "Couldn't get new symtab data section [%zd]",
 			 ndx);
-		  return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 		}
 	      size_t elsize = gelf_fsize (elfnew, ELF_T_SYM, 1, EV_CURRENT);
 	      size_t syms = symd->d_size / elsize;
@@ -1167,7 +1275,9 @@ process_file (const char *fname)
 		  if (sym == NULL)
 		    {
 		      error (0, 0, "2 Couldn't get symbol %zd", i);
-		      return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 		    }
 
 		  if (sym->st_name != 0)
@@ -1177,7 +1287,9 @@ process_file (const char *fname)
 		      if (gelf_update_sym (symd, i, sym) == 0)
 			{
 			  error (0, 0, "Couldn't update symbol %zd", i);
-			  return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 			}
 		    }
 		}
@@ -1195,7 +1307,9 @@ process_file (const char *fname)
 		    {
 		      error (0, 0, "Couldn't get symbol table [%zd]",
 			     symtabndx);
-		      return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 		    }
 
 		  shdr = gelf_getshdr (oldscn, &shdr_mem);
@@ -1203,7 +1317,9 @@ process_file (const char *fname)
 		    {
 		      error (0, 0, "Couldn't get old symbol table shdr [%zd]",
 			     symtabndx);
-		      return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 		    }
 
 		  symtab_name = elf_strptr (elf, shdrstrndx, shdr->sh_name);
@@ -1211,7 +1327,9 @@ process_file (const char *fname)
 		    {
 		      error (0, 0, "Couldn't get old symbol table name [%zd]",
 			     symtabndx);
-		      return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 		    }
 
 		  symtab_size = shdr->sh_size;
@@ -1229,7 +1347,9 @@ process_file (const char *fname)
 					symtab_newname, symtabndx,
 					symtab_compressed == T_COMPRESS_GNU,
 					true, verbose > 0) < 0)
-		    return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 		}
 	    }
 	}
@@ -1243,7 +1363,9 @@ process_file (const char *fname)
       if (gelf_getehdr (elfnew, &newehdr) == NULL)
 	{
 	  error (0, 0, "Couldn't get ehdr: %s", elf_errmsg (-1));
-	  return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 	}
 
       /* Position the shdrs after the last (unallocated) section.  */
@@ -1258,7 +1380,9 @@ process_file (const char *fname)
       if (gelf_update_ehdr (elfnew, &newehdr) == 0)
 	{
 	  error (0, 0, "Couldn't update ehdr: %s", elf_errmsg (-1));
-	  return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 	}
     }
 
@@ -1268,7 +1392,9 @@ process_file (const char *fname)
   if (elf_update (elfnew, ELF_C_WRITE) < 0)
     {
       error (0, 0, "Couldn't write %s: %s", fnew, elf_errmsg (-1));
-      return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
     }
 
   elf_end (elfnew);
@@ -1290,14 +1416,18 @@ process_file (const char *fname)
     if (rename (fnew, fname) != 0)
       {
 	error (0, errno, "Couldn't rename %s to %s", fnew, fname);
-	return cleanup (-1);
+      	              return cleanup (-1,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
       }
 
   /* We are finally done with the new file, don't unlink it now.  */
   free (fnew);
   fnew = NULL;
 
-  return cleanup (0);
+      	              return cleanup (0,elf,elfnew,fd,fdnew,fnew,snamebuf,
+					names,scnstrents,symstrents,scnnames,
+					shnum,namesbuf, sections);
 }
 
 int
diff --git a/src/elflint.c b/src/elflint.c
index ef3e3732..05626084 100644
--- a/src/elflint.c
+++ b/src/elflint.c
@@ -3421,6 +3421,16 @@ section [%2d] '%s': unknown parent version '%s'\n"),
     }
 }
 
+  inline static size_t pos (const unsigned char *p,Elf_Data *data)
+  {
+    return p - (const unsigned char *) data->d_buf;
+  }
+
+inline static size_t left (Elf_Data *data,const unsigned char *p)
+  {
+    return (const unsigned char *) data->d_buf + data->d_size - p;
+  }
+
 static void
 check_attributes (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
 {
@@ -3438,12 +3448,6 @@ check_attributes (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
 	     idx, section_name (ebl, idx));
       return;
     }
-
-  inline size_t pos (const unsigned char *p)
-  {
-    return p - (const unsigned char *) data->d_buf;
-  }
-
   const unsigned char *p = data->d_buf;
   if (*p++ != 'A')
     {
@@ -3452,12 +3456,7 @@ check_attributes (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
       return;
     }
 
-  inline size_t left (void)
-  {
-    return (const unsigned char *) data->d_buf + data->d_size - p;
-  }
-
-  while (left () >= 4)
+    while (left (data,p) >= 4)
     {
       uint32_t len;
       memcpy (&len, p, sizeof len);
@@ -3465,16 +3464,16 @@ check_attributes (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
       if (len == 0)
 	ERROR (gettext ("\
 section [%2d] '%s': offset %zu: zero length field in attribute section\n"),
-	       idx, section_name (ebl, idx), pos (p));
+	       idx, section_name (ebl, idx), pos (p,data));
 
       if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
 	CONVERT (len);
 
-      if (len > left ())
+      if (len > left (data,p))
 	{
 	  ERROR (gettext ("\
 section [%2d] '%s': offset %zu: invalid length in attribute section\n"),
-		 idx, section_name (ebl, idx), pos (p));
+		 idx, section_name (ebl, idx), pos (p,data));
 	  break;
 	}
 
@@ -3486,7 +3485,7 @@ section [%2d] '%s': offset %zu: invalid length in attribute section\n"),
 	{
 	  ERROR (gettext ("\
 section [%2d] '%s': offset %zu: unterminated vendor name string\n"),
-		 idx, section_name (ebl, idx), pos (p));
+		 idx, section_name (ebl, idx), pos (p,data));
 	  break;
 	}
       ++q;
@@ -3503,7 +3502,7 @@ section [%2d] '%s': offset %zu: unterminated vendor name string\n"),
 	      {
 		ERROR (gettext ("\
 section [%2d] '%s': offset %zu: endless ULEB128 in attribute subsection tag\n"),
-		       idx, section_name (ebl, idx), pos (chunk));
+		       idx, section_name (ebl, idx), pos (chunk,data));
 		break;
 	      }
 
@@ -3512,7 +3511,7 @@ section [%2d] '%s': offset %zu: endless ULEB128 in attribute subsection tag\n"),
 	      {
 		ERROR (gettext ("\
 section [%2d] '%s': offset %zu: truncated attribute section\n"),
-		       idx, section_name (ebl, idx), pos (q));
+		       idx, section_name (ebl, idx), pos (q,data));
 		break;
 	      }
 
@@ -3521,7 +3520,7 @@ section [%2d] '%s': offset %zu: truncated attribute section\n"),
 	      {
 		ERROR (gettext ("\
 section [%2d] '%s': offset %zu: zero length field in attribute subsection\n"),
-		       idx, section_name (ebl, idx), pos (q));
+		       idx, section_name (ebl, idx), pos (q,data));
 
 		q += sizeof subsection_len;
 		continue;
@@ -3536,7 +3535,7 @@ section [%2d] '%s': offset %zu: zero length field in attribute subsection\n"),
 	      {
 		ERROR (gettext ("\
 section [%2d] '%s': offset %zu: invalid length in attribute subsection\n"),
-		       idx, section_name (ebl, idx), pos (q));
+		       idx, section_name (ebl, idx), pos (q,data));
 		break;
 	      }
 
@@ -3547,7 +3546,7 @@ section [%2d] '%s': offset %zu: invalid length in attribute subsection\n"),
 	    if (subsection_tag != 1) /* Tag_File */
 	      ERROR (gettext ("\
 section [%2d] '%s': offset %zu: attribute subsection has unexpected tag %u\n"),
-		     idx, section_name (ebl, idx), pos (chunk), subsection_tag);
+		     idx, section_name (ebl, idx), pos (chunk,data), subsection_tag);
 	    else
 	      {
 		chunk += sizeof subsection_len;
@@ -3565,7 +3564,7 @@ section [%2d] '%s': offset %zu: attribute subsection has unexpected tag %u\n"),
 			  {
 			    ERROR (gettext ("\
 section [%2d] '%s': offset %zu: endless ULEB128 in attribute tag\n"),
-				   idx, section_name (ebl, idx), pos (chunk));
+				   idx, section_name (ebl, idx), pos (chunk,data));
 			    break;
 			  }
 		      }
@@ -3576,7 +3575,7 @@ section [%2d] '%s': offset %zu: endless ULEB128 in attribute tag\n"),
 			  {
 			    ERROR (gettext ("\
 section [%2d] '%s': offset %zu: unterminated string in attribute\n"),
-				   idx, section_name (ebl, idx), pos (chunk));
+				   idx, section_name (ebl, idx), pos (chunk,data));
 			    break;
 			  }
 			++r;
@@ -3589,11 +3588,11 @@ section [%2d] '%s': offset %zu: unterminated string in attribute\n"),
 						     &tag_name, &value_name))
 		      ERROR (gettext ("\
 section [%2d] '%s': offset %zu: unrecognized attribute tag %u\n"),
-			     idx, section_name (ebl, idx), pos (chunk), tag);
+			     idx, section_name (ebl, idx), pos (chunk,data), tag);
 		    else if ((tag & 1) == 0 && value_name == NULL)
 		      ERROR (gettext ("\
 section [%2d] '%s': offset %zu: unrecognized %s attribute value %" PRIu64 "\n"),
-			     idx, section_name (ebl, idx), pos (chunk),
+			     idx, section_name (ebl, idx), pos (chunk,data),
 			     tag_name, value);
 
 		    chunk = r;
@@ -3603,13 +3602,13 @@ section [%2d] '%s': offset %zu: unrecognized %s attribute value %" PRIu64 "\n"),
       else
 	ERROR (gettext ("\
 section [%2d] '%s': offset %zu: vendor '%s' unknown\n"),
-	       idx, section_name (ebl, idx), pos (p), name);
+	       idx, section_name (ebl, idx), pos (p,data), name);
     }
 
-  if (left () != 0)
+  if (left (data,p) != 0)
     ERROR (gettext ("\
 section [%2d] '%s': offset %zu: extra bytes after last attribute section\n"),
-	   idx, section_name (ebl, idx), pos (p));
+	   idx, section_name (ebl, idx), pos (p,data));
 }
 
 static bool has_loadable_segment;
@@ -3905,6 +3904,7 @@ section [%2zu] '%s': size not multiple of entry size\n"),
 	  && shdr->sh_type != SHT_GNU_ATTRIBUTES
 	  && shdr->sh_type != SHT_GNU_LIBLIST
 	  && shdr->sh_type != SHT_CHECKSUM
+	  && shdr->sh_type != SHT_LLVM_ADDRSIG
 	  && shdr->sh_type != SHT_GNU_verdef
 	  && shdr->sh_type != SHT_GNU_verneed
 	  && shdr->sh_type != SHT_GNU_versym
diff --git a/src/readelf.c b/src/readelf.c
index f6d13afa..2bfe43bd 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -381,13 +381,7 @@ main (int argc, char *argv[])
   return error_message_count != 0;
 }
 
-
-/* Handle program arguments.  */
-static error_t
-parse_opt (int key, char *arg,
-	   struct argp_state *state __attribute__ ((unused)))
-{
-  void add_dump_section (const char *name, bool implicit)
+static void add_dump_section (const char *name, bool implicit,int key)
   {
     struct section_argument *a = xmalloc (sizeof *a);
     a->arg = name;
@@ -399,7 +393,14 @@ parse_opt (int key, char *arg,
     *tailp = &a->next;
   }
 
-  switch (key)
+
+
+/* Handle program arguments.  */
+static error_t
+parse_opt (int key, char *arg,
+	   struct argp_state *state __attribute__ ((unused)))
+{
+    switch (key)
     {
     case 'a':
       print_file_header = true;
@@ -414,9 +415,9 @@ parse_opt (int key, char *arg,
       print_arch = true;
       print_notes = true;
       implicit_debug_sections |= section_exception;
-      add_dump_section (".strtab", true);
-      add_dump_section (".dynstr", true);
-      add_dump_section (".comment", true);
+      add_dump_section (".strtab", true,key);
+      add_dump_section (".dynstr", true,key);
+      add_dump_section (".comment", true,key);
       any_control_option = true;
       break;
     case 'A':
@@ -562,7 +563,7 @@ parse_opt (int key, char *arg,
 	}
       FALLTHROUGH;
     case 'x':
-      add_dump_section (arg, false);
+      add_dump_section (arg, false,key);
       any_control_option = true;
       break;
     case 'N':
@@ -3567,6 +3568,11 @@ print_liblist (Ebl *ebl)
     }
 }
 
+inline static size_t elf_left (Elf_Data *data,const unsigned char *p)
+      {
+	return (const unsigned char *) data->d_buf + data->d_size - p;
+      }
+
 static void
 print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
 {
@@ -3611,13 +3617,9 @@ print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
 
       fputs_unlocked (gettext ("  Owner          Size\n"), stdout);
 
-      inline size_t left (void)
-      {
-	return (const unsigned char *) data->d_buf + data->d_size - p;
-      }
-
+      
       /* Loop over the sections.  */
-      while (left () >= 4)
+      while (elf_left (data,p) >= 4)
 	{
 	  /* Section length.  */
 	  uint32_t len;
@@ -3626,7 +3628,7 @@ print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
 	  if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
 	    CONVERT (len);
 
-	  if (unlikely (len > left ()))
+	  if (unlikely (len > elf_left (data,p)))
 	    break;
 
 	  /* Section vendor name.  */
@@ -6200,6 +6202,12 @@ read_encoded (unsigned int encoding, const unsigned char *readp,
   return readp;
 }
 
+static const char *regname (unsigned int regno,Ebl *ebl,char *regnamebuf)
+  {
+    register_info (ebl, regno, NULL, regnamebuf, NULL, NULL);
+    return regnamebuf;
+  }
+
 
 static void
 print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
@@ -6210,12 +6218,7 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 		   Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, Dwarf *dbg)
 {
   char regnamebuf[REGNAMESZ];
-  const char *regname (unsigned int regno)
-  {
-    register_info (ebl, regno, NULL, regnamebuf, NULL, NULL);
-    return regnamebuf;
-  }
-
+  
   puts ("\n   Program:");
   Dwarf_Word pc = vma_base;
   while (readp < endp)
@@ -6271,26 +6274,26 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	    get_uleb128 (op2, readp, endp);
 	    printf ("     offset_extended r%" PRIu64 " (%s) at cfa%+" PRId64
 		    "\n",
-		    op1, regname (op1), op2 * data_align);
+		    op1, regname (op1,ebl,regnamebuf), op2 * data_align);
 	    break;
 	  case DW_CFA_restore_extended:
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
 	    get_uleb128 (op1, readp, endp);
 	    printf ("     restore_extended r%" PRIu64 " (%s)\n",
-		    op1, regname (op1));
+		    op1, regname (op1,ebl,regnamebuf));
 	    break;
 	  case DW_CFA_undefined:
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
 	    get_uleb128 (op1, readp, endp);
-	    printf ("     undefined r%" PRIu64 " (%s)\n", op1, regname (op1));
+	    printf ("     undefined r%" PRIu64 " (%s)\n", op1, regname (op1,ebl,regnamebuf));
 	    break;
 	  case DW_CFA_same_value:
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
 	    get_uleb128 (op1, readp, endp);
-	    printf ("     same_value r%" PRIu64 " (%s)\n", op1, regname (op1));
+	    printf ("     same_value r%" PRIu64 " (%s)\n", op1, regname (op1,ebl,regnamebuf));
 	    break;
 	  case DW_CFA_register:
 	    if ((uint64_t) (endp - readp) < 1)
@@ -6300,7 +6303,7 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	      goto invalid;
 	    get_uleb128 (op2, readp, endp);
 	    printf ("     register r%" PRIu64 " (%s) in r%" PRIu64 " (%s)\n",
-		    op1, regname (op1), op2, regname (op2));
+		    op1, regname (op1,ebl,regnamebuf), op2, regname (op2,ebl,regnamebuf));
 	    break;
 	  case DW_CFA_remember_state:
 	    puts ("     remember_state");
@@ -6316,14 +6319,14 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	      goto invalid;
 	    get_uleb128 (op2, readp, endp);
 	    printf ("     def_cfa r%" PRIu64 " (%s) at offset %" PRIu64 "\n",
-		    op1, regname (op1), op2);
+		    op1, regname (op1,ebl,regnamebuf), op2);
 	    break;
 	  case DW_CFA_def_cfa_register:
 	    if ((uint64_t) (endp - readp) < 1)
 	      goto invalid;
 	    get_uleb128 (op1, readp, endp);
 	    printf ("     def_cfa_register r%" PRIu64 " (%s)\n",
-		    op1, regname (op1));
+		    op1, regname (op1,ebl,regnamebuf));
 	    break;
 	  case DW_CFA_def_cfa_offset:
 	    if ((uint64_t) (endp - readp) < 1)
@@ -6354,7 +6357,7 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	      goto invalid;
 	    get_uleb128 (op2, readp, endp);	/* Length of DW_FORM_block.  */
 	    printf ("     expression r%" PRIu64 " (%s) \n",
-		    op1, regname (op1));
+		    op1, regname (op1,ebl,regnamebuf));
 	    if ((uint64_t) (endp - readp) < op2)
 	      goto invalid;
 	    print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, NULL,
@@ -6370,7 +6373,7 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	    get_sleb128 (sop2, readp, endp);
 	    printf ("     offset_extended_sf r%" PRIu64 " (%s) at cfa%+"
 		    PRId64 "\n",
-		    op1, regname (op1), sop2 * data_align);
+		    op1, regname (op1,ebl,regnamebuf), sop2 * data_align);
 	    break;
 	  case DW_CFA_def_cfa_sf:
 	    if ((uint64_t) (endp - readp) < 1)
@@ -6380,7 +6383,7 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	      goto invalid;
 	    get_sleb128 (sop2, readp, endp);
 	    printf ("     def_cfa_sf r%" PRIu64 " (%s) at offset %" PRId64 "\n",
-		    op1, regname (op1), sop2 * data_align);
+		    op1, regname (op1,ebl,regnamebuf), sop2 * data_align);
 	    break;
 	  case DW_CFA_def_cfa_offset_sf:
 	    if ((uint64_t) (endp - readp) < 1)
@@ -6416,7 +6419,7 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	      goto invalid;
 	    get_uleb128 (op2, readp, endp);	/* Length of DW_FORM_block.  */
 	    printf ("     val_expression r%" PRIu64 " (%s)\n",
-		    op1, regname (op1));
+		    op1, regname (op1,ebl,regnamebuf));
 	    if ((uint64_t) (endp - readp) < op2)
 	      goto invalid;
 	    print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0,
@@ -6456,11 +6459,11 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
 	    goto invalid;
 	  get_uleb128 (offset, readp, endp);
 	  printf ("     offset r%u (%s) at cfa%+" PRId64 "\n",
-		  opcode & 0x3f, regname (opcode & 0x3f), offset * data_align);
+		  opcode & 0x3f, regname (opcode & 0x3f,ebl,regnamebuf), offset * data_align);
 	}
       else
 	printf ("     restore r%u (%s)\n",
-		opcode & 0x3f, regname (opcode & 0x3f));
+		opcode & 0x3f, regname (opcode & 0x3f,ebl,regnamebuf));
     }
 }
 
@@ -8343,6 +8346,22 @@ print_form_data (Dwarf *dbg, int form, const unsigned char *readp,
 
   return readp;
 }
+/* Apply the "operation advance" from a special opcode
+	 or DW_LNS_advance_pc (as per DWARF4 6.2.5.1).  */
+      static inline void advance_pc (unsigned int op_advance,
+		     unsigned int *op_addr_advance,
+		     uint_fast8_t minimum_instr_len,unsigned int *op_index ,
+		     uint_fast8_t max_ops_per_instr, Dwarf_Word *address,
+		     bool *show_op_index
+		     )
+      {
+	*op_addr_advance = minimum_instr_len * ((*op_index + op_advance)
+					       / max_ops_per_instr);
+	*address += *op_addr_advance;
+	*show_op_index = (*op_index > 0 ||
+			 (*op_index + op_advance) % max_ops_per_instr > 0);
+	*op_index = (*op_index + op_advance) % max_ops_per_instr;
+      }
 
 static void
 print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
@@ -8731,20 +8750,9 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
       size_t line = 1;
       uint_fast8_t is_stmt = default_is_stmt;
 
-      /* Apply the "operation advance" from a special opcode
-	 or DW_LNS_advance_pc (as per DWARF4 6.2.5.1).  */
       unsigned int op_addr_advance;
       bool show_op_index;
-      inline void advance_pc (unsigned int op_advance)
-      {
-	op_addr_advance = minimum_instr_len * ((op_index + op_advance)
-					       / max_ops_per_instr);
-	address += op_addr_advance;
-	show_op_index = (op_index > 0 ||
-			 (op_index + op_advance) % max_ops_per_instr > 0);
-	op_index = (op_index + op_advance) % max_ops_per_instr;
-      }
-
+      
       if (max_ops_per_instr == 0)
 	{
 	  error (0, 0,
@@ -8777,10 +8785,9 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 	      */
 	      int line_increment = (line_base
 				    + (opcode - opcode_base) % line_range);
-
-	      /* Perform the increments.  */
+      	      /* Perform the increments.  */
 	      line += line_increment;
-	      advance_pc ((opcode - opcode_base) / line_range);
+	      advance_pc ((opcode - opcode_base) / line_range,&op_addr_advance,minimum_instr_len,&op_index,max_ops_per_instr,&address,&show_op_index);
 
 	      printf (gettext (" special opcode %u: address+%u = "),
 		      opcode, op_addr_advance);
@@ -8898,7 +8905,10 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 		  if (lineendp - linep < 1)
 		    goto invalid_unit;
 		  get_uleb128 (u128, linep, lineendp);
-		  advance_pc (u128);
+		  advance_pc (u128,&op_addr_advance,minimum_instr_len,
+				  &op_index,max_ops_per_instr,&address,
+				  &show_op_index
+				  );
 		  {
 		    printf (gettext (" advance address by %u to "),
 			    op_addr_advance);
@@ -8958,8 +8968,10 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
 
 		  if (unlikely (line_range == 0))
 		    goto invalid_unit;
-
-		  advance_pc ((255 - opcode_base) / line_range);
+		  advance_pc ((255 - opcode_base) / line_range,
+				  &op_addr_advance,minimum_instr_len,&op_index,
+				  max_ops_per_instr,&address,
+				  &show_op_index);
 		  {
 		    printf (gettext (" advance address by constant %u to "),
 			    op_addr_advance);
@@ -12067,7 +12079,18 @@ compare_register_sets (const void *a, const void *b)
   const struct register_info *const *p2 = b;
   return compare_sets_by_info (*p1, *p2);
 }
-
+  /* Collect the unique sets and sort them.  */
+  inline static bool same_set (const struct register_info *a,
+			const struct register_info *b,
+			const struct register_info *regs,
+			ssize_t maxnreg
+			)
+  {
+    return (a < &regs[maxnreg] && a->regloc != NULL
+	    && b < &regs[maxnreg] && b->regloc != NULL
+	    && a->bits == b->bits
+	    && (a->set == b->set || !strcmp (a->set, b->set)));
+  }
 static unsigned int
 handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
 		       const Ebl_Register_Location *reglocs, size_t nregloc)
@@ -12105,20 +12128,13 @@ handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
       }
   qsort (regs, maxreg + 1, sizeof regs[0], &compare_registers);
 
-  /* Collect the unique sets and sort them.  */
-  inline bool same_set (const struct register_info *a,
-			const struct register_info *b)
-  {
-    return (a < &regs[maxnreg] && a->regloc != NULL
-	    && b < &regs[maxnreg] && b->regloc != NULL
-	    && a->bits == b->bits
-	    && (a->set == b->set || !strcmp (a->set, b->set)));
-  }
+
   struct register_info *sets[maxreg + 1];
   sets[0] = &regs[0];
   size_t nsets = 1;
   for (int i = 1; i <= maxreg; ++i)
-    if (regs[i].regloc != NULL && !same_set (&regs[i], &regs[i - 1]))
+    if (regs[i].regloc != NULL && 
+		            !same_set (&regs[i], &regs[i - 1],regs, maxnreg))
       sets[nsets++] = &regs[i];
   qsort (sets, nsets, sizeof sets[0], &compare_register_sets);
 
@@ -12129,7 +12145,7 @@ handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
       /* Find the longest name of a register in this set.  */
       size_t maxname = 0;
       const struct register_info *end;
-      for (end = sets[i]; same_set (sets[i], end); ++end)
+      for (end = sets[i]; same_set (sets[i], end,regs,maxnreg); ++end)
 	{
 	  size_t len = strlen (end->name);
 	  if (len > maxname)
diff --git a/src/strip.c b/src/strip.c
index 48792a70..33e47dc0 100644
--- a/src/strip.c
+++ b/src/strip.c
@@ -442,85 +442,14 @@ update_shdrstrndx (Elf *elf, size_t shdrstrndx)
   return 0;
 }
 
-/* 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.  */
-static void
-remove_debug_relocations (Ebl *ebl, Elf *elf, GElf_Ehdr *ehdr,
-			  const char *fname, size_t shstrndx)
-{
-  Elf_Scn *scn = NULL;
-  while ((scn = elf_nextscn (elf, scn)) != NULL)
-    {
-      /* We need the actual section and header from the elf
-	 not just the cached original in shdr_info because we
-	 might want to change the size.  */
-      GElf_Shdr shdr_mem;
-      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
-      if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
-	{
-	  /* Make sure that this relocation section points to a
-	     section to relocate with contents, that isn't
-	     allocated and that is a debug section.  */
-	  Elf_Scn *tscn = elf_getscn (elf, shdr->sh_info);
-	  GElf_Shdr tshdr_mem;
-	  GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem);
-	  if (tshdr->sh_type == SHT_NOBITS
-	      || tshdr->sh_size == 0
-	      || (tshdr->sh_flags & SHF_ALLOC) != 0)
-	    continue;
-
-	  const char *tname =  elf_strptr (elf, shstrndx,
-					   tshdr->sh_name);
-	  if (! tname || ! ebl_debugscn_p (ebl, tname))
-	    continue;
-
-	  /* OK, lets relocate all trivial cross debug section
-	     relocations. */
-	  Elf_Data *reldata = elf_getdata (scn, NULL);
-	  if (reldata == NULL || reldata->d_buf == NULL)
-	    INTERNAL_ERROR (fname);
-
-	  /* Make sure we adjust the uncompressed debug data
-	     (and recompress if necessary at the end).  */
-	  GElf_Chdr tchdr;
-	  int tcompress_type = 0;
-	  bool is_gnu_compressed = false;
-	  if (strncmp (tname, ".zdebug", strlen ("zdebug")) == 0)
-	    {
-	      is_gnu_compressed = true;
-	      if (elf_compress_gnu (tscn, 0, 0) != 1)
-		INTERNAL_ERROR (fname);
-	    }
-	  else
-	    {
-	      if (gelf_getchdr (tscn, &tchdr) != NULL)
-		{
-		  tcompress_type = tchdr.ch_type;
-		  if (elf_compress (tscn, 0, 0) != 1)
-		    INTERNAL_ERROR (fname);
-		}
-	    }
-
-	  Elf_Data *tdata = elf_getdata (tscn, NULL);
-	  if (tdata == NULL || tdata->d_buf == NULL
-	      || tdata->d_type != ELF_T_BYTE)
-	    INTERNAL_ERROR (fname);
-
-	  /* Pick up the symbol table and shndx table to
-	     resolve relocation symbol indexes.  */
-	  Elf64_Word symt = shdr->sh_link;
-	  Elf_Data *symdata, *xndxdata;
-	  Elf_Scn * symscn = elf_getscn (elf, symt);
-	  symdata = elf_getdata (symscn, NULL);
-	  xndxdata = get_xndxdata (elf, symscn);
-	  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)
+	  static bool relocate (GElf_Addr offset, const GElf_Sxword addend,
+			 bool is_rela, int rtype, int symndx,
+			 Ebl *ebl,Elf_Data *symdata,Elf_Data *xndxdata,
+			 Elf *elf,Elf_Data *tdata,GElf_Ehdr  *ehdr,
+			 const char *fname)
 	  {
 	    /* R_*_NONE relocs can always just be removed.  */
 	    if (rtype == 0)
@@ -658,6 +587,82 @@ remove_debug_relocations (Ebl *ebl, Elf *elf, GElf_Ehdr *ehdr,
 	    return false;
 	  }
 
+/* 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.  */
+static void
+remove_debug_relocations (Ebl *ebl, Elf *elf, GElf_Ehdr *ehdr,
+			  const char *fname, size_t shstrndx)
+{
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (elf, scn)) != NULL)
+    {
+      /* We need the actual section and header from the elf
+	 not just the cached original in shdr_info because we
+	 might want to change the size.  */
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
+	{
+	  /* Make sure that this relocation section points to a
+	     section to relocate with contents, that isn't
+	     allocated and that is a debug section.  */
+	  Elf_Scn *tscn = elf_getscn (elf, shdr->sh_info);
+	  GElf_Shdr tshdr_mem;
+	  GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem);
+	  if (tshdr->sh_type == SHT_NOBITS
+	      || tshdr->sh_size == 0
+	      || (tshdr->sh_flags & SHF_ALLOC) != 0)
+	    continue;
+
+	  const char *tname =  elf_strptr (elf, shstrndx,
+					   tshdr->sh_name);
+	  if (! tname || ! ebl_debugscn_p (ebl, tname))
+	    continue;
+
+	  /* OK, lets relocate all trivial cross debug section
+	     relocations. */
+	  Elf_Data *reldata = elf_getdata (scn, NULL);
+	  if (reldata == NULL || reldata->d_buf == NULL)
+	    INTERNAL_ERROR (fname);
+
+	  /* Make sure we adjust the uncompressed debug data
+	     (and recompress if necessary at the end).  */
+	  GElf_Chdr tchdr;
+	  int tcompress_type = 0;
+	  bool is_gnu_compressed = false;
+	  if (strncmp (tname, ".zdebug", strlen ("zdebug")) == 0)
+	    {
+	      is_gnu_compressed = true;
+	      if (elf_compress_gnu (tscn, 0, 0) != 1)
+		INTERNAL_ERROR (fname);
+	    }
+	  else
+	    {
+	      if (gelf_getchdr (tscn, &tchdr) != NULL)
+		{
+		  tcompress_type = tchdr.ch_type;
+		  if (elf_compress (tscn, 0, 0) != 1)
+		    INTERNAL_ERROR (fname);
+		}
+	    }
+
+	  Elf_Data *tdata = elf_getdata (tscn, NULL);
+	  if (tdata == NULL || tdata->d_buf == NULL
+	      || tdata->d_type != ELF_T_BYTE)
+	    INTERNAL_ERROR (fname);
+
+	  /* Pick up the symbol table and shndx table to
+	     resolve relocation symbol indexes.  */
+	  Elf64_Word symt = shdr->sh_link;
+	  Elf_Data *symdata, *xndxdata;
+	  Elf_Scn * symscn = elf_getscn (elf, symt);
+	  symdata = elf_getdata (symscn, NULL);
+	  xndxdata = get_xndxdata (elf, symscn);
+	  if (symdata == NULL)
+	    INTERNAL_ERROR (fname);
+
+
 	  if (shdr->sh_entsize == 0)
 	    INTERNAL_ERROR (fname);
 
@@ -670,7 +675,8 @@ remove_debug_relocations (Ebl *ebl, Elf *elf, GElf_Ehdr *ehdr,
 		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)))
+				GELF_R_SYM (r->r_info),ebl,symdata,xndxdata,
+				elf,tdata,ehdr,fname))
 		  {
 		    if (relidx != next)
 		      gelf_update_rel (reldata, next, r);
@@ -684,7 +690,8 @@ remove_debug_relocations (Ebl *ebl, Elf *elf, GElf_Ehdr *ehdr,
 		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)))
+				GELF_R_SYM (r->r_info),ebl,symdata,xndxdata,
+				elf,tdata,ehdr,fname))
 		  {
 		    if (relidx != next)
 		      gelf_update_rela (reldata, next, r);
@@ -917,6 +924,82 @@ handle_debug_relocs (Elf *elf, Ebl *ebl, Elf *new_elf,
 
   return 0;
 }
+struct shdr_info
+  {
+    Elf_Scn *scn;
+    GElf_Shdr shdr;
+    Elf_Data *data;
+    Elf_Data *debug_data;
+    const char *name;
+    Elf32_Word idx;		/* Index in new file.  */
+    Elf32_Word old_sh_link;	/* Original value of shdr.sh_link.  */
+    Elf32_Word symtab_idx;
+    Elf32_Word version_idx;
+    Elf32_Word group_idx;
+    Elf32_Word group_cnt;
+    Elf_Scn *newscn;
+    Dwelf_Strent *se;
+    Elf32_Word *newsymidx;
+  } *shdr_info = NULL;
+	
+        /* This section is being preserved in the debug file.
+		 Sections it refers to must be preserved there too.
+
+		 In this pass we mark sections to be preserved in both
+		 files by setting the .debug_data pointer to the original
+		 file's .data pointer.  Below, we'll copy the section
+		 contents.  */
+
+	      inline static void check_preserved (size_t i,size_t shnum,
+			      bool *changes,
+			      const char *fname,size_t cnt)
+	      {
+		if (i != 0 && i < shnum + 2 && shdr_info[i].idx != 0
+		    && shdr_info[i].debug_data == NULL)
+		  {
+		    if (shdr_info[i].data == NULL)
+		      shdr_info[i].data = elf_getdata (shdr_info[i].scn, NULL);
+		    if (shdr_info[i].data == NULL)
+		      INTERNAL_ERROR (fname);
+
+		    shdr_info[i].debug_data = shdr_info[i].data;
+		    *changes |= i < cnt;
+		  }
+	      }
+
+	/* Update section headers when the data size has changed.
+	   We also update the SHT_NOBITS section in the debug
+	   file so that the section headers match in sh_size.  */
+	inline static void update_section_size (const Elf_Data *newdata,Elf_Scn *scn,
+				Elf *debugelf, const char *fname,size_t cnt)
+	{
+	  GElf_Shdr shdr_mem;
+	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+	  shdr->sh_size = newdata->d_size;
+	  (void) gelf_update_shdr (scn, shdr);
+	  if (debugelf != NULL)
+	    {
+	      /* libelf will use d_size to set sh_size.  */
+	      Elf_Data *debugdata = elf_getdata (elf_getscn (debugelf,
+							     cnt), NULL);
+	      if (debugdata == NULL)
+		INTERNAL_ERROR (fname);
+	      debugdata->d_size = newdata->d_size;
+	    }
+	}
+
+inline static bool no_symtab_updates (const Elf32_Word symtabidx,size_t cnt)
+	    {
+	      /* If the symbol table hasn't changed, do not do anything.  */
+	      if (shdr_info[symtabidx].newsymidx == NULL)
+		return true;
+
+	      /* If the symbol table is not discarded, but additionally
+		 duplicated in the separate debug file and this section
+		 is discarded, don't adjust anything.  */
+	      return (shdr_info[cnt].idx == 0
+		      && shdr_info[symtabidx].debug_data != NULL);
+	    }
 
 /* Maximum size of array allocated on stack.  */
 #define MAX_STACK_ALLOC	(400 * 1024)
@@ -936,23 +1019,6 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
   GElf_Off lastsec_offset = 0;
   Elf64_Xword lastsec_size = 0;
   size_t shstrndx;
-  struct shdr_info
-  {
-    Elf_Scn *scn;
-    GElf_Shdr shdr;
-    Elf_Data *data;
-    Elf_Data *debug_data;
-    const char *name;
-    Elf32_Word idx;		/* Index in new file.  */
-    Elf32_Word old_sh_link;	/* Original value of shdr.sh_link.  */
-    Elf32_Word symtab_idx;
-    Elf32_Word version_idx;
-    Elf32_Word group_idx;
-    Elf32_Word group_cnt;
-    Elf_Scn *newscn;
-    Dwelf_Strent *se;
-    Elf32_Word *newsymidx;
-  } *shdr_info = NULL;
   Elf_Scn *scn;
   size_t cnt;
   size_t idx;
@@ -1528,32 +1594,11 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
 	  if (debug_fname != NULL
 	      && (shdr_info[cnt].idx == 0 || shdr_info[cnt].debug_data != NULL))
 	    {
-	      /* This section is being preserved in the debug file.
-		 Sections it refers to must be preserved there too.
-
-		 In this pass we mark sections to be preserved in both
-		 files by setting the .debug_data pointer to the original
-		 file's .data pointer.  Below, we'll copy the section
-		 contents.  */
-
-	      inline void check_preserved (size_t i)
-	      {
-		if (i != 0 && i < shnum + 2 && shdr_info[i].idx != 0
-		    && shdr_info[i].debug_data == NULL)
-		  {
-		    if (shdr_info[i].data == NULL)
-		      shdr_info[i].data = elf_getdata (shdr_info[i].scn, NULL);
-		    if (shdr_info[i].data == NULL)
-		      INTERNAL_ERROR (fname);
-
-		    shdr_info[i].debug_data = shdr_info[i].data;
-		    changes |= i < cnt;
-		  }
-	      }
-
-	      check_preserved (shdr_info[cnt].shdr.sh_link);
+	      check_preserved (shdr_info[cnt].shdr.sh_link,shnum,
+			      &changes,fname,cnt);
 	      if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
-		check_preserved (shdr_info[cnt].shdr.sh_info);
+		check_preserved (shdr_info[cnt].shdr.sh_info,shnum,
+				&changes,fname,cnt);
 	    }
 	}
     }
@@ -2124,25 +2169,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
     /* Find all relocation sections which use this symbol table.  */
     for (cnt = 1; cnt <= shdridx; ++cnt)
       {
-	/* Update section headers when the data size has changed.
-	   We also update the SHT_NOBITS section in the debug
-	   file so that the section headers match in sh_size.  */
-	inline void update_section_size (const Elf_Data *newdata)
-	{
-	  GElf_Shdr shdr_mem;
-	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
-	  shdr->sh_size = newdata->d_size;
-	  (void) gelf_update_shdr (scn, shdr);
-	  if (debugelf != NULL)
-	    {
-	      /* libelf will use d_size to set sh_size.  */
-	      Elf_Data *debugdata = elf_getdata (elf_getscn (debugelf,
-							     cnt), NULL);
-	      if (debugdata == NULL)
-		INTERNAL_ERROR (fname);
-	      debugdata->d_size = newdata->d_size;
-	    }
-	}
+
 
 	if (shdr_info[cnt].idx == 0 && debug_fname == NULL)
 	  /* Ignore sections which are discarded.  When we are saving a
@@ -2155,22 +2182,10 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
 	const Elf32_Word *const newsymidx = shdr_info[symtabidx].newsymidx;
 	switch (shdr_info[cnt].shdr.sh_type)
 	  {
-	    inline bool no_symtab_updates (void)
-	    {
-	      /* If the symbol table hasn't changed, do not do anything.  */
-	      if (shdr_info[symtabidx].newsymidx == NULL)
-		return true;
-
-	      /* If the symbol table is not discarded, but additionally
-		 duplicated in the separate debug file and this section
-		 is discarded, don't adjust anything.  */
-	      return (shdr_info[cnt].idx == 0
-		      && shdr_info[symtabidx].debug_data != NULL);
-	    }
-
+	    
 	  case SHT_REL:
 	  case SHT_RELA:
-	    if (no_symtab_updates ())
+	    if (no_symtab_updates (symtabidx,cnt))
 	      break;
 
 	    Elf_Data *d = elf_getdata (shdr_info[cnt].idx == 0
@@ -2227,7 +2242,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
 	    break;
 
 	  case SHT_HASH:
-	    if (no_symtab_updates ())
+	    if (no_symtab_updates (symtabidx,cnt))
 	      break;
 
 	    /* We have to recompute the hash table.  */
@@ -2273,7 +2288,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
 				 * sizeof (Elf32_Word));
 		elf_assert (n_size <= hashd->d_size);
 		hashd->d_size = n_size;
-		update_section_size (hashd);
+		update_section_size (hashd,scn,debugelf,fname,cnt);
 
 		/* Clear the arrays.  */
 		memset (bucket, '\0',
@@ -2335,7 +2350,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
 				 * sizeof (Elf64_Xword));
 		elf_assert (n_size <= hashd->d_size);
 		hashd->d_size = n_size;
-		update_section_size (hashd);
+		update_section_size (hashd,scn,debugelf,fname,cnt);
 
 		/* Clear the arrays.  */
 		memset (bucket, '\0',
@@ -2371,7 +2386,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
 
 	  case SHT_GNU_versym:
 	    /* If the symbol table changed we have to adjust the entries.  */
-	    if (no_symtab_updates ())
+	    if (no_symtab_updates (symtabidx,cnt))
 	      break;
 
 	    elf_assert (shdr_info[cnt].idx > 0);
@@ -2409,11 +2424,11 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
 				       / gelf_fsize (elf, symd->d_type, 1,
 						     EV_CURRENT),
 				       EV_CURRENT);
-	    update_section_size (verd);
+	    update_section_size (verd,scn,debugelf,fname,cnt);
 	    break;
 
 	  case SHT_GROUP:
-	    if (no_symtab_updates ())
+	    if (no_symtab_updates (symtabidx,cnt))
 	      break;
 
 	    /* Yes, the symbol table changed.
diff --git a/src/unstrip.c b/src/unstrip.c
index 231b941d..f3b280f3 100644
--- a/src/unstrip.c
+++ b/src/unstrip.c
@@ -436,14 +436,7 @@ update_sh_size (Elf_Scn *outscn, const Elf_Data *data)
   update_shdr (outscn, newshdr);
 }
 
-/* Update relocation sections using the symbol table.  */
-static void
-adjust_relocs (Elf_Scn *outscn, Elf_Scn *inscn, const GElf_Shdr *shdr,
-	       size_t map[], size_t map_size, const GElf_Shdr *symshdr)
-{
-  Elf_Data *data = elf_getdata (outscn, NULL);
-
-  inline void adjust_reloc (GElf_Xword *info)
+inline static void adjust_reloc (GElf_Xword *info,size_t map_size,size_t map[])
     {
       size_t ndx = GELF_R_SYM (*info);
       if (ndx != STN_UNDEF)
@@ -454,7 +447,15 @@ adjust_relocs (Elf_Scn *outscn, Elf_Scn *inscn, const GElf_Shdr *shdr,
 	}
     }
 
-  switch (shdr->sh_type)
+
+/* Update relocation sections using the symbol table.  */
+static void
+adjust_relocs (Elf_Scn *outscn, Elf_Scn *inscn, const GElf_Shdr *shdr,
+	       size_t map[], size_t map_size, const GElf_Shdr *symshdr)
+{
+  Elf_Data *data = elf_getdata (outscn, NULL);
+
+    switch (shdr->sh_type)
     {
     case SHT_REL:
       if (shdr->sh_entsize == 0)
@@ -464,7 +465,7 @@ adjust_relocs (Elf_Scn *outscn, Elf_Scn *inscn, const GElf_Shdr *shdr,
 	{
 	  GElf_Rel rel_mem;
 	  GElf_Rel *rel = gelf_getrel (data, i, &rel_mem);
-	  adjust_reloc (&rel->r_info);
+	  adjust_reloc (&rel->r_info,map_size,map);
 	  ELF_CHECK (gelf_update_rel (data, i, rel),
 		     _("cannot update relocation: %s"));
 	}
@@ -478,7 +479,7 @@ adjust_relocs (Elf_Scn *outscn, Elf_Scn *inscn, const GElf_Shdr *shdr,
 	{
 	  GElf_Rela rela_mem;
 	  GElf_Rela *rela = gelf_getrela (data, i, &rela_mem);
-	  adjust_reloc (&rela->r_info);
+	  adjust_reloc (&rela->r_info,map_size,map);
 	  ELF_CHECK (gelf_update_rela (data, i, rela),
 		     _("cannot update relocation: %s"));
 	}
@@ -1066,6 +1067,16 @@ get_group_sig (Elf *elf, GElf_Shdr *shdr)
 
   return sig;
 }
+  inline static void check_match (bool match, Elf_Scn *scn, const char *name,bool *fail)
+    {
+      if (!match)
+	{
+	  *fail = true;
+	  error (0, 0, _("cannot find matching section for [%zu] '%s'"),
+		 elf_ndxscn (scn), name);
+	}
+    }
+
 
 /* Fix things up when prelink has moved some allocated sections around
    and the debuginfo file's section headers no longer match up.
@@ -1202,16 +1213,6 @@ find_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab,
     }
 
   bool fail = false;
-  inline void check_match (bool match, Elf_Scn *scn, const char *name)
-    {
-      if (!match)
-	{
-	  fail = true;
-	  error (0, 0, _("cannot find matching section for [%zu] '%s'"),
-		 elf_ndxscn (scn), name);
-	}
-    }
-
   Elf_Scn *scn = NULL;
   while ((scn = elf_nextscn (debug, scn)) != NULL)
     {
@@ -1242,7 +1243,7 @@ find_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab,
       for (size_t i = 0; shdr != NULL && i < nalloc; ++i)
 	if (sections[i].outscn == scn)
 	  shdr = NULL;
-      check_match (shdr == NULL, scn, name);
+      check_match (shdr == NULL, scn, name,&fail);
     }
 
   if (fail)
@@ -1298,7 +1299,7 @@ find_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab,
 	    }
 	}
 
-      check_match (undo_sec == NULL, scn, name);
+      check_match (undo_sec == NULL, scn, name,&fail);
     }
 
   free (undo_sections);
@@ -1377,6 +1378,33 @@ new_shstrtab (Elf *unstripped, size_t unstripped_shnum,
 
   return strtab_data;
 }
+/* Locate a matching unallocated section in SECTIONS.  */
+  inline static struct section *find_unalloc_section (const GElf_Shdr *shdr,
+					       const char *name,
+					       const char *sig,
+					       size_t nalloc,
+					       size_t stripped_shnum,
+  					       struct section *sections
+		  			      )
+    {
+      size_t l = nalloc, u = stripped_shnum - 1;
+      while (l < u)
+	{
+	  size_t i = (l + u) / 2;
+	  struct section *sec = &sections[i];
+	  int cmp = compare_unalloc_sections (shdr, &sec->shdr,
+					      name, sec->name,
+					      sig, sec->sig);
+	  if (cmp < 0)
+	    u = i;
+	  else if (cmp > 0)
+	    l = i + 1;
+	  else
+	    return sec;
+	}
+      return NULL;
+    }
+
 
 /* Fill in any SHT_NOBITS sections in UNSTRIPPED by
    copying their contents and sh_type from STRIPPED.  */
@@ -1450,30 +1478,7 @@ more sections in stripped file than debug file -- arguments reversed?"));
 	stripped_symtab = &sections[nalloc];
     }
 
-  /* Locate a matching unallocated section in SECTIONS.  */
-  inline struct section *find_unalloc_section (const GElf_Shdr *shdr,
-					       const char *name,
-					       const char *sig)
-    {
-      size_t l = nalloc, u = stripped_shnum - 1;
-      while (l < u)
-	{
-	  size_t i = (l + u) / 2;
-	  struct section *sec = &sections[i];
-	  int cmp = compare_unalloc_sections (shdr, &sec->shdr,
-					      name, sec->name,
-					      sig, sec->sig);
-	  if (cmp < 0)
-	    u = i;
-	  else if (cmp > 0)
-	    l = i + 1;
-	  else
-	    return sec;
-	}
-      return NULL;
-    }
-
-  Elf_Data *shstrtab = elf_getdata (elf_getscn (unstripped,
+    Elf_Data *shstrtab = elf_getdata (elf_getscn (unstripped,
 						unstripped_shstrndx), NULL);
   ELF_CHECK (shstrtab != NULL,
 	     _("cannot read section header string table: %s"));
@@ -1533,10 +1538,11 @@ more sections in stripped file than debug file -- arguments reversed?"));
 	    }
 	}
       else
-	{
+	{       
 	  /* Look for the section that matches.  */
 	  sec = find_unalloc_section (shdr, name,
-				      get_group_sig (unstripped, shdr));
+				      get_group_sig (unstripped, shdr),nalloc,
+				      stripped_shnum,sections);
 	  if (sec == NULL)
 	    {
 	      /* An additional unallocated section is fine if not SHT_NOBITS.
@@ -2227,22 +2233,22 @@ open_file (const char *file, bool writable)
     error (EXIT_FAILURE, errno, _("cannot open '%s'"), file);
   return fd;
 }
-
-/* Handle a pair of files we need to open by name.  */
-static void
-handle_explicit_files (const char *output_file, bool create_dirs, bool force,
-		       const char *stripped_file, const char *unstripped_file)
-{
-
-  /* Warn, and exit if not forced to continue, if some ELF header
+/* Warn, and exit if not forced to continue, if some ELF header
      sanity check for the stripped and unstripped files failed.  */
-  void warn (const char *msg)
+  static void warn (const char *msg,bool force,const char *stripped_file,const char *unstripped_file)
   {
     error (force ? 0 : EXIT_FAILURE, 0, "%s'%s' and '%s' %s%s.",
 	   force ? _("WARNING: ") : "",
 	   stripped_file, unstripped_file, msg,
 	   force ? "" : _(", use --force"));
   }
+/* Handle a pair of files we need to open by name.  */
+static void
+handle_explicit_files (const char *output_file, bool create_dirs, bool force,
+		       const char *stripped_file, const char *unstripped_file)
+{
+
+  
 
   int stripped_fd = open_file (stripped_file, false);
   Elf *stripped = elf_begin (stripped_fd, ELF_C_READ, NULL);
@@ -2264,16 +2270,19 @@ handle_explicit_files (const char *output_file, bool create_dirs, bool force,
 
       if (memcmp (stripped_ehdr.e_ident,
 		  unstripped_ehdr.e_ident, EI_NIDENT) != 0)
-	warn (_("ELF header identification (e_ident) different"));
+	warn (_("ELF header identification (e_ident) different"),force,stripped_file,unstripped_file);
 
       if (stripped_ehdr.e_type != unstripped_ehdr.e_type)
-	warn (_("ELF header type (e_type) different"));
+	warn (_("ELF header type (e_type) different"),force,stripped_file,unstripped_file);
+
+;
 
       if (stripped_ehdr.e_machine != unstripped_ehdr.e_machine)
-	warn (_("ELF header machine type (e_machine) different"));
+	warn (_("ELF header machine type (e_machine) different"),force,stripped_file,unstripped_file);
 
       if (stripped_ehdr.e_phnum < unstripped_ehdr.e_phnum)
-	warn (_("stripped program header (e_phnum) smaller than unstripped"));
+	warn (_("stripped program header (e_phnum) smaller than unstripped"),force,stripped_file,unstripped_file);
+
     }
 
   handle_file (output_file, create_dirs, stripped, &stripped_ehdr, unstripped);
@@ -2491,26 +2500,27 @@ match_module (Dwfl_Module *mod,
   return DWARF_CB_OK;
 }
 
+inline static ptrdiff_t next (ptrdiff_t offset,const struct arg_info *info,struct match_module_info *mmi)
+    {
+      return dwfl_getmodules (info->dwfl, &match_module, mmi, offset);
+    }
+
 /* Handle files opened implicitly via libdwfl.  */
 static void
 handle_implicit_modules (const struct arg_info *info)
 {
   struct match_module_info mmi = { info->args, NULL, info->match_files };
-  inline ptrdiff_t next (ptrdiff_t offset)
-    {
-      return dwfl_getmodules (info->dwfl, &match_module, &mmi, offset);
-    }
-  ptrdiff_t offset = next (0);
+    ptrdiff_t offset = next (0,info,&mmi);
   if (offset == 0)
     error (EXIT_FAILURE, 0, _("no matching modules found"));
 
   if (info->list)
     do
       list_module (mmi.found);
-    while ((offset = next (offset)) > 0);
+    while ((offset = next (offset,info,&mmi)) > 0);
   else if (info->output_dir == NULL)
     {
-      if (next (offset) != 0)
+      if (next (offset,info,&mmi) != 0)
 	error (EXIT_FAILURE, 0, _("matched more than one module"));
       handle_dwfl_module (info->output_file, false, info->force, mmi.found,
 			  info->all, info->ignore, info->relocate);
@@ -2520,7 +2530,7 @@ handle_implicit_modules (const struct arg_info *info)
       handle_output_dir_module (info->output_dir, mmi.found, info->force,
 				info->all, info->ignore,
 				info->modnames, info->relocate);
-    while ((offset = next (offset)) > 0);
+    while ((offset = next (offset,info,&mmi)) > 0);
 }
 \f
 int
diff --git a/tests/elfstrmerge.c b/tests/elfstrmerge.c
index ba0d68df..f5277c38 100644
--- a/tests/elfstrmerge.c
+++ b/tests/elfstrmerge.c
@@ -147,6 +147,50 @@ fail_elf_idx (const char *msg, const char *fname, size_t idx)
   abort();
 }
 
+/* section index mapping and sanity checking.  */
+ static size_t newsecndx (size_t secndx, const char *what, size_t widx,
+		    const char *member, size_t midx,size_t shdrstrndx,
+		    size_t shdrnum,
+		    const char *fname)
+  {
+    if (unlikely (secndx == 0 || secndx == shdrstrndx || secndx >= shdrnum))
+      {
+	/* Don't use fail... too specialized messages.  Call release
+	   outselves and then error.  Ignores midx if widx is
+	   zero.  */
+	release ();
+	if (widx == 0)
+	  error (1, 0, "%s: bad section index %zd in %s for %s",
+		 fname, secndx, what, member);
+	else if (midx == 0)
+	  error (1, 0, "%s: bad section index %zd in %s %zd for %s",
+		 fname, secndx, what, widx, member);
+	else
+	  error (1, 0, "%s: bad section index %zd in %s %zd for %s %zd",
+		 fname, secndx, what, widx, member, midx);
+      }
+
+    return secndx < shdrstrndx ? secndx : secndx - 1;
+  }
+
+
+      /* Some sections need a new data buffer because they need to
+	 manipulate the original data.  Allocate and check here, so we
+	 have a list of all data buffers we might need to release when
+	 done.  */
+     static void new_data_buf (Elf_Data *d,const char *fname,size_t ndx,
+		      size_t shdrstrndx, size_t shdrnum)
+      {
+	size_t s = d->d_size;
+	if (s == 0)
+	  fail_idx ("Expected data in section", fname, ndx);
+	void *b = malloc (d->d_size);
+	if (b == NULL)
+	  fail_idx ("Couldn't allocated buffer for section", NULL, ndx);
+	newscnbufs[newsecndx (ndx, "section", ndx, "d_buf", 0,
+			 shdrstrndx, shdrnum,fname )] = d->d_buf = b;
+      }
+
 int
 main (int argc, char **argv)
 {
@@ -325,30 +369,6 @@ main (int argc, char **argv)
   if (newstrtabdata.d_size >= shdrstrshdr->sh_size + strtabshdr->sh_size)
     fail ("Impossible, merged string table is larger", fname);
 
-  /* section index mapping and sanity checking.  */
-  size_t newsecndx (size_t secndx, const char *what, size_t widx,
-		    const char *member, size_t midx)
-  {
-    if (unlikely (secndx == 0 || secndx == shdrstrndx || secndx >= shdrnum))
-      {
-	/* Don't use fail... too specialized messages.  Call release
-	   outselves and then error.  Ignores midx if widx is
-	   zero.  */
-	release ();
-	if (widx == 0)
-	  error (1, 0, "%s: bad section index %zd in %s for %s",
-		 fname, secndx, what, member);
-	else if (midx == 0)
-	  error (1, 0, "%s: bad section index %zd in %s %zd for %s",
-		 fname, secndx, what, widx, member);
-	else
-	  error (1, 0, "%s: bad section index %zd in %s %zd for %s %zd",
-		 fname, secndx, what, widx, member, midx);
-      }
-
-    return secndx < shdrstrndx ? secndx : secndx - 1;
-  }
-
   struct stat st;
   if (fstat (fd, &st) != 0)
     fail_errno("Couldn't fstat", fname);
@@ -392,7 +412,9 @@ main (int argc, char **argv)
   newehdr.e_flags = ehdr.e_flags;
 
   /* The new file uses the new strtab as shstrtab.  */
-  size_t newstrtabndx = newsecndx (strtabndx, "ehdr", 0, "e_shstrndx", 0);
+
+  size_t newstrtabndx = newsecndx (strtabndx, "ehdr", 0, "e_shstrndx", 0,shdrstrndx,
+		  shdrnum,fname);
   if (newstrtabndx < SHN_LORESERVE)
     newehdr.e_shstrndx = newstrtabndx;
   else
@@ -459,30 +481,19 @@ main (int argc, char **argv)
       newshdr.sh_flags = shdr->sh_flags;
       newshdr.sh_addr = shdr->sh_addr;
       newshdr.sh_size = shdr->sh_size;
+
       if (shdr->sh_link != 0)
-	newshdr.sh_link = newsecndx (shdr->sh_link, "shdr", ndx, "sh_link", 0);
+	newshdr.sh_link = newsecndx (shdr->sh_link, "shdr", ndx, "sh_link", 0,
+			shdrstrndx,shdrnum,fname);
       else
 	newshdr.sh_link = 0;
       if (SH_INFO_LINK_P (shdr) && shdr->sh_info != 0)
-	newshdr.sh_info = newsecndx (shdr->sh_info, "shdr", ndx, "sh_info", 0);
+	newshdr.sh_info = newsecndx (shdr->sh_info, "shdr", ndx, "sh_info", 0,
+			shdrstrndx,shdrnum,fname);
       else
 	newshdr.sh_info = shdr->sh_info;
       newshdr.sh_entsize = shdr->sh_entsize;
 
-      /* Some sections need a new data buffer because they need to
-	 manipulate the original data.  Allocate and check here, so we
-	 have a list of all data buffers we might need to release when
-	 done.  */
-      void new_data_buf (Elf_Data *d)
-      {
-	size_t s = d->d_size;
-	if (s == 0)
-	  fail_idx ("Expected data in section", fname, ndx);
-	void *b = malloc (d->d_size);
-	if (b == NULL)
-	  fail_idx ("Couldn't allocated buffer for section", NULL, ndx);
-	newscnbufs[newsecndx (ndx, "section", ndx, "d_buf", 0)] = d->d_buf = b;
-      }
 
       Elf_Data *newdata = elf_newdata (newscn);
       if (newdata == NULL)
@@ -510,7 +521,7 @@ main (int argc, char **argv)
 		const bool update_name = shdr->sh_link == strtabndx;
 		if (update_name && ndx != symtabndx)
 		  fail ("Only one symbol table using strtab expected", fname);
-		new_data_buf (newdata);
+		new_data_buf (newdata,fname,ndx,shdrstrndx,shdrnum);
 		size_t syms = (data->d_size
 			       / gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT));
 		for (size_t i = 0; i < syms; i++)
@@ -527,7 +538,8 @@ main (int argc, char **argv)
 		    else if (sym.st_shndx != SHN_UNDEF
 			     && sym.st_shndx < SHN_LORESERVE)
 		      sym.st_shndx = newsecndx (sym.st_shndx, "section", ndx,
-						"symbol", i);
+						"symbol", i,
+						shdrstrndx, shdrnum,fname );
 		    if (update_name && sym.st_name != 0)
 		      sym.st_name = dwelf_strent_off (symstrents[i]);
 
@@ -541,7 +553,7 @@ main (int argc, char **argv)
 
 	    case SHT_GROUP:
 	      {
-		new_data_buf (newdata);
+		new_data_buf (newdata,fname,ndx,shdrstrndx,shdrnum);
 		/* A section group contains Elf32_Words. The first
 		   word is a falg value, the rest of the words are
 		   indexes of the sections belonging to the group.  */
@@ -553,13 +565,14 @@ main (int argc, char **argv)
 		newgroup[0] = group[0];
 		for (size_t i = 1; i < words; i++)
 		  newgroup[i] = newsecndx (group[i], "section", ndx,
-					   "group", i);
+					   "group", i,
+					   shdrstrndx, shdrnum,fname );
 	      }
 	      break;
 
 	    case SHT_SYMTAB_SHNDX:
 	      {
-		new_data_buf (newdata);
+		new_data_buf (newdata,fname,ndx,shdrstrndx,shdrnum);
 		/* A SHNDX just contains an array of section indexes
 		   for the corresponding symbol table.  The entry is
 		   SHN_UNDEF unless the corresponding symbol is
@@ -572,7 +585,8 @@ main (int argc, char **argv)
 		    newshndx[i] = SHN_UNDEF;
 		  else
 		    newshndx[i] = newsecndx (shndx[i], "section", ndx,
-					     "shndx", i);
+					     "shndx", i,
+					     shdrstrndx, shdrnum,fname );
 	      }
 	      break;
 
diff --git a/tests/zstrptr.c b/tests/zstrptr.c
index 6d8e19f7..173c9426 100644
--- a/tests/zstrptr.c
+++ b/tests/zstrptr.c
@@ -30,6 +30,26 @@
 #include ELFUTILS_HEADER(elf)
 #include <gelf.h>
 
+static void print_strings (Elf_Scn *scn,size_t ndx,Elf *elf)
+  {
+    GElf_Shdr shdr_mem;
+    GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+    printf ("Strings in section %zd (%s):\n", ndx,
+	    ((shdr->sh_flags & SHF_COMPRESSED) != 0
+	     ? "compressed" : "uncompressed"));
+
+    size_t off = 0;
+    const char *str = elf_strptr (elf, ndx, off);
+    while (str != NULL)
+      {
+	printf ("[%zx] '%s'\n", off, str);
+	off += strlen (str) + 1;
+	str = elf_strptr (elf, ndx, off);
+      }
+  }
+
+
 int
 main (int argc, char *argv[])
 {
@@ -79,38 +99,20 @@ main (int argc, char *argv[])
       exit (1);
     }
 
-  void print_strings (void)
-  {
-    GElf_Shdr shdr_mem;
-    GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
-
-    printf ("Strings in section %zd (%s):\n", ndx,
-	    ((shdr->sh_flags & SHF_COMPRESSED) != 0
-	     ? "compressed" : "uncompressed"));
-
-    size_t off = 0;
-    const char *str = elf_strptr (elf, ndx, off);
-    while (str != NULL)
-      {
-	printf ("[%zx] '%s'\n", off, str);
-	off += strlen (str) + 1;
-	str = elf_strptr (elf, ndx, off);
-      }
-  }
-
+  
   if (elf_compress (scn, ELFCOMPRESS_ZLIB, 0) < 0)
     {
       printf ("Couldn't compress section %zd: %s\n", ndx, elf_errmsg (-1));
       exit (1);
     }
-  print_strings ();
+  print_strings (scn,ndx,elf);
 
   if (elf_compress (scn, 0, 0) < 0)
     {
       printf ("Couldn't decompress section %zd: %s\n", ndx, elf_errmsg (-1));
       exit (1);
     }
-  print_strings ();
+  print_strings (scn,ndx,elf);
 
   if (elf_end (elf) != 0)
     {
-- 
2.25.1


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 14/14] segment_report_module: Inline consider_phdr() into only caller
  2020-11-12 16:52   ` Navin P
@ 2020-11-13  7:41     ` Timm Bäder
  2020-11-13  8:00       ` Navin P
  0 siblings, 1 reply; 25+ messages in thread
From: Timm Bäder @ 2020-11-13  7:41 UTC (permalink / raw)
  To: Navin P; +Cc: elfutils-devel

On 12/11/2020 17:52, Navin P wrote:
> Hi,
>   I already have a patch that makes elfutils compile with clang. Since
> you are working
> this will be of use to you. I've attached the patch since it is big.
> 
>   Here are some of the changes
>   1. All functions at file scope have static qualifier so that no
> collison with other files.
>   2. Non global variables declared in the outer function should be
> passed as pointer variable
>      in the new outer file scope function whenever they are assigned in
> the nested  function. The
>      argument  addition in new functions are at the end.
> 
> 3.  With the applied patch above , gcc passes all 220 tests where
> clang fails 3 tests which
>     is due to llvm_addrsig (change in libelf/elf.h ) and other 2 tests
> are error related to
> .rela.eh_frame.

Thanks, Navin. Has this been proposed for inclusion in elfutils? What's
the status on that? Or are you just keeping this locally?

Looking at the patch, I'm not really a fan of a few of those changes,
from a code point of view. consider_phdr() takes 35 arguments now
for example.

Do you have more information on the test failures? Are they caused by
LLVM/clang bugs?



Thanks,
Timm


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 14/14] segment_report_module: Inline consider_phdr() into only caller
  2020-11-13  7:41     ` Timm Bäder
@ 2020-11-13  8:00       ` Navin P
  0 siblings, 0 replies; 25+ messages in thread
From: Navin P @ 2020-11-13  8:00 UTC (permalink / raw)
  To: Timm Bäder; +Cc: elfutils-devel

On Fri, Nov 13, 2020, 13:11 Timm Bäder <tbaeder@redhat.com> wrote:

> On 12/11/2020 17:52, Navin P wrote:
> > Hi,
> >   I already have a patch that makes elfutils compile with clang. Since
> > you are working
> > this will be of use to you. I've attached the patch since it is big.
> >
> >   Here are some of the changes
> >   1. All functions at file scope have static qualifier so that no
> > collison with other files.
> >   2. Non global variables declared in the outer function should be
> > passed as pointer variable
> >      in the new outer file scope function whenever they are assigned in
> > the nested  function. The
> >      argument  addition in new functions are at the end.
> >
> > 3.  With the applied patch above , gcc passes all 220 tests where
> > clang fails 3 tests which
> >     is due to llvm_addrsig (change in libelf/elf.h ) and other 2 tests
> > are error related to
> > .rela.eh_frame.
>
> Thanks, Navin. Has this been proposed for inclusion in elfutils? What's
> the status on that? Or are you just keeping this locally?
>
> Locally.  It is not proposed for inclusion in elfutils but you can  fix
few things or compare/modify and include it.


> Looking at the patch, I'm not really a fan of a few of those changes,
> from a code point of view. consider_phdr() takes 35 arguments now
> for example.
>
 You have few options like collect them in a struct and pass a pointer to
struct with
those members as fields.
Create static global variables but it is bound to collision within same
file.
 Macros are not a good idea because if you have return in a nested func
it returns to the outer func ,where as in  macro it returns from the outer
func.

Once you have all the tests passing , you can refactor it. or you can fix
it and
make the tests pass.

>
> Do you have more information on the test failures? Are they caused by
> LLVM/clang bugs?
>
Well i don't think they are compiler bugs but rather extra output from
utilities
is causing the diff to fail like elflint size.o  . I think we are good from
that
perspective unless i missed something .

With patch applied gcc passes all tests, clang fails 3 out of 220.

>
>
>
> Thanks,
> Timm
>
>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Removing gnu99 constructs from elfutils
  2020-11-12 15:03 Removing gnu99 constructs from elfutils Timm Bäder
                   ` (13 preceding siblings ...)
  2020-11-12 15:04 ` [PATCH 14/14] segment_report_module: Inline consider_phdr() " Timm Bäder
@ 2020-11-13 12:38 ` Mark Wielaard
  2020-11-13 14:09   ` Timm Bäder
  14 siblings, 1 reply; 25+ messages in thread
From: Mark Wielaard @ 2020-11-13 12:38 UTC (permalink / raw)
  To: Timm Bäder, elfutils-devel

Hi Timm,

On Thu, 2020-11-12 at 16:03 +0100, Timm Bäder via Elfutils-devel wrote:
> I'm looking into removing both the nested functions as well as
> variable-length arrays in the elfutils source code, so it can be
> built
> using clang. This is a continuation of
> https://sourceware.org/bugzilla/show_bug.cgi?id=24964 basically.

OK. The mail subject is a little misleading, this is far from turning
the code base into ISO C99. gnu99 is much more than those two features:
https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html

Personally I think it would be nicer if compilers that claim to support
gnu99 implemented them all instead of just cherry-picking some. And the
usage of these particular features does make the code simpler/nicer
(IMHO).

> I did try to incorporate some cleanup commits as well so the result does
> not get too ugly. Some of the nested functions have quite a few hidden
> dependencies on the surrounding code.
> 
> I started with libdwfl/dwfl_segment_report_module.c but am planning on
> converting everything else as well of course.
> 
> What do you think?

See above for what I really think :)

That said, I spot checked some of the patches and they actually look
nice enough. My fear was that this would create various global
functions with dozens of arguments, but it seems you avoided that in
most cases.

Thanks for splitting this up into easily reviewable patches. I'll go
over them next week. I haven't immediately seen anything objectionable,
so I think your approach is good.

Maybe you can work together with Navin to untangle his large patch in a
similar way.

Thanks,

Mark

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: Removing gnu99 constructs from elfutils
  2020-11-13 12:38 ` Removing gnu99 constructs from elfutils Mark Wielaard
@ 2020-11-13 14:09   ` Timm Bäder
  0 siblings, 0 replies; 25+ messages in thread
From: Timm Bäder @ 2020-11-13 14:09 UTC (permalink / raw)
  To: Mark Wielaard, elfutils-devel

On 13/11/2020 13:38, Mark Wielaard wrote:
> OK. The mail subject is a little misleading, this is far from turning
> the code base into ISO C99. gnu99 is much more than those two features:
> https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html

Right, I wasn't trying to get rid of all the gnu99 features used in the
code base.

> 
> Personally I think it would be nicer if compilers that claim to support
> gnu99 implemented them all instead of just cherry-picking some.

I agree, but even if clang stops claiming it supports gnu99, we still
need to stop using those features if elfutils should be compile-able
with clang.

> Thanks for splitting this up into easily reviewable patches. I'll go
> over them next week. I haven't immediately seen anything objectionable,
> so I think your approach is good.
> 
> Maybe you can work together with Navin to untangle his large patch in a
> similar way.

I have a local working build now and around 45 patches. I did run into
the test suite failures Navin described however and am now looking at
what exactly is wrong there.

Next week sounds fine with me, I'll wait for feedback on the general
approach before posting the rest of the patches.


Thanks,
Timm

-- 
Red Hat GmbH, http://www.de.redhat.com/, Registered seat: Grasbrunn,
Commercial register: Amtsgericht Muenchen, HRB 153243,
Managing Directors: Charles Cachera, Michael O'Neill, Tom Savage, Eric 
Shander


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 01/14] segment_report_module: Get rid of variable-length arrays
  2020-11-12 15:03 ` [PATCH 01/14] segment_report_module: Get rid of variable-length arrays Timm Bäder
@ 2020-11-18 23:04   ` Mark Wielaard
  0 siblings, 0 replies; 25+ messages in thread
From: Mark Wielaard @ 2020-11-18 23:04 UTC (permalink / raw)
  To: Timm Bäder; +Cc: elfutils-devel

Hi Tim,

On Thu, Nov 12, 2020 at 04:03:59PM +0100, Timm Bäder via Elfutils-devel wrote:
> This prevents a jump which is needed in a later patch.

I liked them better when they defined the array size, since it shows
the array size equals the for loop bounds. But the usage does look
nicer now. I added a ChangeLog entry and pushed.

Thanks,

Mark

P.S. sourceware mangles the From header which makes applying patches
     with git am somewhat cumbersome. Could you use a different email
     address (that doesn't enforce dkim) or use git send-email
     --from=<address> to get the From header in the actual email body?


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 02/14] segment_report_module: Pull segment_read into file scope
  2020-11-12 15:04 ` [PATCH 02/14] segment_report_module: Pull segment_read into file scope Timm Bäder
@ 2020-11-18 23:18   ` Mark Wielaard
  0 siblings, 0 replies; 25+ messages in thread
From: Mark Wielaard @ 2020-11-18 23:18 UTC (permalink / raw)
  To: Timm Bäder; +Cc: elfutils-devel

Hi Timm,

On Thu, Nov 12, 2020 at 04:04:00PM +0100, Timm Bäder via Elfutils-devel wrote:
> In preparation of getting rid of nested functions

I actually like the nested functions in this case, they simply act as
lambdas. But if you want to get rid of this one then can we inline
the (*memory_callback) (dwfl, segndx, buffer, buffer_available, ...)
call instead of introducing a new top-level function that shuffles the
arguments around?

So instead of:

> -  if (segment_read (ndx, &buffer, &buffer_available,
> +  if (segment_read (dwfl, memory_callback, memory_callback_arg,
> +                    ndx, &buffer, &buffer_available,
>  		    start, sizeof (Elf64_Ehdr))

say:

  if (! (*memory_callback) (dwfl, ndx, &buffer, &buffer_available,
      			    start, sizeof (Elf64_Ehdr), memory_callback_arg))

Thanks,

Mark

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 03/14] segment_report_module: Remove nested finish() function
  2020-11-12 15:04 ` [PATCH 03/14] segment_report_module: Remove nested finish() function Timm Bäder
@ 2020-11-19 11:18   ` Mark Wielaard
  0 siblings, 0 replies; 25+ messages in thread
From: Mark Wielaard @ 2020-11-19 11:18 UTC (permalink / raw)
  To: Timm Bäder, elfutils-devel

On Thu, 2020-11-12 at 16:04 +0100, Timm Bäder via Elfutils-devel wrote:
> This works just as well with a goto-out style label.

And is more in line with how we do error handling in other parts of the
code. I added a ChangeLog entry and pushed.

Thanks,

Mark

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 04/14] segment_report_module: Remove nested release_buffer() function
  2020-11-12 15:04 ` [PATCH 04/14] segment_report_module: Remove nested release_buffer() function Timm Bäder
@ 2020-11-19 11:24   ` Mark Wielaard
  0 siblings, 0 replies; 25+ messages in thread
From: Mark Wielaard @ 2020-11-19 11:24 UTC (permalink / raw)
  To: Timm Bäder, elfutils-devel

Hi Timm,

On Thu, 2020-11-12 at 16:04 +0100, Timm Bäder via Elfutils-devel wrote:
> diff --git a/libdwfl/dwfl_segment_report_module.c
> b/libdwfl/dwfl_segment_report_module.c
> index d06d0ba0..ba11b60a 100644
> --- a/libdwfl/dwfl_segment_report_module.c
> +++ b/libdwfl/dwfl_segment_report_module.c
> @@ -267,13 +267,6 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
>  
>    GElf_Addr start = dwfl->lookup_addr[segment];
>  
> -  inline void release_buffer (void **buffer, size_t *buffer_available)
> -  {
> -    if (*buffer != NULL)
> -      (void) segment_read (dwfl, memory_callback, memory_callback_arg,
> -                           -1, buffer, buffer_available, 0, 0);
> -  }

This depends on [PATCH 02/14] segment_report_module: Pull segment_read
into file scope. For which I rather see us use a direct call to
(*memory_callback). And release_buffer is basically segment_read (with
a *buffer != NULL check), which is basically a (*memory_callback) call.
So if possible I rather see us use something like:
  if (*buffer != NULL) (*memory_callback) (...)
directly.

Thanks,

Mark

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 05/14] segment_report_module: Pull finish_portion() info file scope
  2020-11-12 15:04 ` [PATCH 05/14] segment_report_module: Pull finish_portion() info file scope Timm Bäder
@ 2020-11-19 11:48   ` Mark Wielaard
  0 siblings, 0 replies; 25+ messages in thread
From: Mark Wielaard @ 2020-11-19 11:48 UTC (permalink / raw)
  To: Timm Bäder, elfutils-devel

Hi Timm,

On Thu, 2020-11-12 at 16:04 +0100, Timm Bäder via Elfutils-devel wrote:
> +static inline void
> +finish_portion (Dwfl *dwfl,
> +                Dwfl_Memory_Callback *memory_callback,
> +                void *memory_callback_arg,
> +                void **data, size_t *data_size)
> +{
> +  if (*data_size != 0 && *data != NULL)
> +    (void) segment_read (dwfl, memory_callback, memory_callback_arg,
> +                         -1, data, data_size, 0, 0);
> +}

And again I would like to see this simply inlined instead of
introducing a top-level function that just takes some arguments that it
then rearranges to call a different function that again rearranges its
arguments to call one of the arguments.

I admit this messes up the rest of the patch series, so that none of it
applies cleanly anymore. Apologies.

I do like your creation of single loops, so you can inline some of the
inner functions directly in the loop instead of having multiple
callers. I think all those look good.

The only two commits I have to think about are:
[06/14] segment_report_module: Pull read_portion() into file scope
[07/14] segment_report_module: Use a struct for build id information

Which feel a little clunky to me. But I can probably be convinced they
are OK improvements if you simply say you disagree and resubmit them as
is.

Thanks,

Mark

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2020-11-19 11:48 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-12 15:03 Removing gnu99 constructs from elfutils Timm Bäder
2020-11-12 15:03 ` [PATCH 01/14] segment_report_module: Get rid of variable-length arrays Timm Bäder
2020-11-18 23:04   ` Mark Wielaard
2020-11-12 15:04 ` [PATCH 02/14] segment_report_module: Pull segment_read into file scope Timm Bäder
2020-11-18 23:18   ` Mark Wielaard
2020-11-12 15:04 ` [PATCH 03/14] segment_report_module: Remove nested finish() function Timm Bäder
2020-11-19 11:18   ` Mark Wielaard
2020-11-12 15:04 ` [PATCH 04/14] segment_report_module: Remove nested release_buffer() function Timm Bäder
2020-11-19 11:24   ` Mark Wielaard
2020-11-12 15:04 ` [PATCH 05/14] segment_report_module: Pull finish_portion() info file scope Timm Bäder
2020-11-19 11:48   ` Mark Wielaard
2020-11-12 15:04 ` [PATCH 06/14] segment_report_module: Pull read_portion() into " Timm Bäder
2020-11-12 15:04 ` [PATCH 07/14] segment_report_module: Use a struct for build id information Timm Bäder
2020-11-12 15:04 ` [PATCH 08/14] segment_report_module: Pull consider_notes() into file scope Timm Bäder
2020-11-12 15:04 ` [PATCH 09/14] segment_report_module: Get rid of nested final_read() function Timm Bäder
2020-11-12 15:04 ` [PATCH 10/14] segment_report_module: Use one loop for p32/p64 arrays Timm Bäder
2020-11-12 15:04 ` [PATCH 11/14] segment_report_module: Inline read_phdr() into only caller Timm Bäder
2020-11-12 15:04 ` [PATCH 12/14] segment_report_module: Unify d32/d64 loops Timm Bäder
2020-11-12 15:04 ` [PATCH 13/14] segment_report_module: Inline consider_dyn() into only caller Timm Bäder
2020-11-12 15:04 ` [PATCH 14/14] segment_report_module: Inline consider_phdr() " Timm Bäder
2020-11-12 16:52   ` Navin P
2020-11-13  7:41     ` Timm Bäder
2020-11-13  8:00       ` Navin P
2020-11-13 12:38 ` Removing gnu99 constructs from elfutils Mark Wielaard
2020-11-13 14:09   ` Timm Bäder

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).