diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c index 207a257..c3d7f88 100644 --- a/libdwfl/dwfl_segment_report_module.c +++ b/libdwfl/dwfl_segment_report_module.c @@ -31,6 +31,7 @@ #undef _ #include "libdwflP.h" #include "common.h" +#include "nested_func.h" #include #include @@ -233,15 +234,18 @@ invalid_elf (Elf *elf, bool disk_file_has_build_id, } 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) +dwfl_segment_report_module (Dwfl *dwfl, int const ndx_in, const char* const name_in, + Dwfl_Memory_Callback* const memory_callback, + void* const memory_callback_arg, + Dwfl_Module_Callback * const read_eagerly, + void* const read_eagerly_arg, + const void* const note_file, size_t const note_file_size, + const struct r_debug_info* const r_debug_info) { - size_t segment = ndx; + __BLOCK int ndx = ndx_in; + __BLOCK const char *name = name_in; + + __BLOCK size_t segment = ndx; if (segment >= dwfl->lookup_elts) segment = dwfl->lookup_elts - 1; @@ -255,34 +259,38 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, if (++segment == dwfl->lookup_elts) return 0; - GElf_Addr start = dwfl->lookup_addr[segment]; + __BLOCK 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) + INLINE_NESTED_FUNC (bool, segment_read, + (int , void **, size_t *, GElf_Addr, size_t), + (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) + INLINE_NESTED_FUNC (void, release_buffer, + (void **, size_t *), + (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; - size_t buffer_available = INITIAL_READ; - Elf *elf = NULL; - int fd = -1; + __BLOCK void *buffer = NULL; + __BLOCK size_t buffer_available = INITIAL_READ; + __BLOCK Elf *elf = NULL; + __BLOCK 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; + __BLOCK void *phdrsp = NULL; - inline int finish (void) + INLINE_NESTED_FUNC (int, finish, (void), (void)) { free (phdrsp); release_buffer (&buffer, &buffer_available); @@ -291,15 +299,17 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, if (fd != -1) close (fd); return ndx; - } + }; if (segment_read (ndx, &buffer, &buffer_available, start, sizeof (Elf64_Ehdr)) || memcmp (buffer, ELFMAG, SELFMAG) != 0) return finish (); - inline bool read_portion (void **data, size_t *data_size, - GElf_Addr vaddr, size_t filesz) + INLINE_NESTED_FUNC (bool, read_portion, + (void **, size_t *, GElf_Addr, size_t), + (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 @@ -317,35 +327,37 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, *data = vaddr - start + buffer; *data_size = 0; return false; - } + }; - inline void finish_portion (void **data, size_t *data_size) + INLINE_NESTED_FUNC (void, finish_portion, + (void **, size_t *), + (void **data, size_t *data_size)) { if (*data_size != 0) release_buffer (data, data_size); - } + }; /* 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 + __BLOCK const unsigned char *e_ident; + __BLOCK unsigned char ei_class; + __BLOCK unsigned char ei_data; + __BLOCK uint16_t e_type; + __BLOCK union { Elf32_Ehdr e32; Elf64_Ehdr e64; } ehdr; - GElf_Off phoff; - uint_fast16_t phnum; - uint_fast16_t phentsize; - GElf_Off shdrs_end; - Elf_Data xlatefrom = + __BLOCK GElf_Off phoff; + __BLOCK uint_fast16_t phnum; + __BLOCK uint_fast16_t phentsize; + __BLOCK GElf_Off shdrs_end; + __BLOCK Elf_Data xlatefrom = { .d_type = ELF_T_EHDR, .d_buf = (void *) buffer, .d_version = EV_CURRENT, }; - Elf_Data xlateto = + __BLOCK Elf_Data xlateto = { .d_type = ELF_T_EHDR, .d_buf = &ehdr, @@ -397,8 +409,8 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR; xlatefrom.d_size = phnum * phentsize; - void *ph_buffer = NULL; - size_t ph_buffer_size = 0; + __BLOCK void *ph_buffer = NULL; + __BLOCK size_t ph_buffer_size = 0; if (read_portion (&ph_buffer, &ph_buffer_size, start + phoff, xlatefrom.d_size)) return finish (); @@ -418,31 +430,33 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, xlateto.d_size = phdrsp_bytes; /* Track the bounds of the file visible in memory. */ - GElf_Off file_trimmed_end = 0; /* Proper p_vaddr + p_filesz end. */ - GElf_Off file_end = 0; /* Rounded up to effective page size. */ - GElf_Off contiguous = 0; /* Visible as contiguous file from START. */ - GElf_Off total_filesz = 0; /* Total size of data to read. */ + __BLOCK GElf_Off file_trimmed_end = 0; /* Proper p_vaddr + p_filesz end. */ + __BLOCK GElf_Off file_end = 0; /* Rounded up to effective page size. */ + __BLOCK GElf_Off contiguous = 0; /* Visible as contiguous file from START. */ + __BLOCK GElf_Off total_filesz = 0; /* Total size of data to read. */ /* Collect the bias between START and the containing PT_LOAD's p_vaddr. */ - GElf_Addr bias = 0; - bool found_bias = false; + __BLOCK GElf_Addr bias = 0; + __BLOCK bool found_bias = false; /* Collect the unbiased bounds of the module here. */ - GElf_Addr module_start = -1l; - GElf_Addr module_end = 0; - GElf_Addr module_address_sync = 0; + __BLOCK GElf_Addr module_start = -1l; + __BLOCK GElf_Addr module_end = 0; + __BLOCK GElf_Addr module_address_sync = 0; /* If we see PT_DYNAMIC, record it here. */ - GElf_Addr dyn_vaddr = 0; - GElf_Xword dyn_filesz = 0; + __BLOCK GElf_Addr dyn_vaddr = 0; + __BLOCK 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; + __BLOCK void *build_id = NULL; + __BLOCK size_t build_id_len = 0; + __BLOCK 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) + INLINE_NESTED_FUNC (void, consider_notes, + (GElf_Addr, GElf_Xword), + (GElf_Addr vaddr, GElf_Xword filesz)) { /* If we have already seen a build ID, we don't care any more. */ if (build_id != NULL || filesz == 0) @@ -502,13 +516,18 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, 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) + INLINE_NESTED_FUNC (void, consider_phdr, + (GElf_Word, + GElf_Addr, GElf_Xword, + GElf_Off, GElf_Xword, + GElf_Xword), + (GElf_Word type, + GElf_Addr vaddr, GElf_Xword memsz, + GElf_Off offset, GElf_Xword filesz, + GElf_Xword align)) { switch (type) { @@ -571,7 +590,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, module_end = vaddr_end; break; } - } + }; Elf32_Phdr (*p32)[phnum] = phdrsp; Elf64_Phdr (*p64)[phnum] = phdrsp; @@ -718,11 +737,12 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, We need its DT_STRTAB and DT_STRSZ to decipher DT_SONAME, and they also tell us the essential portion of the file for fetching symbols. */ - GElf_Addr soname_stroff = 0; - GElf_Addr dynstr_vaddr = 0; - GElf_Xword dynstrsz = 0; - bool execlike = false; - inline bool consider_dyn (GElf_Sxword tag, GElf_Xword val) + __BLOCK GElf_Addr soname_stroff = 0; + __BLOCK GElf_Addr dynstr_vaddr = 0; + __BLOCK GElf_Xword dynstrsz = 0; + __BLOCK bool execlike = false; + INLINE_NESTED_FUNC (bool, consider_dyn, (GElf_Sxword, GElf_Xword), + (GElf_Sxword tag, GElf_Xword val)) { switch (tag) { @@ -747,12 +767,12 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, } 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; + __BLOCK void *dyn_data = NULL; + __BLOCK 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)) { @@ -790,8 +810,8 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, if (name == NULL) name = e_type == ET_EXEC ? "[exe]" : execlike ? "[pie]" : "[dso]"; - void *soname = NULL; - size_t soname_size = 0; + __BLOCK void *soname = NULL; + __BLOCK size_t soname_size = 0; if (! name_is_final && dynstrsz != 0 && dynstr_vaddr != 0) { /* We know the bounds of the .dynstr section. @@ -824,7 +844,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, /* Now that we have chosen the module's name and bounds, report it. If we found a build ID, report that too. */ - Dwfl_Module *mod = INTUSE(dwfl_report_module) (dwfl, name, + __BLOCK Dwfl_Module *mod = INTUSE(dwfl_report_module) (dwfl, name, module_start, module_end); // !execlike && ET_EXEC is PIE. @@ -872,29 +892,34 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, /* The caller wants to read the whole file in right now, but hasn't done it for us. Fill in a local image of the virtual file. */ - void *contents = calloc (1, file_trimmed_end); + __BLOCK 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) + INLINE_NESTED_FUNC (void, final_read, + (size_t, GElf_Addr, size_t), + (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); - } + }; 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) + INLINE_NESTED_FUNC (void, read_phdr, + (GElf_Word, GElf_Addr, + GElf_Off, GElf_Xword), + (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) diff --git a/libdwfl/elf-from-memory.c b/libdwfl/elf-from-memory.c index 12a0a1b..e63b7b2 100644 --- a/libdwfl/elf-from-memory.c +++ b/libdwfl/elf-from-memory.c @@ -219,33 +219,37 @@ 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; - } + /* 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. */ + #define handle_segment(_vaddr, _offset, _filesz, _memsz) \ + ( { \ + bool result; \ + GElf_Addr vaddr = _vaddr; \ + GElf_Off offset = _offset; \ + GElf_Xword filesz = _filesz; \ + GElf_Xword memsz = _memsz; \ + /* Sanity check the segment load aligns with the pagesize. */ \ + if (((vaddr - offset) & (pagesize - 1)) != 0) \ + result = true; \ + else \ + { \ + result = false; \ + 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; \ + } \ + result; \ + } ) case ELFCLASS32: if (elf32_xlatetom (&xlateto, &xlatefrom, @@ -302,19 +306,22 @@ 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; - } + false otherwise. */ + #undef handle_segment + #define handle_segment(_vaddr, _offset, _filesz) \ + ( { \ + GElf_Addr vaddr = _vaddr; \ + GElf_Off offset = _offset; \ + GElf_Xword filesz = _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); \ + (nread <= 0); \ + } ) case ELFCLASS32: for (uint_fast16_t i = 0; i < phnum; ++i) diff --git a/libdwfl/link_map.c b/libdwfl/link_map.c index 794668f..b462807 100644 --- a/libdwfl/link_map.c +++ b/libdwfl/link_map.c @@ -30,6 +30,7 @@ #include "libdwflP.h" #include "../libdw/memory-access.h" #include "system.h" +#include "nested_func.h" #include #include @@ -249,20 +250,27 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata, struct r_debug_info *r_debug_info) { /* Skip r_version, to aligned r_map field. */ - GElf_Addr read_vaddr = r_debug_vaddr + addrsize (elfclass); + __BLOCK GElf_Addr read_vaddr = r_debug_vaddr + addrsize (elfclass); - void *buffer = NULL; - size_t buffer_available = 0; - inline int release_buffer (int result) + __BLOCK void *buffer = NULL; + __BLOCK size_t buffer_available = 0; + INLINE_NESTED_FUNC (int, release_buffer, (int), (int result)) { if (buffer != NULL) (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) + }; + +#if __clang__ + /* Clang Blocks cannot copy an array to a closure. */ + __BLOCK GElf_Addr *addrs = alloca(4 * sizeof (GElf_Addr)); +#else + /* gcc complains about unbounded stack usage from alloca. */ + GElf_Addr addrs[4]; +#endif + INLINE_NESTED_FUNC (bool, read_addrs, + (GElf_Addr, size_t), (GElf_Addr vaddr, size_t n)) { size_t nb = n * addrsize (elfclass); /* Address words -> bytes to read. */ @@ -305,7 +313,7 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata, } return false; - } + }; if (unlikely (read_addrs (read_vaddr, 1))) return release_buffer (-1); @@ -690,7 +698,6 @@ find_executable (Dwfl *dwfl, GElf_Addr at_phdr, GElf_Addr at_entry, return 0; } - int dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size, @@ -698,17 +705,17 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size, void *memory_callback_arg, struct r_debug_info *r_debug_info) { - GElf_Addr r_debug_vaddr = 0; + __BLOCK GElf_Addr r_debug_vaddr = 0; - uint_fast8_t elfclass = ELFCLASSNONE; - uint_fast8_t elfdata = ELFDATANONE; + __BLOCK uint_fast8_t elfclass = ELFCLASSNONE; + __BLOCK uint_fast8_t elfdata = ELFDATANONE; if (likely (auxv != NULL) && likely (auxv_format_probe (auxv, auxv_size, &elfclass, &elfdata))) { - GElf_Addr entry = 0; - GElf_Addr phdr = 0; - GElf_Xword phent = 0; - GElf_Xword phnum = 0; + __BLOCK GElf_Addr entry = 0; + __BLOCK GElf_Addr phdr = 0; + __BLOCK GElf_Xword phent = 0; + __BLOCK GElf_Xword phnum = 0; #define READ_AUXV32(ptr) read_4ubyte_unaligned_noncvt (ptr) #define READ_AUXV64(ptr) read_8ubyte_unaligned_noncvt (ptr) @@ -754,12 +761,13 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size, } /* If we found the phdr dimensions, search phdrs for PT_DYNAMIC. */ - GElf_Addr dyn_vaddr = 0; - GElf_Xword dyn_filesz = 0; - GElf_Addr dyn_bias = (GElf_Addr) -1; + __BLOCK GElf_Addr dyn_vaddr = 0; + __BLOCK GElf_Xword dyn_filesz = 0; + __BLOCK GElf_Addr dyn_bias = (GElf_Addr) -1; - inline bool consider_phdr (GElf_Word type, - GElf_Addr vaddr, GElf_Xword filesz) + INLINE_NESTED_FUNC (bool, consider_phdr, + (GElf_Word, GElf_Addr, GElf_Xword), + (GElf_Word type, GElf_Addr vaddr, GElf_Xword filesz)) { switch (type) { @@ -781,7 +789,7 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size, } return false; - } + }; if (phdr != 0 && phnum != 0) { diff --git a/src/addr2line.c b/src/addr2line.c index ba414a7..f939a87 100644 --- a/src/addr2line.c +++ b/src/addr2line.c @@ -692,19 +692,22 @@ 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); + #define show(get_arg, note_arg) \ + { \ + int (*get) (Dwarf_Line *, bool *) = get_arg; \ + const char *note = note_arg; \ + 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); + + #define show_int(get_arg, name_arg) \ + { \ + int (*get) (Dwarf_Line *, unsigned int *) = get_arg; \ + const char *name = name_arg; \ + unsigned int val; \ + if ((*get) (info, &val) == 0 && val != 0) \ + printf (" (%s %u)", name, val); \ } show (&dwarf_linebeginstatement, " (is_stmt)"); diff --git a/src/ar.c b/src/ar.c index ec32cee..7ba2b11 100644 --- a/src/ar.c +++ b/src/ar.c @@ -446,20 +446,21 @@ do_oper_extract (int oper, const char *arfname, char **argv, int argc, memset (found, '\0', sizeof (found)); size_t name_max = 0; - inline bool should_truncate_fname (void) - { - if (errno == ENAMETOOLONG && allow_truncate_fname) - { - if (name_max == 0) - { - long int len = pathconf (".", _PC_NAME_MAX); - if (len > 0) - name_max = len; - } - return name_max != 0; - } - return false; - } + #define should_truncate_fname() \ + ( { \ + bool result = false; \ + if (errno == ENAMETOOLONG && allow_truncate_fname) \ + { \ + if (name_max == 0) \ + { \ + long int len = pathconf (".", _PC_NAME_MAX); \ + if (len > 0) \ + name_max = len; \ + } \ + result = (name_max != 0); \ + } \ + result; \ + } ) off_t index_off = -1; size_t index_size = 0; diff --git a/src/arlib-argp.c b/src/arlib-argp.c index 1bdd8d0..3b52479 100644 --- a/src/arlib-argp.c +++ b/src/arlib-argp.c @@ -59,13 +59,13 @@ parse_opt (int key, char *arg __attribute__ ((unused)), static char * help_filter (int key, const char *text, void *input __attribute__ ((unused))) { - inline char *text_for_default (void) - { - char *new_text; - if (unlikely (asprintf (&new_text, gettext ("%s (default)"), text) < 0)) - return (char *) text; - return new_text; - } + #define text_for_default() \ + ( { \ + char *new_text; \ + if (unlikely (asprintf (&new_text, gettext ("%s (default)"), text) < 0)) \ + new_text = (char *) text; \ + new_text; \ + } ) switch (key) { diff --git a/src/elfcompress.c b/src/elfcompress.c index 8e0d5c5..893c6b4 100644 --- a/src/elfcompress.c +++ b/src/elfcompress.c @@ -276,50 +276,43 @@ process_file (const char *fname) size_t shnum = 0; #define WORD_BITS (8U * sizeof (unsigned int)) - void set_section (size_t ndx) - { - sections[ndx / WORD_BITS] |= (1U << (ndx % WORD_BITS)); - } - bool get_section (size_t ndx) - { - return (sections[ndx / WORD_BITS] & (1U << (ndx % WORD_BITS))) != 0; - } - - int cleanup (int res) - { - elf_end (elf); - close (fd); - - elf_end (elfnew); - close (fdnew); - - if (fnew != NULL) - { - unlink (fnew); - free (fnew); - fnew = NULL; - } - - free (snamebuf); - if (names != NULL) - { - dwelf_strtab_free (names); - free (scnstrents); - free (symstrents); - free (namesbuf); - if (scnnames != NULL) - { - for (size_t n = 0; n < shnum; n++) - free (scnnames[n]); - free (scnnames); - } - } - - free (sections); - - return res; - } +#define set_section(ndx) \ + sections[ndx / WORD_BITS] |= (1U << (ndx % WORD_BITS)) + +#define get_section(ndx) \ + ((sections[ndx / WORD_BITS] & (1U << (ndx % WORD_BITS))) != 0) + + #define cleanup(res) \ + ( { \ + int result = res; \ + elf_end (elf); \ + close (fd); \ + elf_end (elfnew); \ + close (fdnew); \ + if (fnew != NULL) \ + { \ + unlink (fnew); \ + free (fnew); \ + fnew = NULL; \ + } \ + free (snamebuf); \ + if (names != NULL) \ + { \ + dwelf_strtab_free (names); \ + free (scnstrents); \ + free (symstrents); \ + free (namesbuf); \ + if (scnnames != NULL) \ + { \ + for (size_t n = 0; n < shnum; n++) \ + free (scnnames[n]); \ + free (scnnames); \ + } \ + } \ + free (sections); \ + result; \ + } ) fd = open (fname, O_RDONLY); if (fd < 0) diff --git a/src/elflint.c b/src/elflint.c index 51e53c2..2463f92 100644 --- a/src/elflint.c +++ b/src/elflint.c @@ -3433,10 +3433,8 @@ check_attributes (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx) return; } - inline size_t pos (const unsigned char *p) - { - return p - (const unsigned char *) data->d_buf; - } + #define pos(p) \ + ((const unsigned char *) (p) - (const unsigned char *) data->d_buf) const unsigned char *p = data->d_buf; if (*p++ != 'A') @@ -3446,10 +3444,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; - } + #define left() ((const unsigned char *) data->d_buf + data->d_size - p) while (left () >= 4) { diff --git a/src/readelf.c b/src/readelf.c index 5e2f3fc..a32a22b 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -333,16 +333,18 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state __attribute__ ((unused))) { - void add_dump_section (const char *name, bool implicit) - { - struct section_argument *a = xmalloc (sizeof *a); - a->arg = name; - a->next = NULL; - a->implicit = implicit; - struct section_argument ***tailp - = key == 'x' ? &dump_data_sections_tail : &string_sections_tail; - **tailp = a; - *tailp = &a->next; + #define add_dump_section(name_arg, implicit_arg) \ + { \ + const char *name = name_arg; \ + bool implicit = implicit_arg; \ + struct section_argument *a = xmalloc (sizeof *a); \ + a->arg = name; \ + a->next = NULL; \ + a->implicit = implicit; \ + struct section_argument ***tailp \ + = key == 'x' ? &dump_data_sections_tail : &string_sections_tail; \ + **tailp = a; \ + *tailp = &a->next; \ } switch (key) @@ -3470,10 +3472,7 @@ 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; - } + #define left() ((const unsigned char *) data->d_buf + data->d_size - p) /* Loop over the sections. */ while (left () >= 4) @@ -5166,11 +5165,12 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp, Dwfl_Module *dwflmod, Ebl *ebl, Dwarf *dbg) { char regnamebuf[REGNAMESZ]; - const char *regname (unsigned int regno) - { - register_info (ebl, regno, NULL, regnamebuf, NULL, NULL); - return regnamebuf; - } + #define regname(regno_arg) \ + ( { \ + unsigned int regno = regno_arg; \ + register_info (ebl, regno, NULL, regnamebuf, NULL, NULL); \ + regnamebuf; \ + } ) puts ("\n Program:"); Dwarf_Word pc = vma_base; @@ -6742,14 +6742,16 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, 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_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; + + #define advance_pc(op_advance_arg) \ + { \ + unsigned int op_advance = op_advance_arg; \ + op_addr_advance = minimum_instr_len * ((op_index + (op_advance)) \ + / max_ops_per_instr); \ + address += (op_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) @@ -9160,14 +9162,16 @@ 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 < ®s[maxnreg] && a->regloc != NULL - && b < ®s[maxnreg] && b->regloc != NULL - && a->bits == b->bits - && (a->set == b->set || !strcmp (a->set, b->set))); - } + #define same_set(a_arg, b_arg) \ + ( { \ + const struct register_info *a = a_arg; \ + const struct register_info *b = b_arg; \ + (a < ®s[maxnreg] && a->regloc != NULL \ + && b < ®s[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] = ®s[0]; size_t nsets = 1; diff --git a/src/strip.c b/src/strip.c index 773ed54..d0a0d01 100644 --- a/src/strip.c +++ b/src/strip.c @@ -457,6 +457,167 @@ process_file (const char *fname) /* Maximum size of array allocated on stack. */ #define MAX_STACK_ALLOC (400 * 1024) +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; +}; + +#define declare_relocate_closure \ + Ebl * const ebl, \ + Elf_Data * const symdata, \ + Elf_Data * const xndxdata, \ + size_t const shnum, \ + const char * const fname, \ + struct shdr_info * const shdr_info, \ + Elf_Data * const tdata, \ + Elf * const debugelf, \ + GElf_Ehdr * const ehdr + +#define pass_relocate_closure \ + ebl, symdata, xndxdata, shnum, fname, shdr_info, tdata, debugelf, ehdr + +/* Apply one relocation. Returns true when trivial + relocation actually done. */ +static bool +relocate (declare_relocate_closure, GElf_Addr offset, + const GElf_Sxword addend, bool is_rela, int rtype, int symndx) +{ + /* R_*_NONE relocs can always just be removed. */ + if (rtype == 0) + return true; + + /* We only do simple absolute relocations. */ + Elf_Type type = ebl_reloc_simple_type (ebl, rtype); + if (type == ELF_T_NUM) + return false; + + /* These are the types we can relocate. */ +#define TYPES DO_TYPE (BYTE, Byte); DO_TYPE (HALF, Half); \ + DO_TYPE (WORD, Word); DO_TYPE (SWORD, Sword); \ + DO_TYPE (XWORD, Xword); DO_TYPE (SXWORD, Sxword) + + /* And only for relocations against other debug sections. */ + GElf_Sym sym_mem; + Elf32_Word xndx; + GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata, + symndx, &sym_mem, + &xndx); + Elf32_Word sec = (sym->st_shndx == SHN_XINDEX + ? xndx : sym->st_shndx); + if (sec >= shnum + 2) + INTERNAL_ERROR (fname); + + if (ebl_debugscn_p (ebl, shdr_info[sec].name)) + { + size_t size; + +#define DO_TYPE(NAME, Name) GElf_##Name Name; + union { TYPES; } tmpbuf; +#undef DO_TYPE + + switch (type) + { +#define DO_TYPE(NAME, Name) \ + case ELF_T_##NAME: \ + size = sizeof (GElf_##Name); \ + tmpbuf.Name = 0; \ + break; + TYPES; +#undef DO_TYPE + default: + return false; + } + + if (offset > tdata->d_size + || tdata->d_size - offset < size) + { + cleanup_debug (); + error (EXIT_FAILURE, 0, gettext ("bad relocation")); + } + + /* When the symbol value is zero then for SHT_REL + sections this is all that needs to be checked. + The addend is contained in the original data at + the offset already. So if the (section) symbol + address is zero and the given addend is zero + just remove the relocation, it isn't needed + anymore. */ + if (addend == 0 && sym->st_value == 0) + return true; + + Elf_Data tmpdata = + { + .d_type = type, + .d_buf = &tmpbuf, + .d_size = size, + .d_version = EV_CURRENT, + }; + Elf_Data rdata = + { + .d_type = type, + .d_buf = tdata->d_buf + offset, + .d_size = size, + .d_version = EV_CURRENT, + }; + + GElf_Addr value = sym->st_value; + if (is_rela) + { + /* For SHT_RELA sections we just take the + given addend and add it to the value. */ + value += addend; + } + else + { + /* For SHT_REL sections we have to peek at + what is already in the section at the given + offset to get the addend. */ + Elf_Data *d = gelf_xlatetom (debugelf, &tmpdata, + &rdata, + ehdr->e_ident[EI_DATA]); + if (d == NULL) + INTERNAL_ERROR (fname); + assert (d == &tmpdata); + } + + switch (type) + { +#define DO_TYPE(NAME, Name) \ + case ELF_T_##NAME: \ + tmpbuf.Name += (GElf_##Name) value; \ + break; + TYPES; +#undef DO_TYPE + default: + abort (); + } + + /* Now finally put in the new value. */ + Elf_Data *s = gelf_xlatetof (debugelf, &rdata, + &tmpdata, + ehdr->e_ident[EI_DATA]); + if (s == NULL) + INTERNAL_ERROR (fname); + assert (s == &rdata); + + return true; + } + return false; +} + static int handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, mode_t mode, struct timespec tvp[2]) @@ -470,23 +631,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, int result = 0; size_t shdridx = 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; + struct shdr_info *shdr_info = NULL; Elf_Scn *scn; size_t cnt; size_t idx; @@ -1024,19 +1169,19 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, 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; - } + #define check_preserved(i_arg) \ + { \ + size_t i = i_arg; \ + 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); @@ -1562,21 +1707,22 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, /* 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; - } + #define update_section_size(newdata_arg) \ + { \ + const Elf_Data *newdata = newdata_arg; \ + 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) @@ -1590,18 +1736,21 @@ 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); - } + #define no_symtab_updates() \ + ( { \ + bool no_updates; \ + /* If the symbol table hasn't changed, do not do anything. */ \ + if (shdr_info[symtabidx].newsymidx == NULL) { \ + no_updates = true; \ + } else { \ + /* If the symbol table is not discarded, but additionally */ \ + /* duplicated in the separate debug file and this section */ \ + /* is discarded, don't adjust anything. */ \ + no_updates = (shdr_info[cnt].idx == 0 \ + && shdr_info[symtabidx].debug_data != NULL); \ + } \ + no_updates; \ + } ) case SHT_REL: case SHT_RELA: @@ -1936,134 +2085,6 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, xndxdata = (shdr_info[shdr_info[symt].symtab_idx].debug_data ?: shdr_info[shdr_info[symt].symtab_idx].data); - /* Apply one relocation. Returns true when trivial - relocation actually done. */ - bool relocate (GElf_Addr offset, const GElf_Sxword addend, - bool is_rela, int rtype, int symndx) - { - /* R_*_NONE relocs can always just be removed. */ - if (rtype == 0) - return true; - - /* We only do simple absolute relocations. */ - Elf_Type type = ebl_reloc_simple_type (ebl, rtype); - if (type == ELF_T_NUM) - return false; - - /* These are the types we can relocate. */ -#define TYPES DO_TYPE (BYTE, Byte); DO_TYPE (HALF, Half); \ - DO_TYPE (WORD, Word); DO_TYPE (SWORD, Sword); \ - DO_TYPE (XWORD, Xword); DO_TYPE (SXWORD, Sxword) - - /* And only for relocations against other debug sections. */ - GElf_Sym sym_mem; - Elf32_Word xndx; - GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata, - symndx, &sym_mem, - &xndx); - Elf32_Word sec = (sym->st_shndx == SHN_XINDEX - ? xndx : sym->st_shndx); - if (sec >= shnum + 2) - INTERNAL_ERROR (fname); - - if (ebl_debugscn_p (ebl, shdr_info[sec].name)) - { - size_t size; - -#define DO_TYPE(NAME, Name) GElf_##Name Name; - union { TYPES; } tmpbuf; -#undef DO_TYPE - - switch (type) - { -#define DO_TYPE(NAME, Name) \ - case ELF_T_##NAME: \ - size = sizeof (GElf_##Name); \ - tmpbuf.Name = 0; \ - break; - TYPES; -#undef DO_TYPE - default: - return false; - } - - if (offset > tdata->d_size - || tdata->d_size - offset < size) - { - cleanup_debug (); - error (EXIT_FAILURE, 0, gettext ("bad relocation")); - } - - /* When the symbol value is zero then for SHT_REL - sections this is all that needs to be checked. - The addend is contained in the original data at - the offset already. So if the (section) symbol - address is zero and the given addend is zero - just remove the relocation, it isn't needed - anymore. */ - if (addend == 0 && sym->st_value == 0) - return true; - - Elf_Data tmpdata = - { - .d_type = type, - .d_buf = &tmpbuf, - .d_size = size, - .d_version = EV_CURRENT, - }; - Elf_Data rdata = - { - .d_type = type, - .d_buf = tdata->d_buf + offset, - .d_size = size, - .d_version = EV_CURRENT, - }; - - GElf_Addr value = sym->st_value; - if (is_rela) - { - /* For SHT_RELA sections we just take the - given addend and add it to the value. */ - value += addend; - } - else - { - /* For SHT_REL sections we have to peek at - what is already in the section at the given - offset to get the addend. */ - Elf_Data *d = gelf_xlatetom (debugelf, &tmpdata, - &rdata, - ehdr->e_ident[EI_DATA]); - if (d == NULL) - INTERNAL_ERROR (fname); - assert (d == &tmpdata); - } - - switch (type) - { -#define DO_TYPE(NAME, Name) \ - case ELF_T_##NAME: \ - tmpbuf.Name += (GElf_##Name) value; \ - break; - TYPES; -#undef DO_TYPE - default: - abort (); - } - - /* Now finally put in the new value. */ - Elf_Data *s = gelf_xlatetof (debugelf, &rdata, - &tmpdata, - ehdr->e_ident[EI_DATA]); - if (s == NULL) - INTERNAL_ERROR (fname); - assert (s == &rdata); - - return true; - } - return false; - } - if (shdr->sh_entsize == 0) INTERNAL_ERROR (fname); @@ -2074,7 +2095,8 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, { GElf_Rel rel_mem; GElf_Rel *r = gelf_getrel (reldata, relidx, &rel_mem); - if (! relocate (r->r_offset, 0, false, + if (! relocate (pass_relocate_closure, + r->r_offset, 0, false, GELF_R_TYPE (r->r_info), GELF_R_SYM (r->r_info))) { @@ -2088,7 +2110,8 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, { GElf_Rela rela_mem; GElf_Rela *r = gelf_getrela (reldata, relidx, &rela_mem); - if (! relocate (r->r_offset, r->r_addend, true, + if (! relocate (pass_relocate_closure, + r->r_offset, r->r_addend, true, GELF_R_TYPE (r->r_info), GELF_R_SYM (r->r_info))) { diff --git a/src/unstrip.c b/src/unstrip.c index 5074909..8f5da71 100644 --- a/src/unstrip.c +++ b/src/unstrip.c @@ -417,11 +417,12 @@ adjust_relocs (Elf_Scn *outscn, Elf_Scn *inscn, const GElf_Shdr *shdr, { Elf_Data *data = elf_getdata (outscn, NULL); - inline void adjust_reloc (GElf_Xword *info) - { - size_t ndx = GELF_R_SYM (*info); - if (ndx != STN_UNDEF) - *info = GELF_R_INFO (map[ndx - 1], GELF_R_TYPE (*info)); + #define adjust_reloc(info_arg) \ + { \ + GElf_Xword *info = info_arg; \ + size_t ndx = GELF_R_SYM (*info); \ + if (ndx != STN_UNDEF) \ + *info = GELF_R_INFO (map[ndx - 1], GELF_R_TYPE (*info)); \ } switch (shdr->sh_type) @@ -1091,14 +1092,17 @@ 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); - } + #define check_match(match_arg, scn_arg, name_arg) \ + { \ + bool match = match_arg; \ + Elf_Scn *scnp = scn_arg; \ + const char *sect_name = name_arg; \ + if (!match) \ + { \ + fail = true; \ + error (0, 0, _("cannot find matching section for [%zu] '%s'"), \ + elf_ndxscn (scnp), sect_name); \ + } \ } Elf_Scn *scn = NULL; @@ -1324,25 +1328,29 @@ more sections in stripped file than debug file -- arguments reversed?")); } /* Locate a matching unallocated section in SECTIONS. */ - inline struct section *find_unalloc_section (const GElf_Shdr *shdr, - const char *name) - { - size_t l = nalloc, u = stripped_shnum - 1; - while (l < u) - { - size_t i = (l + u) / 2; - struct section *sec = §ions[i]; - int cmp = compare_unalloc_sections (shdr, &sec->shdr, - name, sec->name); - if (cmp < 0) - u = i; - else if (cmp > 0) - l = i + 1; - else - return sec; - } - return NULL; - } + #define find_unalloc_section(shdr_arg, name_arg) \ + ( { \ + const GElf_Shdr *shdr_p = shdr_arg; \ + const char *sect_name = name_arg; \ + struct section * result = NULL; \ + size_t l = nalloc, u = stripped_shnum - 1; \ + while (l < u) \ + { \ + size_t i = (l + u) / 2; \ + struct section *secp = §ions[i]; \ + int cmp = compare_unalloc_sections (shdr_p, &secp->shdr, \ + sect_name, secp->name); \ + if (cmp < 0) \ + u = i; \ + else if (cmp > 0) \ + l = i + 1; \ + else { \ + result = secp; \ + break; \ + } \ + } \ + result; \ + } ) Elf_Data *shstrtab = elf_getdata (elf_getscn (unstripped, unstripped_shstrndx), NULL); @@ -2061,13 +2069,14 @@ handle_explicit_files (const char *output_file, bool create_dirs, bool force, /* 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) - { - error (force ? 0 : EXIT_FAILURE, 0, "%s'%s' and '%s' %s%s.", - force ? _("WARNING: ") : "", - stripped_file, unstripped_file, msg, - force ? "" : _(", use --force")); - } + #define warn(msg_arg) \ + { \ + const char *msg = msg_arg; \ + error (force ? 0 : EXIT_FAILURE, 0, "%s'%s' and '%s' %s%s.", \ + force ? _("WARNING: ") : "", \ + stripped_file, unstripped_file, msg, \ + force ? "" : _(", use --force")); \ + } int stripped_fd = open_file (stripped_file, false); Elf *stripped = elf_begin (stripped_fd, ELF_C_READ, NULL); @@ -2322,10 +2331,11 @@ 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); - } + #define next(offset_arg) \ + ( { \ + ptrdiff_t old_offset = offset_arg; \ + dwfl_getmodules (info->dwfl, &match_module, &mmi, old_offset); \ + } ) ptrdiff_t offset = next (0); if (offset == 0) error (EXIT_FAILURE, 0, _("no matching modules found"));