Home | History | Annotate | Line # | Download | only in lib
dwarf.exp revision 1.6
      1 # Copyright 2010-2016 Free Software Foundation, Inc.
      2 
      3 # This program is free software; you can redistribute it and/or modify
      4 # it under the terms of the GNU General Public License as published by
      5 # the Free Software Foundation; either version 3 of the License, or
      6 # (at your option) any later version.
      7 #
      8 # This program is distributed in the hope that it will be useful,
      9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
     10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     11 # GNU General Public License for more details.
     12 #
     13 # You should have received a copy of the GNU General Public License
     14 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
     15 
     16 # Return true if the target supports DWARF-2 and uses gas.
     17 # For now pick a sampling of likely targets.
     18 proc dwarf2_support {} {
     19     if {[istarget *-*-linux*]
     20 	|| [istarget *-*-gnu*]
     21 	|| [istarget *-*-elf*]
     22 	|| [istarget *-*-openbsd*]
     23 	|| [istarget arm*-*-eabi*]
     24 	|| [istarget arm*-*-symbianelf*]
     25 	|| [istarget powerpc-*-eabi*]} {
     26 	return 1
     27     }
     28 
     29     return 0
     30 }
     31 
     32 # Build an executable from a fission-based .S file.
     33 # This handles the extra work of splitting the .o into non-dwo and dwo
     34 # pieces, making sure the .dwo is available if we're using cc-with-tweaks.sh
     35 # to build a .dwp file.
     36 # The arguments and results are the same as for build_executable.
     37 #
     38 # Current restrictions:
     39 # - only supports one source file
     40 # - cannot be run on remote hosts
     41 
     42 proc build_executable_from_fission_assembler { testname executable sources options } {
     43     verbose -log "build_executable_from_fission_assembler $testname $executable $sources $options"
     44     if { [llength $sources] != 1 } {
     45 	error "Only one source file supported."
     46     }
     47     if [is_remote host] {
     48 	error "Remote hosts are not supported."
     49     }
     50 
     51     global srcdir subdir
     52     set source_file ${srcdir}/${subdir}/${sources}
     53     set root_name [file rootname [file tail $source_file]]
     54     set output_base [standard_output_file $root_name]
     55     set object_file ${output_base}.o
     56     set dwo_file ${output_base}.dwo
     57     set object_options "object $options"
     58     set objcopy [gdb_find_objcopy]
     59 
     60     set result [gdb_compile $source_file $object_file object $options]
     61     if { "$result" != "" } {
     62 	return -1
     63     }
     64 
     65     set command "$objcopy --extract-dwo $object_file $dwo_file"
     66     verbose -log "Executing $command"
     67     set result [catch "exec $command" output]
     68     verbose -log "objcopy --extract-dwo output: $output"
     69     if { $result == 1 } {
     70 	return -1
     71     }
     72 
     73     set command "$objcopy --strip-dwo $object_file"
     74     verbose -log "Executing $command"
     75     set result [catch "exec $command" output]
     76     verbose -log "objcopy --strip-dwo output: $output"
     77     if { $result == 1 } {
     78 	return -1
     79     }
     80 
     81     set result [gdb_compile $object_file $executable executable $options]
     82     if { "$result" != "" } {
     83 	return -1
     84     }
     85 
     86     return 0
     87 }
     88 
     89 # Return a list of expressions about function FUNC's address and length.
     90 # The first expression is the address of function FUNC, and the second
     91 # one is FUNC's length.  SRC is the source file having function FUNC.
     92 # An internal label ${func}_label must be defined inside FUNC:
     93 #
     94 #  int main (void)
     95 #  {
     96 #    asm ("main_label: .globl main_label");
     97 #    return 0;
     98 #  }
     99 #
    100 # This label is needed to compute the start address of function FUNC.
    101 # If the compiler is gcc, we can do the following to get function start
    102 # and end address too:
    103 #
    104 # asm ("func_start: .globl func_start");
    105 # static void func (void) {}
    106 # asm ("func_end: .globl func_end");
    107 #
    108 # however, this isn't portable, because other compilers, such as clang,
    109 # may not guarantee the order of global asms and function.  The code
    110 # becomes:
    111 #
    112 # asm ("func_start: .globl func_start");
    113 # asm ("func_end: .globl func_end");
    114 # static void func (void) {}
    115 #
    116 
    117 proc function_range { func src } {
    118     global decimal gdb_prompt
    119 
    120     set exe [standard_temp_file func_addr[pid].x]
    121 
    122     gdb_compile $src $exe executable {debug}
    123 
    124     gdb_exit
    125     gdb_start
    126     gdb_load "$exe"
    127 
    128     # Compute the label offset, and we can get the function start address
    129     # by "${func}_label - $func_label_offset".
    130     set func_label_offset ""
    131     set test "p ${func}_label - ${func}"
    132     gdb_test_multiple $test $test {
    133 	-re ".* = ($decimal)\r\n$gdb_prompt $" {
    134 	    set func_label_offset $expect_out(1,string)
    135 	}
    136     }
    137 
    138     # Compute the function length.
    139     global hex
    140     set func_length ""
    141     set test "disassemble $func"
    142     gdb_test_multiple $test $test {
    143 	-re ".*$hex <\\+($decimal)>:\[^\r\n\]+\r\nEnd of assembler dump\.\r\n$gdb_prompt $" {
    144 	    set func_length $expect_out(1,string)
    145 	}
    146     }
    147 
    148     # Compute the size of the last instruction.
    149     if { $func_length == 0 } then {
    150 	set func_pattern "$func"
    151     } else {
    152 	set func_pattern "$func\\+$func_length"
    153     }
    154     set test "x/2i $func+$func_length"
    155     gdb_test_multiple $test $test {
    156 	-re ".*($hex) <$func_pattern>:\[^\r\n\]+\r\n\[ \]+($hex).*\.\r\n$gdb_prompt $" {
    157 	    set start $expect_out(1,string)
    158 	    set end $expect_out(2,string)
    159 
    160 	    set func_length [expr $func_length + $end - $start]
    161 	}
    162     }
    163 
    164     return [list "${func}_label - $func_label_offset" $func_length]
    165 }
    166 
    167 # A DWARF assembler.
    168 #
    169 # All the variables in this namespace are private to the
    170 # implementation.  Also, any procedure whose name starts with "_" is
    171 # private as well.  Do not use these.
    172 #
    173 # Exported functions are documented at their definition.
    174 #
    175 # In addition to the hand-written functions documented below, this
    176 # module automatically generates a function for each DWARF tag.  For
    177 # most tags, two forms are made: a full name, and one with the
    178 # "DW_TAG_" prefix stripped.  For example, you can use either
    179 # 'DW_TAG_compile_unit' or 'compile_unit' interchangeably.
    180 #
    181 # There are two exceptions to this rule: DW_TAG_variable and
    182 # DW_TAG_namespace.  For these, the full name must always be used,
    183 # as the short name conflicts with Tcl builtins.  (Should future
    184 # versions of Tcl or DWARF add more conflicts, this list will grow.
    185 # If you want to be safe you should always use the full names.)
    186 #
    187 # Each tag procedure is defined like:
    188 #
    189 # proc DW_TAG_mumble {{attrs {}} {children {}}} { ... }
    190 #
    191 # ATTRS is an optional list of attributes.
    192 # It is run through 'subst' in the caller's context before processing.
    193 #
    194 # Each attribute in the list has one of two forms:
    195 #   1. { NAME VALUE }
    196 #   2. { NAME VALUE FORM }
    197 #
    198 # In each case, NAME is the attribute's name.
    199 # This can either be the full name, like 'DW_AT_name', or a shortened
    200 # name, like 'name'.  These are fully equivalent.
    201 #
    202 # Besides DWARF standard attributes, assembler supports 'macro' attribute
    203 # which will be substituted by one or more standard or macro attributes.
    204 # supported macro attributes are:
    205 #
    206 #  - MACRO_AT_range { FUNC FILE }
    207 #  It is substituted by DW_AT_low_pc and DW_AT_high_pc with the start and
    208 #  end address of function FUNC in file FILE.
    209 #
    210 #  - MACRO_AT_func { FUNC FILE }
    211 #  It is substituted by DW_AT_name with FUNC and MACRO_AT_range.
    212 #
    213 # If FORM is given, it should name a DW_FORM_ constant.
    214 # This can either be the short form, like 'DW_FORM_addr', or a
    215 # shortened version, like 'addr'.  If the form is given, VALUE
    216 # is its value; see below.  In some cases, additional processing
    217 # is done; for example, DW_FORM_strp manages the .debug_str
    218 # section automatically.
    219 #
    220 # If FORM is 'SPECIAL_expr', then VALUE is treated as a location
    221 # expression.  The effective form is then DW_FORM_block, and VALUE
    222 # is passed to the (internal) '_location' proc to be translated.
    223 # This proc implements a miniature DW_OP_ assembler.
    224 #
    225 # If FORM is not given, it is guessed:
    226 # * If VALUE starts with the "@" character, the rest of VALUE is
    227 #   looked up as a DWARF constant, and DW_FORM_sdata is used.  For
    228 #   example, '@DW_LANG_c89' could be used.
    229 # * If VALUE starts with the ":" character, then it is a label
    230 #   reference.  The rest of VALUE is taken to be the name of a label,
    231 #   and DW_FORM_ref4 is used.  See 'new_label' and 'define_label'.
    232 # * Otherwise, VALUE is taken to be a string and DW_FORM_string is
    233 #   used.  In order to prevent bugs where a numeric value is given but
    234 #   no form is specified, it is an error if the value looks like a number
    235 #   (using Tcl's "string is integer") and no form is provided.
    236 # More form-guessing functionality may be added.
    237 #
    238 # CHILDREN is just Tcl code that can be used to define child DIEs.  It
    239 # is evaluated in the caller's context.
    240 #
    241 # Currently this code is missing nice support for CFA handling, and
    242 # probably other things as well.
    243 
    244 namespace eval Dwarf {
    245     # True if the module has been initialized.
    246     variable _initialized 0
    247 
    248     # Constants from dwarf2.h.
    249     variable _constants
    250     # DW_AT short names.
    251     variable _AT
    252     # DW_FORM short names.
    253     variable _FORM
    254     # DW_OP short names.
    255     variable _OP
    256 
    257     # The current output file.
    258     variable _output_file
    259 
    260     # Note: The _cu_ values here also apply to type units (TUs).
    261     # Think of a TU as a special kind of CU.
    262 
    263     # Current CU count.
    264     variable _cu_count
    265 
    266     # The current CU's base label.
    267     variable _cu_label
    268 
    269     # The current CU's version.
    270     variable _cu_version
    271 
    272     # The current CU's address size.
    273     variable _cu_addr_size
    274     # The current CU's offset size.
    275     variable _cu_offset_size
    276 
    277     # Label generation number.
    278     variable _label_num
    279 
    280     # The deferred output array.  The index is the section name; the
    281     # contents hold the data for that section.
    282     variable _deferred_output
    283 
    284     # If empty, we should write directly to the output file.
    285     # Otherwise, this is the name of a section to write to.
    286     variable _defer
    287 
    288     # The abbrev section.  Typically .debug_abbrev but can be .debug_abbrev.dwo
    289     # for Fission.
    290     variable _abbrev_section
    291 
    292     # The next available abbrev number in the current CU's abbrev
    293     # table.
    294     variable _abbrev_num
    295 
    296     # The string table for this assembly.  The key is the string; the
    297     # value is the label for that string.
    298     variable _strings
    299 
    300     # Current .debug_line unit count.
    301     variable _line_count
    302 
    303     # Whether a file_name entry was seen.
    304     variable _line_saw_file
    305 
    306     # Whether a line table program has been seen.
    307     variable _line_saw_program
    308 
    309     # A Label for line table header generation.
    310     variable _line_header_end_label
    311 
    312     # The address size for debug ranges section.
    313     variable _debug_ranges_64_bit
    314 
    315     proc _process_one_constant {name value} {
    316 	variable _constants
    317 	variable _AT
    318 	variable _FORM
    319 	variable _OP
    320 
    321 	set _constants($name) $value
    322 
    323 	if {![regexp "^DW_(\[A-Z\]+)_(\[A-Za-z0-9_\]+)$" $name \
    324 		  ignore prefix name2]} {
    325 	    error "non-matching name: $name"
    326 	}
    327 
    328 	if {$name2 == "lo_user" || $name2 == "hi_user"} {
    329 	    return
    330 	}
    331 
    332 	# We only try to shorten some very common things.
    333 	# FIXME: CFA?
    334 	switch -exact -- $prefix {
    335 	    TAG {
    336 		# Create two procedures for the tag.  These call
    337 		# _handle_DW_TAG with the full tag name baked in; this
    338 		# does all the actual work.
    339 		proc $name {{attrs {}} {children {}}} \
    340 		    "_handle_DW_TAG $name \$attrs \$children"
    341 
    342 		# Filter out ones that are known to clash.
    343 		if {$name2 == "variable" || $name2 == "namespace"} {
    344 		    set name2 "tag_$name2"
    345 		}
    346 
    347 		if {[info commands $name2] != {}} {
    348 		    error "duplicate proc name: from $name"
    349 		}
    350 
    351 		proc $name2 {{attrs {}} {children {}}} \
    352 		    "_handle_DW_TAG $name \$attrs \$children"
    353 	    }
    354 
    355 	    AT {
    356 		set _AT($name2) $name
    357 	    }
    358 
    359 	    FORM {
    360 		set _FORM($name2) $name
    361 	    }
    362 
    363 	    OP {
    364 		set _OP($name2) $name
    365 	    }
    366 
    367 	    default {
    368 		return
    369 	    }
    370 	}
    371     }
    372 
    373     proc _read_constants {} {
    374 	global srcdir hex decimal
    375 	variable _constants
    376 
    377 	# DWARF name-matching regexp.
    378 	set dwrx "DW_\[a-zA-Z0-9_\]+"
    379 	# Whitespace regexp.
    380 	set ws "\[ \t\]+"
    381 
    382 	set fd [open [file join $srcdir .. .. include dwarf2.h]]
    383 	while {![eof $fd]} {
    384 	    set line [gets $fd]
    385 	    if {[regexp -- "^${ws}($dwrx)${ws}=${ws}($hex|$decimal),?$" \
    386 		     $line ignore name value ignore2]} {
    387 		_process_one_constant $name $value
    388 	    }
    389 	}
    390 	close $fd
    391 
    392 	set fd [open [file join $srcdir .. .. include dwarf2.def]]
    393 	while {![eof $fd]} {
    394 	    set line [gets $fd]
    395 	    if {[regexp -- \
    396 		     "^DW_\[A-Z_\]+${ws}\\(($dwrx),${ws}($hex|$decimal)\\)$" \
    397 		     $line ignore name value ignore2]} {
    398 		_process_one_constant $name $value
    399 	    }
    400 	}
    401 	close $fd
    402 
    403 	set _constants(SPECIAL_expr) $_constants(DW_FORM_block)
    404     }
    405 
    406     proc _quote {string} {
    407 	# FIXME
    408 	return "\"${string}\\0\""
    409     }
    410 
    411     proc _nz_quote {string} {
    412 	# For now, no quoting is done.
    413 	return "\"${string}\""
    414     }
    415 
    416     proc _handle_DW_FORM {form value} {
    417 	switch -exact -- $form {
    418 	    DW_FORM_string  {
    419 		_op .ascii [_quote $value]
    420 	    }
    421 
    422 	    DW_FORM_flag_present {
    423 		# We don't need to emit anything.
    424 	    }
    425 
    426 	    DW_FORM_data4 -
    427 	    DW_FORM_ref4 {
    428 		_op .4byte $value
    429 	    }
    430 
    431 	    DW_FORM_ref_addr {
    432 		variable _cu_offset_size
    433 		variable _cu_version
    434 		variable _cu_addr_size
    435 
    436 		if {$_cu_version == 2} {
    437 		    set size $_cu_addr_size
    438 		} else {
    439 		    set size $_cu_offset_size
    440 		}
    441 
    442 		_op .${size}byte $value
    443 	    }
    444 
    445 	    DW_FORM_sec_offset {
    446 		variable _cu_offset_size
    447 		_op .${_cu_offset_size}byte $value
    448 	    }
    449 
    450 	    DW_FORM_ref1 -
    451 	    DW_FORM_flag -
    452 	    DW_FORM_data1 {
    453 		_op .byte $value
    454 	    }
    455 
    456 	    DW_FORM_sdata {
    457 		_op .sleb128 $value
    458 	    }
    459 
    460 	    DW_FORM_ref_udata -
    461 	    DW_FORM_udata {
    462 		_op .uleb128 $value
    463 	    }
    464 
    465 	    DW_FORM_addr {
    466 		variable _cu_addr_size
    467 
    468 		_op .${_cu_addr_size}byte $value
    469 	    }
    470 
    471 	    DW_FORM_data2 -
    472 	    DW_FORM_ref2 {
    473 		_op .2byte $value
    474 	    }
    475 
    476 	    DW_FORM_data8 -
    477 	    DW_FORM_ref8 -
    478 	    DW_FORM_ref_sig8 {
    479 		_op .8byte $value
    480 	    }
    481 
    482 	    DW_FORM_strp {
    483 		variable _strings
    484 		variable _cu_offset_size
    485 
    486 		if {![info exists _strings($value)]} {
    487 		    set _strings($value) [new_label strp]
    488 		    _defer_output .debug_string {
    489 			define_label $_strings($value)
    490 			_op .ascii [_quote $value]
    491 		    }
    492 		}
    493 
    494 		_op .${_cu_offset_size}byte $_strings($value) "strp: $value"
    495 	    }
    496 
    497 	    SPECIAL_expr {
    498 		set l1 [new_label "expr_start"]
    499 		set l2 [new_label "expr_end"]
    500 		_op .uleb128 "$l2 - $l1" "expression"
    501 		define_label $l1
    502 		_location $value
    503 		define_label $l2
    504 	    }
    505 
    506 	    DW_FORM_block1 {
    507 		set len [string length $value]
    508 		if {$len > 255} {
    509 		    error "DW_FORM_block1 length too long"
    510 		}
    511 		_op .byte $len
    512 		_op .ascii [_nz_quote $value]
    513 	    }
    514 
    515 	    DW_FORM_block2 -
    516 	    DW_FORM_block4 -
    517 
    518 	    DW_FORM_block -
    519 
    520 	    DW_FORM_ref2 -
    521 	    DW_FORM_indirect -
    522 	    DW_FORM_exprloc -
    523 
    524 	    DW_FORM_GNU_addr_index -
    525 	    DW_FORM_GNU_str_index -
    526 	    DW_FORM_GNU_ref_alt -
    527 	    DW_FORM_GNU_strp_alt -
    528 
    529 	    default {
    530 		error "unhandled form $form"
    531 	    }
    532 	}
    533     }
    534 
    535     proc _guess_form {value varname} {
    536 	upvar $varname new_value
    537 
    538 	switch -exact -- [string range $value 0 0] {
    539 	    @ {
    540 		# Constant reference.
    541 		variable _constants
    542 
    543 		set new_value $_constants([string range $value 1 end])
    544 		# Just the simplest.
    545 		return DW_FORM_sdata
    546 	    }
    547 
    548 	    : {
    549 		# Label reference.
    550 		variable _cu_label
    551 
    552 		set new_value "[string range $value 1 end] - $_cu_label"
    553 
    554 		return DW_FORM_ref4
    555 	    }
    556 
    557 	    default {
    558 		return DW_FORM_string
    559 	    }
    560 	}
    561     }
    562 
    563     # Map NAME to its canonical form.
    564     proc _map_name {name ary} {
    565 	variable $ary
    566 
    567 	if {[info exists ${ary}($name)]} {
    568 	    set name [set ${ary}($name)]
    569 	}
    570 
    571 	return $name
    572     }
    573 
    574     proc _handle_attribute { attr_name attr_value attr_form } {
    575 	variable _abbrev_section
    576 	variable _constants
    577 
    578 	_handle_DW_FORM $attr_form $attr_value
    579 
    580 	_defer_output $_abbrev_section {
    581 	    _op .uleb128 $_constants($attr_name) $attr_name
    582 	    _op .uleb128 $_constants($attr_form) $attr_form
    583 	}
    584     }
    585 
    586     # Handle macro attribute MACRO_AT_range.
    587 
    588     proc _handle_macro_at_range { attr_value } {
    589 	if {[llength $attr_value] != 2} {
    590 	    error "usage: MACRO_AT_range { func file }"
    591 	}
    592 
    593 	set func [lindex $attr_value 0]
    594 	set src [lindex $attr_value 1]
    595 	set result [function_range $func $src]
    596 
    597 	_handle_attribute DW_AT_low_pc [lindex $result 0] \
    598 	    DW_FORM_addr
    599 	_handle_attribute DW_AT_high_pc \
    600 	    "[lindex $result 0] + [lindex $result 1]" DW_FORM_addr
    601     }
    602 
    603     # Handle macro attribute MACRO_AT_func.
    604 
    605     proc _handle_macro_at_func { attr_value } {
    606 	if {[llength $attr_value] != 2} {
    607 	    error "usage: MACRO_AT_func { func file }"
    608 	}
    609 	_handle_attribute DW_AT_name [lindex $attr_value 0] DW_FORM_string
    610 	_handle_macro_at_range $attr_value
    611     }
    612 
    613     proc _handle_DW_TAG {tag_name {attrs {}} {children {}}} {
    614 	variable _abbrev_section
    615 	variable _abbrev_num
    616 	variable _constants
    617 
    618 	set has_children [expr {[string length $children] > 0}]
    619 	set my_abbrev [incr _abbrev_num]
    620 
    621 	# We somewhat wastefully emit a new abbrev entry for each tag.
    622 	# There's no reason for this other than laziness.
    623 	_defer_output $_abbrev_section {
    624 	    _op .uleb128 $my_abbrev "Abbrev start"
    625 	    _op .uleb128 $_constants($tag_name) $tag_name
    626 	    _op .byte $has_children "has_children"
    627 	}
    628 
    629 	_op .uleb128 $my_abbrev "Abbrev ($tag_name)"
    630 
    631 	foreach attr $attrs {
    632 	    set attr_name [_map_name [lindex $attr 0] _AT]
    633 
    634 	    # When the length of ATTR is greater than 2, the last
    635 	    # element of the list must be a form.  The second through
    636 	    # the penultimate elements are joined together and
    637 	    # evaluated using subst.  This allows constructs such as
    638 	    # [gdb_target_symbol foo] to be used.
    639 
    640 	    if {[llength $attr] > 2} {
    641 	        set attr_value [uplevel 2 [list subst [join [lrange $attr 1 end-1]]]]
    642 	    } else {
    643 	        set attr_value [uplevel 2 [list subst [lindex $attr 1]]]
    644 	    }
    645 
    646 	    if { [string equal "MACRO_AT_func" $attr_name] } {
    647 		_handle_macro_at_func $attr_value
    648 	    } elseif { [string equal "MACRO_AT_range" $attr_name] } {
    649 		_handle_macro_at_range $attr_value
    650 	    } else {
    651 		if {[llength $attr] > 2} {
    652 		    set attr_form [lindex $attr end]
    653 		} else {
    654 		    # If the value looks like an integer, a form is required.
    655 		    if [string is integer $attr_value] {
    656 			error "Integer value requires a form"
    657 		    }
    658 		    set attr_form [_guess_form $attr_value attr_value]
    659 		}
    660 		set attr_form [_map_name $attr_form _FORM]
    661 
    662 		_handle_attribute $attr_name $attr_value $attr_form
    663 	    }
    664 	}
    665 
    666 	_defer_output $_abbrev_section {
    667 	    # Terminator.
    668 	    _op .byte 0x0 Terminator
    669 	    _op .byte 0x0 Terminator
    670 	}
    671 
    672 	if {$has_children} {
    673 	    uplevel 2 $children
    674 
    675 	    # Terminate children.
    676 	    _op .byte 0x0 "Terminate children"
    677 	}
    678     }
    679 
    680     proc _emit {string} {
    681 	variable _output_file
    682 	variable _defer
    683 	variable _deferred_output
    684 
    685 	if {$_defer == ""} {
    686 	    puts $_output_file $string
    687 	} else {
    688 	    append _deferred_output($_defer) ${string}\n
    689 	}
    690     }
    691 
    692     proc _section {name {flags ""} {type ""}} {
    693 	if {$flags == "" && $type == ""} {
    694 	    _emit "        .section $name"
    695 	} elseif {$type == ""} {
    696 	    _emit "        .section $name, \"$flags\""
    697 	} else {
    698 	    _emit "        .section $name, \"$flags\", %$type"
    699 	}
    700     }
    701 
    702     # SECTION_SPEC is a list of arguments to _section.
    703     proc _defer_output {section_spec body} {
    704 	variable _defer
    705 	variable _deferred_output
    706 
    707 	set old_defer $_defer
    708 	set _defer [lindex $section_spec 0]
    709 
    710 	if {![info exists _deferred_output($_defer)]} {
    711 	    set _deferred_output($_defer) ""
    712 	    eval _section $section_spec
    713 	}
    714 
    715 	uplevel $body
    716 
    717 	set _defer $old_defer
    718     }
    719 
    720     proc _defer_to_string {body} {
    721 	variable _defer
    722 	variable _deferred_output
    723 
    724 	set old_defer $_defer
    725 	set _defer temp
    726 
    727 	set _deferred_output($_defer) ""
    728 
    729 	uplevel $body
    730 
    731 	set result $_deferred_output($_defer)
    732 	unset _deferred_output($_defer)
    733 
    734 	set _defer $old_defer
    735 	return $result
    736     }
    737 
    738     proc _write_deferred_output {} {
    739 	variable _output_file
    740 	variable _deferred_output
    741 
    742 	foreach section [array names _deferred_output] {
    743 	    # The data already has a newline.
    744 	    puts -nonewline $_output_file $_deferred_output($section)
    745 	}
    746 
    747 	# Save some memory.
    748 	unset _deferred_output
    749     }
    750 
    751     proc _op {name value {comment ""}} {
    752 	set text "        ${name}        ${value}"
    753 	if {$comment != ""} {
    754 	    # Try to make stuff line up nicely.
    755 	    while {[string length $text] < 40} {
    756 		append text " "
    757 	    }
    758 	    append text "/* ${comment} */"
    759 	}
    760 	_emit $text
    761     }
    762 
    763     proc _compute_label {name} {
    764 	return ".L${name}"
    765     }
    766 
    767     # Return a name suitable for use as a label.  If BASE_NAME is
    768     # specified, it is incorporated into the label name; this is to
    769     # make debugging the generated assembler easier.  If BASE_NAME is
    770     # not specified a generic default is used.  This proc does not
    771     # define the label; see 'define_label'.  'new_label' attempts to
    772     # ensure that label names are unique.
    773     proc new_label {{base_name label}} {
    774 	variable _label_num
    775 
    776 	return [_compute_label ${base_name}[incr _label_num]]
    777     }
    778 
    779     # Define a label named NAME.  Ordinarily, NAME comes from a call
    780     # to 'new_label', but this is not required.
    781     proc define_label {name} {
    782 	_emit "${name}:"
    783     }
    784 
    785     # Declare a global label.  This is typically used to refer to
    786     # labels defined in other files, for example a function defined in
    787     # a .c file.
    788     proc extern {args} {
    789 	foreach name $args {
    790 	    _op .global $name
    791 	}
    792     }
    793 
    794     # A higher-level interface to label handling.
    795     #
    796     # ARGS is a list of label descriptors.  Each one is either a
    797     # single element, or a list of two elements -- a name and some
    798     # text.  For each descriptor, 'new_label' is invoked.  If the list
    799     # form is used, the second element in the list is passed as an
    800     # argument.  The label name is used to define a variable in the
    801     # enclosing scope; this can be used to refer to the label later.
    802     # The label name is also used to define a new proc whose name is
    803     # the label name plus a trailing ":".  This proc takes a body as
    804     # an argument and can be used to define the label at that point;
    805     # then the body, if any, is evaluated in the caller's context.
    806     #
    807     # For example:
    808     #
    809     # declare_labels int_label
    810     # something { ... $int_label }   ;# refer to the label
    811     # int_label: constant { ... }    ;# define the label
    812     proc declare_labels {args} {
    813 	foreach arg $args {
    814 	    set name [lindex $arg 0]
    815 	    set text [lindex $arg 1]
    816 
    817 	    upvar $name label_var
    818 	    if {$text == ""} {
    819 		set label_var [new_label]
    820 	    } else {
    821 		set label_var [new_label $text]
    822 	    }
    823 
    824 	    proc ${name}: {args} [format {
    825 		define_label %s
    826 		uplevel $args
    827 	    } $label_var]
    828 	}
    829     }
    830 
    831     # This is a miniature assembler for location expressions.  It is
    832     # suitable for use in the attributes to a DIE.  Its output is
    833     # prefixed with "=" to make it automatically use DW_FORM_block.
    834     # BODY is split by lines, and each line is taken to be a list.
    835     # (FIXME should use 'info complete' here.)
    836     # Each list's first element is the opcode, either short or long
    837     # forms are accepted.
    838     # FIXME argument handling
    839     # FIXME move docs
    840     proc _location {body} {
    841 	variable _constants
    842 	variable _cu_label
    843 	variable _cu_addr_size
    844 	variable _cu_offset_size
    845 
    846 	foreach line [split $body \n] {
    847 	    # Ignore blank lines, and allow embedded comments.
    848 	    if {[lindex $line 0] == "" || [regexp -- {^[ \t]*#} $line]} {
    849 		continue
    850 	    }
    851 	    set opcode [_map_name [lindex $line 0] _OP]
    852 	    _op .byte $_constants($opcode) $opcode
    853 
    854 	    switch -exact -- $opcode {
    855 		DW_OP_addr {
    856 		    _op .${_cu_addr_size}byte [lindex $line 1]
    857 		}
    858 
    859 		DW_OP_regx {
    860 		    _op .uleb128 [lindex $line 1]
    861 		}
    862 
    863 		DW_OP_pick -
    864 		DW_OP_const1u -
    865 		DW_OP_const1s {
    866 		    _op .byte [lindex $line 1]
    867 		}
    868 
    869 		DW_OP_const2u -
    870 		DW_OP_const2s {
    871 		    _op .2byte [lindex $line 1]
    872 		}
    873 
    874 		DW_OP_const4u -
    875 		DW_OP_const4s {
    876 		    _op .4byte [lindex $line 1]
    877 		}
    878 
    879 		DW_OP_const8u -
    880 		DW_OP_const8s {
    881 		    _op .8byte [lindex $line 1]
    882 		}
    883 
    884 		DW_OP_constu {
    885 		    _op .uleb128 [lindex $line 1]
    886 		}
    887 		DW_OP_consts {
    888 		    _op .sleb128 [lindex $line 1]
    889 		}
    890 
    891 		DW_OP_plus_uconst {
    892 		    _op .uleb128 [lindex $line 1]
    893 		}
    894 
    895 		DW_OP_piece {
    896 		    _op .uleb128 [lindex $line 1]
    897 		}
    898 
    899 		DW_OP_bit_piece {
    900 		    _op .uleb128 [lindex $line 1]
    901 		    _op .uleb128 [lindex $line 2]
    902 		}
    903 
    904 		DW_OP_skip -
    905 		DW_OP_bra {
    906 		    _op .2byte [lindex $line 1]
    907 		}
    908 
    909 		DW_OP_GNU_implicit_pointer {
    910 		    if {[llength $line] != 3} {
    911 			error "usage: DW_OP_GNU_implicit_pointer LABEL OFFSET"
    912 		    }
    913 
    914 		    # Here label is a section offset.
    915 		    set label [lindex $line 1]
    916 		    _op .${_cu_offset_size}byte $label
    917 		    _op .sleb128 [lindex $line 2]
    918 		}
    919 
    920 		DW_OP_deref_size {
    921 		    if {[llength $line] != 2} {
    922 			error "usage: DW_OP_deref_size SIZE"
    923 		    }
    924 
    925 		    _op .byte [lindex $line 1]
    926 		}
    927 
    928 		DW_OP_bregx {
    929 		    _op .uleb128 [lindex $line 1]
    930 		    _op .sleb128 [lindex $line 2]
    931 		}
    932 
    933 		default {
    934 		    if {[llength $line] > 1} {
    935 			error "Unimplemented: operands in location for $opcode"
    936 		    }
    937 		}
    938 	    }
    939 	}
    940     }
    941 
    942     # Emit a DWARF CU.
    943     # OPTIONS is a list with an even number of elements containing
    944     # option-name and option-value pairs.
    945     # Current options are:
    946     # is_64 0|1    - boolean indicating if you want to emit 64-bit DWARF
    947     #                default = 0 (32-bit)
    948     # version n    - DWARF version number to emit
    949     #                default = 4
    950     # addr_size n  - the size of addresses, 32, 64, or default
    951     #                default = default
    952     # fission 0|1  - boolean indicating if generating Fission debug info
    953     #                default = 0
    954     # BODY is Tcl code that emits the DIEs which make up the body of
    955     # the CU.  It is evaluated in the caller's context.
    956     proc cu {options body} {
    957 	variable _cu_count
    958 	variable _abbrev_section
    959 	variable _abbrev_num
    960 	variable _cu_label
    961 	variable _cu_version
    962 	variable _cu_addr_size
    963 	variable _cu_offset_size
    964 
    965 	# Establish the defaults.
    966 	set is_64 0
    967 	set _cu_version 4
    968 	set _cu_addr_size default
    969 	set fission 0
    970 	set section ".debug_info"
    971 	set _abbrev_section ".debug_abbrev"
    972 
    973 	foreach { name value } $options {
    974 	    switch -exact -- $name {
    975 		is_64 { set is_64 $value }
    976 		version { set _cu_version $value }
    977 		addr_size { set _cu_addr_size $value }
    978 		fission { set fission $value }
    979 		default { error "unknown option $name" }
    980 	    }
    981 	}
    982 	if {$_cu_addr_size == "default"} {
    983 	    if {[is_64_target]} {
    984 		set _cu_addr_size 8
    985 	    } else {
    986 		set _cu_addr_size 4
    987 	    }
    988 	}
    989 	set _cu_offset_size [expr { $is_64 ? 8 : 4 }]
    990 	if { $fission } {
    991 	    set section ".debug_info.dwo"
    992 	    set _abbrev_section ".debug_abbrev.dwo"
    993 	}
    994 
    995 	_section $section
    996 
    997 	set cu_num [incr _cu_count]
    998 	set my_abbrevs [_compute_label "abbrev${cu_num}_begin"]
    999 	set _abbrev_num 1
   1000 
   1001 	set _cu_label [_compute_label "cu${cu_num}_begin"]
   1002 	set start_label [_compute_label "cu${cu_num}_start"]
   1003 	set end_label [_compute_label "cu${cu_num}_end"]
   1004 
   1005 	define_label $_cu_label
   1006 	if {$is_64} {
   1007 	    _op .4byte 0xffffffff
   1008 	    _op .8byte "$end_label - $start_label"
   1009 	} else {
   1010 	    _op .4byte "$end_label - $start_label"
   1011 	}
   1012 	define_label $start_label
   1013 	_op .2byte $_cu_version Version
   1014 	_op .${_cu_offset_size}byte $my_abbrevs Abbrevs
   1015 	_op .byte $_cu_addr_size "Pointer size"
   1016 
   1017 	_defer_output $_abbrev_section {
   1018 	    define_label $my_abbrevs
   1019 	}
   1020 
   1021 	uplevel $body
   1022 
   1023 	_defer_output $_abbrev_section {
   1024 	    # Emit the terminator.
   1025 	    _op .byte 0x0 Terminator
   1026 	    _op .byte 0x0 Terminator
   1027 	}
   1028 
   1029 	define_label $end_label
   1030     }
   1031 
   1032     # Emit a DWARF TU.
   1033     # OPTIONS is a list with an even number of elements containing
   1034     # option-name and option-value pairs.
   1035     # Current options are:
   1036     # is_64 0|1    - boolean indicating if you want to emit 64-bit DWARF
   1037     #                default = 0 (32-bit)
   1038     # version n    - DWARF version number to emit
   1039     #                default = 4
   1040     # addr_size n  - the size of addresses, 32, 64, or default
   1041     #                default = default
   1042     # fission 0|1  - boolean indicating if generating Fission debug info
   1043     #                default = 0
   1044     # SIGNATURE is the 64-bit signature of the type.
   1045     # TYPE_LABEL is the label of the type defined by this TU,
   1046     # or "" if there is no type (i.e., type stubs in Fission).
   1047     # BODY is Tcl code that emits the DIEs which make up the body of
   1048     # the TU.  It is evaluated in the caller's context.
   1049     proc tu {options signature type_label body} {
   1050 	variable _cu_count
   1051 	variable _abbrev_section
   1052 	variable _abbrev_num
   1053 	variable _cu_label
   1054 	variable _cu_version
   1055 	variable _cu_addr_size
   1056 	variable _cu_offset_size
   1057 
   1058 	# Establish the defaults.
   1059 	set is_64 0
   1060 	set _cu_version 4
   1061 	set _cu_addr_size default
   1062 	set fission 0
   1063 	set section ".debug_types"
   1064 	set _abbrev_section ".debug_abbrev"
   1065 
   1066 	foreach { name value } $options {
   1067 	    switch -exact -- $name {
   1068 		is_64 { set is_64 $value }
   1069 		version { set _cu_version $value }
   1070 		addr_size { set _cu_addr_size $value }
   1071 		fission { set fission $value }
   1072 		default { error "unknown option $name" }
   1073 	    }
   1074 	}
   1075 	if {$_cu_addr_size == "default"} {
   1076 	    if {[is_64_target]} {
   1077 		set _cu_addr_size 8
   1078 	    } else {
   1079 		set _cu_addr_size 4
   1080 	    }
   1081 	}
   1082 	set _cu_offset_size [expr { $is_64 ? 8 : 4 }]
   1083 	if { $fission } {
   1084 	    set section ".debug_types.dwo"
   1085 	    set _abbrev_section ".debug_abbrev.dwo"
   1086 	}
   1087 
   1088 	_section $section
   1089 
   1090 	set cu_num [incr _cu_count]
   1091 	set my_abbrevs [_compute_label "abbrev${cu_num}_begin"]
   1092 	set _abbrev_num 1
   1093 
   1094 	set _cu_label [_compute_label "cu${cu_num}_begin"]
   1095 	set start_label [_compute_label "cu${cu_num}_start"]
   1096 	set end_label [_compute_label "cu${cu_num}_end"]
   1097 
   1098 	define_label $_cu_label
   1099 	if {$is_64} {
   1100 	    _op .4byte 0xffffffff
   1101 	    _op .8byte "$end_label - $start_label"
   1102 	} else {
   1103 	    _op .4byte "$end_label - $start_label"
   1104 	}
   1105 	define_label $start_label
   1106 	_op .2byte $_cu_version Version
   1107 	_op .${_cu_offset_size}byte $my_abbrevs Abbrevs
   1108 	_op .byte $_cu_addr_size "Pointer size"
   1109 	_op .8byte $signature Signature
   1110 	if { $type_label != "" } {
   1111 	    uplevel declare_labels $type_label
   1112 	    upvar $type_label my_type_label
   1113 	    if {$is_64} {
   1114 		_op .8byte "$my_type_label - $_cu_label"
   1115 	    } else {
   1116 		_op .4byte "$my_type_label - $_cu_label"
   1117 	    }
   1118 	} else {
   1119 	    if {$is_64} {
   1120 		_op .8byte 0
   1121 	    } else {
   1122 		_op .4byte 0
   1123 	    }
   1124 	}
   1125 
   1126 	_defer_output $_abbrev_section {
   1127 	    define_label $my_abbrevs
   1128 	}
   1129 
   1130 	uplevel $body
   1131 
   1132 	_defer_output $_abbrev_section {
   1133 	    # Emit the terminator.
   1134 	    _op .byte 0x0 Terminator
   1135 	    _op .byte 0x0 Terminator
   1136 	}
   1137 
   1138 	define_label $end_label
   1139     }
   1140 
   1141     # Emit a DWARF .debug_ranges unit.
   1142     # OPTIONS is a list with an even number of elements containing
   1143     # option-name and option-value pairs.
   1144     # Current options are:
   1145     # is_64 0|1    - boolean indicating if you want to emit 64-bit DWARF
   1146     #                default = 0 (32-bit)
   1147     #
   1148     # BODY is Tcl code that emits the content of the .debug_ranges
   1149     # unit, it is evaluated in the caller's context.
   1150     proc ranges {options body} {
   1151 	variable _debug_ranges_64_bit
   1152 
   1153 	foreach { name value } $options {
   1154 	    switch -exact -- $name {
   1155 		is_64 { set _debug_ranges_64_bit [subst $value] }
   1156 		default { error "unknown option $name" }
   1157 	    }
   1158 	}
   1159 
   1160 	set section ".debug_ranges"
   1161 	_section $section
   1162 
   1163 	proc sequence {{ranges {}}} {
   1164 	    variable _debug_ranges_64_bit
   1165 
   1166 	    # Emit the sequence of addresses.
   1167 	    set base ""
   1168 	    foreach range $ranges {
   1169 		set range [uplevel 1 "subst \"$range\""]
   1170 		set type [lindex $range 0]
   1171 		switch -exact -- $type {
   1172 		    base {
   1173 			set base [lrange $range 1 end]
   1174 
   1175 			if { $_debug_ranges_64_bit } then {
   1176 			    _op .8byte 0xffffffffffffffff "Base Marker"
   1177 			    _op .8byte $base "Base Address"
   1178 			} else {
   1179 			    _op .4byte 0xffffffff "Base Marker"
   1180 			    _op .4byte $base "Base Address"
   1181 			}
   1182 		    }
   1183 		    range {
   1184 			set start [lindex $range 1]
   1185 			set end [lrange $range 2 end]
   1186 
   1187 			if { $_debug_ranges_64_bit } then {
   1188 			    _op .8byte $start "Start Address"
   1189 			    _op .8byte $end "End Address"
   1190 			} else {
   1191 			    _op .4byte $start "Start Address"
   1192 			    _op .4byte $end "End Address"
   1193 			}
   1194 		    }
   1195 		    default { error "unknown range type: $type " }
   1196 		}
   1197 	    }
   1198 
   1199 	    # End of the sequence.
   1200 	    if { $_debug_ranges_64_bit } then {
   1201 		_op .8byte 0x0 "End of Sequence Marker (Part 1)"
   1202 		_op .8byte 0x0 "End of Sequence Marker (Part 2)"
   1203 	    } else {
   1204 		_op .4byte 0x0 "End of Sequence Marker (Part 1)"
   1205 		_op .4byte 0x0 "End of Sequence Marker (Part 2)"
   1206 	    }
   1207 	}
   1208 
   1209 	uplevel $body
   1210     }
   1211 
   1212 
   1213     # Emit a DWARF .debug_line unit.
   1214     # OPTIONS is a list with an even number of elements containing
   1215     # option-name and option-value pairs.
   1216     # Current options are:
   1217     # is_64 0|1    - boolean indicating if you want to emit 64-bit DWARF
   1218     #                default = 0 (32-bit)
   1219     # version n    - DWARF version number to emit
   1220     #                default = 4
   1221     # addr_size n  - the size of addresses, 32, 64, or default
   1222     #                default = default
   1223     #
   1224     # LABEL is the label of the current unit (which is probably
   1225     # referenced by a DW_AT_stmt_list), or "" if there is no such
   1226     # label.
   1227     #
   1228     # BODY is Tcl code that emits the parts which make up the body of
   1229     # the line unit.  It is evaluated in the caller's context.  The
   1230     # following commands are available for the BODY section:
   1231     #
   1232     #   include_dir "dirname" -- adds a new include directory
   1233     #
   1234     #   file_name "file.c" idx -- adds a new file name.  IDX is a
   1235     #   1-based index referencing an include directory or 0 for
   1236     #   current directory.
   1237 
   1238     proc lines {options label body} {
   1239 	variable _line_count
   1240 	variable _line_saw_file
   1241 	variable _line_saw_program
   1242 	variable _line_header_end_label
   1243 
   1244 	# Establish the defaults.
   1245 	set is_64 0
   1246 	set _unit_version 4
   1247 	set _unit_addr_size default
   1248 
   1249 	foreach { name value } $options {
   1250 	    switch -exact -- $name {
   1251 		is_64 { set is_64 $value }
   1252 		version { set _unit_version $value }
   1253 		addr_size { set _unit_addr_size $value }
   1254 		default { error "unknown option $name" }
   1255 	    }
   1256 	}
   1257 	if {$_unit_addr_size == "default"} {
   1258 	    if {[is_64_target]} {
   1259 		set _unit_addr_size 8
   1260 	    } else {
   1261 		set _unit_addr_size 4
   1262 	    }
   1263 	}
   1264 
   1265 	set unit_num [incr _line_count]
   1266 
   1267 	set section ".debug_line"
   1268 	_section $section
   1269 
   1270 	if { "$label" != "" } {
   1271 	    # Define the user-provided label at this point.
   1272 	    $label:
   1273 	}
   1274 
   1275 	set unit_len_label [_compute_label "line${_line_count}_start"]
   1276 	set unit_end_label [_compute_label "line${_line_count}_end"]
   1277 	set header_len_label [_compute_label "line${_line_count}_header_start"]
   1278 	set _line_header_end_label [_compute_label "line${_line_count}_header_end"]
   1279 
   1280 	if {$is_64} {
   1281 	    _op .4byte 0xffffffff
   1282 	    _op .8byte "$unit_end_label - $unit_len_label" "unit_length"
   1283 	} else {
   1284 	    _op .4byte "$unit_end_label - $unit_len_label" "unit_length"
   1285 	}
   1286 
   1287 	define_label $unit_len_label
   1288 
   1289 	_op .2byte $_unit_version version
   1290 
   1291 	if {$is_64} {
   1292 	    _op .8byte "$_line_header_end_label - $header_len_label" "header_length"
   1293 	} else {
   1294 	    _op .4byte "$_line_header_end_label - $header_len_label" "header_length"
   1295 	}
   1296 
   1297 	define_label $header_len_label
   1298 
   1299 	_op .byte 1 "minimum_instruction_length"
   1300 	_op .byte 1 "default_is_stmt"
   1301 	_op .byte 1 "line_base"
   1302 	_op .byte 1 "line_range"
   1303 	_op .byte 10 "opcode_base"
   1304 
   1305 	# The standard_opcode_lengths table.  The number of arguments
   1306 	# for each of the standard opcodes.  Generating 9 entries here
   1307 	# matches the use of 10 in the opcode_base above.  These 9
   1308 	# entries match the 9 standard opcodes for DWARF2, making use
   1309 	# of only 9 should be fine, even if we are generating DWARF3
   1310 	# or DWARF4.
   1311 	_op .byte 0 "standard opcode 1"
   1312 	_op .byte 1 "standard opcode 2"
   1313 	_op .byte 1 "standard opcode 3"
   1314 	_op .byte 1 "standard opcode 4"
   1315 	_op .byte 1 "standard opcode 5"
   1316 	_op .byte 0 "standard opcode 6"
   1317 	_op .byte 0 "standard opcode 7"
   1318 	_op .byte 0 "standard opcode 8"
   1319 	_op .byte 1 "standard opcode 9"
   1320 
   1321 	proc include_dir {dirname} {
   1322 	    _op .ascii [_quote $dirname]
   1323 	}
   1324 
   1325 	proc file_name {filename diridx} {
   1326 	    variable _line_saw_file
   1327 	    if "! $_line_saw_file" {
   1328 		# Terminate the dir list.
   1329 		_op .byte 0 "Terminator."
   1330 		set _line_saw_file 1
   1331 	    }
   1332 
   1333 	    _op .ascii [_quote $filename]
   1334 	    _op .sleb128 $diridx
   1335 	    _op .sleb128 0 "mtime"
   1336 	    _op .sleb128 0 "length"
   1337 	}
   1338 
   1339 	proc program {statements} {
   1340 	    variable _line_saw_program
   1341 	    variable _line_header_end_label
   1342 
   1343 	    if "! $_line_saw_program" {
   1344 		# Terminate the file list.
   1345 		_op .byte 0 "Terminator."
   1346 		define_label $_line_header_end_label
   1347 		set _line_saw_program 1
   1348 	    }
   1349 
   1350 	    proc DW_LNE_set_address {addr} {
   1351 		_op .byte 0
   1352 		set start [new_label "set_address_start"]
   1353 		set end [new_label "set_address_end"]
   1354 		_op .uleb128 "${end} - ${start}"
   1355 		define_label ${start}
   1356 		_op .byte 2
   1357 		if {[is_64_target]} {
   1358 		    _op .8byte ${addr}
   1359 		} else {
   1360 		    _op .4byte ${addr}
   1361 		}
   1362 		define_label ${end}
   1363 	    }
   1364 
   1365 	    proc DW_LNE_end_sequence {} {
   1366 		_op .byte 0
   1367 		_op .uleb128 1
   1368 		_op .byte 1
   1369 	    }
   1370 
   1371 	    proc DW_LNS_copy {} {
   1372 		_op .byte 1
   1373 	    }
   1374 
   1375 	    proc DW_LNS_advance_pc {offset} {
   1376 		_op .byte 2
   1377 		_op .uleb128 ${offset}
   1378 	    }
   1379 
   1380 	    proc DW_LNS_advance_line {offset} {
   1381 		_op .byte 3
   1382 		_op .sleb128 ${offset}
   1383 	    }
   1384 
   1385 	    foreach statement $statements {
   1386 		uplevel 1 $statement
   1387 	    }
   1388 	}
   1389 
   1390 	uplevel $body
   1391 
   1392 	rename include_dir ""
   1393 	rename file_name ""
   1394 
   1395 	# Terminate dir list if we saw no files.
   1396 	if "! $_line_saw_file" {
   1397 	    _op .byte 0 "Terminator."
   1398 	}
   1399 
   1400 	# Terminate the file list.
   1401 	if "! $_line_saw_program" {
   1402 	    _op .byte 0 "Terminator."
   1403 	    define_label $_line_header_end_label
   1404 	}
   1405 
   1406 	define_label $unit_end_label
   1407     }
   1408 
   1409     proc _empty_array {name} {
   1410 	upvar $name the_array
   1411 
   1412 	catch {unset the_array}
   1413 	set the_array(_) {}
   1414 	unset the_array(_)
   1415     }
   1416 
   1417     # Emit a .gnu_debugaltlink section with the given file name and
   1418     # build-id.  The buildid should be represented as a hexadecimal
   1419     # string, like "ffeeddcc".
   1420     proc gnu_debugaltlink {filename buildid} {
   1421 	_defer_output .gnu_debugaltlink {
   1422 	    _op .ascii [_quote $filename]
   1423 	    foreach {a b} [split $buildid {}] {
   1424 		_op .byte 0x$a$b
   1425 	    }
   1426 	}
   1427     }
   1428 
   1429     proc _note {type name hexdata} {
   1430 	set namelen [expr [string length $name] + 1]
   1431 
   1432 	# Name size.
   1433 	_op .4byte $namelen
   1434 	# Data size.
   1435 	_op .4byte [expr [string length $hexdata] / 2]
   1436 	# Type.
   1437 	_op .4byte $type
   1438 	# The name.
   1439 	_op .ascii [_quote $name]
   1440 	# Alignment.
   1441 	set align 2
   1442 	set total [expr {($namelen + (1 << $align) - 1) & -(1 << $align)}]
   1443 	for {set i $namelen} {$i < $total} {incr i} {
   1444 	    _op .byte 0
   1445 	}
   1446 	# The data.
   1447 	foreach {a b} [split $hexdata {}] {
   1448 	    _op .byte 0x$a$b
   1449 	}
   1450     }
   1451 
   1452     # Emit a note section holding the given build-id.
   1453     proc build_id {buildid} {
   1454 	_defer_output {.note.gnu.build-id a note} {
   1455 	    # From elf/common.h.
   1456 	    set NT_GNU_BUILD_ID 3
   1457 
   1458 	    _note $NT_GNU_BUILD_ID GNU $buildid
   1459 	}
   1460     }
   1461 
   1462     # The top-level interface to the DWARF assembler.
   1463     # FILENAME is the name of the file where the generated assembly
   1464     # code is written.
   1465     # BODY is Tcl code to emit the assembly.  It is evaluated via
   1466     # "eval" -- not uplevel as you might expect, because it is
   1467     # important to run the body in the Dwarf namespace.
   1468     #
   1469     # A typical invocation is something like:
   1470     #    Dwarf::assemble $file {
   1471     #        cu 0 2 8 {
   1472     #            compile_unit {
   1473     #            ...
   1474     #            }
   1475     #        }
   1476     #        cu 0 2 8 {
   1477     #        ...
   1478     #        }
   1479     #    }
   1480     proc assemble {filename body} {
   1481 	variable _initialized
   1482 	variable _output_file
   1483 	variable _deferred_output
   1484 	variable _defer
   1485 	variable _label_num
   1486 	variable _strings
   1487 	variable _cu_count
   1488 	variable _line_count
   1489 	variable _line_saw_file
   1490 	variable _line_saw_program
   1491 	variable _line_header_end_label
   1492 	variable _debug_ranges_64_bit
   1493 
   1494 	if {!$_initialized} {
   1495 	    _read_constants
   1496 	    set _initialized 1
   1497 	}
   1498 
   1499 	set _output_file [open $filename w]
   1500 	set _cu_count 0
   1501 	_empty_array _deferred_output
   1502 	set _defer ""
   1503 	set _label_num 0
   1504 	_empty_array _strings
   1505 
   1506 	set _line_count 0
   1507 	set _line_saw_file 0
   1508 	set _line_saw_program 0
   1509 	set _debug_ranges_64_bit [is_64_target]
   1510 
   1511 	# Not "uplevel" here, because we want to evaluate in this
   1512 	# namespace.  This is somewhat bad because it means we can't
   1513 	# readily refer to outer variables.
   1514 	eval $body
   1515 
   1516 	_write_deferred_output
   1517 
   1518 	catch {close $_output_file}
   1519 	set _output_file {}
   1520     }
   1521 }
   1522