From e60e3ec8c6e2c752543d1938619bde1171bbd40b Mon Sep 17 00:00:00 2001
From: Chih-Hung Hsieh <chh@google.com>
Date: Thu, 10 Sep 2015 11:44:09 -0700
Subject: [PATCH] For clang use Blocks instead of nested functions.

* Clang has Blocks like closures that can serve similar
  purpose as the nested functions in gnu99.
  Syntax of Blocks is similar to nested functions that
  *NESTED_FUNC macro can be used for the function/block
  declarations.
  See spec in http://clang.llvm.org/docs/BlockLanguageSpec.html
* Local variables used in a closure should have __BLOCK
  attribute unless they are constants.
* Formal parameters used in a closure should be copied
  to local variable and declared as __BLOCK.
* Cannot goto and jump over __BLOCK variables, so these
  variables have been moved to be declared before goto.
* Clang Blocks cannot copy an array to a closure,
  and gcc complains about unbounded stack usage from alloca.

Signed-off-by: Chih-Hung Hsieh <chh@google.com>
---
 backends/ChangeLog                   |   7 ++
 backends/aarch64_regs.c              |  10 +-
 backends/ia64_retval.c               |   6 +-
 lib/nested_func.h                    |  85 ++++++++++++++++
 libdw/ChangeLog                      |  13 +++
 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/ChangeLog                   |   6 ++
 libdwelf/dwelf_elf_gnu_build_id.c    |   7 +-
 libdwfl/ChangeLog                    |  37 +++++++
 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       |  77 +++++++++------
 libdwfl/dwfl_module_getsrc_file.c    |  28 +++---
 libdwfl/dwfl_segment_report_module.c | 187 ++++++++++++++++++++---------------
 libdwfl/elf-from-memory.c            | 133 +++++++++++++------------
 libdwfl/frame_unwind.c               |  17 ++--
 libdwfl/gzip.c                       |  35 +++----
 libdwfl/link_map.c                   |  61 +++++++-----
 libdwfl/linux-kernel-modules.c       |  37 +++----
 libdwfl/linux-proc-maps.c            |  13 +--
 libdwfl/relocate.c                   |  41 ++++----
 libelf/ChangeLog                     |   7 ++
 libelf/elf32_updatefile.c            |   5 +-
 libelf/elf_begin.c                   |   5 +-
 src/ChangeLog                        |  21 ++++
 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 ++++----
 39 files changed, 790 insertions(+), 484 deletions(-)
 create mode 100644 lib/nested_func.h

