This is the mail archive of the
elfutils-devel@sourceware.org
mailing list for the elfutils project.
[PATCH] For clang use Blocks instead of nested functions.
- From: Chih-Hung Hsieh <chh at google dot com>
- To: elfutils-devel at lists dot fedorahosted dot org
- Date: Fri, 04 Sep 2015 16:54:25 -0700
- Subject: [PATCH] For clang use Blocks instead of nested functions.
* Clang has Blocks like closures that can serve similar
purpose as the nested functions in gnu99.
Syntax of Blocks is similar to nested functions that
*NESTED_FUNC macro can be used for the function/block
declarations.
See spec in http://clang.llvm.org/docs/BlockLanguageSpec.html
* Local variables used in a closure should have __BLOCK
attribute unless they are constants.
* Formal parameters used in a closure should be copied
to local variable and declared as __BLOCK.
* Cannot goto and jump over __BLOCK variables, so these
variables have been moved to be declared before goto.
* Clang Blocks cannot copy an array to a closure,
and gcc complains about unbounded stack usage from alloca.
Signed-off-by: Chih-Hung Hsieh <chh@google.com>
---
backends/aarch64_regs.c | 10 +-
backends/ia64_retval.c | 6 +-
lib/nested_func.h | 85 ++++++++++++++++
libdw/cfi.c | 13 +--
libdw/dwarf_entry_breakpoints.c | 18 ++--
libdw/dwarf_getscopevar.c | 8 +-
libdw/dwarf_getsrclines.c | 60 +++++++-----
libdw/libdw_visit_scopes.c | 22 +++--
libdwelf/dwelf_elf_gnu_build_id.c | 7 +-
libdwfl/argp-std.c | 13 ++-
libdwfl/core-file.c | 28 +++---
libdwfl/dwfl_module.c | 7 +-
libdwfl/dwfl_module_addrsym.c | 55 ++++++-----
libdwfl/dwfl_module_getdwarf.c | 73 ++++++++------
libdwfl/dwfl_module_getsrc_file.c | 29 +++---
libdwfl/dwfl_segment_report_module.c | 185 ++++++++++++++++++++---------------
libdwfl/elf-from-memory.c | 125 ++++++++++++-----------
libdwfl/frame_unwind.c | 17 ++--
libdwfl/gzip.c | 35 +++----
libdwfl/link_map.c | 59 ++++++-----
libdwfl/linux-kernel-modules.c | 37 +++----
libdwfl/linux-proc-maps.c | 13 +--
libdwfl/relocate.c | 41 ++++----
libelf/elf32_updatefile.c | 5 +-
libelf/elf_begin.c | 5 +-
src/addr2line.c | 19 ++--
src/ar.c | 7 +-
src/arlib-argp.c | 5 +-
src/elflint.c | 14 +--
src/ld.c | 5 +-
src/readelf.c | 48 +++++----
src/strip.c | 74 +++++++-------
src/unstrip.c | 40 ++++----
33 files changed, 693 insertions(+), 475 deletions(-)
create mode 100644 lib/nested_func.h
diff --git a/backends/aarch64_regs.c b/backends/aarch64_regs.c
index 7a8a678..053c99e 100644
--- a/backends/aarch64_regs.c
+++ b/backends/aarch64_regs.c
@@ -37,6 +37,7 @@
#define BACKEND aarch64_
#include "libebl_CPU.h"
+#include "nested_func.h"
ssize_t
aarch64_register_info (Ebl *ebl __attribute__ ((unused)),
@@ -47,9 +48,10 @@ aarch64_register_info (Ebl *ebl __attribute__ ((unused)),
if (name == NULL)
return 128;
- __attribute__ ((format (printf, 3, 4)))
- ssize_t
- regtype (const char *setname, int type, const char *fmt, ...)
+ NESTED_FUNC (__attribute__ ((format (printf, 3, 4))) ssize_t,
+ regtype,
+ (const char *, int, const char *, ...),
+ (const char *setname, int type, const char *fmt, ...))
{
*setnamep = setname;
*typep = type;
@@ -62,7 +64,7 @@ aarch64_register_info (Ebl *ebl __attribute__ ((unused)),
if (s < 0 || (unsigned) s >= namelen)
return -1;
return s + 1;
- }
+ };
*prefix = "";
*bits = 64;
diff --git a/backends/ia64_retval.c b/backends/ia64_retval.c
index b5928c5..339f092 100644
--- a/backends/ia64_retval.c
+++ b/backends/ia64_retval.c
@@ -35,6 +35,7 @@
#define BACKEND ia64_
#include "libebl_CPU.h"
+#include "nested_func.h"
/* r8, or pair r8, r9, or aggregate up to r8-r11. */
@@ -100,14 +101,15 @@ hfa_type (Dwarf_Die *typedie, Dwarf_Word size,
If we find a datum that's not the same FP type as the first datum, punt.
If we count more than eight total homogeneous FP data, punt. */
- inline int hfa (const Dwarf_Op *loc, int nregs)
+ INLINE_NESTED_FUNC (int, hfa, (const Dwarf_Op *, int),
+ (const Dwarf_Op *loc, int nregs))
{
if (fpregs_used == 0)
*locp = loc;
else if (*locp != loc)
return 9;
return fpregs_used + nregs;
- }
+ };
int tag = DWARF_TAG_OR_RETURN (typedie);
switch (tag)
diff --git a/lib/nested_func.h b/lib/nested_func.h
new file mode 100644
index 0000000..be44a31
--- /dev/null
+++ b/lib/nested_func.h
@@ -0,0 +1,85 @@
+/* Copyright (C) 2015 Red Hat, Inc.
+ This file is part of elfutils.
+ Written by Chih-Hung Hsieh <chh@google.com>, 2015.
+
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of either
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at
+ your option) any later version
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at
+ your option) any later version
+
+ or both in parallel, as here.
+
+ elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received copies of the GNU General Public License and
+ the GNU Lesser General Public License along with this program. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef _NESTED_FUNC_H
+#define _NESTED_FUNC_H 1
+
+#if __clang__
+
+ #define __BLOCK __block
+
+ #define NESTED_FUNC(return_type, function_name, \
+ arg_types, arg_types_and_names) \
+ return_type (^function_name) arg_types = \
+ ^ return_type arg_types_and_names
+
+ /* Clang does not like inline keyword before a block variable. */
+ #define INLINE_NESTED_FUNC(r, f, t, a) \
+ NESTED_FUNC (r, f, t, a)
+
+ #define INLINE_INTUSE_NESTED_FUNC(r, f, t, a) \
+ NESTED_FUNC (r, INTUSE(f), t, a)
+
+ /* Recrusive blocks need to be declared before used. */
+ #define RECURSIVE_NESTED_FUNC(return_type, function_name, \
+ arg_types, arg_types_and_names) \
+ __BLOCK return_type (^function_name) arg_types; \
+ function_name = ^ return_type arg_types_and_names
+
+ #define INLINE_RECURSIVE_NESTED_FUNC(r, f, t, a) \
+ RECURSIVE_NESTED_FUNC (r, f, t, a)
+
+ #define INLINE_INTUSE_RECURSIVE_NESTED_FUNC(r, f, t, a) \
+ RECURSIVE_NESTED_FUNC (r, INTUSE(f), t, a)
+
+#else /* gcc nested function */
+
+ #define __BLOCK
+
+ #define NESTED_FUNC(return_type, function_name, \
+ arg_types, arg_types_and_names) \
+ return_type function_name arg_types_and_names
+
+ #define INLINE_NESTED_FUNC(r, f, t, a) \
+ inline NESTED_FUNC (r, f, t, a)
+
+ #define INLINE_INTUSE_NESTED_FUNC(r, f, t, a) \
+ inline NESTED_FUNC (r, INTUSE(f), t, a)
+
+ #define RECURSIVE_NESTED_FUNC(r, f, t, a) \
+ NESTED_FUNC (r, f, t, a)
+
+ #define INLINE_RECURSIVE_NESTED_FUNC(r, f, t, a) \
+ inline RECURSIVE_NESTED_FUNC (r, f, t, a)
+
+ #define INLINE_INTUSE_RECURSIVE_NESTED_FUNC(r, f, t, a) \
+ INLINE_RECURSIVE_NESTED_FUNC (r, INTUSE(f), t, a)
+
+#endif
+
+#endif /* _NESTED_FUNC_H */
diff --git a/libdw/cfi.c b/libdw/cfi.c
index 5a6f956..fccf2c5 100644
--- a/libdw/cfi.c
+++ b/libdw/cfi.c
@@ -34,6 +34,7 @@
#include "../libebl/libebl.h"
#include "cfi.h"
#include "memory-access.h"
+#include "nested_func.h"
#include "encoded-value.h"
#include "system.h"
#include <assert.h>
@@ -68,7 +69,7 @@ execute_cfi (Dwarf_CFI *cache,
/* The caller should not give us anything out of range. */
assert (loc <= find_pc);
- int result = DWARF_E_NOERROR;
+ __BLOCK int result = DWARF_E_NOERROR;
#define cfi_assert(ok) do { \
if (likely (ok)) break; \
@@ -76,8 +77,8 @@ execute_cfi (Dwarf_CFI *cache,
goto out; \
} while (0)
- Dwarf_Frame *fs = *state;
- inline bool enough_registers (Dwarf_Word reg)
+ __BLOCK Dwarf_Frame *fs = *state;
+ INLINE_NESTED_FUNC (bool, enough_registers, (Dwarf_Word), (Dwarf_Word reg))
{
/* Don't allow insanely large register numbers. 268435456 registers
should be enough for anybody. And very large values might overflow
@@ -107,13 +108,13 @@ execute_cfi (Dwarf_CFI *cache,
}
}
return true;
- }
+ };
- inline void require_cfa_offset (void)
+ INLINE_NESTED_FUNC (void, require_cfa_offset, (void), (void))
{
if (unlikely (fs->cfa_rule != cfa_offset))
fs->cfa_rule = cfa_invalid;
- }
+ };
#define register_rule(regno, r_rule, r_value) do { \
if (unlikely (! enough_registers (regno))) \
diff --git a/libdw/dwarf_entry_breakpoints.c b/libdw/dwarf_entry_breakpoints.c
index ffd5169..65484ce 100644
--- a/libdw/dwarf_entry_breakpoints.c
+++ b/libdw/dwarf_entry_breakpoints.c
@@ -30,6 +30,7 @@
# include <config.h>
#endif
#include "libdwP.h"
+#include "nested_func.h"
#include <dwarf.h>
#include <stdlib.h>
@@ -39,11 +40,11 @@ dwarf_entry_breakpoints (die, bkpts)
Dwarf_Die *die;
Dwarf_Addr **bkpts;
{
- int nbkpts = 0;
+ __BLOCK int nbkpts = 0;
*bkpts = NULL;
/* Add one breakpoint location to the result vector. */
- inline int add_bkpt (Dwarf_Addr pc)
+ INLINE_NESTED_FUNC (int, add_bkpt, (Dwarf_Addr), (Dwarf_Addr pc))
{
Dwarf_Addr *newlist = realloc (*bkpts, ++nbkpts * sizeof newlist[0]);
if (newlist == NULL)
@@ -56,14 +57,14 @@ dwarf_entry_breakpoints (die, bkpts)
newlist[nbkpts - 1] = pc;
*bkpts = newlist;
return nbkpts;
- }
+ };
/* Fallback result, break at the entrypc/lowpc value. */
- inline int entrypc_bkpt (void)
+ INLINE_NESTED_FUNC (int, entrypc_bkpt, (void), (void))
{
Dwarf_Addr pc;
return INTUSE(dwarf_entrypc) (die, &pc) < 0 ? -1 : add_bkpt (pc);
- }
+ };
/* Fetch the CU's line records to look for this DIE's addresses. */
Dwarf_Die cudie = CUDIE (die->cu);
@@ -81,8 +82,9 @@ dwarf_entry_breakpoints (die, bkpts)
/* Search a contiguous PC range for prologue-end markers.
If DWARF, look for proper markers.
Failing that, if ADHOC, look for the ad hoc convention. */
- inline int search_range (Dwarf_Addr low, Dwarf_Addr high,
- bool dwarf, bool adhoc)
+ INLINE_NESTED_FUNC (int, search_range,
+ (Dwarf_Addr, Dwarf_Addr, bool, bool),
+ (Dwarf_Addr low, Dwarf_Addr high, bool dwarf, bool adhoc))
{
size_t l = 0, u = nlines;
while (l < u)
@@ -115,7 +117,7 @@ dwarf_entry_breakpoints (die, bkpts)
}
__libdw_seterrno (DWARF_E_INVALID_DWARF);
return -1;
- }
+ };
/* Search each contiguous address range for DWARF prologue_end markers. */
diff --git a/libdw/dwarf_getscopevar.c b/libdw/dwarf_getscopevar.c
index eb50c0a..73c9475 100644
--- a/libdw/dwarf_getscopevar.c
+++ b/libdw/dwarf_getscopevar.c
@@ -33,6 +33,7 @@
#include <stdbool.h>
#include <string.h>
#include "libdwP.h"
+#include "nested_func.h"
#include <dwarf.h>
@@ -70,9 +71,10 @@ dwarf_getscopevar (Dwarf_Die *scopes, int nscopes,
{
/* Match against the given file name. */
size_t match_file_len = match_file == NULL ? 0 : strlen (match_file);
- bool lastfile_matches = false;
+ __BLOCK bool lastfile_matches = false;
const char *lastfile = NULL;
- inline bool file_matches (Dwarf_Files *files, size_t idx)
+ INLINE_NESTED_FUNC (bool, file_matches,
+ (Dwarf_Files *, size_t), (Dwarf_Files *files, size_t idx))
{
if (idx >= files->nfiles)
return false;
@@ -87,7 +89,7 @@ dwarf_getscopevar (Dwarf_Die *scopes, int nscopes,
|| file[len - match_file_len - 1] == '/'));
}
return lastfile_matches;
- }
+ };
/* Start with the innermost scope and move out. */
for (int out = 0; out < nscopes; ++out)
diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c
index 389c824..f200d70 100644
--- a/libdw/dwarf_getsrclines.c
+++ b/libdw/dwarf_getsrclines.c
@@ -38,6 +38,7 @@
#include "dwarf.h"
#include "libdwP.h"
+#include "nested_func.h"
struct filelist
@@ -86,10 +87,29 @@ read_srclines (Dwarf *dbg,
{
int res = -1;
- struct linelist *linelist = NULL;
- size_t nlinelist = 0;
- size_t nfilelist = 0;
- unsigned int ndirlist = 0;
+ __BLOCK struct linelist *linelist = NULL;
+ __BLOCK size_t nlinelist = 0;
+ __BLOCK size_t nfilelist = 0;
+ __BLOCK unsigned int ndirlist = 0;
+ /* We are about to process the statement program. Initialize the
+ state machine registers (see 6.2.2 in the v2.1 specification). */
+ __BLOCK Dwarf_Word addr = 0;
+ __BLOCK unsigned int op_index = 0;
+ __BLOCK unsigned int file = 1;
+ /* We only store an int, but want to check for overflow (see SET below). */
+ __BLOCK int64_t line = 1;
+ __BLOCK unsigned int column = 0;
+ __BLOCK uint_fast8_t is_stmt = 0;
+ __BLOCK bool basic_block = false;
+ __BLOCK bool prologue_end = false;
+ __BLOCK bool epilogue_begin = false;
+ __BLOCK unsigned int isa = 0;
+ __BLOCK unsigned int discriminator = 0;
+ /* Next the minimum instruction length. */
+ __BLOCK uint_fast8_t minimum_instr_len = 0;
+ /* Next the maximum operations per instruction, in version 4 format. */
+ __BLOCK uint_fast8_t max_ops_per_instr = 1;
+
struct filelist null_file =
{
@@ -159,10 +179,8 @@ read_srclines (Dwarf *dbg,
const unsigned char *header_start = linep;
/* Next the minimum instruction length. */
- uint_fast8_t minimum_instr_len = *linep++;
+ minimum_instr_len = *linep++;
- /* Next the maximum operations per instruction, in version 4 format. */
- uint_fast8_t max_ops_per_instr = 1;
if (version >= 4)
{
if (unlikely (lineendp - linep < 5))
@@ -176,6 +194,8 @@ read_srclines (Dwarf *dbg,
register. */
uint_fast8_t default_is_stmt = *linep++;
+ is_stmt = default_is_stmt;
+
/* Now the line base. */
int_fast8_t line_base = (int8_t) *linep++;
@@ -321,29 +341,15 @@ read_srclines (Dwarf *dbg,
goto out;
}
- /* We are about to process the statement program. Initialize the
- state machine registers (see 6.2.2 in the v2.1 specification). */
- Dwarf_Word addr = 0;
- unsigned int op_index = 0;
- unsigned int file = 1;
- /* We only store an int, but want to check for overflow (see SET below). */
- int64_t line = 1;
- unsigned int column = 0;
- uint_fast8_t is_stmt = default_is_stmt;
- bool basic_block = false;
- bool prologue_end = false;
- bool epilogue_begin = false;
- unsigned int isa = 0;
- unsigned int discriminator = 0;
-
/* Apply the "operation advance" from a special opcode or
DW_LNS_advance_pc (as per DWARF4 6.2.5.1). */
- inline void advance_pc (unsigned int op_advance)
+ INLINE_NESTED_FUNC (void, advance_pc,
+ (unsigned int), (unsigned int op_advance))
{
addr += minimum_instr_len * ((op_index + op_advance)
/ max_ops_per_instr);
op_index = (op_index + op_advance) % max_ops_per_instr;
- }
+ };
/* Process the instructions. */
@@ -361,7 +367,9 @@ read_srclines (Dwarf *dbg,
goto invalid_data; \
} while (0)
- inline bool add_new_line (struct linelist *new_line, bool end_sequence)
+ INLINE_NESTED_FUNC (bool, add_new_line,
+ (struct linelist *, bool),
+ (struct linelist *new_line, bool end_sequence))
{
new_line->next = linelist;
new_line->sequence = nlinelist;
@@ -395,7 +403,7 @@ read_srclines (Dwarf *dbg,
#undef SET
return false;
- }
+ };
while (linep < lineendp)
{
diff --git a/libdw/libdw_visit_scopes.c b/libdw/libdw_visit_scopes.c
index ac7e853..d115a39 100644
--- a/libdw/libdw_visit_scopes.c
+++ b/libdw/libdw_visit_scopes.c
@@ -31,6 +31,7 @@
#endif
#include "libdwP.h"
+#include "nested_func.h"
#include <dwarf.h>
@@ -65,29 +66,30 @@ may_have_scopes (Dwarf_Die *die)
}
int
-__libdw_visit_scopes (depth, root, imports, previsit, postvisit, arg)
+__libdw_visit_scopes (depth, root, imports_param, previsit, postvisit, arg)
unsigned int depth;
struct Dwarf_Die_Chain *root;
- struct Dwarf_Die_Chain *imports;
+ struct Dwarf_Die_Chain *imports_param;
int (*previsit) (unsigned int depth, struct Dwarf_Die_Chain *, void *);
int (*postvisit) (unsigned int depth, struct Dwarf_Die_Chain *, void *);
void *arg;
{
- struct Dwarf_Die_Chain child;
- int ret;
+ __BLOCK struct Dwarf_Die_Chain child;
+ __BLOCK int ret;
+ __BLOCK struct Dwarf_Die_Chain *imports = imports_param;
child.parent = root;
if ((ret = INTUSE(dwarf_child) (&root->die, &child.die)) != 0)
return ret < 0 ? -1 : 0; // Having zero children is legal.
- inline int recurse (void)
+ INLINE_NESTED_FUNC (int, recurse, (void), (void))
{
return __libdw_visit_scopes (depth + 1, &child, imports,
previsit, postvisit, arg);
- }
+ };
/* Checks the given DIE hasn't been imported yet to prevent cycles. */
- inline bool imports_contains (Dwarf_Die *die)
+ INLINE_NESTED_FUNC (bool, imports_contains, (Dwarf_Die *), (Dwarf_Die *die))
{
for (struct Dwarf_Die_Chain *import = imports; import != NULL;
import = import->parent)
@@ -95,9 +97,9 @@ __libdw_visit_scopes (depth, root, imports, previsit, postvisit, arg)
return true;
return false;
- }
+ };
- inline int walk_children ()
+ INLINE_RECURSIVE_NESTED_FUNC (int, walk_children, (void), (void))
{
do
{
@@ -163,7 +165,7 @@ __libdw_visit_scopes (depth, root, imports, previsit, postvisit, arg)
while ((ret = INTUSE(dwarf_siblingof) (&child.die, &child.die)) == 0);
return ret < 0 ? -1 : 0;
- }
+ };
return walk_children ();
}
diff --git a/libdwelf/dwelf_elf_gnu_build_id.c b/libdwelf/dwelf_elf_gnu_build_id.c
index 1ed501d..8aff36b 100644
--- a/libdwelf/dwelf_elf_gnu_build_id.c
+++ b/libdwelf/dwelf_elf_gnu_build_id.c
@@ -32,6 +32,7 @@
#include "libdwelfP.h"
#include "libdwflP.h"
+#include "nested_func.h"
#define NO_VADDR ((GElf_Addr) -1l)
@@ -42,7 +43,9 @@ find_elf_build_id (Dwfl_Module *mod, int e_type, Elf *elf,
const void **build_id_bits, GElf_Addr *build_id_elfaddr,
int *build_id_len)
{
- int check_notes (Elf_Data *data, GElf_Addr data_elfaddr)
+ NESTED_FUNC (int, check_notes,
+ (Elf_Data *, GElf_Addr),
+ (Elf_Data *data, GElf_Addr data_elfaddr))
{
size_t pos = 0;
GElf_Nhdr nhdr;
@@ -60,7 +63,7 @@ find_elf_build_id (Dwfl_Module *mod, int e_type, Elf *elf,
return 1;
}
return 0;
- }
+ };
size_t shstrndx = SHN_UNDEF;
int result = 0;
diff --git a/libdwfl/argp-std.c b/libdwfl/argp-std.c
index 42b7e78..06ba3b6 100644
--- a/libdwfl/argp-std.c
+++ b/libdwfl/argp-std.c
@@ -27,6 +27,7 @@
not, see <http://www.gnu.org/licenses/>. */
#include "libdwflP.h"
+#include "nested_func.h"
#include <argp.h>
#include <stdlib.h>
#include <assert.h>
@@ -103,7 +104,9 @@ struct parse_opt
static error_t
parse_opt (int key, char *arg, struct argp_state *state)
{
- inline void failure (Dwfl *dwfl, int errnum, const char *msg)
+ INLINE_NESTED_FUNC (void, failure,
+ (Dwfl *, int, const char *),
+ (Dwfl *dwfl, int errnum, const char *msg))
{
if (dwfl != NULL)
dwfl_end (dwfl);
@@ -112,12 +115,14 @@ parse_opt (int key, char *arg, struct argp_state *state)
msg, INTUSE(dwfl_errmsg) (-1));
else
argp_failure (state, EXIT_FAILURE, errnum, "%s", msg);
- }
- inline error_t fail (Dwfl *dwfl, int errnum, const char *msg)
+ };
+ INLINE_NESTED_FUNC (error_t, fail,
+ (Dwfl *, int , const char *),
+ (Dwfl *dwfl, int errnum, const char *msg))
{
failure (dwfl, errnum, msg);
return errnum == -1 ? EIO : errnum;
- }
+ };
switch (key)
{
diff --git a/libdwfl/core-file.c b/libdwfl/core-file.c
index bbe0899..ad94035 100644
--- a/libdwfl/core-file.c
+++ b/libdwfl/core-file.c
@@ -37,6 +37,7 @@
#include <endian.h>
#include <byteswap.h>
#include "system.h"
+#include "nested_func.h"
/* This is a prototype of what a new libelf interface might be.
@@ -49,14 +50,14 @@ elf_begin_rand (Elf *parent, loff_t offset, loff_t size, loff_t *next)
return NULL;
/* On failure return, we update *NEXT to point back at OFFSET. */
- inline Elf *fail (int error)
+ INLINE_NESTED_FUNC (Elf *, fail, (int), (int error))
{
if (next != NULL)
*next = offset;
//__libelf_seterrno (error);
__libdwfl_seterrno (DWFL_E (LIBELF, error));
return NULL;
- }
+ };
loff_t min = (parent->kind == ELF_K_ELF ?
(parent->class == ELFCLASS32
@@ -239,13 +240,14 @@ core_file_read_eagerly (Dwfl_Module *mod,
}
bool
-dwfl_elf_phdr_memory_callback (Dwfl *dwfl, int ndx,
+dwfl_elf_phdr_memory_callback (Dwfl *dwfl, int ndx_parameter,
void **buffer, size_t *buffer_available,
GElf_Addr vaddr,
size_t minread,
void *arg)
{
- Elf *elf = arg;
+ __BLOCK int ndx = ndx_parameter;
+ __BLOCK Elf *elf = arg;
if (ndx == -1)
{
@@ -258,7 +260,7 @@ dwfl_elf_phdr_memory_callback (Dwfl *dwfl, int ndx,
}
const GElf_Off align = dwfl->segment_align ?: 1;
- GElf_Phdr phdr;
+ __BLOCK GElf_Phdr phdr;
do
if (unlikely (gelf_getphdr (elf, ndx++, &phdr) == NULL))
@@ -266,20 +268,20 @@ dwfl_elf_phdr_memory_callback (Dwfl *dwfl, int ndx,
while (phdr.p_type != PT_LOAD
|| ((phdr.p_vaddr + phdr.p_memsz + align - 1) & -align) <= vaddr);
- GElf_Off start = vaddr - phdr.p_vaddr + phdr.p_offset;
- GElf_Off end;
- GElf_Addr end_vaddr;
+ __BLOCK GElf_Off start = vaddr - phdr.p_vaddr + phdr.p_offset;
+ __BLOCK GElf_Off end;
+ __BLOCK GElf_Addr end_vaddr;
- inline void update_end ()
+ INLINE_NESTED_FUNC (void, update_end, (void), (void))
{
end = (phdr.p_offset + phdr.p_filesz + align - 1) & -align;
end_vaddr = (phdr.p_vaddr + phdr.p_memsz + align - 1) & -align;
- }
+ };
update_end ();
/* Use following contiguous segments to get towards SIZE. */
- inline bool more (size_t size)
+ INLINE_NESTED_FUNC (bool, more, (size_t), (size_t size))
{
while (end <= start || end - start < size)
{
@@ -287,7 +289,7 @@ dwfl_elf_phdr_memory_callback (Dwfl *dwfl, int ndx,
/* This segment is truncated, so no following one helps us. */
return false;
- if (unlikely (gelf_getphdr (elf, ndx++, &phdr) == NULL))
+ if (unlikely (gelf_getphdr (elf, ndx++, (Elf64_Phdr *) &phdr) == NULL))
return false;
if (phdr.p_type == PT_LOAD)
@@ -301,7 +303,7 @@ dwfl_elf_phdr_memory_callback (Dwfl *dwfl, int ndx,
}
}
return true;
- }
+ };
/* We need at least this much. */
if (! more (minread))
diff --git a/libdwfl/dwfl_module.c b/libdwfl/dwfl_module.c
index 8efcfaa..7035a89 100644
--- a/libdwfl/dwfl_module.c
+++ b/libdwfl/dwfl_module.c
@@ -27,6 +27,7 @@
not, see <http://www.gnu.org/licenses/>. */
#include "libdwflP.h"
+#include "nested_func.h"
#include <search.h>
#include <unistd.h>
@@ -132,9 +133,9 @@ Dwfl_Module *
dwfl_report_module (Dwfl *dwfl, const char *name,
GElf_Addr start, GElf_Addr end)
{
- Dwfl_Module **tailp = &dwfl->modulelist, **prevp = tailp;
+ __BLOCK Dwfl_Module **tailp = &dwfl->modulelist, **prevp = tailp;
- inline Dwfl_Module *use (Dwfl_Module *mod)
+ INLINE_NESTED_FUNC (Dwfl_Module *, use, (Dwfl_Module *), (Dwfl_Module *mod))
{
mod->next = *tailp;
*tailp = mod;
@@ -146,7 +147,7 @@ dwfl_report_module (Dwfl *dwfl, const char *name,
}
return mod;
- }
+ };
for (Dwfl_Module *m = *prevp; m != NULL; m = *(prevp = &m->next))
{
diff --git a/libdwfl/dwfl_module_addrsym.c b/libdwfl/dwfl_module_addrsym.c
index d205832..1f0d020 100644
--- a/libdwfl/dwfl_module_addrsym.c
+++ b/libdwfl/dwfl_module_addrsym.c
@@ -27,6 +27,7 @@
not, see <http://www.gnu.org/licenses/>. */
#include "libdwflP.h"
+#include "nested_func.h"
/* Returns the name of the symbol "closest" to ADDR.
Never returns symbols at addresses above ADDR. */
@@ -37,14 +38,16 @@ __libdwfl_addrsym (Dwfl_Module *mod, GElf_Addr addr, GElf_Off *off,
GElf_Sym *closest_sym, GElf_Word *shndxp,
Elf **elfp, Dwarf_Addr *biasp, bool adjust_st_value)
{
- int syments = INTUSE(dwfl_module_getsymtab) (mod);
+ __BLOCK int syments = INTUSE(dwfl_module_getsymtab) (mod);
if (syments < 0)
return NULL;
/* Return true iff we consider ADDR to lie in the same section as SYM. */
- GElf_Word addr_shndx = SHN_UNDEF;
- Elf *addr_symelf = NULL;
- inline bool same_section (GElf_Addr value, Elf *symelf, GElf_Word shndx)
+ __BLOCK GElf_Word addr_shndx = SHN_UNDEF;
+ __BLOCK Elf *addr_symelf = NULL;
+ INLINE_NESTED_FUNC (bool, same_section,
+ (GElf_Addr, Elf *, GElf_Word),
+ (GElf_Addr value, Elf *symelf, GElf_Word shndx))
{
/* For absolute symbols and the like, only match exactly. */
if (shndx >= SHN_LORESERVE)
@@ -87,29 +90,33 @@ __libdwfl_addrsym (Dwfl_Module *mod, GElf_Addr addr, GElf_Off *off,
}
return shndx == addr_shndx && addr_symelf == symelf;
- }
+ };
/* Keep track of the closest symbol we have seen so far.
Here we store only symbols with nonzero st_size. */
- const char *closest_name = NULL;
- GElf_Addr closest_value = 0;
- GElf_Word closest_shndx = SHN_UNDEF;
- Elf *closest_elf = NULL;
+ __BLOCK const char *closest_name = NULL;
+ __BLOCK GElf_Addr closest_value = 0;
+ __BLOCK GElf_Word closest_shndx = SHN_UNDEF;
+ __BLOCK Elf *closest_elf = NULL;
/* Keep track of an eligible symbol with st_size == 0 as a fallback. */
- const char *sizeless_name = NULL;
- GElf_Sym sizeless_sym = { 0, 0, 0, 0, 0, SHN_UNDEF };
- GElf_Addr sizeless_value = 0;
- GElf_Word sizeless_shndx = SHN_UNDEF;
- Elf *sizeless_elf = NULL;
+ __BLOCK const char *sizeless_name = NULL;
+ __BLOCK GElf_Sym sizeless_sym = { 0, 0, 0, 0, 0, SHN_UNDEF };
+ __BLOCK GElf_Addr sizeless_value = 0;
+ __BLOCK GElf_Word sizeless_shndx = SHN_UNDEF;
+ __BLOCK Elf *sizeless_elf = NULL;
/* Keep track of the lowest address a relevant sizeless symbol could have. */
- GElf_Addr min_label = 0;
+ __BLOCK GElf_Addr min_label = 0;
/* Try one symbol and associated value from the search table. */
- inline void try_sym_value (GElf_Addr value, GElf_Sym *sym,
- const char *name, GElf_Word shndx,
- Elf *elf, bool resolved)
+ INLINE_NESTED_FUNC (void, try_sym_value,
+ (GElf_Addr, GElf_Sym *,
+ const char *, GElf_Word,
+ Elf *, bool),
+ (GElf_Addr value, GElf_Sym *sym,
+ const char *name, GElf_Word shndx,
+ Elf *elf, bool resolved))
{
/* Even if we don't choose this symbol, its existence excludes
any sizeless symbol (assembly label) that is below its upper
@@ -120,7 +127,9 @@ __libdwfl_addrsym (Dwfl_Module *mod, GElf_Addr addr, GElf_Off *off,
if (sym->st_size == 0 || addr - value < sym->st_size)
{
/* Return GELF_ST_BIND as higher-is-better integer. */
- inline int binding_value (const GElf_Sym *symp)
+ INLINE_NESTED_FUNC (int, binding_value,
+ (const GElf_Sym *),
+ (const GElf_Sym *symp))
{
switch (GELF_ST_BIND (symp->st_info))
{
@@ -133,7 +142,7 @@ __libdwfl_addrsym (Dwfl_Module *mod, GElf_Addr addr, GElf_Off *off,
default:
return 0;
}
- }
+ };
/* This symbol is a better candidate than the current one
if it's closer to ADDR or is global when it was local. */
@@ -185,10 +194,10 @@ __libdwfl_addrsym (Dwfl_Module *mod, GElf_Addr addr, GElf_Off *off,
closest_name = name;
}
}
- }
+ };
/* Look through the symbol table for a matching symbol. */
- inline void search_table (int start, int end)
+ INLINE_NESTED_FUNC (void, search_table, (int, int), (int start, int end))
{
for (int i = start; i < end; ++i)
{
@@ -222,7 +231,7 @@ __libdwfl_addrsym (Dwfl_Module *mod, GElf_Addr addr, GElf_Off *off,
}
}
}
- }
+ };
/* First go through global symbols. mod->first_global and
mod->aux_first_global are setup by dwfl_module_getsymtab to the
diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c
index dba9d66..3a7a00c 100644
--- a/libdwfl/dwfl_module_getdwarf.c
+++ b/libdwfl/dwfl_module_getdwarf.c
@@ -33,6 +33,7 @@
#include <unistd.h>
#include "../libdw/libdwP.h" /* DWARF_E_* values are here. */
#include "../libelf/libelfP.h"
+#include "nested_func.h"
static inline Dwfl_Error
open_elf_file (Elf **elf, int *fd, char **name)
@@ -251,11 +252,11 @@ static Dwfl_Error
find_prelink_address_sync (Dwfl_Module *mod, struct dwfl_file *file)
{
/* The magic section is only identified by name. */
- size_t shstrndx;
+ __BLOCK size_t shstrndx;
if (elf_getshdrstrndx (mod->main.elf, &shstrndx) < 0)
return DWFL_E_LIBELF;
- Elf_Scn *scn = NULL;
+ __BLOCK Elf_Scn *scn = NULL;
while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL)
{
GElf_Shdr shdr_mem;
@@ -279,7 +280,7 @@ find_prelink_address_sync (Dwfl_Module *mod, struct dwfl_file *file)
/* There was no .gnu.prelink_undo section. */
return DWFL_E_NOERROR;
- Elf_Data *undodata = elf_rawdata (scn, NULL);
+ __BLOCK Elf_Data *undodata = elf_rawdata (scn, NULL);
if (unlikely (undodata == NULL))
return DWFL_E_LIBELF;
@@ -291,14 +292,14 @@ find_prelink_address_sync (Dwfl_Module *mod, struct dwfl_file *file)
Elf32_Ehdr e32;
Elf64_Ehdr e64;
} ehdr;
- Elf_Data dst =
+ __BLOCK Elf_Data dst =
{
.d_buf = &ehdr,
.d_size = sizeof ehdr,
.d_type = ELF_T_EHDR,
.d_version = EV_CURRENT
};
- Elf_Data src = *undodata;
+ __BLOCK Elf_Data src = *undodata;
src.d_size = gelf_fsize (mod->main.elf, ELF_T_EHDR, 1, EV_CURRENT);
src.d_type = ELF_T_EHDR;
if (unlikely (gelf_xlatetom (mod->main.elf, &dst, &src,
@@ -306,11 +307,11 @@ find_prelink_address_sync (Dwfl_Module *mod, struct dwfl_file *file)
== NULL))
return DWFL_E_LIBELF;
- size_t shentsize = gelf_fsize (mod->main.elf, ELF_T_SHDR, 1, EV_CURRENT);
- size_t phentsize = gelf_fsize (mod->main.elf, ELF_T_PHDR, 1, EV_CURRENT);
+ __BLOCK size_t shentsize = gelf_fsize (mod->main.elf, ELF_T_SHDR, 1, EV_CURRENT);
+ __BLOCK size_t phentsize = gelf_fsize (mod->main.elf, ELF_T_PHDR, 1, EV_CURRENT);
- uint_fast16_t phnum;
- uint_fast16_t shnum;
+ __BLOCK uint_fast16_t phnum;
+ __BLOCK uint_fast16_t shnum;
if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32)
{
if (ehdr.e32.e_shentsize != shentsize
@@ -417,7 +418,7 @@ find_prelink_address_sync (Dwfl_Module *mod, struct dwfl_file *file)
Elf32_Shdr s32[shnum - 1];
Elf64_Shdr s64[shnum - 1];
} shdr;
- shdr *shdrs = malloc (sizeof (shdr));
+ __BLOCK shdr *shdrs = malloc (sizeof (shdr));
if (unlikely (shdrs == NULL))
return DWFL_E_NOMEM;
dst.d_buf = shdrs;
@@ -445,13 +446,19 @@ find_prelink_address_sync (Dwfl_Module *mod, struct dwfl_file *file)
image remaining the same but being spread across the two sections.
So we consider the highest section end, which still matches up. */
- GElf_Addr highest;
-
- inline void consider_shdr (GElf_Addr interp,
- GElf_Word sh_type,
- GElf_Xword sh_flags,
- GElf_Addr sh_addr,
- GElf_Xword sh_size)
+ __BLOCK GElf_Addr highest;
+
+ INLINE_NESTED_FUNC (void, consider_shdr,
+ (GElf_Addr,
+ GElf_Word,
+ GElf_Xword,
+ GElf_Addr,
+ GElf_Xword),
+ (GElf_Addr interp,
+ GElf_Word sh_type,
+ GElf_Xword sh_flags,
+ GElf_Addr sh_addr,
+ GElf_Xword sh_size))
{
if ((sh_flags & SHF_ALLOC)
&& ((sh_type == SHT_PROGBITS && sh_addr != interp)
@@ -461,7 +468,7 @@ find_prelink_address_sync (Dwfl_Module *mod, struct dwfl_file *file)
if (sh_end > highest)
highest = sh_end;
}
- }
+ };
highest = 0;
scn = NULL;
@@ -673,17 +680,17 @@ find_offsets (Elf *elf, GElf_Addr main_bias, size_t phnum, size_t n,
static void
find_dynsym (Dwfl_Module *mod)
{
- GElf_Ehdr ehdr_mem;
- GElf_Ehdr *ehdr = gelf_getehdr (mod->main.elf, &ehdr_mem);
+ __BLOCK GElf_Ehdr ehdr_mem;
+ __BLOCK GElf_Ehdr *ehdr = gelf_getehdr (mod->main.elf, &ehdr_mem);
- size_t phnum;
+ __BLOCK size_t phnum;
if (unlikely (elf_getphdrnum (mod->main.elf, &phnum) != 0))
return;
for (size_t i = 0; i < phnum; ++i)
{
- GElf_Phdr phdr_mem;
- GElf_Phdr *phdr = gelf_getphdr (mod->main.elf, i, &phdr_mem);
+ __BLOCK GElf_Phdr phdr_mem;
+ __BLOCK GElf_Phdr *phdr = gelf_getphdr (mod->main.elf, i, &phdr_mem);
if (phdr == NULL)
break;
@@ -691,7 +698,7 @@ find_dynsym (Dwfl_Module *mod)
{
/* Examine the dynamic section for the pointers we need. */
- Elf_Data *data = elf_getdata_rawchunk (mod->main.elf,
+ __BLOCK Elf_Data *data = elf_getdata_rawchunk (mod->main.elf,
phdr->p_offset, phdr->p_filesz,
ELF_T_DYN);
if (data == NULL)
@@ -705,10 +712,17 @@ find_dynsym (Dwfl_Module *mod)
i_gnu_hash,
i_max
};
+#if __clang__
+ /* Clang Blocks cannot copy an array to a closure. */
+ GElf_Addr *addrs = alloca ((int) i_max * sizeof (GElf_Addr));
+ memset (addrs, 0, i_max * sizeof (GElf_Addr));
+#else
+ /* gcc complains about unbounded stack usage from alloca. */
GElf_Addr addrs[i_max] = { 0, };
- GElf_Xword strsz = 0;
- size_t n = data->d_size / gelf_fsize (mod->main.elf,
- ELF_T_DYN, 1, EV_CURRENT);
+#endif
+ __BLOCK GElf_Xword strsz = 0;
+ __BLOCK size_t n =
+ data->d_size / gelf_fsize (mod->main.elf, ELF_T_DYN, 1, EV_CURRENT);
for (size_t j = 0; j < n; ++j)
{
GElf_Dyn dyn_mem;
@@ -747,7 +761,8 @@ find_dynsym (Dwfl_Module *mod)
/* Translate pointers into file offsets. ADJUST is either zero
in case the dynamic segment wasn't adjusted or mod->main_bias. */
- void translate_offs (GElf_Addr adjust)
+ NESTED_FUNC (void, translate_offs,
+ (GElf_Addr), (GElf_Addr adjust))
{
GElf_Off offs[i_max] = { 0, };
find_offsets (mod->main.elf, adjust, phnum, i_max, addrs, offs);
@@ -862,7 +877,7 @@ find_dynsym (Dwfl_Module *mod)
mod->symerr = DWFL_E_NOERROR;
}
}
- }
+ };
/* First try unadjusted, like ELF files from disk, vdso.
Then try for already adjusted dynamic section, like ELF
diff --git a/libdwfl/dwfl_module_getsrc_file.c b/libdwfl/dwfl_module_getsrc_file.c
index 20aa8a5..eb5f0ca 100644
--- a/libdwfl/dwfl_module_getsrc_file.c
+++ b/libdwfl/dwfl_module_getsrc_file.c
@@ -28,7 +28,7 @@
#include "libdwflP.h"
#include "../libdw/libdwP.h"
-
+#include "nested_func.h"
int
dwfl_module_getsrc_file (Dwfl_Module *mod,
@@ -45,31 +45,34 @@ dwfl_module_getsrc_file (Dwfl_Module *mod,
return -1;
}
- bool is_basename = strchr (fname, '/') == NULL;
+ const bool is_basename = strchr (fname, '/') == NULL;
- size_t max_match = *nsrcs ?: ~0u;
- size_t act_match = *nsrcs;
- size_t cur_match = 0;
- Dwfl_Line **match = *nsrcs == 0 ? NULL : *srcsp;
+ __BLOCK size_t max_match = *nsrcs ?: ~0u;
+ __BLOCK size_t act_match = *nsrcs;
+ __BLOCK size_t cur_match = 0;
+ __BLOCK Dwfl_Line **match = *nsrcs == 0 ? NULL : *srcsp;
- struct dwfl_cu *cu = NULL;
+ __BLOCK struct dwfl_cu *cu = NULL;
Dwfl_Error error;
while ((error = __libdwfl_nextcu (mod, cu, &cu)) == DWFL_E_NOERROR
&& cu != NULL
&& (error = __libdwfl_cu_getsrclines (cu)) == DWFL_E_NOERROR)
{
- inline const char *INTUSE(dwarf_line_file) (const Dwarf_Line *line)
+ INLINE_INTUSE_NESTED_FUNC (const char *, dwarf_line_file,
+ (const Dwarf_Line *), (const Dwarf_Line *line))
{
return line->files->info[line->file].name;
- }
- inline Dwarf_Line *dwfl_line (const Dwfl_Line *line)
+ };
+ INLINE_NESTED_FUNC (Dwarf_Line *, dwfl_line,
+ (const Dwfl_Line *), (const Dwfl_Line *line))
{
return &dwfl_linecu (line)->die.cu->lines->info[line->idx];
- }
- inline const char *dwfl_line_file (const Dwfl_Line *line)
+ };
+ INLINE_NESTED_FUNC (const char *, dwfl_line_file,
+ (const Dwfl_Line *), (const Dwfl_Line *line))
{
return INTUSE(dwarf_line_file) (dwfl_line (line));
- }
+ };
/* Search through all the line number records for a matching
file and line/column number. If any of the numbers is zero,
diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c
index a0f07ad..508c2ea 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 <elf.h>
#include <gelf.h>
@@ -232,15 +233,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;
@@ -254,34 +258,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);
@@ -290,15 +298,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
@@ -316,35 +326,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,
@@ -396,8 +408,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 ();
@@ -413,37 +425,39 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
phdrsp = malloc (sizeof (phdrsn));
if (unlikely (phdrsp == NULL))
return finish ();
- phdrsn *phdrs = (phdrsn *) phdrsp;
+ __BLOCK phdrsn *phdrs = (phdrsn *) phdrsp;
xlateto.d_buf = phdrs;
xlateto.d_size = sizeof (phdrsn);
/* 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)
@@ -503,13 +517,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)
{
@@ -572,7 +591,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
module_end = vaddr_end;
break;
}
- }
+ };
if (ei_class == ELFCLASS32)
{
if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
@@ -716,11 +735,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)
{
@@ -745,13 +765,13 @@ 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 *dyns = NULL;
- void *dyn_data = NULL;
- size_t dyn_data_size = 0;
+ __BLOCK void *dyns = NULL;
+ __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))
{
@@ -793,8 +813,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.
@@ -827,7 +847,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.
@@ -875,29 +895,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 ed8f6e9..a5ab679 100644
--- a/libdwfl/elf-from-memory.c
+++ b/libdwfl/elf-from-memory.c
@@ -31,6 +31,7 @@
#undef _
#include "libdwflP.h"
+#include "nested_func.h"
#include <gelf.h>
#include <sys/types.h>
@@ -38,6 +39,10 @@
#include <stdlib.h>
#include <string.h>
+#ifndef max
+#define max(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
/* 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
@@ -65,12 +70,12 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
{
/* 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;
/* First read in the file header and check its sanity. */
const size_t initial_bufsize = 256;
- unsigned char *buffer = malloc (initial_bufsize);
+ __BLOCK unsigned char *buffer = malloc (initial_bufsize);
if (unlikely (buffer == NULL))
{
no_memory:
@@ -78,7 +83,7 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
return NULL;
}
- ssize_t nread = (*read_memory) (arg, buffer, ehdr_vma,
+ __BLOCK ssize_t nread = (*read_memory) (arg, buffer, ehdr_vma,
sizeof (Elf32_Ehdr), initial_bufsize);
if (nread <= 0)
{
@@ -100,18 +105,18 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
/* Extract the information we need from the file header. */
- union
+ __BLOCK union
{
Elf32_Ehdr e32;
Elf64_Ehdr e64;
} ehdr;
- Elf_Data xlatefrom =
+ __BLOCK Elf_Data xlatefrom =
{
.d_type = ELF_T_EHDR,
.d_buf = buffer,
.d_version = EV_CURRENT,
};
- Elf_Data xlateto =
+ __BLOCK Elf_Data xlateto =
{
.d_type = ELF_T_EHDR,
.d_buf = &ehdr,
@@ -119,10 +124,10 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
.d_version = EV_CURRENT,
};
- GElf_Off phoff;
- uint_fast16_t phnum;
- uint_fast16_t phentsize;
- GElf_Off shdrs_end;
+ __BLOCK GElf_Off phoff;
+ __BLOCK uint_fast16_t phnum;
+ __BLOCK uint_fast16_t phentsize;
+ __BLOCK GElf_Off shdrs_end;
switch (buffer[EI_CLASS])
{
@@ -209,48 +214,51 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
xlateto.d_size = sizeof (phdrsn);
/* 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;
- switch (ehdr.e32.e_ident[EI_CLASS])
+ __BLOCK size_t contents_size = 0;
+ __BLOCK GElf_Off segments_end = 0;
+ __BLOCK GElf_Off segments_end_mem = 0;
+ __BLOCK GElf_Addr loadbase = ehdr_vma;
+ __BLOCK bool found_base = 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. */
+ INLINE_NESTED_FUNC (bool, handle_segment1,
+ (GElf_Addr, GElf_Off, GElf_Xword, GElf_Xword),
+ (GElf_Addr vaddr, GElf_Off offset,
+ GElf_Xword filesz, GElf_Xword memsz))
{
- /* 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;
+ /* 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);
+ GElf_Off segment_end = ((offset + filesz + pagesize - 1)
+ & -pagesize);
- if (segment_end > (GElf_Off) contents_size)
- contents_size = segment_end;
+ 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;
- }
+ 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;
- }
+ segments_end = offset + filesz;
+ segments_end_mem = offset + memsz;
+ return false;
+ };
+ switch (ehdr.e32.e_ident[EI_CLASS])
+ {
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 (phdrs->p32[i].p_type == PT_LOAD)
- if (handle_segment (phdrs->p32[i].p_vaddr, phdrs->p32[i].p_offset,
+ if (handle_segment1 (phdrs->p32[i].p_vaddr, phdrs->p32[i].p_offset,
phdrs->p32[i].p_filesz, phdrs->p32[i].p_memsz))
goto bad_elf;
break;
@@ -261,7 +269,7 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
goto libelf_error;
for (uint_fast16_t i = 0; i < phnum; ++i)
if (phdrs->p64[i].p_type == PT_LOAD)
- if (handle_segment (phdrs->p64[i].p_vaddr, phdrs->p64[i].p_offset,
+ if (handle_segment1 (phdrs->p64[i].p_vaddr, phdrs->p64[i].p_offset,
phdrs->p64[i].p_filesz, phdrs->p64[i].p_memsz))
goto bad_elf;
break;
@@ -296,27 +304,28 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
goto no_memory;
}
- switch (ehdr.e32.e_ident[EI_CLASS])
+ /* Reads the given segment. Returns true if reading fails,
+ false otherwise. */
+ INLINE_NESTED_FUNC (bool, handle_segment2,
+ (GElf_Addr, GElf_Off, GElf_Xword),
+ (GElf_Addr vaddr, GElf_Off offset, GElf_Xword filesz))
{
- /* 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;
- }
+ 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;
+ };
+ switch (ehdr.e32.e_ident[EI_CLASS])
+ {
case ELFCLASS32:
for (uint_fast16_t i = 0; i < phnum; ++i)
if (phdrs->p32[i].p_type == PT_LOAD)
- if (handle_segment (phdrs->p32[i].p_vaddr, phdrs->p32[i].p_offset,
+ if (handle_segment2 (phdrs->p32[i].p_vaddr, phdrs->p32[i].p_offset,
phdrs->p32[i].p_filesz))
goto read_error;
@@ -343,7 +352,7 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
case ELFCLASS64:
for (uint_fast16_t i = 0; i < phnum; ++i)
if (phdrs->p64[i].p_type == PT_LOAD)
- if (handle_segment (phdrs->p64[i].p_vaddr, phdrs->p64[i].p_offset,
+ if (handle_segment2 (phdrs->p64[i].p_vaddr, phdrs->p64[i].p_offset,
phdrs->p64[i].p_filesz))
goto read_error;
diff --git a/libdwfl/frame_unwind.c b/libdwfl/frame_unwind.c
index 16cebd0..52c7d2d 100644
--- a/libdwfl/frame_unwind.c
+++ b/libdwfl/frame_unwind.c
@@ -34,6 +34,7 @@
#include <stdlib.h>
#include "libdwflP.h"
#include "../libdw/dwarf.h"
+#include "nested_func.h"
#include <sys/ptrace.h>
/* Maximum number of DWARF expression stack slots before returning an error. */
@@ -108,17 +109,16 @@ static bool
expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
size_t nops, Dwarf_Addr *result, Dwarf_Addr bias)
{
- Dwfl_Process *process = state->thread->process;
+ __BLOCK Dwfl_Process *process = state->thread->process;
if (nops == 0)
{
__libdwfl_seterrno (DWFL_E_INVALID_DWARF);
return false;
}
- Dwarf_Addr *stack = NULL;
- size_t stack_used = 0, stack_allocated = 0;
+ __BLOCK Dwarf_Addr *stack = NULL;
+ __BLOCK size_t stack_used = 0, stack_allocated = 0;
- bool
- push (Dwarf_Addr val)
+ NESTED_FUNC (bool, push, (Dwarf_Addr), (Dwarf_Addr val))
{
if (stack_used >= DWARF_EXPR_STACK_MAX)
{
@@ -138,10 +138,9 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
}
stack[stack_used++] = val;
return true;
- }
+ };
- bool
- pop (Dwarf_Addr *val)
+ NESTED_FUNC (bool, pop, (Dwarf_Addr *), (Dwarf_Addr *val))
{
if (stack_used == 0)
{
@@ -150,7 +149,7 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
}
*val = stack[--stack_used];
return true;
- }
+ };
Dwarf_Addr val1, val2;
bool is_location = false;
diff --git a/libdwfl/gzip.c b/libdwfl/gzip.c
index b7dde5d..af466e6 100644
--- a/libdwfl/gzip.c
+++ b/libdwfl/gzip.c
@@ -28,6 +28,7 @@
#include "libdwflP.h"
#include "system.h"
+#include "nested_func.h"
#include <unistd.h>
@@ -79,9 +80,9 @@ unzip (int fd, off64_t start_offset,
void *mapped, size_t mapped_size,
void **whole, size_t *whole_size)
{
- void *buffer = NULL;
- size_t size = 0;
- inline bool bigger_buffer (size_t start)
+ __BLOCK void *buffer = NULL;
+ __BLOCK size_t size = 0;
+ INLINE_NESTED_FUNC (bool, bigger_buffer, (size_t), (size_t start))
{
size_t more = size ? size * 2 : start;
char *b = realloc (buffer, more);
@@ -92,17 +93,17 @@ unzip (int fd, off64_t start_offset,
buffer = b;
size = more;
return true;
- }
- inline void smaller_buffer (size_t end)
+ };
+ INLINE_NESTED_FUNC (void, smaller_buffer, (size_t), (size_t end))
{
buffer = realloc (buffer, end) ?: end == 0 ? NULL : buffer;
size = end;
- }
+ };
- void *input_buffer = NULL;
- off_t input_pos = 0;
+ __BLOCK void *input_buffer = NULL;
+ __BLOCK off_t input_pos = 0;
- inline Dwfl_Error fail (Dwfl_Error failure)
+ INLINE_NESTED_FUNC (Dwfl_Error, fail, (Dwfl_Error), (Dwfl_Error failure))
{
if (input_pos == (off_t) mapped_size)
*whole = input_buffer;
@@ -113,9 +114,9 @@ unzip (int fd, off64_t start_offset,
}
free (buffer);
return failure;
- }
+ };
- inline Dwfl_Error zlib_fail (int result)
+ INLINE_NESTED_FUNC (Dwfl_Error, zlib_fail, (int), (int result))
{
switch (result)
{
@@ -126,7 +127,7 @@ unzip (int fd, off64_t start_offset,
default:
return fail (DWFL_E_ZLIB);
}
- }
+ };
if (mapped == NULL)
{
@@ -169,8 +170,8 @@ unzip (int fd, off64_t start_offset,
The stupid zlib interface has nothing to grok the
gzip file headers except the slow gzFile interface. */
- z_stream z = { .next_in = mapped, .avail_in = mapped_size };
- int result = inflateInit (&z);
+ __BLOCK z_stream z = { .next_in = mapped, .avail_in = mapped_size };
+ __BLOCK int result = inflateInit (&z);
if (result != Z (OK))
{
inflateEnd (&z);
@@ -223,8 +224,8 @@ unzip (int fd, off64_t start_offset,
/* Let the decompression library read the file directly. */
- gzFile zf;
- Dwfl_Error open_stream (void)
+ __BLOCK gzFile zf;
+ NESTED_FUNC (Dwfl_Error, open_stream, (void), (void))
{
int d = dup (fd);
if (unlikely (d < 0))
@@ -248,7 +249,7 @@ unzip (int fd, off64_t start_offset,
/* From here on, zlib will close D. */
return DWFL_E_NOERROR;
- }
+ };
Dwfl_Error result = open_stream ();
diff --git a/libdwfl/link_map.c b/libdwfl/link_map.c
index 030c600..204444d 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 <byteswap.h>
#include <endian.h>
@@ -48,14 +49,14 @@ static bool
auxv_format_probe (const void *auxv, size_t size,
uint_fast8_t *elfclass, uint_fast8_t *elfdata)
{
- const union
+ __BLOCK const union
{
char buf[size];
Elf32_auxv_t a32[size / sizeof (Elf32_auxv_t)];
Elf64_auxv_t a64[size / sizeof (Elf64_auxv_t)];
} *u = auxv;
- inline bool check64 (size_t i)
+ INLINE_NESTED_FUNC (bool, check64, (size_t), (size_t i))
{
/* The AUXV pointer might not even be naturally aligned for 64-bit
data, because note payloads in a core file are not aligned. */
@@ -78,9 +79,9 @@ auxv_format_probe (const void *auxv, size_t size,
}
return false;
- }
+ };
- inline bool check32 (size_t i)
+ INLINE_NESTED_FUNC (bool, check32, (size_t), (size_t i))
{
/* The AUXV pointer might not even be naturally aligned for 32-bit
data, because note payloads in a core file are not aligned. */
@@ -103,7 +104,7 @@ auxv_format_probe (const void *auxv, size_t size,
}
return false;
- }
+ };
for (size_t i = 0; i < size / sizeof (Elf64_auxv_t); ++i)
{
@@ -247,20 +248,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;
- }
+ };
+#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];
- inline bool read_addrs (GElf_Addr vaddr, size_t n)
+#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. */
@@ -306,7 +314,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);
@@ -697,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)
@@ -753,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)
{
@@ -780,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/libdwfl/linux-kernel-modules.c b/libdwfl/linux-kernel-modules.c
index 236e2cd..5620bc1 100644
--- a/libdwfl/linux-kernel-modules.c
+++ b/libdwfl/linux-kernel-modules.c
@@ -34,6 +34,7 @@
#include <config.h>
#include "libdwflP.h"
+#include "nested_func.h"
#include <inttypes.h>
#include <errno.h>
#include <stdio.h>
@@ -444,7 +445,7 @@ INTDEF (dwfl_linux_kernel_report_offline)
static int
intuit_kernel_bounds (Dwarf_Addr *start, Dwarf_Addr *end, Dwarf_Addr *notes)
{
- FILE *f = fopen (KSYMSFILE, "r");
+ __BLOCK FILE *f = fopen (KSYMSFILE, "r");
if (f == NULL)
return errno;
@@ -452,13 +453,13 @@ intuit_kernel_bounds (Dwarf_Addr *start, Dwarf_Addr *end, Dwarf_Addr *notes)
*notes = 0;
- char *line = NULL;
- size_t linesz = 0;
- size_t n;
- char *p = NULL;
- const char *type;
+ __BLOCK char *line = NULL;
+ __BLOCK size_t linesz = 0;
+ __BLOCK size_t n;
+ __BLOCK char *p = NULL;
+ __BLOCK const char *type;
- inline bool read_address (Dwarf_Addr *addr)
+ INLINE_NESTED_FUNC (bool, read_address, (Dwarf_Addr *), (Dwarf_Addr *addr))
{
if ((n = getline (&line, &linesz, f)) < 1 || line[n - 2] == ']')
return false;
@@ -468,7 +469,7 @@ intuit_kernel_bounds (Dwarf_Addr *start, Dwarf_Addr *end, Dwarf_Addr *notes)
if (type == NULL)
return false;
return p != NULL && p != line;
- }
+ };
int result;
do
@@ -619,12 +620,12 @@ check_module_notes (Dwfl_Module *mod)
int
dwfl_linux_kernel_report_kernel (Dwfl *dwfl)
{
- Dwarf_Addr start;
- Dwarf_Addr end;
- inline Dwfl_Module *report (void)
+ __BLOCK Dwarf_Addr start;
+ __BLOCK Dwarf_Addr end;
+ INLINE_NESTED_FUNC (Dwfl_Module *, report, (void), (void))
{
return INTUSE(dwfl_report_module) (dwfl, KERNEL_MODNAME, start, end);
- }
+ };
/* This is a bit of a kludge. If we already reported the kernel,
don't bother figuring it out again--it never changes. */
@@ -683,18 +684,18 @@ dwfl_linux_kernel_find_elf (Dwfl_Module *mod,
/* Do "find /lib/modules/`uname -r` -name MODULE_NAME.ko". */
- char *modulesdir[] = { NULL, NULL };
+ __BLOCK char *modulesdir[] = { NULL, NULL };
if (asprintf (&modulesdir[0], MODULEDIRFMT, release) < 0)
return -1;
- FTS *fts = fts_open (modulesdir, FTS_NOSTAT | FTS_LOGICAL, NULL);
+ __BLOCK FTS *fts = fts_open (modulesdir, FTS_NOSTAT | FTS_LOGICAL, NULL);
if (fts == NULL)
{
free (modulesdir[0]);
return -1;
}
- size_t namelen = strlen (module_name);
+ __BLOCK size_t namelen = strlen (module_name);
/* This is a kludge. There is no actual necessary relationship between
the name of the .ko file installed and the module name the kernel
@@ -707,13 +708,13 @@ dwfl_linux_kernel_find_elf (Dwfl_Module *mod,
two files when either a '_' or '-' appears in a module name, one using
only '_' and one only using '-'. */
- char *alternate_name = malloc (namelen + 1);
+ __BLOCK char *alternate_name = malloc (namelen + 1);
if (unlikely (alternate_name == NULL))
{
free (modulesdir[0]);
return ENOMEM;
}
- inline bool subst_name (char from, char to)
+ INLINE_NESTED_FUNC (bool, subst_name, (char, char), (char from, char to))
{
const char *n = memchr (module_name, from, namelen);
if (n == NULL)
@@ -730,7 +731,7 @@ dwfl_linux_kernel_find_elf (Dwfl_Module *mod,
}
memcpy (a, n, namelen - (n - module_name) + 1);
return true;
- }
+ };
if (!subst_name ('-', '_') && !subst_name ('_', '-'))
alternate_name[0] = '\0';
diff --git a/libdwfl/linux-proc-maps.c b/libdwfl/linux-proc-maps.c
index d085834..f22e0bb 100644
--- a/libdwfl/linux-proc-maps.c
+++ b/libdwfl/linux-proc-maps.c
@@ -41,6 +41,7 @@
#include <assert.h>
#include <endian.h>
#include "system.h"
+#include "nested_func.h"
#define PROCMAPSFMT "/proc/%d/maps"
@@ -178,12 +179,12 @@ grovel_auxv (pid_t pid, Dwfl *dwfl, GElf_Addr *sysinfo_ehdr)
static int
proc_maps_report (Dwfl *dwfl, FILE *f, GElf_Addr sysinfo_ehdr, pid_t pid)
{
- unsigned int last_dmajor = -1, last_dminor = -1;
- uint64_t last_ino = -1;
- char *last_file = NULL;
- Dwarf_Addr low = 0, high = 0;
+ __BLOCK unsigned int last_dmajor = -1, last_dminor = -1;
+ __BLOCK uint64_t last_ino = -1;
+ __BLOCK char *last_file = NULL;
+ __BLOCK Dwarf_Addr low = 0, high = 0;
- inline bool report (void)
+ INLINE_NESTED_FUNC (bool, report, (void), (void))
{
if (last_file != NULL)
{
@@ -195,7 +196,7 @@ proc_maps_report (Dwfl *dwfl, FILE *f, GElf_Addr sysinfo_ehdr, pid_t pid)
return true;
}
return false;
- }
+ };
char *line = NULL;
size_t linesz;
diff --git a/libdwfl/relocate.c b/libdwfl/relocate.c
index e102e1e..fdbf096 100644
--- a/libdwfl/relocate.c
+++ b/libdwfl/relocate.c
@@ -27,6 +27,7 @@
not, see <http://www.gnu.org/licenses/>. */
#include "libdwflP.h"
+#include "nested_func.h"
typedef uint8_t GElf_Byte;
@@ -284,9 +285,9 @@ relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr,
Elf_Scn *tscn, bool debugscn, bool partial)
{
/* First, fetch the name of the section these relocations apply to. */
- GElf_Shdr tshdr_mem;
- GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem);
- const char *tname = elf_strptr (relocated, shstrndx, tshdr->sh_name);
+ __BLOCK GElf_Shdr tshdr_mem;
+ __BLOCK GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem);
+ __BLOCK const char *tname = elf_strptr (relocated, shstrndx, tshdr->sh_name);
if (tname == NULL)
return DWFL_E_LIBELF;
@@ -300,7 +301,7 @@ relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr,
return DWFL_E_NOERROR;
/* Fetch the section data that needs the relocations applied. */
- Elf_Data *tdata = elf_rawdata (tscn, NULL);
+ __BLOCK Elf_Data *tdata = elf_rawdata (tscn, NULL);
if (tdata == NULL)
return DWFL_E_LIBELF;
@@ -310,26 +311,26 @@ relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr,
isn't illegal for ELF section data to overlap the header data,
but updating the (relocation) data might corrupt the in-memory
libelf headers causing strange corruptions or errors. */
- size_t ehsize = gelf_fsize (relocated, ELF_T_EHDR, 1, EV_CURRENT);
+ __BLOCK size_t ehsize = gelf_fsize (relocated, ELF_T_EHDR, 1, EV_CURRENT);
if (unlikely (shdr->sh_offset < ehsize
|| tshdr->sh_offset < ehsize))
return DWFL_E_BADELF;
- GElf_Off shdrs_start = ehdr->e_shoff;
- size_t shnums;
+ __BLOCK GElf_Off shdrs_start = ehdr->e_shoff;
+ __BLOCK size_t shnums;
if (elf_getshdrnum (relocated, &shnums) < 0)
return DWFL_E_LIBELF;
/* Overflows will have been checked by elf_getshdrnum/get|rawdata. */
- size_t shentsize = gelf_fsize (relocated, ELF_T_SHDR, 1, EV_CURRENT);
- GElf_Off shdrs_end = shdrs_start + shnums * shentsize;
+ __BLOCK size_t shentsize = gelf_fsize (relocated, ELF_T_SHDR, 1, EV_CURRENT);
+ __BLOCK GElf_Off shdrs_end = shdrs_start + shnums * shentsize;
if (unlikely ((shdrs_start < shdr->sh_offset + shdr->sh_size
&& shdr->sh_offset < shdrs_end)
|| (shdrs_start < tshdr->sh_offset + tshdr->sh_size
&& tshdr->sh_offset < shdrs_end)))
return DWFL_E_BADELF;
- GElf_Off phdrs_start = ehdr->e_phoff;
- size_t phnums;
+ __BLOCK GElf_Off phdrs_start = ehdr->e_phoff;
+ __BLOCK size_t phnums;
if (elf_getphdrnum (relocated, &phnums) < 0)
return DWFL_E_LIBELF;
if (phdrs_start != 0 && phnums != 0)
@@ -345,8 +346,10 @@ relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr,
}
/* Apply one relocation. Returns true for any invalid data. */
- Dwfl_Error relocate (GElf_Addr offset, const GElf_Sxword *addend,
- int rtype, int symndx)
+ NESTED_FUNC (Dwfl_Error, relocate,
+ (GElf_Addr, const GElf_Sxword *, int, int),
+ (GElf_Addr offset, const GElf_Sxword *addend,
+ int rtype, int symndx))
{
/* First see if this is a reloc we can handle.
If we are skipping it, don't bother resolving the symbol. */
@@ -482,16 +485,16 @@ relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr,
/* We have applied this relocation! */
return DWFL_E_NOERROR;
- }
+ };
/* Fetch the relocation section and apply each reloc in it. */
- Elf_Data *reldata = elf_getdata (scn, NULL);
+ __BLOCK Elf_Data *reldata = elf_getdata (scn, NULL);
if (reldata == NULL)
return DWFL_E_LIBELF;
- Dwfl_Error result = DWFL_E_NOERROR;
- bool first_badreltype = true;
- inline void check_badreltype (void)
+ __BLOCK Dwfl_Error result = DWFL_E_NOERROR;
+ __BLOCK bool first_badreltype = true;
+ INLINE_NESTED_FUNC (void, check_badreltype, (void), (void))
{
if (first_badreltype)
{
@@ -501,7 +504,7 @@ relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr,
any libebl_CPU.so library. Diagnose that clearly. */
result = DWFL_E_UNKNOWN_MACHINE;
}
- }
+ };
size_t sh_entsize
= gelf_fsize (relocated, shdr->sh_type == SHT_REL ? ELF_T_REL : ELF_T_RELA,
diff --git a/libelf/elf32_updatefile.c b/libelf/elf32_updatefile.c
index 832f852..e0f43c6 100644
--- a/libelf/elf32_updatefile.c
+++ b/libelf/elf32_updatefile.c
@@ -43,6 +43,7 @@
#include <system.h>
#include "libelfP.h"
+#include "nested_func.h"
#ifndef LIBELFBITS
@@ -303,7 +304,7 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
Elf_Data_List *dl = &scn->data_list;
bool scn_changed = false;
- void fill_mmap (size_t offset)
+ NESTED_FUNC (void, fill_mmap, (size_t), (size_t offset))
{
size_t written = 0;
@@ -322,7 +323,7 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
memset (fill_start, __libelf_fill_byte,
scn_start + offset - fill_start);
}
- }
+ };
if (scn->data_list_rear != NULL)
do
diff --git a/libelf/elf_begin.c b/libelf/elf_begin.c
index f002ebf..6878298 100644
--- a/libelf/elf_begin.c
+++ b/libelf/elf_begin.c
@@ -46,6 +46,7 @@
#include <system.h>
#include "libelfP.h"
#include "common.h"
+#include "nested_func.h"
/* Create descriptor for archive in memory. */
@@ -1067,7 +1068,7 @@ elf_begin (fildes, cmd, ref)
return NULL;
}
- Elf *lock_dup_elf ()
+ NESTED_FUNC (Elf *, lock_dup_elf, (void), (void))
{
/* We need wrlock to dup an archive. */
if (ref->kind == ELF_K_AR)
@@ -1078,7 +1079,7 @@ elf_begin (fildes, cmd, ref)
/* Duplicate the descriptor. */
return dup_elf (fildes, cmd, ref);
- }
+ };
switch (cmd)
{
diff --git a/src/addr2line.c b/src/addr2line.c
index 0ce854f..4932189 100644
--- a/src/addr2line.c
+++ b/src/addr2line.c
@@ -39,6 +39,7 @@
#include <system.h>
+#include "nested_func.h"
/* Name and version of program. */
static void print_version (FILE *stream, struct argp_state *state);
@@ -705,20 +706,26 @@ 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)
+ INLINE_NESTED_FUNC (void, show,
+ (int (*) (Dwarf_Line *, bool *),
+ const char *),
+ (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)
+ };
+ INLINE_NESTED_FUNC (void, show_int,
+ (int (*) (Dwarf_Line *, unsigned int *),
+ const char *),
+ (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)");
diff --git a/src/ar.c b/src/ar.c
index 1320d07..f4f2668 100644
--- a/src/ar.c
+++ b/src/ar.c
@@ -43,6 +43,7 @@
#include <system.h>
#include "arlib.h"
+#include "nested_func.h"
/* Name and version of program. */
@@ -459,8 +460,8 @@ do_oper_extract (int oper, const char *arfname, char **argv, int argc,
bool found[argc];
memset (found, '\0', sizeof (found));
- size_t name_max = 0;
- inline bool should_truncate_fname (void)
+ __BLOCK size_t name_max = 0;
+ INLINE_NESTED_FUNC (bool, should_truncate_fname, (void), (void))
{
if (errno == ENAMETOOLONG && allow_truncate_fname)
{
@@ -473,7 +474,7 @@ do_oper_extract (int oper, const char *arfname, char **argv, int argc,
return name_max != 0;
}
return false;
- }
+ };
off_t index_off = -1;
size_t index_size = 0;
diff --git a/src/arlib-argp.c b/src/arlib-argp.c
index 1bdd8d0..1fcb375 100644
--- a/src/arlib-argp.c
+++ b/src/arlib-argp.c
@@ -23,6 +23,7 @@
#include <libintl.h>
#include "arlib.h"
+#include "nested_func.h"
bool arlib_deterministic_output = DEFAULT_AR_DETERMINISTIC;
@@ -59,13 +60,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)
+ INLINE_NESTED_FUNC (char *, text_for_default, (void), (void))
{
char *new_text;
if (unlikely (asprintf (&new_text, gettext ("%s (default)"), text) < 0))
return (char *) text;
return new_text;
- }
+ };
switch (key)
{
diff --git a/src/elflint.c b/src/elflint.c
index 0d5f34d..6781980 100644
--- a/src/elflint.c
+++ b/src/elflint.c
@@ -45,6 +45,7 @@
#include "../libdw/libdwP.h"
#include "../libdwfl/libdwflP.h"
#include "../libdw/memory-access.h"
+#include "nested_func.h"
/* Name and version of program. */
@@ -3387,7 +3388,7 @@ check_attributes (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
return;
}
- Elf_Data *data = elf_rawdata (elf_getscn (ebl->elf, idx), NULL);
+ __BLOCK Elf_Data *data = elf_rawdata (elf_getscn (ebl->elf, idx), NULL);
if (data == NULL || data->d_size == 0 || data->d_buf == NULL)
{
ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
@@ -3395,12 +3396,13 @@ check_attributes (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
return;
}
- inline size_t pos (const unsigned char *p)
+ INLINE_NESTED_FUNC (size_t, pos, (const unsigned char *),
+ (const unsigned char *p))
{
return p - (const unsigned char *) data->d_buf;
- }
+ };
- const unsigned char *p = data->d_buf;
+ __BLOCK const unsigned char *p = data->d_buf;
if (*p++ != 'A')
{
ERROR (gettext ("section [%2d] '%s': unrecognized attribute format\n"),
@@ -3408,10 +3410,10 @@ check_attributes (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
return;
}
- inline size_t left (void)
+ INLINE_NESTED_FUNC (size_t, left, (void), (void))
{
return (const unsigned char *) data->d_buf + data->d_size - p;
- }
+ };
while (left () >= 4)
{
diff --git a/src/ld.c b/src/ld.c
index 6e96ae2..c24f75e 100644
--- a/src/ld.c
+++ b/src/ld.c
@@ -35,6 +35,7 @@
#include <system.h>
#include "ld.h"
#include "list.h"
+#include "nested_func.h"
/* Name and version of program. */
@@ -1078,7 +1079,7 @@ determine_output_format (void)
int fd = open (runp->name, O_RDONLY);
if (fd != -1)
{
- int try (Elf *elf)
+ INLINE_RECURSIVE_NESTED_FUNC (int, try, (Elf *), (Elf *elf))
{
int result = 0;
@@ -1121,7 +1122,7 @@ determine_output_format (void)
elf_end (elf);
return result;
- }
+ };
if (try (elf_begin (fd, ELF_C_READ_MMAP, NULL)) != 0)
/* Found a file. */
diff --git a/src/readelf.c b/src/readelf.c
index d3c2b6b..ab7f9f7 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -53,6 +53,7 @@
#include "../libdw/memory-access.h"
#include "../libdw/known-dwarf.h"
+#include "nested_func.h"
/* Name and version of program. */
@@ -308,7 +309,8 @@ static error_t
parse_opt (int key, char *arg,
struct argp_state *state __attribute__ ((unused)))
{
- void add_dump_section (const char *name, bool implicit)
+ NESTED_FUNC (void, add_dump_section,
+ (const char *, bool), (const char *name, bool implicit))
{
struct section_argument *a = xmalloc (sizeof *a);
a->arg = name;
@@ -318,7 +320,7 @@ parse_opt (int key, char *arg,
= key == 'x' ? &dump_data_sections_tail : &string_sections_tail;
**tailp = a;
*tailp = &a->next;
- }
+ };
switch (key)
{
@@ -3318,11 +3320,11 @@ print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
shdr->sh_size, shdr->sh_offset);
- Elf_Data *data = elf_rawdata (scn, NULL);
+ __BLOCK Elf_Data *data = elf_rawdata (scn, NULL);
if (unlikely (data == NULL || data->d_size == 0))
return;
- const unsigned char *p = data->d_buf;
+ __BLOCK const unsigned char *p = data->d_buf;
/* There is only one 'version', A. */
if (unlikely (*p++ != 'A'))
@@ -3330,10 +3332,10 @@ print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
fputs_unlocked (gettext (" Owner Size\n"), stdout);
- inline size_t left (void)
+ INLINE_NESTED_FUNC (size_t, left, (void), (void))
{
return (const unsigned char *) data->d_buf + data->d_size - p;
- }
+ };
/* Loop over the sections. */
while (left () >= 4)
@@ -4943,12 +4945,12 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
unsigned int version, unsigned int ptr_size,
Dwfl_Module *dwflmod, Ebl *ebl, Dwarf *dbg)
{
- char regnamebuf[REGNAMESZ];
- const char *regname (unsigned int regno)
+ __BLOCK char regnamebuf[REGNAMESZ];
+ NESTED_FUNC (const char *, regname, (unsigned int), (unsigned int regno))
{
register_info (ebl, regno, NULL, regnamebuf, NULL, NULL);
return regnamebuf;
- }
+ };
puts ("\n Program:");
Dwarf_Word pc = vma_base;
@@ -6423,7 +6425,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
uint_fast8_t minimum_instr_len = *linep++;
/* Next the maximum operations per instruction, in version 4 format. */
- uint_fast8_t max_ops_per_instr = version < 4 ? 1 : *linep++;
+ const uint_fast8_t max_ops_per_instr = version < 4 ? 1 : *linep++;
/* Then the flag determining the default value of the is_stmt
register. */
@@ -6536,8 +6538,8 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
++linep;
puts (gettext ("\nLine number statements:"));
- Dwarf_Word address = 0;
- unsigned int op_index = 0;
+ __BLOCK Dwarf_Word address = 0;
+ __BLOCK unsigned int op_index = 0;
size_t line = 1;
uint_fast8_t is_stmt = default_is_stmt;
@@ -6571,9 +6573,10 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
/* 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)
+ __BLOCK unsigned int op_addr_advance;
+ __BLOCK bool show_op_index;
+ INLINE_NESTED_FUNC (void, advance_pc,
+ (unsigned int), (unsigned int op_advance))
{
op_addr_advance = minimum_instr_len * ((op_index + op_advance)
/ max_ops_per_instr);
@@ -6581,7 +6584,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
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)
{
@@ -8882,7 +8885,7 @@ handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
if (nregloc == 0)
return 0;
- ssize_t maxnreg = ebl_register_info (ebl, 0, NULL, 0, NULL, NULL, NULL, NULL);
+ __BLOCK ssize_t maxnreg = ebl_register_info (ebl, 0, NULL, 0, NULL, NULL, NULL, NULL);
if (maxnreg <= 0)
{
for (size_t i = 0; i < nregloc; ++i)
@@ -8891,7 +8894,7 @@ handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
assert (maxnreg > 0);
}
- struct register_info regs[maxnreg];
+ __BLOCK struct register_info regs[maxnreg];
memset (regs, 0, sizeof regs);
/* Sort to collect the sets together. */
@@ -8913,14 +8916,17 @@ 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)
+ INLINE_NESTED_FUNC (bool, same_set,
+ (const struct register_info *,
+ const struct register_info *),
+ (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)));
- }
+ };
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 5e69334..0ffad15 100644
--- a/src/strip.c
+++ b/src/strip.c
@@ -44,6 +44,8 @@
#include <libebl.h>
#include <system.h>
+#include "nested_func.h"
+
typedef uint8_t GElf_Byte;
/* Name and version of program. */
@@ -409,16 +411,16 @@ static int
handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
mode_t mode, struct timespec tvp[2])
{
- size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
- size_t fname_len = strlen (fname) + 1;
- char *fullname = alloca (prefix_len + 1 + fname_len);
- char *cp = fullname;
- Elf *debugelf = NULL;
+ __BLOCK size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
+ __BLOCK size_t fname_len = strlen (fname) + 1;
+ __BLOCK char *fullname = alloca (prefix_len + 1 + fname_len);
+ __BLOCK char *cp = fullname;
+ __BLOCK Elf *debugelf = NULL;
tmp_debug_fname = NULL;
- int result = 0;
- size_t shdridx = 0;
- size_t shstrndx;
- struct shdr_info
+ __BLOCK int result = 0;
+ __BLOCK size_t shdridx = 0;
+ __BLOCK size_t shstrndx;
+ __BLOCK struct shdr_info
{
Elf_Scn *scn;
GElf_Shdr shdr;
@@ -435,19 +437,19 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
struct Ebl_Strent *se;
Elf32_Word *newsymidx;
} *shdr_info = NULL;
- Elf_Scn *scn;
- size_t cnt;
- size_t idx;
- bool changes;
- GElf_Ehdr newehdr_mem;
- GElf_Ehdr *newehdr;
- GElf_Ehdr debugehdr_mem;
- GElf_Ehdr *debugehdr;
- struct Ebl_Strtab *shst = NULL;
- Elf_Data debuglink_crc_data;
- bool any_symtab_changes = false;
- Elf_Data *shstrtab_data = NULL;
- void *debuglink_buf = NULL;
+ __BLOCK Elf_Scn *scn;
+ __BLOCK size_t cnt;
+ __BLOCK size_t idx;
+ __BLOCK bool changes;
+ __BLOCK GElf_Ehdr newehdr_mem;
+ __BLOCK GElf_Ehdr *newehdr;
+ __BLOCK GElf_Ehdr debugehdr_mem;
+ __BLOCK GElf_Ehdr *debugehdr;
+ __BLOCK struct Ebl_Strtab *shst = NULL;
+ __BLOCK Elf_Data debuglink_crc_data;
+ __BLOCK bool any_symtab_changes = false;
+ __BLOCK Elf_Data *shstrtab_data = NULL;
+ __BLOCK void *debuglink_buf = NULL;
/* Create the full name of the file. */
if (prefix != NULL)
@@ -474,7 +476,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
option or resolving all relocations between debug sections with
the --reloc-debug-sections option are currently the only reasons
we need EBL so don't open the backend unless necessary. */
- Ebl *ebl = NULL;
+ __BLOCK Ebl *ebl = NULL;
if (remove_debug || reloc_debug)
{
ebl = ebl_openbackend (elf);
@@ -929,7 +931,7 @@ 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)
+ INLINE_NESTED_FUNC (void, check_preserved, (size_t), (size_t i))
{
if (i != 0 && i < shnum + 2 && shdr_info[i].idx != 0
&& shdr_info[i].debug_data == NULL)
@@ -942,7 +944,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
shdr_info[i].debug_data = shdr_info[i].data;
changes |= i < cnt;
}
- }
+ };
check_preserved (shdr_info[cnt].shdr.sh_link);
if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
@@ -1433,7 +1435,7 @@ 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)
+ INLINE_NESTED_FUNC (void, update_section_size, (const Elf_Data *), (const Elf_Data *newdata))
{
GElf_Shdr shdr_mem;
GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
@@ -1448,7 +1450,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
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
@@ -1459,9 +1461,8 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
const Elf32_Word symtabidx = shdr_info[cnt].old_sh_link;
elf_assert (symtabidx < shnum + 2);
const Elf32_Word *const newsymidx = shdr_info[symtabidx].newsymidx;
- switch (shdr_info[cnt].shdr.sh_type)
- {
- inline bool no_symtab_updates (void)
+
+ INLINE_NESTED_FUNC (bool, no_symtab_updates, (void), (void))
{
/* If the symbol table hasn't changed, do not do anything. */
if (shdr_info[symtabidx].newsymidx == NULL)
@@ -1472,8 +1473,10 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
is discarded, don't adjust anything. */
return (shdr_info[cnt].idx == 0
&& shdr_info[symtabidx].debug_data != NULL);
- }
+ };
+ switch (shdr_info[cnt].shdr.sh_type)
+ {
case SHT_REL:
case SHT_RELA:
if (no_symtab_updates ())
@@ -1790,7 +1793,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
/* Pick up the symbol table and shndx table to
resolve relocation symbol indexes. */
Elf64_Word symt = shdr->sh_link;
- Elf_Data *symdata, *xndxdata;
+ __BLOCK Elf_Data *symdata, *xndxdata;
elf_assert (symt < shnum + 2);
elf_assert (shdr_info[symt].symtab_idx < shnum + 2);
symdata = (shdr_info[symt].debug_data
@@ -1800,8 +1803,9 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *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)
+ NESTED_FUNC (bool, relocate,
+ (GElf_Addr, const GElf_Sxword, bool, int, int),
+ (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)
@@ -1924,7 +1928,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
return true;
}
return false;
- }
+ };
if (shdr->sh_entsize == 0)
INTERNAL_ERROR (fname);
diff --git a/src/unstrip.c b/src/unstrip.c
index 8833094..4d899fa 100644
--- a/src/unstrip.c
+++ b/src/unstrip.c
@@ -49,6 +49,7 @@
#include <libebl.h>
#include <libdwfl.h>
#include "system.h"
+#include "nested_func.h"
#ifndef _
# define _(str) gettext (str)
@@ -395,14 +396,14 @@ static void
adjust_relocs (Elf_Scn *outscn, Elf_Scn *inscn, const GElf_Shdr *shdr,
size_t map[], const GElf_Shdr *symshdr)
{
- Elf_Data *data = elf_getdata (outscn, NULL);
+ __BLOCK Elf_Data *data = elf_getdata (outscn, NULL);
- inline void adjust_reloc (GElf_Xword *info)
+ INLINE_NESTED_FUNC (void, adjust_reloc, (GElf_Xword *), (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));
- }
+ };
switch (shdr->sh_type)
{
@@ -1059,8 +1060,10 @@ find_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab,
sizeof undo_sections[0], compare_sections_nonrel);
}
- bool fail = false;
- inline void check_match (bool match, Elf_Scn *scn, const char *name)
+ __BLOCK bool fail = false;
+ INLINE_NESTED_FUNC (void, check_match,
+ (bool, Elf_Scn *, const char *),
+ (bool match, Elf_Scn *scn, const char *name))
{
if (!match)
{
@@ -1068,7 +1071,7 @@ find_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab,
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)
@@ -1260,8 +1263,8 @@ copy_elided_sections (Elf *unstripped, Elf *stripped,
more sections in stripped file than debug file -- arguments reversed?"));
/* Cache the stripped file's section details. */
- struct section sections[stripped_shnum - 1];
- Elf_Scn *scn = NULL;
+ __BLOCK struct section sections[stripped_shnum - 1];
+ __BLOCK Elf_Scn *scn = NULL;
while ((scn = elf_nextscn (stripped, scn)) != NULL)
{
size_t i = elf_ndxscn (scn) - 1;
@@ -1277,13 +1280,13 @@ more sections in stripped file than debug file -- arguments reversed?"));
sections[i].strent = NULL;
}
- const struct section *stripped_symtab = NULL;
+ __BLOCK const struct section *stripped_symtab = NULL;
/* Sort the sections, allocated by address and others after. */
qsort (sections, stripped_shnum - 1, sizeof sections[0],
stripped_ehdr->e_type == ET_REL
? compare_sections_rel : compare_sections_nonrel);
- size_t nalloc = stripped_shnum - 1;
+ __BLOCK size_t nalloc = stripped_shnum - 1;
while (nalloc > 0 && !(sections[nalloc - 1].shdr.sh_flags & SHF_ALLOC))
{
--nalloc;
@@ -1292,8 +1295,9 @@ 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)
+ INLINE_NESTED_FUNC (struct section *, find_unalloc_section,
+ (const GElf_Shdr *, const char *),
+ (const GElf_Shdr *shdr, const char *name))
{
size_t l = nalloc, u = stripped_shnum - 1;
while (l < u)
@@ -1310,7 +1314,7 @@ more sections in stripped file than debug file -- arguments reversed?"));
return sec;
}
return NULL;
- }
+ };
Elf_Data *shstrtab = elf_getdata (elf_getscn (unstripped,
unstripped_shstrndx), NULL);
@@ -1984,13 +1988,13 @@ 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)
+ NESTED_FUNC (void, warn, (const char *), (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"));
- }
+ };
int stripped_fd = open_file (stripped_file, false);
Elf *stripped = elf_begin (stripped_fd, ELF_C_READ, NULL);
@@ -2244,11 +2248,11 @@ match_module (Dwfl_Module *mod,
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)
+ __BLOCK struct match_module_info mmi = { info->args, NULL, info->match_files };
+ INLINE_NESTED_FUNC (ptrdiff_t, next, (ptrdiff_t), (ptrdiff_t offset))
{
return dwfl_getmodules (info->dwfl, &match_module, &mmi, offset);
- }
+ };
ptrdiff_t offset = next (0);
if (offset == 0)
error (EXIT_FAILURE, 0, _("no matching modules found"));
--
2.5.0.457.gab17608