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


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

Re: [PATCH] For clang use Blocks instead of nested functions.


My original "For clang use Blocks instead of nested functions" patch will
have some merge conflict with my "Do without union of variable length
arrays" patch.
Those two patches were made to be reviewed independently.

Assuming that "Do without union of variable length arrays" patch will be
merged first, here the attached
0002-For-clang-use-Blocks-instead-of-nested-functions.patch is the
equivalent changes to be applied after. I also updated the ChangeLog files
in this new 0002* patch.
Please review/test it if you have already applied my previous "Do without
union of variable length arrays" patch. Thanks.



On Fri, Sep 4, 2015 at 4:54 PM, Chih-Hung Hsieh <chh@google.com> wrote:

> * 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 < &regs[maxnreg] && a->regloc != NULL
>             && b < &regs[maxnreg] && b->regloc != NULL
>             && a->bits == b->bits
>             && (a->set == b->set || !strcmp (a->set, b->set)));
> -  }
> +  };
>    struct register_info *sets[maxreg + 1];
>    sets[0] = &regs[0];
>    size_t nsets = 1;
> 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
>
>
My original "For clang use Blocks instead of nested functions" patch will have some merge conflict with my "Do without union of variable length arrays" patch.
Those two patches were made to be reviewed independently.

Assuming that "Do without union of variable length arrays" patch will be merged first, here the attached 0002-For-clang-use-Blocks-instead-of-nested-functions.patch is the equivalent changes to be applied after. I also updated the ChangeLog files in this new 0002* patch.
Please review/test it if you have already applied my previous "Do without union of variable length arrays" patch. Thanks.



On Fri, Sep 4, 2015 at 4:54 PM, Chih-Hung Hsieh <chh@google.com> wrote:
* 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-> 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 = ""> +  __BLOCK Elf_Data src = "">    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 = "" (mod->main.elf,
+         __BLOCK Elf_Data *data = "" (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 = "" - 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_getscn (ebl->elf, idx), NULL);
+  __BLOCK Elf_Data *data = "" (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 = "" (scn, NULL);
+      __BLOCK Elf_Data *data = "" (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 < &regs[maxnreg] && a->regloc != NULL
            && b < &regs[maxnreg] && b->regloc != NULL
            && a->bits == b->bits
            && (a->set == b->set || !strcmp (a->set, b->set)));
-  }
+  };
   struct register_info *sets[maxreg + 1];
   sets[0] = &regs[0];
   size_t nsets = 1;
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 = "" (outscn, NULL);
+  __BLOCK Elf_Data *data = "" (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


Attachment: 0002-For-clang-use-Blocks-instead-of-nested-functions.patch
Description: Binary data


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