diff --git a/backends/ChangeLog b/backends/ChangeLog
index 2059d86..32e0e38 100644
--- a/backends/ChangeLog
+++ b/backends/ChangeLog
@@ -1,3 +1,10 @@
+2015-09-10  Chih-Hung Hsieh  <chh@google.com>
+
+	* aarch64_regs.c (aarch64_register_info): Use *NESTED_FUNC macro
+	for nested functions and __BLOCK macro for variables used inside
+	nested functions.
+	* ia64_retval.c (hfa_type): Likewise.
+
 2015-09-04  Chih-Hung Hsieh  <chh@google.com>
 
 	* aarch64_init.c (aarch64_init): Replace K&R function definition
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/ChangeLog b/libdw/ChangeLog
index 13beefc..6366f69 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,16 @@
+2015-09-10  Chih-Hung Hsieh  <chh@google.com>
+
+	* cfi.c (execute_cfi): Use *NESTED_FUNC macro
+	for nested functions and __BLOCK macro for variables used inside
+	nested functions.
+	* dwarf_entry_breakpoints.c (dwarf_entry_breakpoints): Likewise.
+	* dwarf_getscopevar.c (dwarf_getscopevar): Likewise.
+	* dwarf_getsrclines.c (read_srclines): Likewise.
+	__BLOCK variables cannot be jumpped over.
+	Their declarations are moved to the top of the enclosing function.
+	* dwarf_visit_scopes.c (may_have_scopes): Likewise.
+	(__libdw_visit_scopes): Likewise.
+
 2015-09-09  Chih-Hung Hsieh  <chh@google.com>
 
 	* dwarf_macro_getsrcfiles.c (dwarf_macro_getsrcfiles): Remove
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 d0b5134..06895b4 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
       {
@@ -161,7 +163,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/ChangeLog b/libdwelf/ChangeLog
index 342cb9c..cc7a47f 100644
--- a/libdwelf/ChangeLog
+++ b/libdwelf/ChangeLog
@@ -1,3 +1,9 @@
+2015-09-10  Chih-Hung Hsieh  <chh@google.com>
+
+	* dwelf_elf_gnu_build_id.c (find_elf_build_id): Use *NESTED_FUNC macro
+	for nested functions and __BLOCK macro for variables used inside
+	nested functions.
+
 2014-11-14  Mark Wielaard  <mjw@redhat.com>
 
 	* dwelf_elf_gnu_debuglink.c (dwelf_elf_gnu_debuglink): Check d_buf
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/ChangeLog b/libdwfl/ChangeLog
index 03404e9..8dd29b2 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,40 @@
+2015-09-10  Chih-Hung Hsieh  <chh@google.com>
+
+	* argp-std.c (parse_opt): Use *NESTED_FUNC macro
+	for nested functions and __BLOCK macro for variables used inside
+	nested functions.
+	* core-file.c (elf_begin_rand): Likewise.
+	(core_file_read_eagerly): Likewise.
+	Parameters used in a nested function are copied to local
+	__BLOCK variable for nested functions.
+	(dwfl_elf_phdr_memory_callback): Likewise.
+	* dwfl_module.c (dwfl_report_module): Likewise.
+	* dwfl_module_addrsym.c (__libdwfl_addrsym): Likewise.
+	* dwfl_module_getdwarf.c (find_prelink_address_sync): Likewise.
+	(find_offsets): Likewise.
+	(find_dynsym): Likewise, change local array to pointer variable
+	to be used inside a clang Block.
+	* dwfl_module_getsrc_file.c (dwfl_module_getsrc_file): Likewise.
+	* dwfl_segment_report_module.c (invalid_elf): Likewise.
+	(dwfl_segment_report_module): Likewise, copy parameter to local
+	__BLOCK variable to be used inside clang Blocks.
+	* elf-from-memory.c (elf_from_remote_memory): Likewise.
+	Clang Blocks cannot be nested inside switches like existing code;
+	move two handle_segment functions out of the swtich statements and
+	rename them to handle_segment1 and handle_segment2.
+	* frame_unwind.c (expr_eval): Likewise.
+	* gzip.c (unzip): Likewise.
+	* link_map.c (auxv_format_probe): Likewise.
+	(report_r_debug): Likewise, change array to pointer __BLOCK variable
+	for clang nested Blocks.
+	(dwfl_link_map_report): Likewise.
+	* linux-kernel-modules.c (intuit_kernel_bounds): Likewise.
+	(check_module_notes): Likewise.
+	(dwfl_linux_kernel_find_elf): Likewise.
+	* linux-proc-maps.c (grovel_auxv): Likewise.
+	(proc_maps_report): Likewise.
+	* relocate.c (relocate_section): Likewise.
+
 2015-09-10  Chih-Hung Hsieh <chh@google.com>
 
 	* dwfl_module_getdwarf.c (find_prelink_address_sync): Do not use
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 93afb76..f772ca7 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"
 
 #ifndef MAX
 # define MAX(a, b) ((a) > (b) ? (a) : (b))
@@ -255,11 +256,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;
@@ -283,7 +284,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;
 
@@ -295,14 +296,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,
@@ -310,11 +311,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,9 +418,9 @@ find_prelink_address_sync (Dwfl_Module *mod, struct dwfl_file *file)
 
   const int shdrs_bytes =
       (shnum - 1) * MAX (sizeof (Elf32_Shdr), sizeof (Elf64_Shdr));
-  void *shdrs = malloc (shdrs_bytes);
-  Elf32_Shdr *s32 = shdrs;
-  Elf64_Shdr *s64 = shdrs;
+  __BLOCK void *shdrs = malloc (shdrs_bytes);
+  __BLOCK Elf32_Shdr *s32 = shdrs;
+  __BLOCK Elf64_Shdr *s64 = shdrs;
   if (unlikely (shdrs == NULL))
     return DWFL_E_NOMEM;
   dst.d_buf = shdrs;
@@ -447,13 +448,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)
@@ -463,7 +470,7 @@ find_prelink_address_sync (Dwfl_Module *mod, struct dwfl_file *file)
 	if (sh_end > highest)
 	  highest = sh_end;
       }
