This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Move nested functions in elf-from-memory.c to file scope.


* Move nested function 'handle_segment' to the file scope
  to compile with clang.

Signed-off-by: Chih-Hung Hsieh <chh@google.com>
---
 libdwfl/ChangeLog         |   6 ++
 libdwfl/elf-from-memory.c | 248 +++++++++++++++++++++++++++-------------------
 2 files changed, 150 insertions(+), 104 deletions(-)

diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 163a6f1..6e89cc0 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,9 @@
+2015-11-18  Chih-Hung Hsieh <chh@google.com>
+
+	* elf-from-memory.c (elf_from_remote_memory): Move nested functions
+	'handle_segment' to the file scope as 'do_check_segment' and
+	'do_read_segment'.
+
 2015-11-13  Chih-Hung Hsieh <chh@google.com>
 
 	* gzip.c (unzip): Move nested functions to file scope.
diff --git a/libdwfl/elf-from-memory.c b/libdwfl/elf-from-memory.c
index dd42e95..1f00ce9 100644
--- a/libdwfl/elf-from-memory.c
+++ b/libdwfl/elf-from-memory.c
@@ -38,6 +38,79 @@
 #include <stdlib.h>
 #include <string.h>
 
+typedef ssize_t (*ptr_read_memory_func) (void *arg, void *data,
+					 GElf_Addr address,
+					 size_t minread,
+					 size_t maxread);
+
+struct check_read_segment_state {
+  GElf_Addr ehdr_vma;
+  GElf_Xword pagesize;
+  GElf_Off segments_end;
+  GElf_Off segments_end_mem;
+  size_t contents_size;
+  bool found_base;
+  GElf_Addr loadbase;
+  void *arg;
+  unsigned char *buffer;
+  ssize_t nread;
+  ptr_read_memory_func read_memory;
+};
+
+/* 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.  */
+static inline bool
+do_check_segment (struct check_read_segment_state *state,
+                  GElf_Addr vaddr, GElf_Off offset,
+                  GElf_Xword filesz, GElf_Xword memsz)
+{
+  /* Sanity check the segment load aligns with the pagesize.  */
+  if (((vaddr - offset) & (state->pagesize - 1)) != 0)
+    return true;
+
+  GElf_Off segment_end = ((offset + filesz + state->pagesize - 1)
+			  & - state->pagesize);
+
+  if (segment_end > (GElf_Off) state->contents_size)
+    state->contents_size = segment_end;
+
+  if (!state->found_base && (offset & - state->pagesize) == 0)
+    {
+      state->loadbase = state->ehdr_vma - (vaddr & - state->pagesize);
+      state->found_base = true;
+    }
+
+  state->segments_end = offset + filesz;
+  state->segments_end_mem = offset + memsz;
+  return false;
+}
+
+#define check_segment(vaddr, offset, filesz, memsz) \
+  do_check_segment (&state, vaddr, offset, filesz, memsz)
+
+/* Reads the given segment.  Returns true if reading fails,
+   false otherwise.  */
+static inline bool
+do_read_segment (struct check_read_segment_state *state,
+                 GElf_Addr vaddr, GElf_Off offset,
+                 GElf_Xword filesz)
+{
+  GElf_Off start = offset & - state->pagesize;
+  GElf_Off end = (offset + filesz + state->pagesize - 1) & - state->pagesize;
+  if (end > (GElf_Off) state->contents_size)
+    end = state->contents_size;
+  state->nread = (*state->read_memory) (
+      state->arg, state->buffer + start,
+      (state->loadbase + vaddr) & - state->pagesize,
+      end - start, end - start);
+  return state->nread <= 0;
+}
+
+#define read_segment(vaddr, offset, filesz) \
+  do_read_segment (&state, vaddr, offset, filesz)
+
 /* 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
@@ -54,15 +127,27 @@
    segments.  */
 
 Elf *
