When a static variable is defined in a function, clang(1) emits the
following DWARF:

 <1><90>: Abbrev Number: 9 (DW_TAG_subprogram)
      DW_AT_name        : (indirect string, offset: 0x213b): pageflttrap
      [...]
 <2><af>: Abbrev Number: 10 (DW_TAG_variable)
      DW_AT_name        : (indirect string, offset: 0xc9): faultbuf
      [...]
 <2><c4>: Abbrev Number: 11 (DW_TAG_formal_parameter)
     DW_AT_name        : (indirect string, offset: 0x217d): frame
      [...]
 <2><d3>: Abbrev Number: 11 (DW_TAG_formal_parameter)
     DW_AT_name        : (indirect string, offset: 0x2183): usermode
      [...]

As you can see the function arguments are placed *after* the local static
variable.  ctfconv(1) currently stops parsing a `DW_TAG_subprogram' section
as soon as it find a variable definition.  That means with modern clang(1)
functions like panic(9) or pageflttrap() are incorrectly identified as having
no argument.

Diff below fixes that, ok?

Index: parse.c
===================================================================
RCS file: /cvs/src/usr.bin/ctfconv/parse.c,v
retrieving revision 1.11
diff -u -p -r1.11 parse.c
--- parse.c     31 Jan 2018 14:47:13 -0000      1.11
+++ parse.c     6 Nov 2019 13:43:32 -0000
@@ -1138,12 +1142,19 @@ subparse_arguments(struct dwdie *die, si
                 * Nested declaration.
                 *
                 * This matches the case where a ``struct'', ``union'',
-                * ``enum'' or ``typedef'' is first declared "inside" a
-                * function declaration.
+                * ``enum'', ``typedef'' or ``static'' variable is first
+                * declared inside a function declaration.
                 */
-               if (tag == DW_TAG_structure_type || tag == DW_TAG_union_type ||
-                   tag == DW_TAG_enumeration_type || tag == DW_TAG_typedef)
+               switch (tag) {
+               case DW_TAG_structure_type:
+               case DW_TAG_union_type:
+               case DW_TAG_enumeration_type:
+               case DW_TAG_typedef:
+               case DW_TAG_variable:
                        continue;
+               default:
+                       break;
+               }
 
                if (tag != DW_TAG_formal_parameter)
                        break;

Reply via email to