-  }
+  };
 
   highest = 0;
   scn = NULL;
@@ -675,17 +682,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;
 
@@ -693,7 +700,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)
@@ -707,10 +714,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;
@@ -749,7 +763,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);
@@ -864,7 +879,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..7ec8652 100644
--- a/libdwfl/dwfl_module_getsrc_file.c
+++ b/libdwfl/dwfl_module_getsrc_file.c
@@ -28,6 +28,7 @@
 
 #include "libdwflP.h"
 #include "../libdw/libdwP.h"
+#include "nested_func.h"
 
 
 int
@@ -45,31 +46,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 43742ef..82581f3 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>
@@ -236,15 +237,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;
@@ -258,34 +262,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);
@@ -294,15 +302,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
@@ -320,35 +330,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,
@@ -400,8 +412,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 ();
@@ -411,8 +423,8 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
   const int phdrsp_bytes =
       phnum * MAX (sizeof (Elf32_Phdr), sizeof (Elf64_Phdr));
   phdrsp = malloc (phdrsp_bytes);
-  Elf32_Phdr *p32 = phdrsp;
-  Elf64_Phdr *p64 = phdrsp;
+  __BLOCK Elf32_Phdr *p32 = phdrsp;
+  __BLOCK Elf64_Phdr *p64 = phdrsp;
   if (unlikely (phdrsp == NULL))
     return finish ();
 
@@ -420,31 +432,33 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
   xlateto.d_size = phdrsp_bytes;
 
   /* Track the bounds of the file visible in memory.  */
-  GElf_Off file_trimmed_end = 0; /* Proper p_vaddr + p_filesz end.  */
-  GElf_Off file_end = 0;	 /* Rounded up to effective page size.  */
-  GElf_Off contiguous = 0;	 /* Visible as contiguous file from START.  */
-  GElf_Off total_filesz = 0;	 /* Total size of data to read.  */
+  __BLOCK GElf_Off file_trimmed_end = 0; /* Proper p_vaddr + p_filesz end.  */
+  __BLOCK GElf_Off file_end = 0;	 /* Rounded up to effective page size.  */
+  __BLOCK GElf_Off contiguous = 0;	 /* Visible as contiguous file from START.  */
+  __BLOCK GElf_Off total_filesz = 0;	 /* Total size of data to read.  */
 
   /* Collect the bias between START and the containing PT_LOAD's p_vaddr.  */
-  GElf_Addr bias = 0;
-  bool found_bias = false;
+  __BLOCK GElf_Addr bias = 0;
+  __BLOCK bool found_bias = false;
 
   /* Collect the unbiased bounds of the module here.  */
-  GElf_Addr module_start = -1l;
-  GElf_Addr module_end = 0;
-  GElf_Addr module_address_sync = 0;
+  __BLOCK GElf_Addr module_start = -1l;
+  __BLOCK GElf_Addr module_end = 0;
+  __BLOCK GElf_Addr module_address_sync = 0;
 
   /* If we see PT_DYNAMIC, record it here.  */
-  GElf_Addr dyn_vaddr = 0;
-  GElf_Xword dyn_filesz = 0;
+  __BLOCK GElf_Addr dyn_vaddr = 0;
+  __BLOCK GElf_Xword dyn_filesz = 0;
 
   /* Collect the build ID bits here.  */
-  void *build_id = NULL;
-  size_t build_id_len = 0;
-  GElf_Addr build_id_vaddr = 0;
+  __BLOCK void *build_id = NULL;
+  __BLOCK size_t build_id_len = 0;
+  __BLOCK GElf_Addr build_id_vaddr = 0;
 
   /* Consider a PT_NOTE we've found in the image.  */
