22cf85f
diff --git a/dwflpp.cxx b/dwflpp.cxx
22cf85f
index 636cd38..c31548d 100644
22cf85f
--- a/dwflpp.cxx
22cf85f
+++ b/dwflpp.cxx
22cf85f
@@ -2272,7 +2272,15 @@ dwflpp::express_as_string (string prelude,
22cf85f
 
22cf85f
   fprintf(memstream, "{\n");
22cf85f
   fprintf(memstream, "%s", prelude.c_str());
22cf85f
-  bool deref = c_emit_location (memstream, head, 1);
22cf85f
+
22cf85f
+  unsigned int stack_depth;
22cf85f
+  bool deref = c_emit_location (memstream, head, 1, &stack_depth);
22cf85f
+
22cf85f
+  // Ensure that DWARF keeps loc2c to a "reasonable" stack size
22cf85f
+  // 32 intptr_t leads to max 256 bytes on the stack
22cf85f
+  if (stack_depth > 32)
22cf85f
+    throw semantic_error("oversized DWARF stack");
22cf85f
+
22cf85f
   fprintf(memstream, "%s", postlude.c_str());
22cf85f
   fprintf(memstream, "  goto out;\n");
22cf85f
 
22cf85f
diff --git a/loc2c-test.c b/loc2c-test.c
22cf85f
index 495a95f..ed7aa4b 100644
22cf85f
--- a/loc2c-test.c
22cf85f
+++ b/loc2c-test.c
22cf85f
@@ -329,11 +329,14 @@ handle_variable (Dwarf_Die *lscopes, int lnscopes, int out,
22cf85f
 	"{\n"
22cf85f
 	"  intptr_t value;");
22cf85f
 
22cf85f
-  bool deref = c_emit_location (stdout, head, 1);
22cf85f
+  unsigned int stack_depth;
22cf85f
+  bool deref = c_emit_location (stdout, head, 1, &stack_depth);
22cf85f
 
22cf85f
   obstack_free (&pool, NULL);
22cf85f
 
22cf85f
-  puts (store ? " return;" :
22cf85f
+  printf ("  /* max expression stack depth %u */\n", stack_depth);
22cf85f
+
22cf85f
+  puts (store ? "  return;" :
22cf85f
 	"  printk (\" ---> %ld\\n\", (unsigned long) value);\n"
22cf85f
 	"  return;");
22cf85f
 
22cf85f
diff --git a/loc2c.c b/loc2c.c
22cf85f
index 5d6b549..0716c7d 100644
22cf85f
--- a/loc2c.c
22cf85f
+++ b/loc2c.c
22cf85f
@@ -2071,7 +2071,8 @@ emit_loc_address (FILE *out, struct location *loc, unsigned int indent,
22cf85f
    assign it to an address-sized value.  */
22cf85f
 static void
22cf85f
 emit_loc_value (FILE *out, struct location *loc, unsigned int indent,
22cf85f
-		const char *target, bool declare)
22cf85f
+		const char *target, bool declare,
22cf85f
+		bool *used_deref, unsigned int *max_stack)
22cf85f
 {
22cf85f
   if (declare)
22cf85f
     emit ("%*s%s %s;\n", indent * 2, "", STACK_TYPE, target);
22cf85f
@@ -2091,6 +2092,9 @@ emit_loc_value (FILE *out, struct location *loc, unsigned int indent,
22cf85f
     case loc_address:
22cf85f
     case loc_value:
22cf85f
       emit_loc_address (out, loc, indent, target);
22cf85f
+      *used_deref = *used_deref || loc->address.used_deref;
22cf85f
+      if (loc->address.stack_depth > *max_stack)
22cf85f
+	*max_stack = loc->address.stack_depth;
22cf85f
       break;
22cf85f
     }
22cf85f
 
22cf85f
@@ -2098,7 +2102,8 @@ emit_loc_value (FILE *out, struct location *loc, unsigned int indent,
22cf85f
 }
22cf85f
 
22cf85f
 bool
22cf85f
-c_emit_location (FILE *out, struct location *loc, int indent)
22cf85f
+c_emit_location (FILE *out, struct location *loc, int indent,
22cf85f
+		 unsigned int *max_stack)
22cf85f
 {
22cf85f
   emit ("%*s{\n", indent * 2, "");
22cf85f
 
22cf85f
@@ -2134,9 +2139,11 @@ c_emit_location (FILE *out, struct location *loc, int indent)
22cf85f
       }
22cf85f
 
22cf85f
   bool deref = false;
22cf85f
+  *max_stack = 0;
22cf85f
 
22cf85f
   if (loc->frame_base != NULL)
22cf85f
-    emit_loc_value (out, loc->frame_base, indent, "frame_base", true);
22cf85f
+    emit_loc_value (out, loc->frame_base, indent, "frame_base", true,
22cf85f
+		    &deref, max_stack);
22cf85f
 
22cf85f
   for (; loc->next != NULL; loc = loc->next)
22cf85f
     switch (loc->type)
22cf85f
@@ -2144,8 +2151,7 @@ c_emit_location (FILE *out, struct location *loc, int indent)
22cf85f
       case loc_address:
22cf85f
       case loc_value:
22cf85f
 	/* Emit the program fragment to calculate the address.  */
22cf85f
-	emit_loc_value (out, loc, indent + 1, "addr", false);
22cf85f
-	deref = deref || loc->address.used_deref;
22cf85f
+	emit_loc_value (out, loc, indent + 1, "addr", false, &deref, max_stack);
22cf85f
 	break;
22cf85f
 
22cf85f
       case loc_fragment:
22cf85f
@@ -2172,6 +2178,9 @@ c_emit_location (FILE *out, struct location *loc, int indent)
22cf85f
 
22cf85f
   emit ("%s%*s}\n", loc->address.program, indent * 2, "");
22cf85f
 
22cf85f
+  if (loc->address.stack_depth > *max_stack)
22cf85f
+    *max_stack = loc->address.stack_depth;
22cf85f
+
22cf85f
   return deref || loc->address.used_deref;
22cf85f
 }
22cf85f
 
22cf85f
diff --git a/loc2c.h b/loc2c.h
22cf85f
index becf2d8..45d9382 100644
22cf85f
--- a/loc2c.h
22cf85f
+++ b/loc2c.h
22cf85f
@@ -112,6 +112,7 @@ struct location *c_translate_argument (struct obstack *,
22cf85f
 
22cf85f
    Writes complete lines of C99, code forming a complete C block, to STREAM.
22cf85f
    Return value is true iff that code uses the `deref' runtime macros.  */
22cf85f
-bool c_emit_location (FILE *stream, struct location *loc, int indent);
22cf85f
+bool c_emit_location (FILE *stream, struct location *loc, int indent,
22cf85f
+		      unsigned int *max_stack);
22cf85f
 
22cf85f
 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
22cf85f