-elf_from_remote_memory (GElf_Addr ehdr_vma,
-			GElf_Xword pagesize,
+elf_from_remote_memory (GElf_Addr _ehdr_vma,
+			GElf_Xword _pagesize,
 			GElf_Addr *loadbasep,
-			ssize_t (*read_memory) (void *arg, void *data,
-						GElf_Addr address,
-						size_t minread,
-						size_t maxread),
-			void *arg)
+                        ptr_read_memory_func _read_memory,
+			void *_arg)
 {
+  struct check_read_segment_state state =
+    {
+      .ehdr_vma = _ehdr_vma,
+      .pagesize = _pagesize,
+      .segments_end = 0,
+      .segments_end_mem = 0,
+      .contents_size = 0,
+      .found_base = false,
+      .loadbase = _ehdr_vma,
+      .arg = _arg,
+      .buffer = NULL,
+      .nread = 0,
+      .read_memory = _read_memory
+    };
+
   /* We might have to reserve some memory for the phdrs.  Set to NULL
      here so we can always safely free it.  */
   void *phdrsp = NULL;
@@ -70,29 +155,29 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
   /* First read in the file header and check its sanity.  */
 
   const size_t initial_bufsize = 256;
-  unsigned char *buffer = malloc (initial_bufsize);
-  if (unlikely (buffer == NULL))
+  state.buffer = malloc (initial_bufsize);
+  if (unlikely (state.buffer == NULL))
     {
     no_memory:
       __libdwfl_seterrno (DWFL_E_NOMEM);
       return NULL;
     }
 
-  ssize_t nread = (*read_memory) (arg, buffer, ehdr_vma,
-				  sizeof (Elf32_Ehdr), initial_bufsize);
-  if (nread <= 0)
+  state.nread = (*state.read_memory) (state.arg, state.buffer, state.ehdr_vma,
+				      sizeof (Elf32_Ehdr), initial_bufsize);
+  if (state.nread <= 0)
     {
     read_error:
-      free (buffer);
+      free (state.buffer);
       free (phdrsp);
-      __libdwfl_seterrno (nread < 0 ? DWFL_E_ERRNO : DWFL_E_TRUNCATED);
+      __libdwfl_seterrno (state.nread < 0 ? DWFL_E_ERRNO : DWFL_E_TRUNCATED);
       return NULL;
     }
 
-  if (memcmp (buffer, ELFMAG, SELFMAG) != 0)
+  if (memcmp (state.buffer, ELFMAG, SELFMAG) != 0)
     {
     bad_elf:
-      free (buffer);
+      free (state.buffer);
       free (phdrsp);
       __libdwfl_seterrno (DWFL_E_BADELF);
       return NULL;
@@ -108,7 +193,7 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
   Elf_Data xlatefrom =
     {
       .d_type = ELF_T_EHDR,
-      .d_buf = buffer,
+      .d_buf = state.buffer,
       .d_version = EV_CURRENT,
     };
   Elf_Data xlateto =
@@ -124,11 +209,11 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
   uint_fast16_t phentsize;
   GElf_Off shdrs_end;
 
-  switch (buffer[EI_CLASS])
+  switch (state.buffer[EI_CLASS])
     {
     case ELFCLASS32:
       xlatefrom.d_size = sizeof (Elf32_Ehdr);
-      if (elf32_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL)
+      if (elf32_xlatetom (&xlateto, &xlatefrom, state.buffer[EI_DATA]) == NULL)
 	{
 	libelf_error:
 	  __libdwfl_seterrno (DWFL_E_LIBELF);
@@ -144,7 +229,7 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
 
     case ELFCLASS64:
       xlatefrom.d_size = sizeof (Elf64_Ehdr);
-      if (elf64_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL)
+      if (elf64_xlatetom (&xlateto, &xlatefrom, state.buffer[EI_DATA]) == NULL)
 	goto libelf_error;
       phoff = ehdr.e64.e_phoff;
       phnum = ehdr.e64.e_phnum;
@@ -165,44 +250,46 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
   xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR;
   xlatefrom.d_size = phnum * phentsize;
 
-  if ((size_t) nread >= phoff + phnum * phentsize)
+  if ((size_t) state.nread >= phoff + phnum * phentsize)
     /* We already have all the phdrs from the initial read.  */
-    xlatefrom.d_buf = buffer + phoff;
+    xlatefrom.d_buf = state.buffer + phoff;
   else
     {
       /* Read in the program headers.  */
 
       if (initial_bufsize < phnum * phentsize)
 	{
-	  unsigned char *newbuf = realloc (buffer, phnum * phentsize);
+	  unsigned char *newbuf = realloc (state.buffer, phnum * phentsize);
 	  if (newbuf == NULL)
 	    {
-	      free (buffer);
+	      free (state.buffer);
 	      free (phdrsp);
 	      goto no_memory;
 	    }
-	  buffer = newbuf;
+	  state.buffer = newbuf;
 	}
-      nread = (*read_memory) (arg, buffer, ehdr_vma + phoff,
-			      phnum * phentsize, phnum * phentsize);
-      if (nread <= 0)
+      state.nread = (*state.read_memory) (state.arg, state.buffer,
+                                          state.ehdr_vma + phoff,
+                                          phnum * phentsize,
+                                          phnum * phentsize);
+      if (state.nread <= 0)
 	goto read_error;
 
-      xlatefrom.d_buf = buffer;
+      xlatefrom.d_buf = state.buffer;
     }
 
   bool class32 = ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32;
   size_t phdr_size = class32 ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr);
   if (unlikely (phnum > SIZE_MAX / phdr_size))
     {
-      free (buffer);
+      free (state.buffer);
       goto no_memory;
     }
   const size_t phdrsp_bytes = phnum * phdr_size;
   phdrsp = malloc (phdrsp_bytes);
   if (unlikely (phdrsp == NULL))
     {
-      free (buffer);
+      free (state.buffer);
       goto no_memory;
     }
 
@@ -210,51 +297,19 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
   xlateto.d_size = phdrsp_bytes;
 
   /* Scan for PT_LOAD segments to find the total size of the file image.  */
-  size_t contents_size = 0;
-  GElf_Off segments_end = 0;
-  GElf_Off segments_end_mem = 0;
-  GElf_Addr loadbase = ehdr_vma;
-  bool found_base = false;
   Elf32_Phdr (*p32)[phnum] = phdrsp;
   Elf64_Phdr (*p64)[phnum] = phdrsp;
+  state.loadbase = state.ehdr_vma;
   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 (check_segment ((*p32)[i].p_vaddr, (*p32)[i].p_offset,
+			     (*p32)[i].p_filesz, (*p32)[i].p_memsz))
 	    goto bad_elf;
       break;
 
@@ -264,8 +319,8 @@ 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 (check_segment ((*p64)[i].p_vaddr, (*p64)[i].p_offset,
+			     (*p64)[i].p_filesz, (*p64)[i].p_memsz))
 	    goto bad_elf;
       break;
 
@@ -278,22 +333,22 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
      that are off the end of the file.  However, if the extra bit in that
      page includes the section headers and the memory isn't extended (which
      might indicate it will have been reused otherwise), keep them.  */
-  if ((GElf_Off) contents_size > segments_end
-      && (GElf_Off) contents_size >= shdrs_end
-      && segments_end == segments_end_mem)
+  if ((GElf_Off) state.contents_size > state.segments_end
+      && (GElf_Off) state.contents_size >= shdrs_end
+      && state.segments_end == state.segments_end_mem)
     {
-      contents_size = segments_end;
-      if ((GElf_Off) contents_size < shdrs_end)
-	contents_size = shdrs_end;
+      state.contents_size = state.segments_end;
+      if ((GElf_Off) state.contents_size < shdrs_end)
+	state.contents_size = shdrs_end;
     }
   else
-    contents_size = segments_end;
+    state.contents_size = state.segments_end;
 
-  free (buffer);
+  free (state.buffer);
 
   /* Now we know the size of the whole image we want read in.  */
-  buffer = calloc (1, contents_size);
-  if (buffer == NULL)
+  state.buffer = calloc (1, state.contents_size);
+  if (state.buffer == NULL)
     {
       free (phdrsp);
       goto no_memory;
@@ -301,31 +356,16 @@ 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 (read_segment ((*p32)[i].p_vaddr, (*p32)[i].p_offset,
+			    (*p32)[i].p_filesz))
 	    goto read_error;
 
       /* If the segments visible in memory didn't include the section
 	 headers, then clear them from the file header.  */
-      if (contents_size < shdrs_end)
+      if (state.contents_size < shdrs_end)
 	{
 	  ehdr.e32.e_shoff = 0;
 	  ehdr.e32.e_shnum = 0;
@@ -337,7 +377,7 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
       xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR;
       xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e32;
       xlatefrom.d_buf = &ehdr.e32;
-      xlateto.d_buf = buffer;
+      xlateto.d_buf = state.buffer;
       if (elf32_xlatetof (&xlateto, &xlatefrom,
 			  ehdr.e32.e_ident[EI_DATA]) == NULL)
 	goto libelf_error;
@@ -346,13 +386,13 @@ 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 (read_segment ((*p64)[i].p_vaddr, (*p64)[i].p_offset,
+			    (*p64)[i].p_filesz))
 	    goto read_error;
 
       /* If the segments visible in memory didn't include the section
 	 headers, then clear them from the file header.  */
-      if (contents_size < shdrs_end)
+      if (state.contents_size < shdrs_end)
 	{
 	  ehdr.e64.e_shoff = 0;
 	  ehdr.e64.e_shnum = 0;
@@ -364,7 +404,7 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
       xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR;
       xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e64;
       xlatefrom.d_buf = &ehdr.e64;
-      xlateto.d_buf = buffer;
+      xlateto.d_buf = state.buffer;
       if (elf64_xlatetof (&xlateto, &xlatefrom,
 			  ehdr.e64.e_ident[EI_DATA]) == NULL)
 	goto libelf_error;
@@ -380,15 +420,15 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
 
   /* Now we have the image.  Open libelf on it.  */
 
-  Elf *elf = elf_memory ((char *) buffer, contents_size);
+  Elf *elf = elf_memory ((char *) state.buffer, state.contents_size);
   if (elf == NULL)
     {
-      free (buffer);
+      free (state.buffer);
       goto libelf_error;
     }
 
   elf->flags |= ELF_F_MALLOCED;
   if (loadbasep != NULL)
-    *loadbasep = loadbase;
+    *loadbasep = state.loadbase;
   return elf;
 }
-- 
2.6.0.rc2.230.g3dd15c0

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]