-  inline void consider_notes (GElf_Addr vaddr, GElf_Xword filesz)
+  INLINE_NESTED_FUNC (void, consider_notes,
+                      (GElf_Addr, GElf_Xword),
+                      (GElf_Addr vaddr, GElf_Xword filesz))
   {
     /* If we have already seen a build ID, we don't care any more.  */
     if (build_id != NULL || filesz == 0)
@@ -504,13 +518,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)
       {
@@ -573,7 +592,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)
@@ -717,11 +736,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)
       {
@@ -746,7 +766,7 @@ 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));
@@ -755,9 +775,9 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
   if (dyn_filesz != 0 && dyn_filesz % dyn_entsize == 0
       && ! read_portion (&dyn_data, &dyn_data_size, dyn_vaddr, dyn_filesz))
     {
-      void *dyns = malloc (dyn_filesz);
-      Elf32_Dyn *d32 = dyns;
-      Elf64_Dyn *d64 = dyns;
+      __BLOCK void *dyns = malloc (dyn_filesz);
+      __BLOCK Elf32_Dyn *d32 = dyns;
+      __BLOCK Elf64_Dyn *d64 = dyns;
       if (unlikely (dyns == NULL))
 	return finish ();
 
@@ -789,8 +809,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.
@@ -823,7 +843,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.
@@ -871,29 +891,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 47e743d..120f16e 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>
@@ -69,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:
@@ -82,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)
     {
@@ -104,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,
@@ -123,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])
     {
@@ -198,8 +199,8 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
   const int phdrsp_bytes =
       phnum * MAX (sizeof (Elf32_Phdr), sizeof (Elf64_Phdr));
   phdrsp = malloc (phdrsp_bytes);
-  Elf32_Phdr *p32 = phdrsp;
-  Elf64_Phdr *p64 = phdrsp;
+  __BLOCK Elf32_Phdr *p32 = phdrsp;
+  __BLOCK Elf64_Phdr *p64 = phdrsp;
   if (unlikely (phdrsp == NULL))
     {
       free (buffer);
@@ -210,49 +211,52 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
   xlateto.d_size = phdrsp_bytes;
 
   /* Scan for PT_LOAD segments to find the total size of the file image.  */
-  size_t contents_size = 0;
-  GElf_Off segments_end = 0;
-  GElf_Off segments_end_mem = 0;
-  GElf_Addr loadbase = ehdr_vma;
-  bool found_base = false;
-  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 (p32[i].p_type == PT_LOAD)
-	  if (handle_segment (p32[i].p_vaddr, p32[i].p_offset,
-			      p32[i].p_filesz, p32[i].p_memsz))
+	  if (handle_segment1 (p32[i].p_vaddr, p32[i].p_offset,
+			       p32[i].p_filesz, p32[i].p_memsz))
 	    goto bad_elf;
       break;
 
@@ -262,8 +266,8 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
 	goto libelf_error;
       for (uint_fast16_t i = 0; i < phnum; ++i)
 	if (p64[i].p_type == PT_LOAD)
-	  if (handle_segment (p64[i].p_vaddr, p64[i].p_offset,
-			      p64[i].p_filesz, p64[i].p_memsz))
+	  if (handle_segment1 (p64[i].p_vaddr, p64[i].p_offset,
+			       p64[i].p_filesz, p64[i].p_memsz))
 	    goto bad_elf;
       break;
 
@@ -297,28 +301,29 @@ 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 (p32[i].p_type == PT_LOAD)
-	  if (handle_segment (p32[i].p_vaddr, p32[i].p_offset,
-			      p32[i].p_filesz))
+	  if (handle_segment2 (p32[i].p_vaddr, p32[i].p_offset,
+			       p32[i].p_filesz))
 	    goto read_error;
 
       /* If the segments visible in memory didn't include the section
@@ -344,8 +349,8 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
     case ELFCLASS64:
       for (uint_fast16_t i = 0; i < phnum; ++i)
 	if (p64[i].p_type == PT_LOAD)
-	  if (handle_segment (p64[i].p_vaddr, p64[i].p_offset,
-			      p64[i].p_filesz))
+	  if (handle_segment2 (p64[i].p_vaddr, p64[i].p_offset,
+			       p64[i].p_filesz))
 	    goto read_error;
 
       /* If the segments visible in memory didn't include the section
diff --git a/libdwfl/frame_unwind.c b/libdwfl/frame_unwind.c
index bd100b8..51c1f90 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 a756e43..24e0166 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,10 +49,10 @@ static bool
 auxv_format_probe (const void *auxv, size_t size,
 		   uint_fast8_t *elfclass, uint_fast8_t *elfdata)
 {
-  const Elf32_auxv_t *a32 = auxv;
-  const Elf64_auxv_t *a64 = auxv;
+  __BLOCK const Elf32_auxv_t *a32 = auxv;
+  __BLOCK const Elf64_auxv_t *a64 = 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.  */
@@ -74,9 +75,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.  */
@@ -99,7 +100,7 @@ auxv_format_probe (const void *auxv, size_t size,
       }
 
     return false;
-  }
+  };
 
   for (size_t i = 0; i < size / sizeof (Elf64_auxv_t); ++i)
     {
@@ -243,20 +244,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.  */
 
@@ -299,7 +307,7 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
       }
 
     return false;
