From 47a9587f4c8aa10b155b054e892109b57c6e0ad4 Mon Sep 17 00:00:00 2001 From: Yunlian Jiang Date: Fri, 28 Jul 2017 09:27:20 -0700 Subject: [PATCH] libdwfl: move nested function in dwfl_segment_report_module.c * Move nested function 'segment_read' to file scope to compile with clang. * Move nested function 'release_buffer' to file scope to compile with clang. * Move nested function 'read_portion' to file scope to compile with clang. * Move nested function 'finish_portion' to file scope to compile with clang. Signed-off-by: Yunlian Jiang --- libdwfl/dwfl_segment_report_module.c | 198 +++++++++++++++++++++-------------- 1 file changed, 120 insertions(+), 78 deletions(-) diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c index 207a2573..462cb7d5 100644 --- a/libdwfl/dwfl_segment_report_module.c +++ b/libdwfl/dwfl_segment_report_module.c @@ -232,6 +232,85 @@ invalid_elf (Elf *elf, bool disk_file_has_build_id, return false; } +static inline bool +segment_read (int segndx, void **buffer, size_t *buffer_available, + 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); +} + +static inline 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, dwfl, + memory_callback, memory_callback_arg); +} + +static inline int +finish(void *phdrsp, void *buffer, size_t buffer_available, + Elf *elf, int fd, int ndx, Dwfl *dwfl, + Dwfl_Memory_Callback *memory_callback, + void *memory_callback_arg) + +{ + free (phdrsp); + release_buffer (&buffer, &buffer_available, dwfl, memory_callback, + memory_callback_arg); + if (elf != NULL) + elf_end (elf); + if (fd != -1) + close (fd); + return ndx; +} + +#define DO_REAL_FINISH finish(phdrsp, buffer, buffer_available, elf, fd, ndx, \ + dwfl, memory_callback, memory_callback_arg) + +static inline bool +read_portion (void **data, size_t *data_size, + GElf_Addr vaddr, size_t filesz, + GElf_Addr start, size_t segment, + void *buffer, size_t buffer_available, + Dwfl *dwfl, + Dwfl_Memory_Callback *memory_callback, + void *memory_callback_arg + ) +{ + if (vaddr - start + filesz > buffer_available + /* 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 (addr_segndx (dwfl, segment, vaddr, false), + 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_size = 0; + return false; +} + +static inline 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, dwfl, memory_callback, memory_callback_arg); +} + int dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, Dwfl_Memory_Callback *memory_callback, @@ -257,20 +336,6 @@ 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); - } - /* First read in the file header and check its sanity. */ void *buffer = NULL; @@ -282,48 +347,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 (ndx, &buffer, &buffer_available, - start, sizeof (Elf64_Ehdr)) + start, sizeof (Elf64_Ehdr), + dwfl, memory_callback, memory_callback_arg) || memcmp (buffer, ELFMAG, SELFMAG) != 0) - return finish (); - - inline bool read_portion (void **data, size_t *data_size, - GElf_Addr vaddr, size_t filesz) - { - if (vaddr - start + filesz > buffer_available - /* 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 (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; - } - - inline void finish_portion (void **data, size_t *data_size) - { - if (*data_size != 0) - release_buffer (data, data_size); - } + return DO_REAL_FINISH; /* Extract the information we need from the file header. */ const unsigned char *e_ident; @@ -360,31 +388,31 @@ 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 DO_REAL_FINISH; 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 DO_REAL_FINISH; shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * ehdr.e32.e_shentsize; break; case ELFCLASS64: xlatefrom.d_size = sizeof (Elf64_Ehdr); if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL) - return finish (); + return DO_REAL_FINISH; 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 DO_REAL_FINISH; shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * ehdr.e64.e_shentsize; break; default: - return finish (); + return DO_REAL_FINISH; } /* The file header tells where to find the program headers. @@ -392,7 +420,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 (); + return DO_REAL_FINISH; xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR; xlatefrom.d_size = phnum * phentsize; @@ -400,19 +428,21 @@ 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, + start, segment, buffer, buffer_available, + dwfl, memory_callback, memory_callback_arg)) + return DO_REAL_FINISH; xlatefrom.d_buf = ph_buffer; 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 DO_REAL_FINISH; const size_t phdrsp_bytes = phnum * phdr_size; phdrsp = malloc (phdrsp_bytes); if (unlikely (phdrsp == NULL)) - return finish (); + return DO_REAL_FINISH; xlateto.d_buf = phdrsp; xlateto.d_size = phdrsp_bytes; @@ -450,7 +480,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 (&data, &data_size, vaddr, filesz, + start, segment, buffer, buffer_available, + dwfl, memory_callback, memory_callback_arg)) return; assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr)); @@ -501,7 +533,8 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, done: if (notes != data) free (notes); - finish_portion (&data, &data_size); + finish_portion (&data, &data_size, + dwfl, memory_callback, memory_callback_arg); } /* Consider each of the program headers we've read from the image. */ @@ -598,14 +631,15 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, (*p64)[i].p_align); } - 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 DO_REAL_FINISH; } /* Now we know enough to report a module for sure: its bounds. */ @@ -676,7 +710,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, if (skip_this_module) { free (build_id); - return finish (); + return DO_REAL_FINISH; } } @@ -754,13 +788,15 @@ 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 (&dyn_data, &dyn_data_size, dyn_vaddr, dyn_filesz, + start, segment, buffer, buffer_available, + dwfl, memory_callback, memory_callback_arg)) { void *dyns = malloc (dyn_filesz); 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 DO_REAL_FINISH; xlatefrom.d_type = xlateto.d_type = ELF_T_DYN; xlatefrom.d_buf = (void *) dyn_data; @@ -784,7 +820,8 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, } 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) @@ -817,7 +854,9 @@ 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, + start, segment, buffer, buffer_available, + dwfl, memory_callback, memory_callback_arg)) name = soname; } @@ -845,12 +884,13 @@ 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 DO_REAL_FINISH; } /* We have reported the module. Now let the caller decide whether we @@ -874,14 +914,15 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, void *contents = calloc (1, file_trimmed_end); if (unlikely (contents == NULL)) - return finish (); + return DO_REAL_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); + &into, &read_size, vaddr, size, + dwfl, memory_callback, memory_callback_arg); } if (contiguous < file_trimmed_end) @@ -935,5 +976,6 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, mod->main_bias = bias; } - return finish (); + return DO_REAL_FINISH; } +#undef DO_REAL_FINISH -- 2.14.0.rc0.400.g1c36432dff-goog