-  }
+  };
 
   if (unlikely (read_addrs (read_vaddr, 1)))
     return release_buffer (-1);
@@ -690,17 +698,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)
@@ -746,12 +754,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)
 	  {
@@ -773,7 +782,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/ChangeLog b/libelf/ChangeLog
index a9685ba..f55712a 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,10 @@
+2015-09-10  Chih-Hung Hsieh  <chh@google.com>
+
+	* elf32_updatefile.c (__elfw2(LIBELFBITS,updatemmap)): Use *NESTED_FUNC
+	macro for nested functions and __BLOCK macro for variables used inside
+	nested functions.
+	* elf_begin.c (elf_begin): Likewise.
+
 2015-09-08  Chih-Hung Hsieh <chh@google.com>
 
 	* elf_getarsym.c (elf_getarsym): Do not use
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/ChangeLog b/src/ChangeLog
index 7848064..3965281 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,24 @@
+2015-09-10  Chih-Hung Hsieh  <chh@google.com>
+
+	* addr2line.c (handle_address): Use *NESTED_FUNC
+	macro for nested functions and __BLOCK macro for variables used inside
+	nested functions.
+	* ar.c (do_oper_extract): Likewise.
+	* arlib-argp.c (parse_opt): Likewise.
+	* elflint.c (check_attributes): Likewise.
+	* ld.c (determine_output_format): Likewise.
+	* readelf.c (parse_opt): Likewise.
+	(print_attributes): Likewise.
+	(print_cfa_program): Likewise.
+	(print_debug_line_section): Likewise.
+	(handle_core_registers): Likewise.
+	* strip.c (handle_elf): Likewise.
+	* unstrip.c (adjust_relocs): Likewise.
+	(find_alloc_sections_prelink): Likewise.
+	(copy_elided_sections): Likewise.
+	(handle_explicit_files): Likewise.
+	(match_module): Likewise.
+
 2015-09-10  Chih-Hung Hsieh <chh@google.com>
 
 	* readelf.c (print_cfa_program): Do not use
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 c1f0be5..f3c325a 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 a082039..bcd2366 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 = alloca (REGNAMESZ);
-  const char *regname (unsigned int regno)
+   __BLOCK char *regnamebuf = alloca (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)
 	{
@@ -8896,7 +8899,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)
@@ -8906,7 +8909,7 @@ handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
     }
 
   const int sizeof_regs = sizeof (struct register_info) * maxnreg;
-  struct register_info *regs = alloca (sizeof_regs);
+  __BLOCK struct register_info *regs = alloca (sizeof_regs);
   memset (regs, 0, sizeof_regs);
 
   /* Sort to collect the sets together.  */
@@ -8928,14 +8931,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 a42aad6..4fca18b 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)
@@ -399,14 +400,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)
     {
@@ -1063,8 +1064,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)
 	{
@@ -1072,7 +1075,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)
@@ -1264,9 +1267,9 @@ 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 =
+  __BLOCK struct section *sections =
       alloca (sizeof (struct section) * (stripped_shnum - 1));
-  Elf_Scn *scn = NULL;
+  __BLOCK Elf_Scn *scn = NULL;
   while ((scn = elf_nextscn (stripped, scn)) != NULL)
     {
       size_t i = elf_ndxscn (scn) - 1;
@@ -1282,13 +1285,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;
@@ -1297,8 +1300,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)
@@ -1315,7 +1319,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);
@@ -1989,13 +1993,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);
@@ -2249,11 +2253,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.6.0.rc0.131.gf624c3d

