1# Copyright 2010-2024 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.
18proc dwarf2_support {} {
19    if {[istarget *-*-linux*]
20          || [istarget *-*-gnu*]
21          || [istarget *-*-elf*]
22          || [istarget *-*-openbsd*]
23          || [istarget arm*-*-eabi*]
24          || [istarget powerpc-*-eabi*]} {
25          return 1
26    }
27
28    return 0
29}
30
31# Use 'objcopy --extract-dwo to extract DWO information from
32# OBJECT_FILE and place it into DWO_FILE.
33#
34# Return 0 on success, otherwise, return -1.
35proc extract_dwo_information { object_file dwo_file } {
36    set objcopy [gdb_find_objcopy]
37    set command "$objcopy --extract-dwo $object_file $dwo_file"
38    verbose -log "Executing $command"
39    set result [catch "exec $command" output]
40    verbose -log "objcopy --extract-dwo output: $output"
41    if { $result == 1 } {
42          return -1
43    }
44    return 0
45}
46
47# Use 'objcopy --strip-dwo to remove DWO information from
48# FILENAME.
49#
50# Return 0 on success, otherwise, return -1.
51proc strip_dwo_information { filename } {
52    set objcopy [gdb_find_objcopy]
53    set command "$objcopy --strip-dwo $filename"
54    verbose -log "Executing $command"
55    set result [catch "exec $command" output]
56    verbose -log "objcopy --strip-dwo output: $output"
57    if { $result == 1 } {
58          return -1
59    }
60    return 0
61}
62
63# Build an executable, with the debug information split out into a
64# separate .dwo file.
65#
66# This function is based on build_executable_from_specs in
67# lib/gdb.exp, but with threading support, and rust support removed.
68#
69# TESTNAME is the name of the test; this is passed to 'untested' if
70# something fails.
71#
72# EXECUTABLE is the executable to create, this can be an absolute
73# path, or a relative path, in which case the EXECUTABLE will be
74# created in the standard output directory.
75#
76# OPTIONS is passed to the final link, using gdb_compile.  If OPTIONS
77# contains any option that indicates threads is required, of if the
78# option rust is included, then this function will return failure.
79#
80# ARGS is a series of lists.  Each list is a spec for one source file
81# that will be compiled to make EXECUTABLE.  Each spec in ARGS has the
82# form:
83#         [ SOURCE OPTIONS ]
84# or:
85#       [ SOURCE OPTIONS OBJFILE ]
86#
87# Where SOURCE is the path to the source file to compile.  This can be
88# absolute, or relative to the standard global ${subdir}/${srcdir}/
89# path.
90#
91# OPTIONS are the options to use when compiling SOURCE into an object
92# file.
93#
94# OBJFILE is optional, if present this is the name of the object file
95# to create for SOURCE.  If this is not provided then a suitable name
96# will be auto-generated.
97#
98# If OPTIONS contains the option 'split-dwo' then the debug
99# information is extracted from the object file created by compiling
100# SOURCE and placed into a file with a dwo extension.  The name of
101# this file is generated based on the name of the object file that was
102# created (with the .o replaced with .dwo).
103proc build_executable_and_dwo_files { testname executable options args } {
104    global subdir
105    global srcdir
106
107    if {![regexp "^/" "$executable"]} {
108          set binfile [standard_output_file $executable]
109    } else {
110          set binfile $executable
111    }
112
113    set func gdb_compile
114    if {[lsearch -regexp $options \
115               {^(pthreads|shlib|shlib_pthreads|openmp)$}] != -1} {
116          # Currently don't support compiling thread based tests here.
117          # If this is required then look to build_executable_from_specs
118          # for inspiration.
119          return -1
120    }
121    if {[lsearch -exact $options rust] != -1} {
122          # Currently don't support compiling rust tests here.  If this
123          # is required then look to build_executable_from_specs for
124          # inspiration.
125          return -1
126    }
127
128    # Must be run on local host due to use of objcopy.
129    if [is_remote host] {
130          return -1
131    }
132
133    set objects {}
134    set i 0
135    foreach spec $args {
136          if {[llength $spec] < 2} {
137              error "invalid spec length"
138              return -1
139          }
140
141          verbose -log "APB: SPEC: $spec"
142
143          set s [lindex $spec 0]
144          set local_options [lindex $spec 1]
145
146          if {![regexp "^/" "$s"]} {
147              set s "$srcdir/$subdir/$s"
148          }
149
150          if {[llength $spec] > 2} {
151              set objfile [lindex $spec 2]
152          } else {
153              set objfile "${binfile}${i}.o"
154              incr i
155          }
156
157          if  { [$func "${s}" "${objfile}" object $local_options] != "" } {
158              untested $testname
159              return -1
160          }
161
162          lappend objects "$objfile"
163
164          if {[lsearch -exact $local_options "split-dwo"] >= 0} {
165              # Split out the DWO file.
166              set dwo_file "[file rootname ${objfile}].dwo"
167
168              if { [extract_dwo_information $objfile $dwo_file] == -1 } {
169                    untested $testname
170                    return -1
171              }
172
173              if { [strip_dwo_information $objfile] == -1 } {
174                    untested $testname
175                    return -1
176              }
177          }
178    }
179
180    verbose -log "APB: OBJECTS = $objects"
181
182    set ret [$func $objects "${binfile}" executable $options]
183    if  { $ret != "" } {
184        untested $testname
185        return -1
186    }
187
188    return 0
189}
190
191# Utility function for procs shared_gdb_*.
192
193proc init_shared_gdb {} {
194    global shared_gdb_enabled
195    global shared_gdb_started
196
197    if { ! [info exists shared_gdb_enabled] } {
198          set shared_gdb_enabled 0
199          set shared_gdb_started 0
200    }
201}
202
203# Cluster of four procs:
204# - shared_gdb_enable
205# - shared_gdb_disable
206# - shared_gdb_start_use SRC OPTIONS
207# - shared_gdb_end_use
208#
209# Can be used like so:
210#
211#   {
212#     if { $share } shared_gdb_enable
213#     ...
214#     shared_gdb_start_use $src $options
215#     ...
216#     shared_gdb_end_use
217#     ...
218#     shared_gdb_start_use $src $options
219#     ...
220#     shared_gdb_end_use
221#     ...
222#     if { $share } shared_gdb_disable
223#   }
224#
225# to write functionalty that could share ($share == 1) or could not
226# share ($share == 0) a gdb session between two uses.
227
228proc shared_gdb_enable {} {
229    set me shared_gdb_enable
230
231    init_shared_gdb
232    global shared_gdb_enabled
233    global shared_gdb_started
234
235    if { $shared_gdb_enabled } {
236          error "$me: gdb sharing already enabled"
237    }
238    set shared_gdb_enabled 1
239
240    if { $shared_gdb_started } {
241          error "$me: gdb sharing not stopped"
242    }
243}
244
245# See above.
246
247proc shared_gdb_disable {} {
248    init_shared_gdb
249    global shared_gdb_enabled
250    global shared_gdb_started
251
252    if { ! $shared_gdb_enabled } {
253          error "$me: gdb sharing not enabled"
254    }
255    set shared_gdb_enabled 0
256
257    if { $shared_gdb_started } {
258          gdb_exit
259          set shared_gdb_started 0
260    }
261}
262
263# Share the current gdb session.
264
265proc share_gdb { src options } {
266    global shared_gdb_started
267    global shared_gdb_src
268    global shared_gdb_options
269
270    set shared_gdb_started 1
271    set shared_gdb_src $src
272    set shared_gdb_options $options
273}
274
275# See above.
276
277proc shared_gdb_start_use { src options } {
278    set me shared_gdb_start_use
279
280    init_shared_gdb
281    global shared_gdb_enabled
282    global shared_gdb_started
283    global shared_gdb_src
284    global shared_gdb_options
285
286    set do_start 1
287    if { $shared_gdb_enabled && $shared_gdb_started } {
288          if { $shared_gdb_src != $src
289               || $shared_gdb_options != $options } {
290              error "$me: gdb sharing inconsistent"
291          }
292
293          set do_start 0
294    }
295
296    if { $do_start } {
297          set exe [standard_temp_file func_addr.x]
298
299          gdb_compile $src $exe executable $options
300
301          gdb_exit
302          gdb_start
303          gdb_load "$exe"
304
305          if { $shared_gdb_enabled } {
306              share_gdb $src $options
307          }
308    }
309}
310
311# See above.
312
313proc shared_gdb_end_use {} {
314    init_shared_gdb
315    global shared_gdb_enabled
316
317    if { ! $shared_gdb_enabled } {
318          gdb_exit
319    }
320}
321
322# Enable gdb session sharing within BODY.
323
324proc with_shared_gdb { body } {
325    shared_gdb_enable
326    set code [catch { uplevel 1 $body } result]
327    shared_gdb_disable
328
329    # Return as appropriate.
330    if { $code == 1 } {
331          global errorInfo errorCode
332          return -code error -errorinfo $errorInfo -errorcode $errorCode $result
333    } elseif { $code > 1 } {
334          return -code $code $result
335    }
336
337    return $result
338}
339
340# Return a list of expressions about function FUNC's address and length.
341# The first expression is the address of function FUNC, and the second
342# one is FUNC's length.  SRC is the source file having function FUNC.
343# An internal label ${func}_label must be defined inside FUNC:
344#
345#  int main (void)
346#  {
347#    asm ("main_label: .globl main_label");
348#    return 0;
349#  }
350#
351# This label is needed to compute the start address of function FUNC.
352# If the compiler is gcc, we can do the following to get function start
353# and end address too:
354#
355# asm ("func_start: .globl func_start");
356# static void func (void) {}
357# asm ("func_end: .globl func_end");
358#
359# however, this isn't portable, because other compilers, such as clang,
360# may not guarantee the order of global asms and function.  The code
361# becomes:
362#
363# asm ("func_start: .globl func_start");
364# asm ("func_end: .globl func_end");
365# static void func (void) {}
366#
367
368proc function_range { func src {options {debug}} } {
369    global decimal gdb_prompt
370
371    shared_gdb_start_use $src $options
372
373    # Compute the label offset, and we can get the function start address
374    # by "${func}_label - $func_label_offset".
375    set func_label_offset ""
376    set test "p ${func}_label - ${func}"
377    gdb_test_multiple $test $test {
378          -re ".* = ($decimal)\r\n$gdb_prompt $" {
379              set func_label_offset $expect_out(1,string)
380          }
381    }
382
383    # Compute the function length.
384    global hex
385    set func_length ""
386    set test "disassemble $func"
387    gdb_test_multiple $test $test {
388          -re ".*$hex <\\+($decimal)>:\[^\r\n\]+\r\nEnd of assembler dump\.\r\n$gdb_prompt $" {
389              set func_length $expect_out(1,string)
390          }
391    }
392
393    # Compute the size of the last instruction.
394    # For C++, GDB appends arguments to the names of functions if they don't
395    # have a linkage name.  For example, asking gdb to disassemble a C++ main
396    # will print the function name as main() or main(int argc, char **argv).
397    # Take this into account by optionally allowing an argument list after
398    # the function name.
399    set func_pattern "$func\(\?\:\\(\.\*\\)\)?"
400    if { $func_length != 0 } {
401          set func_pattern "$func_pattern\\+$func_length"
402    }
403    set test "with print asm-demangle on -- x/2i $func+$func_length"
404    gdb_test_multiple $test $test {
405          -re ".*($hex) <$func_pattern>:\[^\r\n\]+\r\n\[ \]+($hex).*\.\r\n$gdb_prompt $" {
406              set start $expect_out(1,string)
407              set end $expect_out(2,string)
408
409              set func_length [expr $func_length + $end - $start]
410          }
411    }
412
413    shared_gdb_end_use
414
415    return [list "${func}_label - $func_label_offset" $func_length]
416}
417
418# Extract the start, length, and end for function called NAME and
419# create suitable variables in the callers scope.
420# Return the list of created variables.
421proc get_func_info { name {options {debug}} } {
422    global srcdir subdir srcfile
423
424    upvar 1 "${name}_start" func_start
425    upvar 1 "${name}_len" func_len
426    upvar 1 "${name}_end" func_end
427
428    lassign [function_range ${name} \
429                     [list ${srcdir}/${subdir}/$srcfile] \
430                     ${options}]  \
431          func_start func_len
432    set func_end "$func_start + $func_len"
433
434    return [list \
435                    "${name}_start" \
436                    "${name}_len" \
437                    "${name}_end"]
438}
439
440# A DWARF assembler.
441#
442# All the variables in this namespace are private to the
443# implementation.  Also, any procedure whose name starts with "_" is
444# private as well.  Do not use these.
445#
446# Exported functions are documented at their definition.
447#
448# In addition to the hand-written functions documented below, this
449# module automatically generates a function for each DWARF tag.  For
450# most tags, two forms are made: a full name, and one with the
451# "DW_TAG_" prefix stripped.  For example, you can use either
452# 'DW_TAG_compile_unit' or 'compile_unit' interchangeably.
453#
454# There are two exceptions to this rule: DW_TAG_variable and
455# DW_TAG_namespace.  For these, the full name must always be used,
456# as the short name conflicts with Tcl builtins.  (Should future
457# versions of Tcl or DWARF add more conflicts, this list will grow.
458# If you want to be safe you should always use the full names.)
459#
460# Each tag procedure is defined like:
461#
462# proc DW_TAG_mumble {{attrs {}} {children {}}} { ... }
463#
464# ATTRS is an optional list of attributes.
465# It is run through 'subst' in the caller's context before processing.
466#
467# Each attribute in the list has one of two forms:
468#   1. { NAME VALUE }
469#   2. { NAME VALUE FORM }
470#
471# In each case, NAME is the attribute's name.
472# This can either be the full name, like 'DW_AT_name', or a shortened
473# name, like 'name'.  These are fully equivalent.
474#
475# Besides DWARF standard attributes, assembler supports 'macro' attribute
476# which will be substituted by one or more standard or macro attributes.
477# supported macro attributes are:
478#
479#  - MACRO_AT_range { FUNC }
480#  It is substituted by DW_AT_low_pc and DW_AT_high_pc with the start and
481#  end address of function FUNC in file $srcdir/$subdir/$srcfile.
482#
483#  - MACRO_AT_func { FUNC }
484#  It is substituted by DW_AT_name with FUNC and MACRO_AT_range.
485#
486# If FORM is given, it should name a DW_FORM_ constant.
487# This can either be the short form, like 'DW_FORM_addr', or a
488# shortened version, like 'addr'.  If the form is given, VALUE
489# is its value; see below.  In some cases, additional processing
490# is done; for example, DW_FORM_strp manages the .debug_str
491# section automatically.
492#
493# If FORM is 'SPECIAL_expr', then VALUE is treated as a location
494# expression.  The effective form is then DW_FORM_block or DW_FORM_exprloc
495# for DWARF version >= 4, and VALUE is passed to the (internal)
496# '_location' proc to be translated.
497# This proc implements a miniature DW_OP_ assembler.
498#
499# If FORM is not given, it is guessed:
500# * If VALUE starts with the "@" character, the rest of VALUE is
501#   looked up as a DWARF constant, and DW_FORM_sdata is used.  For
502#   example, '@DW_LANG_c89' could be used.
503# * If VALUE starts with the ":" character, then it is a label
504#   reference.  The rest of VALUE is taken to be the name of a label,
505#   and DW_FORM_ref4 is used.  See 'new_label' and 'define_label'.
506# * If VALUE starts with the "%" character, then it is a label
507#   reference too, but DW_FORM_ref_addr is used.
508# * Otherwise, if the attribute name has a default form (f.i. DW_FORM_addr for
509#   DW_AT_low_pc), then that one is used.
510# * Otherwise, an error is reported.  Either specify a form explicitly, or
511#   add a default for the the attribute name in _default_form.
512#
513# CHILDREN is just Tcl code that can be used to define child DIEs.  It
514# is evaluated in the caller's context.
515#
516# Currently this code is missing nice support for CFA handling, and
517# probably other things as well.
518
519namespace eval Dwarf {
520    # True if the module has been initialized.
521    variable _initialized 0
522
523    # Constants from dwarf2.h.
524    variable _constants
525    # DW_AT short names.
526    variable _AT
527    # DW_FORM short names.
528    variable _FORM
529    # DW_OP short names.
530    variable _OP
531
532    # The current output file.
533    variable _output_file
534
535    # Note: The _cu_ values here also apply to type units (TUs).
536    # Think of a TU as a special kind of CU.
537
538    # Current CU count.
539    variable _cu_count
540
541    # The current CU's base label.
542    variable _cu_label
543
544    # The current CU's version.
545    variable _cu_version
546
547    # The current CU's address size.
548    variable _cu_addr_size
549    # The current CU's offset size.
550    variable _cu_offset_size
551
552    # The current macro unit's offset size.
553    variable _mu_offset_size
554
555    # Label generation number.
556    variable _label_num
557
558    # The deferred output array.  The index is the section name; the
559    # contents hold the data for that section.
560    variable _deferred_output
561
562    # If empty, we should write directly to the output file.
563    # Otherwise, this is the name of a section to write to.
564    variable _defer
565
566    # The abbrev section.  Typically .debug_abbrev but can be .debug_abbrev.dwo
567    # for Fission.
568    variable _abbrev_section
569
570    # The next available abbrev number in the current CU's abbrev
571    # table.
572    variable _abbrev_num
573
574    # The string table for this assembly.  The key is the string; the
575    # value is the label for that string.
576    variable _strings
577
578    # Current .debug_line unit count.
579    variable _line_count
580
581    # A Label for line table header generation.
582    variable _line_header_end_label
583
584    # The address size for debug ranges section.
585    variable _debug_ranges_64_bit
586
587    # The index into the .debug_addr section (used for fission
588    # generation).
589    variable _debug_addr_index
590
591    # Flag, true if the current CU is contains fission information,
592    # otherwise false.
593    variable _cu_is_fission
594
595    proc _process_one_constant {name value} {
596          variable _constants
597          variable _AT
598          variable _FORM
599          variable _OP
600
601          set _constants($name) $value
602
603          if {![regexp "^DW_(\[A-Z\]+)_(\[A-Za-z0-9_\]+)$" $name \
604                      ignore prefix name2]} {
605              error "non-matching name: $name"
606          }
607
608          if {$name2 == "lo_user" || $name2 == "hi_user"} {
609              return
610          }
611
612          # We only try to shorten some very common things.
613          # FIXME: CFA?
614          switch -exact -- $prefix {
615              TAG {
616                    # Create two procedures for the tag.  These call
617                    # _handle_DW_TAG with the full tag name baked in; this
618                    # does all the actual work.
619                    proc $name {{attrs {}} {children {}}} \
620                        "_handle_DW_TAG $name \$attrs \$children"
621
622                    # Filter out ones that are known to clash.
623                    if {$name2 == "variable" || $name2 == "namespace"} {
624                        set name2 "tag_$name2"
625                    }
626
627                    if {[info commands $name2] != {}} {
628                        error "duplicate proc name: from $name"
629                    }
630
631                    proc $name2 {{attrs {}} {children {}}} \
632                        "_handle_DW_TAG $name \$attrs \$children"
633              }
634
635              AT {
636                    set _AT($name2) $name
637              }
638
639              FORM {
640                    set _FORM($name2) $name
641              }
642
643              OP {
644                    set _OP($name2) $name
645              }
646
647              default {
648                    return
649              }
650          }
651    }
652
653    proc _read_constants {} {
654          global srcdir hex decimal
655
656          # DWARF name-matching regexp.
657          set dwrx "DW_\[a-zA-Z0-9_\]+"
658          # Whitespace regexp.
659          set ws "\[ \t\]+"
660
661          set fd [open [file join $srcdir .. .. include dwarf2.h]]
662          while {![eof $fd]} {
663              set line [gets $fd]
664              if {[regexp -- "^${ws}($dwrx)${ws}=${ws}($hex|$decimal),?$" \
665                         $line ignore name value ignore2]} {
666                    _process_one_constant $name $value
667              }
668          }
669          close $fd
670
671          set fd [open [file join $srcdir .. .. include dwarf2.def]]
672          while {![eof $fd]} {
673              set line [gets $fd]
674              if {[regexp -- \
675                         "^DW_\[A-Z_\]+${ws}\\(($dwrx),${ws}($hex|$decimal)\\)$" \
676                         $line ignore name value ignore2]} {
677                    _process_one_constant $name $value
678              }
679          }
680          close $fd
681    }
682
683    proc _quote {string} {
684          # FIXME
685          return "\"${string}\\0\""
686    }
687
688    proc _nz_quote {string} {
689          # For now, no quoting is done.
690          return "\"${string}\""
691    }
692
693    proc _handle_DW_FORM {form value} {
694          switch -exact -- $form {
695              DW_FORM_string  {
696                    _op .ascii [_quote $value]
697              }
698
699              DW_FORM_implicit_const -
700              DW_FORM_flag_present {
701                    # We don't need to emit anything.
702              }
703
704              DW_FORM_data4 -
705              DW_FORM_ref4 {
706                    _op .4byte $value
707              }
708
709              DW_FORM_ref_addr {
710                    variable _cu_offset_size
711                    variable _cu_version
712                    variable _cu_addr_size
713
714                    if {$_cu_version == 2} {
715                        set size $_cu_addr_size
716                    } else {
717                        set size $_cu_offset_size
718                    }
719
720                    _op .${size}byte $value
721              }
722
723              DW_FORM_GNU_ref_alt -
724              DW_FORM_GNU_strp_alt -
725              DW_FORM_sec_offset {
726                    variable _cu_offset_size
727                    _op_offset $_cu_offset_size $value
728              }
729
730              DW_FORM_ref1 -
731              DW_FORM_flag -
732              DW_FORM_data1 {
733                    _op .byte $value
734              }
735
736              DW_FORM_sdata {
737                    _op .sleb128 $value
738              }
739
740              DW_FORM_ref_udata -
741              DW_FORM_udata -
742              DW_FORM_loclistx -
743              DW_FORM_rnglistx {
744                    _op .uleb128 $value
745              }
746
747              DW_FORM_addr {
748                    variable _cu_addr_size
749
750                    _op .${_cu_addr_size}byte $value
751              }
752
753              DW_FORM_GNU_addr_index {
754                    variable _debug_addr_index
755                    variable _cu_addr_size
756
757                    _op .uleb128 ${_debug_addr_index}
758                    incr _debug_addr_index
759
760                    _defer_output .debug_addr {
761                        _op .${_cu_addr_size}byte $value
762                    }
763              }
764
765              DW_FORM_data2 -
766              DW_FORM_ref2 {
767                    _op .2byte $value
768              }
769
770              DW_FORM_data8 -
771              DW_FORM_ref8 -
772              DW_FORM_ref_sig8 {
773                    _op .8byte $value
774              }
775
776              DW_FORM_data16 {
777                    _op .8byte $value
778              }
779
780              DW_FORM_strp {
781                    variable _strings
782                    variable _cu_offset_size
783
784                    if {![info exists _strings($value)]} {
785                        set _strings($value) [new_label strp]
786                        _defer_output .debug_str {
787                              define_label $_strings($value)
788                              _op .ascii [_quote $value]
789                        }
790                    }
791
792                    _op_offset $_cu_offset_size $_strings($value) "strp: $value"
793              }
794
795              SPECIAL_expr {
796                    variable _cu_version
797                    variable _cu_addr_size
798                    variable _cu_offset_size
799
800                    set l1 [new_label "expr_start"]
801                    set l2 [new_label "expr_end"]
802                    _op .uleb128 "$l2 - $l1" "expression"
803                    define_label $l1
804                    _location $value $_cu_version $_cu_addr_size $_cu_offset_size
805                    define_label $l2
806              }
807
808              DW_FORM_block1 {
809                    set len [string length $value]
810                    if {$len > 255} {
811                        error "DW_FORM_block1 length too long"
812                    }
813                    _op .byte $len
814                    _op .ascii [_nz_quote $value]
815              }
816
817              DW_FORM_block2 -
818              DW_FORM_block4 -
819
820              DW_FORM_block -
821
822              DW_FORM_ref2 -
823              DW_FORM_indirect -
824              DW_FORM_exprloc -
825
826              DW_FORM_strx -
827              DW_FORM_strx1 -
828              DW_FORM_strx2 -
829              DW_FORM_strx3 -
830              DW_FORM_strx4 -
831
832              DW_FORM_GNU_str_index -
833
834              default {
835                    error "unhandled form $form"
836              }
837          }
838    }
839
840    proc _guess_form {value varname} {
841          upvar $varname new_value
842
843          switch -exact -- [string range $value 0 0] {
844              @ {
845                    # Constant reference.
846                    variable _constants
847
848                    set new_value $_constants([string range $value 1 end])
849                    # Just the simplest.
850                    return DW_FORM_sdata
851              }
852
853              : {
854                    # Label reference.
855                    variable _cu_label
856
857                    set new_value "[string range $value 1 end] - $_cu_label"
858
859                    return DW_FORM_ref4
860              }
861
862              % {
863                    # Label reference, an offset from .debug_info.
864                    set new_value "[string range $value 1 end]"
865
866                    return DW_FORM_ref_addr
867              }
868
869              default {
870                    return ""
871              }
872          }
873    }
874
875    proc _default_form { attr } {
876          switch -exact -- $attr {
877              DW_AT_low_pc  {
878                    return DW_FORM_addr
879              }
880              DW_AT_producer -
881              DW_AT_comp_dir -
882              DW_AT_linkage_name -
883              DW_AT_MIPS_linkage_name -
884              DW_AT_name {
885                    return DW_FORM_string
886              }
887              DW_AT_GNU_addr_base {
888                    return DW_FORM_sec_offset
889              }
890          }
891          return ""
892    }
893
894    # Map NAME to its canonical form.
895    proc _map_name {name ary} {
896          variable $ary
897
898          if {[info exists ${ary}($name)]} {
899              set name [set ${ary}($name)]
900          }
901
902          return $name
903    }
904
905    proc _handle_attribute { attr_name attr_value attr_form } {
906          variable _abbrev_section
907          variable _constants
908          variable _cu_version
909
910          _handle_DW_FORM $attr_form $attr_value
911
912          _defer_output $_abbrev_section {
913              if { $attr_form eq "SPECIAL_expr" } {
914                    if { $_cu_version < 4 } {
915                        set attr_form_comment "DW_FORM_block"
916                    } else {
917                        set attr_form_comment "DW_FORM_exprloc"
918                    }
919              } else {
920                    set attr_form_comment $attr_form
921              }
922              _op .uleb128 $_constants($attr_name) $attr_name
923              _op .uleb128 $_constants($attr_form) $attr_form_comment
924              if {$attr_form eq "DW_FORM_implicit_const"} {
925                    _op .sleb128 $attr_value "the constant"
926              }
927          }
928    }
929
930    # Handle macro attribute MACRO_AT_range.
931
932    proc _handle_macro_at_range { attr_value } {
933          variable _cu_is_fission
934
935          if {[llength $attr_value] != 1} {
936              error "usage: MACRO_AT_range { func }"
937          }
938
939          set func [lindex $attr_value 0]
940          global srcdir subdir srcfile
941          set src ${srcdir}/${subdir}/${srcfile}
942          set result [function_range $func $src]
943
944          set form DW_FORM_addr
945          if { $_cu_is_fission } {
946              set form DW_FORM_GNU_addr_index
947          }
948
949          _handle_attribute DW_AT_low_pc [lindex $result 0] $form
950          _handle_attribute DW_AT_high_pc \
951              "[lindex $result 0] + [lindex $result 1]" $form
952    }
953
954    # Handle macro attribute MACRO_AT_func.
955
956    proc _handle_macro_at_func { attr_value } {
957          if {[llength $attr_value] != 1} {
958              error "usage: MACRO_AT_func { func file }"
959          }
960          _handle_attribute DW_AT_name [lindex $attr_value 0] DW_FORM_string
961          _handle_macro_at_range $attr_value
962    }
963
964    # Return the next available abbrev number in the current CU's abbrev
965    # table.
966    proc _get_abbrev_num {} {
967          variable _abbrev_num
968          set res $_abbrev_num
969          incr _abbrev_num
970          return $res
971    }
972
973    proc _handle_DW_TAG {tag_name {attrs {}} {children {}}} {
974          variable _abbrev_section
975          variable _abbrev_num
976          variable _constants
977
978          set has_children [expr {[string length $children] > 0}]
979          set my_abbrev [_get_abbrev_num]
980
981          # We somewhat wastefully emit a new abbrev entry for each tag.
982          # There's no reason for this other than laziness.
983          _defer_output $_abbrev_section {
984              _op .uleb128 $my_abbrev "Abbrev start"
985              _op .uleb128 $_constants($tag_name) $tag_name
986              _op .byte $has_children "has_children"
987          }
988
989          _op .uleb128 $my_abbrev "Abbrev ($tag_name)"
990
991          foreach attr $attrs {
992              set attr_name [_map_name [lindex $attr 0] _AT]
993
994              # When the length of ATTR is greater than 2, the last
995              # element of the list must be a form.  The second through
996              # the penultimate elements are joined together and
997              # evaluated using subst.  This allows constructs such as
998              # [gdb_target_symbol foo] to be used.
999
1000              if {[llength $attr] > 2} {
1001                  set attr_value [uplevel 2 [list subst [join [lrange $attr 1 end-1]]]]
1002              } else {
1003                  set attr_value [uplevel 2 [list subst [lindex $attr 1]]]
1004              }
1005
1006              if { [string equal "MACRO_AT_func" $attr_name] } {
1007                    _handle_macro_at_func $attr_value
1008              } elseif { [string equal "MACRO_AT_range" $attr_name] } {
1009                    _handle_macro_at_range $attr_value
1010              } else {
1011                    if {[llength $attr] > 2} {
1012                        set attr_form [uplevel 2 [list subst [lindex $attr end]]]
1013
1014                        if { [string index $attr_value 0] == ":" } {
1015                              # It is a label, get its value.
1016                              _guess_form $attr_value attr_value
1017                        }
1018                    } else {
1019                        set attr_form [_guess_form $attr_value attr_value]
1020                        if { $attr_form eq "" } {
1021                              set attr_form [_default_form $attr_name]
1022                        }
1023                        if { $attr_form eq "" } {
1024                              error "No form for $attr_name $attr_value"
1025                        }
1026                    }
1027                    set attr_form [_map_name $attr_form _FORM]
1028
1029                    _handle_attribute $attr_name $attr_value $attr_form
1030              }
1031          }
1032
1033          _defer_output $_abbrev_section {
1034              # Terminator.
1035              _op .byte 0x0 "DW_AT - Terminator"
1036              _op .byte 0x0 "DW_FORM - Terminator"
1037          }
1038
1039          if {$has_children} {
1040              uplevel 2 $children
1041
1042              # Terminate children.
1043              _op .byte 0x0 "Terminate children"
1044          }
1045    }
1046
1047    proc _emit {string} {
1048          variable _output_file
1049          variable _defer
1050          variable _deferred_output
1051
1052          if {$_defer == ""} {
1053              puts $_output_file $string
1054          } else {
1055              append _deferred_output($_defer) ${string}\n
1056          }
1057    }
1058
1059    proc _section {name {flags ""} {type ""}} {
1060          if {$flags == "" && $type == ""} {
1061              _emit "        .section $name"
1062          } elseif {$type == ""} {
1063              _emit "        .section $name, \"$flags\""
1064          } else {
1065              _emit "        .section $name, \"$flags\", %$type"
1066          }
1067    }
1068
1069    # SECTION_SPEC is a list of arguments to _section.
1070    proc _defer_output {section_spec body} {
1071          variable _defer
1072          variable _deferred_output
1073
1074          set old_defer $_defer
1075          set _defer [lindex $section_spec 0]
1076
1077          if {![info exists _deferred_output($_defer)]} {
1078              set _deferred_output($_defer) ""
1079              eval _section $section_spec
1080          }
1081
1082          uplevel $body
1083
1084          set _defer $old_defer
1085    }
1086
1087    proc _defer_to_string {body} {
1088          variable _defer
1089          variable _deferred_output
1090
1091          set old_defer $_defer
1092          set _defer temp
1093
1094          set _deferred_output($_defer) ""
1095
1096          uplevel $body
1097
1098          set result $_deferred_output($_defer)
1099          unset _deferred_output($_defer)
1100
1101          set _defer $old_defer
1102          return $result
1103    }
1104
1105    proc _write_deferred_output {} {
1106          variable _output_file
1107          variable _deferred_output
1108
1109          foreach section [array names _deferred_output] {
1110              # The data already has a newline.
1111              puts -nonewline $_output_file $_deferred_output($section)
1112          }
1113
1114          # Save some memory.
1115          unset _deferred_output
1116    }
1117
1118    proc _op {name value {comment ""}} {
1119          set text "        ${name}        ${value}"
1120          if {$comment != ""} {
1121              # Try to make stuff line up nicely.
1122              while {[string length $text] < 40} {
1123                    append text " "
1124              }
1125              append text "/* ${comment} */"
1126          }
1127          _emit $text
1128    }
1129
1130    proc _op_offset { size offset {comment ""} } {
1131          if { $size == 4 } {
1132              _op .4byte $offset $comment
1133          } elseif { $size == 8 } {
1134              if {[is_64_target]} {
1135                    _op .8byte $offset $comment
1136              } else {
1137                    # This allows us to emit 64-bit dwarf for
1138                    # 32-bit targets.
1139                    if { [target_endianness] == "little" } {
1140                        _op .4byte $offset "$comment (lsw)"
1141                        _op .4byte 0 "$comment (msw)"
1142                    } else {
1143                        _op .4byte 0 "$comment (msw)"
1144                        _op .4byte $offset "$comment (lsw)"
1145                    }
1146              }
1147          } else {
1148              error "Don't know how to handle offset size $size"
1149          }
1150    }
1151
1152    proc _compute_label {name} {
1153          return ".L${name}"
1154    }
1155
1156    # Return a name suitable for use as a label.  If BASE_NAME is
1157    # specified, it is incorporated into the label name; this is to
1158    # make debugging the generated assembler easier.  If BASE_NAME is
1159    # not specified a generic default is used.  This proc does not
1160    # define the label; see 'define_label'.  'new_label' attempts to
1161    # ensure that label names are unique.
1162    proc new_label {{base_name label}} {
1163          variable _label_num
1164
1165          return [_compute_label ${base_name}[incr _label_num]]
1166    }
1167
1168    # Define a label named NAME.  Ordinarily, NAME comes from a call
1169    # to 'new_label', but this is not required.
1170    proc define_label {name} {
1171          _emit "${name}:"
1172    }
1173
1174    # A higher-level interface to label handling.
1175    #
1176    # ARGS is a list of label descriptors.  Each one is either a
1177    # single element, or a list of two elements -- a name and some
1178    # text.  For each descriptor, 'new_label' is invoked.  If the list
1179    # form is used, the second element in the list is passed as an
1180    # argument.  The label name is used to define a variable in the
1181    # enclosing scope; this can be used to refer to the label later.
1182    # The label name is also used to define a new proc whose name is
1183    # the label name plus a trailing ":".  This proc takes a body as
1184    # an argument and can be used to define the label at that point;
1185    # then the body, if any, is evaluated in the caller's context.
1186    #
1187    # For example:
1188    #
1189    # declare_labels int_label
1190    # something { ... $int_label }   ;# refer to the label
1191    # int_label: constant { ... }    ;# define the label
1192    proc declare_labels {args} {
1193          foreach arg $args {
1194              set name [lindex $arg 0]
1195              set text [lindex $arg 1]
1196
1197              if { $text == "" } {
1198                    set text $name
1199              }
1200
1201              upvar $name label_var
1202              set label_var [new_label $text]
1203
1204              proc ${name}: {args} [format {
1205                    define_label %s
1206                    uplevel $args
1207              } $label_var]
1208          }
1209    }
1210
1211    # Assign elements from LINE to the elements of an array named
1212    # "argvec" in the caller scope.  The keys used are named in ARGS.
1213    # If the wrong number of elements appear in LINE, error.
1214    proc _get_args {line op args} {
1215          if {[llength $line] != [llength $args] + 1} {
1216              error "usage: $op [string toupper $args]"
1217          }
1218
1219          upvar argvec argvec
1220          foreach var $args value [lreplace $line 0 0] {
1221              set argvec($var) $value
1222          }
1223    }
1224
1225    # This is a miniature assembler for location expressions.  It is
1226    # suitable for use in the attributes to a DIE.  Its output is
1227    # prefixed with "=" to make it automatically use DW_FORM_block.
1228    #
1229    # BODY is split by lines, and each line is taken to be a list.
1230    #
1231    # DWARF_VERSION is the DWARF version for the section where the location
1232    # description is found.
1233    #
1234    # ADDR_SIZE is the length in bytes (4 or 8) of an address on the target
1235    # machine (typically found in the header of the section where the location
1236    # description is found).
1237    #
1238    # OFFSET_SIZE is the length in bytes (4 or 8) of an offset into a DWARF
1239    # section.  This typically depends on whether 32-bit or 64-bit DWARF is
1240    # used, as indicated in the header of the section where the location
1241    # description is found.
1242    #
1243    # (FIXME should use 'info complete' here.)
1244    # Each list's first element is the opcode, either short or long
1245    # forms are accepted.
1246    # FIXME argument handling
1247    # FIXME move docs
1248    proc _location { body dwarf_version addr_size offset_size } {
1249          variable _constants
1250
1251          foreach line [split $body \n] {
1252              # Ignore blank lines, and allow embedded comments.
1253              if {[lindex $line 0] == "" || [regexp -- {^[ \t]*#} $line]} {
1254                    continue
1255              }
1256              set opcode [_map_name [lindex $line 0] _OP]
1257              _op .byte $_constants($opcode) $opcode
1258
1259              array unset argvec *
1260              switch -exact -- $opcode {
1261                    DW_OP_addr {
1262                        _get_args $line $opcode size
1263                        _op .${addr_size}byte $argvec(size)
1264                    }
1265
1266                    DW_OP_GNU_addr_index {
1267                        variable _debug_addr_index
1268                        variable _cu_addr_size
1269
1270                        _op .uleb128 ${_debug_addr_index}
1271                        incr _debug_addr_index
1272
1273                        _defer_output .debug_addr {
1274                              _op .${_cu_addr_size}byte [lindex $line 1]
1275                        }
1276                    }
1277
1278                    DW_OP_regx {
1279                        _get_args $line $opcode register
1280                        _op .uleb128 $argvec(register)
1281                    }
1282
1283                    DW_OP_pick -
1284                    DW_OP_const1u -
1285                    DW_OP_const1s {
1286                        _get_args $line $opcode const
1287                        _op .byte $argvec(const)
1288                    }
1289
1290                    DW_OP_const2u -
1291                    DW_OP_const2s {
1292                        _get_args $line $opcode const
1293                        _op .2byte $argvec(const)
1294                    }
1295
1296                    DW_OP_const4u -
1297                    DW_OP_const4s {
1298                        _get_args $line $opcode const
1299                        _op .4byte $argvec(const)
1300                    }
1301
1302                    DW_OP_const8u -
1303                    DW_OP_const8s {
1304                        _get_args $line $opcode const
1305                        _op .8byte $argvec(const)
1306                    }
1307
1308                    DW_OP_constu {
1309                        _get_args $line $opcode const
1310                        _op .uleb128 $argvec(const)
1311                    }
1312                    DW_OP_consts {
1313                        _get_args $line $opcode const
1314                        _op .sleb128 $argvec(const)
1315                    }
1316
1317                    DW_OP_plus_uconst {
1318                        _get_args $line $opcode const
1319                        _op .uleb128 $argvec(const)
1320                    }
1321
1322                    DW_OP_piece {
1323                        _get_args $line $opcode size
1324                        _op .uleb128 $argvec(size)
1325                    }
1326
1327                    DW_OP_bit_piece {
1328                        _get_args $line $opcode size offset
1329                        _op .uleb128 $argvec(size)
1330                        _op .uleb128 $argvec(offset)
1331                    }
1332
1333                    DW_OP_skip -
1334                    DW_OP_bra {
1335                        _get_args $line $opcode label
1336                        _op .2byte $argvec(label)
1337                    }
1338
1339                    DW_OP_implicit_value {
1340                        set l1 [new_label "value_start"]
1341                        set l2 [new_label "value_end"]
1342                        _op .uleb128 "$l2 - $l1"
1343                        define_label $l1
1344                        foreach value [lrange $line 1 end] {
1345                              switch -regexp -- $value {
1346                                  {^0x[[:xdigit:]]{1,2}$} {_op .byte $value}
1347                                  {^0x[[:xdigit:]]{4}$} {_op .2byte $value}
1348                                  {^0x[[:xdigit:]]{8}$} {_op .4byte $value}
1349                                  {^0x[[:xdigit:]]{16}$} {_op .8byte $value}
1350                                  default {
1351                                        error "bad value '$value' in DW_OP_implicit_value"
1352                                  }
1353                              }
1354                        }
1355                        define_label $l2
1356                    }
1357
1358                    DW_OP_implicit_pointer -
1359                    DW_OP_GNU_implicit_pointer {
1360                        _get_args $line $opcode label offset
1361
1362                        # Here label is a section offset.
1363                        if { $dwarf_version == 2 } {
1364                              _op .${addr_size}byte $argvec(label)
1365                        } else {
1366                              _op_offset $offset_size $argvec(label)
1367                        }
1368                        _op .sleb128 $argvec(offset)
1369                    }
1370
1371                    DW_OP_GNU_variable_value {
1372                        _get_args $line $opcode label
1373
1374                        # Here label is a section offset.
1375                        if { $dwarf_version == 2 } {
1376                              _op .${addr_size}byte $argvec(label)
1377                        } else {
1378                              _op_offset $offset_size $argvec(label)
1379                        }
1380                    }
1381
1382                    DW_OP_deref_size {
1383                        _get_args $line $opcode size
1384                        _op .byte $argvec(size)
1385                    }
1386
1387                    DW_OP_bregx {
1388                        _get_args $line $opcode register offset
1389                        _op .uleb128 $argvec(register)
1390                        _op .sleb128 $argvec(offset)
1391                    }
1392
1393                    DW_OP_fbreg {
1394                        _get_args $line $opcode offset
1395                        _op .sleb128 $argvec(offset)
1396                    }
1397
1398                    DW_OP_fbreg {
1399                        _op .sleb128 [lindex $line 1]
1400                    }
1401
1402                    default {
1403                        if {[llength $line] > 1} {
1404                              error "Unimplemented: operands in location for $opcode"
1405                        }
1406                    }
1407              }
1408          }
1409    }
1410
1411    # Return a label that references the current position in the
1412    # .debug_addr table.  When a user is creating split DWARF they
1413    # will define two CUs, the first will be the split DWARF content,
1414    # and the second will be the non-split stub CU.  The split DWARF
1415    # CU fills in the .debug_addr section, but the non-split CU
1416    # includes a reference to the start of the section.  The label
1417    # returned by this proc provides that reference.
1418    proc debug_addr_label {} {
1419          variable _debug_addr_index
1420
1421          set lbl [new_label "debug_addr_idx_${_debug_addr_index}_"]
1422          _defer_output .debug_addr {
1423              define_label $lbl
1424          }
1425          return $lbl
1426    }
1427
1428    # Emit a DWARF CU.
1429    # OPTIONS is a list with an even number of elements containing
1430    # option-name and option-value pairs.
1431    # Current options are:
1432    # is_64 0|1    - boolean indicating if you want to emit 64-bit DWARF
1433    #                default = 0 (32-bit)
1434    # version n    - DWARF version number to emit
1435    #                default = 4
1436    # addr_size n  - the size of addresses in bytes: 4, 8, or default
1437    #                default = default
1438    # fission 0|1  - boolean indicating if generating Fission debug info
1439    #                default = 0
1440    # label <label>
1441    #              - string indicating label to be defined at the start
1442    #                of the CU header.
1443    #                default = ""
1444    # BODY is Tcl code that emits the DIEs which make up the body of
1445    # the CU.  It is evaluated in the caller's context.
1446    proc cu {options body} {
1447          variable _constants
1448          variable _cu_count
1449          variable _abbrev_section
1450          variable _abbrev_num
1451          variable _cu_label
1452          variable _cu_version
1453          variable _cu_addr_size
1454          variable _cu_offset_size
1455          variable _cu_is_fission
1456
1457          # Establish the defaults.
1458          set is_64 0
1459          set _cu_version 4
1460          set _cu_addr_size default
1461          set _cu_is_fission 0
1462          set section ".debug_info"
1463          set _abbrev_section ".debug_abbrev"
1464          set label ""
1465
1466          foreach { name value } $options {
1467              set value [uplevel 1 "subst \"$value\""]
1468              switch -exact -- $name {
1469                    is_64 { set is_64 $value }
1470                    version { set _cu_version $value }
1471                    addr_size { set _cu_addr_size $value }
1472                    fission { set _cu_is_fission $value }
1473                    label { set label $value }
1474                    default { error "unknown option $name" }
1475              }
1476          }
1477          if {$_cu_addr_size == "default"} {
1478              if {[is_64_target]} {
1479                    set _cu_addr_size 8
1480              } else {
1481                    set _cu_addr_size 4
1482              }
1483          }
1484          set _cu_offset_size [expr { $is_64 ? 8 : 4 }]
1485          if { $_cu_is_fission } {
1486              set section ".debug_info.dwo"
1487              set _abbrev_section ".debug_abbrev.dwo"
1488          }
1489
1490          if {$_cu_version < 4} {
1491              set _constants(SPECIAL_expr) $_constants(DW_FORM_block)
1492          } else {
1493              set _constants(SPECIAL_expr) $_constants(DW_FORM_exprloc)
1494          }
1495
1496          _section $section
1497
1498          set cu_num [incr _cu_count]
1499          set my_abbrevs [_compute_label "abbrev${cu_num}_begin"]
1500          set _abbrev_num 1
1501
1502          set _cu_label [_compute_label "cu${cu_num}_begin"]
1503          set start_label [_compute_label "cu${cu_num}_start"]
1504          set end_label [_compute_label "cu${cu_num}_end"]
1505
1506          if { $label != "" } {
1507              upvar $label my_label
1508              set my_label $_cu_label
1509          }
1510
1511          define_label $_cu_label
1512          if {$is_64} {
1513              _op .4byte 0xffffffff
1514              _op .8byte "$end_label - $start_label"
1515          } else {
1516              _op .4byte "$end_label - $start_label"
1517          }
1518          define_label $start_label
1519          _op .2byte $_cu_version Version
1520
1521          # The CU header for DWARF 4 and 5 are slightly different.
1522          if { $_cu_version == 5 } {
1523              _op .byte 0x1 "DW_UT_compile"
1524              _op .byte $_cu_addr_size "Pointer size"
1525              _op_offset $_cu_offset_size $my_abbrevs Abbrevs
1526          } else {
1527              _op_offset $_cu_offset_size $my_abbrevs Abbrevs
1528              _op .byte $_cu_addr_size "Pointer size"
1529          }
1530
1531          _defer_output $_abbrev_section {
1532              define_label $my_abbrevs
1533          }
1534
1535          uplevel $body
1536
1537          _defer_output $_abbrev_section {
1538              # Emit the terminator.
1539              _op .byte 0x0 "Abbrev end - Terminator"
1540          }
1541
1542          define_label $end_label
1543    }
1544
1545    # Emit a DWARF TU.
1546    # OPTIONS is a list with an even number of elements containing
1547    # option-name and option-value pairs.
1548    # Current options are:
1549    # is_64 0|1    - boolean indicating if you want to emit 64-bit DWARF
1550    #                default = 0 (32-bit)
1551    # version n    - DWARF version number to emit
1552    #                default = 4
1553    # addr_size n  - the size of addresses in bytes: 4, 8, or default
1554    #                default = default
1555    # fission 0|1  - boolean indicating if generating Fission debug info
1556    #                default = 0
1557    # SIGNATURE is the 64-bit signature of the type.
1558    # TYPE_LABEL is the label of the type defined by this TU,
1559    # or "" if there is no type (i.e., type stubs in Fission).
1560    # BODY is Tcl code that emits the DIEs which make up the body of
1561    # the TU.  It is evaluated in the caller's context.
1562    proc tu {options signature type_label body} {
1563          variable _cu_count
1564          variable _abbrev_section
1565          variable _abbrev_num
1566          variable _cu_label
1567          variable _cu_version
1568          variable _cu_addr_size
1569          variable _cu_offset_size
1570          variable _cu_is_fission
1571
1572          # Establish the defaults.
1573          set is_64 0
1574          set _cu_version 4
1575          set _cu_addr_size default
1576          set _cu_is_fission 0
1577          set section ".debug_types"
1578          set _abbrev_section ".debug_abbrev"
1579          set label ""
1580
1581          foreach { name value } $options {
1582              set value [uplevel 1 "subst \"$value\""]
1583              switch -exact -- $name {
1584                    is_64 { set is_64 $value }
1585                    version { set _cu_version $value }
1586                    addr_size { set _cu_addr_size $value }
1587                    fission { set _cu_is_fission $value }
1588                    label { set label $value }
1589                    default { error "unknown option $name" }
1590              }
1591          }
1592          if {$_cu_addr_size == "default"} {
1593              if {[is_64_target]} {
1594                    set _cu_addr_size 8
1595              } else {
1596                    set _cu_addr_size 4
1597              }
1598          }
1599          set _cu_offset_size [expr { $is_64 ? 8 : 4 }]
1600          if { $_cu_version == 5 } {
1601              set section ".debug_info"
1602          }
1603          if { $_cu_is_fission } {
1604              set section "$section.dwo"
1605              set _abbrev_section "$section.dwo"
1606          }
1607
1608          _section $section
1609
1610          set cu_num [incr _cu_count]
1611          set my_abbrevs [_compute_label "abbrev${cu_num}_begin"]
1612          set _abbrev_num 1
1613
1614          set _cu_label [_compute_label "cu${cu_num}_begin"]
1615          set start_label [_compute_label "cu${cu_num}_start"]
1616          set end_label [_compute_label "cu${cu_num}_end"]
1617
1618          if { $label != "" } {
1619              upvar $label my_label
1620              set my_label $_cu_label
1621          }
1622
1623          define_label $_cu_label
1624          if {$is_64} {
1625              _op .4byte 0xffffffff
1626              _op .8byte "$end_label - $start_label"
1627          } else {
1628              _op .4byte "$end_label - $start_label"
1629          }
1630          define_label $start_label
1631          _op .2byte $_cu_version Version
1632
1633          # The CU header for DWARF 4 and 5 are slightly different.
1634          if { $_cu_version == 5 } {
1635              _op .byte 0x2 "DW_UT_type"
1636              _op .byte $_cu_addr_size "Pointer size"
1637              _op_offset $_cu_offset_size $my_abbrevs Abbrevs
1638          } else {
1639              _op_offset $_cu_offset_size $my_abbrevs Abbrevs
1640              _op .byte $_cu_addr_size "Pointer size"
1641          }
1642
1643          _op .8byte $signature Signature
1644          if { $type_label != "" } {
1645              uplevel declare_labels $type_label
1646              upvar $type_label my_type_label
1647              if {$is_64} {
1648                    _op .8byte "$my_type_label - $_cu_label"
1649              } else {
1650                    _op .4byte "$my_type_label - $_cu_label"
1651              }
1652          } else {
1653              if {$is_64} {
1654                    _op .8byte 0
1655              } else {
1656                    _op .4byte 0
1657              }
1658          }
1659
1660          _defer_output $_abbrev_section {
1661              define_label $my_abbrevs
1662          }
1663
1664          uplevel $body
1665
1666          _defer_output $_abbrev_section {
1667              # Emit the terminator.
1668              _op .byte 0x0 "Abbrev end - Terminator"
1669          }
1670
1671          define_label $end_label
1672    }
1673
1674    # Emit a DWARF .debug_ranges unit.
1675    # OPTIONS is a list with an even number of elements containing
1676    # option-name and option-value pairs.
1677    # Current options are:
1678    # is_64 0|1    - boolean indicating if you want to emit 64-bit DWARF
1679    #                default = 0 (32-bit)
1680    #
1681    # BODY is Tcl code that emits the content of the .debug_ranges
1682    # unit, it is evaluated in the caller's context.
1683    proc ranges {options body} {
1684          variable _debug_ranges_64_bit
1685
1686          foreach { name value } $options {
1687              switch -exact -- $name {
1688                    is_64 { set _debug_ranges_64_bit [subst $value] }
1689                    default { error "unknown option $name" }
1690              }
1691          }
1692
1693          set section ".debug_ranges"
1694          _section $section
1695
1696          proc sequence { body } {
1697              variable _debug_ranges_64_bit
1698
1699              # Emit the sequence of addresses.
1700
1701              proc base { addr } {
1702                    variable _debug_ranges_64_bit
1703
1704                    if {$_debug_ranges_64_bit} {
1705                        _op .8byte 0xffffffffffffffff "Base Marker"
1706                        _op .8byte $addr "Base Address"
1707                    } else {
1708                        _op .4byte 0xffffffff "Base Marker"
1709                        _op .4byte $addr "Base Address"
1710                    }
1711              }
1712
1713              proc range { start end } {
1714                    variable _debug_ranges_64_bit
1715
1716                    if {$_debug_ranges_64_bit} {
1717                        _op .8byte $start "Start Address"
1718                        _op .8byte $end "End Address"
1719                    } else {
1720                        _op .4byte $start "Start Address"
1721                        _op .4byte $end "End Address"
1722                    }
1723              }
1724
1725              uplevel $body
1726
1727              # End of the sequence.
1728              if {$_debug_ranges_64_bit} {
1729                    _op .8byte 0x0 "End of Sequence Marker (Part 1)"
1730                    _op .8byte 0x0 "End of Sequence Marker (Part 2)"
1731              } else {
1732                    _op .4byte 0x0 "End of Sequence Marker (Part 1)"
1733                    _op .4byte 0x0 "End of Sequence Marker (Part 2)"
1734              }
1735          }
1736
1737          uplevel $body
1738    }
1739
1740    # Emit a DWARF .debug_rnglists section.
1741    #
1742    # The target address size is based on the current target's address size.
1743    #
1744    # BODY must be Tcl code that emits the content of the section.  It is
1745    # evaluated in the caller's context.
1746    #
1747    # The `is-64 true|false` options tells whether to use 64-bit DWARF instead
1748    # of 32-bit DWARF.  The default is 32-bit.
1749
1750    proc rnglists { options body } {
1751          variable _debug_rnglists_addr_size
1752          variable _debug_rnglists_offset_size
1753          variable _debug_rnglists_is_64_dwarf
1754
1755          parse_options {{"is-64" "false"}}
1756
1757          if [is_64_target] {
1758              set _debug_rnglists_addr_size 8
1759          } else {
1760              set _debug_rnglists_addr_size 4
1761          }
1762
1763          if { ${is-64} } {
1764              set _debug_rnglists_offset_size 8
1765              set _debug_rnglists_is_64_dwarf true
1766          } else {
1767              set _debug_rnglists_offset_size 4
1768              set _debug_rnglists_is_64_dwarf false
1769          }
1770
1771          _section ".debug_rnglists"
1772
1773          # Count of tables in the section.
1774          variable _debug_rnglists_table_count 0
1775
1776          # Compute the label name for list at index LIST_IDX, for the current
1777          # table.
1778
1779          proc _compute_list_label { list_idx } {
1780              variable _debug_rnglists_table_count
1781
1782              return ".Lrnglists_table_${_debug_rnglists_table_count}_list_${list_idx}"
1783          }
1784
1785          with_override Dwarf::table Dwarf::_rnglists_table {
1786              uplevel $body
1787          }
1788    }
1789
1790    # Generate one rnglists table (header + offset array + range lists).
1791    #
1792    # This proc is meant to be used within proc rnglists' body.  It is made
1793    # available as `table` while inside proc rnglists' body.
1794    #
1795    # BODY must be Tcl code that emits the content of the table.  It may call
1796    # the LIST_ procedure to generate rnglists.  It is evaluated in the
1797    # caller's context.
1798    #
1799    # The `post-header-label` option can be used to define a label just after
1800    # the header of the table.  This is the label that a DW_AT_rnglists_base
1801    # attribute will usually refer to.
1802    #
1803    # The `with-offset-array true|false` option can be used to control whether
1804    # the headers of the location list tables have an array of offset.  The
1805    # default is true.
1806
1807    proc _rnglists_table { options body } {
1808          variable _debug_rnglists_table_count
1809          variable _debug_rnglists_addr_size
1810          variable _debug_rnglists_offset_size
1811          variable _debug_rnglists_is_64_dwarf
1812
1813          parse_options {
1814              {post-header-label ""}
1815              {with-offset-array true}
1816          }
1817
1818          # Count of lists in the table.
1819          variable _debug_rnglists_list_count 0
1820
1821          # Generate the lists ops first, because we need to know how many
1822          # lists there are to generate the header and offset table.
1823          set lists_ops [_defer_to_string {
1824              with_override Dwarf::list_ Dwarf::_rnglists_list {
1825                    uplevel $body
1826              }
1827          }]
1828
1829          set post_unit_len_label \
1830              [_compute_label "rnglists_table_${_debug_rnglists_table_count}_post_unit_len"]
1831          set post_header_label \
1832              [_compute_label "rnglists_table_${_debug_rnglists_table_count}_post_header"]
1833          set table_end_label \
1834              [_compute_label "rnglists_table_${_debug_rnglists_table_count}_end"]
1835
1836          # Emit the table header.
1837          if { $_debug_rnglists_is_64_dwarf } {
1838              _op .4byte 0xffffffff "unit length 1/2"
1839              _op .8byte "$table_end_label - $post_unit_len_label" "unit length 2/2"
1840          } else {
1841              _op .4byte "$table_end_label - $post_unit_len_label" "unit length"
1842          }
1843
1844          define_label $post_unit_len_label
1845
1846          _op .2byte 5 "dwarf version"
1847          _op .byte $_debug_rnglists_addr_size "address size"
1848          _op .byte 0 "segment selector size"
1849
1850          if { ${with-offset-array} } {
1851            _op .4byte "$_debug_rnglists_list_count" "offset entry count"
1852          } else {
1853            _op .4byte 0 "offset entry count"
1854          }
1855
1856          define_label $post_header_label
1857
1858          # Define the user post-header label, if provided.
1859          if { ${post-header-label} != "" } {
1860              define_label ${post-header-label}
1861          }
1862
1863          # Emit the offset array.
1864          if { ${with-offset-array} } {
1865              for {set list_idx 0} {$list_idx < $_debug_rnglists_list_count} {incr list_idx} {
1866                    set list_label [_compute_list_label $list_idx]
1867                    _op_offset $_debug_rnglists_offset_size \
1868                        "$list_label - $post_header_label" \
1869                        "offset of list $list_idx"
1870              }
1871          }
1872
1873          # Emit the actual list data.
1874          _emit "$lists_ops"
1875
1876          define_label $table_end_label
1877
1878          incr _debug_rnglists_table_count
1879    }
1880
1881    # Generate one rnglists range list.
1882    #
1883    # This proc is meant to be used within proc _rnglists_table's body.  It is
1884    # made available as `list_` while inside proc _rnglists_table's body.
1885    #
1886    # BODY may call the various procs defined below to generate list entries.
1887    # They correspond to the range list entry kinds described in section 2.17.3
1888    # of the DWARF 5 spec.
1889    #
1890    # To define a label pointing to the beginning of the list, use the
1891    # conventional way of declaring and defining labels:
1892    #
1893    #   declare_labels the_list
1894    #
1895    #   the_list: list_ { ...  }
1896
1897    proc _rnglists_list { body } {
1898          variable _debug_rnglists_list_count
1899
1900          # Define a label for this list.  It is used to build the offset
1901          # array later.
1902          set list_label [_compute_list_label $_debug_rnglists_list_count]
1903          define_label $list_label
1904
1905          with_override Dwarf::start_end Dwarf::_rnglists_start_end {
1906              uplevel $body
1907          }
1908
1909          # Emit end of list.
1910          _op .byte 0x00 "DW_RLE_end_of_list"
1911
1912          incr _debug_rnglists_list_count
1913    }
1914
1915    # Emit a rnglists DW_RLE_start_end entry.
1916    #
1917    # This proc is meant to be used within proc _rnglists_list's body.  It is
1918    # made available as `start_end` while inside proc _rnglists_list's body.
1919
1920    proc _rnglists_start_end { start end } {
1921          variable _debug_rnglists_addr_size
1922
1923          _op .byte 0x06 "DW_RLE_start_end"
1924          _op .${_debug_rnglists_addr_size}byte $start "start"
1925          _op .${_debug_rnglists_addr_size}byte $end "end"
1926    }
1927
1928    # Emit a DWARF .debug_loclists section.
1929    #
1930    # The target address size is based on the current target's address size.
1931    #
1932    # BODY must be Tcl code that emits the content of the section.  It is
1933    # evaluated in the caller's context.
1934    #
1935    # The `is-64 true|false` options tells whether to use 64-bit DWARF instead
1936    # of 32-bit DWARF.  The default is 32-bit.
1937
1938    proc loclists { options body } {
1939          variable _debug_loclists_addr_size
1940          variable _debug_loclists_offset_size
1941          variable _debug_loclists_is_64_dwarf
1942
1943          parse_options {{"is-64" "false"}}
1944
1945          if [is_64_target] {
1946              set _debug_loclists_addr_size 8
1947          } else {
1948              set _debug_loclists_addr_size 4
1949          }
1950
1951          if { ${is-64} } {
1952              set _debug_loclists_offset_size 8
1953              set _debug_loclists_is_64_dwarf true
1954          } else {
1955              set _debug_loclists_offset_size 4
1956              set _debug_loclists_is_64_dwarf false
1957          }
1958
1959          _section ".debug_loclists"
1960
1961          # Count of tables in the section.
1962          variable _debug_loclists_table_count 0
1963
1964          # Compute the label name for list at index LIST_IDX, for the current
1965          # table.
1966
1967          proc _compute_list_label { list_idx } {
1968              variable _debug_loclists_table_count
1969
1970              return ".Lloclists_table_${_debug_loclists_table_count}_list_${list_idx}"
1971          }
1972
1973          with_override Dwarf::table Dwarf::_loclists_table {
1974              uplevel $body
1975          }
1976    }
1977
1978    # Generate one loclists table (header + offset array + location lists).
1979    #
1980    # This proc is meant to be used within proc loclists' body.  It is made
1981    # available as `table` while inside proc rnglists' body.
1982    #
1983    # BODY must be Tcl code that emits the content of the table.  It may call
1984    # the LIST_ procedure to generate rnglists.  It is evaluated in the
1985    # caller's context.
1986    #
1987    # The `post-header-label` option can be used to define a label just after
1988    # the header of the table.  This is the label that a DW_AT_loclists_base
1989    # attribute will usually refer to.
1990    #
1991    # The `with-offset-array true|false` option can be used to control
1992    # whether the headers of the location list tables have an array of
1993    # offset.  The default is true.
1994
1995    proc _loclists_table { options body } {
1996          variable _debug_loclists_table_count
1997          variable _debug_loclists_addr_size
1998          variable _debug_loclists_offset_size
1999          variable _debug_loclists_is_64_dwarf
2000
2001          parse_options {
2002              {post-header-label ""}
2003              {with-offset-array true}
2004          }
2005
2006          # Count of lists in the table.
2007          variable _debug_loclists_list_count 0
2008
2009          # Generate the lists ops first, because we need to know how many
2010          # lists there are to generate the header and offset table.
2011          set lists_ops [_defer_to_string {
2012              with_override Dwarf::list_ Dwarf::_loclists_list {
2013                    uplevel $body
2014              }
2015          }]
2016
2017          set post_unit_len_label \
2018              [_compute_label "loclists_table_${_debug_loclists_table_count}_post_unit_len"]
2019          set post_header_label \
2020              [_compute_label "loclists_table_${_debug_loclists_table_count}_post_header"]
2021          set table_end_label \
2022              [_compute_label "loclists_table_${_debug_loclists_table_count}_end"]
2023
2024          # Emit the table header.
2025          if { $_debug_loclists_is_64_dwarf } {
2026              _op .4byte 0xffffffff "unit length 1/2"
2027              _op .8byte "$table_end_label - $post_unit_len_label" "unit length 2/2"
2028          } else {
2029              _op .4byte "$table_end_label - $post_unit_len_label" "unit length"
2030          }
2031
2032          define_label $post_unit_len_label
2033
2034          _op .2byte 5 "DWARF version"
2035          _op .byte $_debug_loclists_addr_size "address size"
2036          _op .byte 0 "segment selector size"
2037
2038          if { ${with-offset-array} } {
2039            _op .4byte "$_debug_loclists_list_count" "offset entry count"
2040          } else {
2041            _op .4byte 0 "offset entry count"
2042          }
2043
2044          define_label $post_header_label
2045
2046          # Define the user post-header label, if provided.
2047          if { ${post-header-label} != "" } {
2048              define_label ${post-header-label}
2049          }
2050
2051          # Emit the offset array.
2052          if { ${with-offset-array} } {
2053              for {set list_idx 0} {$list_idx < $_debug_loclists_list_count} {incr list_idx} {
2054                    set list_label [_compute_list_label $list_idx]
2055                    _op_offset $_debug_loclists_offset_size \
2056                        "$list_label - $post_header_label" \
2057                        "offset of list $list_idx"
2058              }
2059          }
2060
2061          # Emit the actual list data.
2062          _emit "$lists_ops"
2063
2064          define_label $table_end_label
2065
2066          incr _debug_loclists_table_count
2067    }
2068
2069    # Generate one loclists location list.
2070    #
2071    # This proc is meant to be used within proc _loclists_table's body.  It is
2072    # made available as `list_` while inside proc _loclists_table's body.
2073    #
2074    # BODY may call the various procs defined below to generate list
2075    # entries.  They correspond to the location list entry kinds
2076    # described in section 2.6.2 of the DWARF 5 spec.
2077    #
2078    # To define a label pointing to the beginning of the list, use
2079    # the conventional way of declaring and defining labels:
2080    #
2081    #   declare_labels the_list
2082    #
2083    #   the_list: list_ {
2084    #     ...
2085    #   }
2086
2087    proc _loclists_list { body } {
2088          variable _debug_loclists_list_count
2089
2090          # Count the location descriptions in this list.
2091          variable _debug_loclists_locdesc_count 0
2092
2093          # Define a label for this list.  It is used to build the offset
2094          # array later.
2095          set list_label [_compute_list_label $_debug_loclists_list_count]
2096          define_label $list_label
2097
2098          with_override Dwarf::start_length Dwarf::_loclists_start_length {
2099          with_override Dwarf::base_address Dwarf::_loclists_base_address {
2100          with_override Dwarf::start_end Dwarf::_loclists_start_end {
2101              uplevel $body
2102          }}}
2103
2104          # Emit end of list.
2105          _op .byte 0x00 "DW_LLE_end_of_list"
2106
2107          incr _debug_loclists_list_count
2108    }
2109
2110    # Emit a DW_LLE_start_length entry.
2111    #
2112    # This proc is meant to be used within proc _loclists_list's body.  It is
2113    # made available as `start_length` while inside proc _loclists_list's body.
2114
2115    proc _loclists_start_length { start length locdesc } {
2116          variable _debug_loclists_is_64_dwarf
2117          variable _debug_loclists_addr_size
2118          variable _debug_loclists_offset_size
2119          variable _debug_loclists_table_count
2120          variable _debug_loclists_list_count
2121          variable _debug_loclists_locdesc_count
2122
2123          set locdesc [uplevel [list subst $locdesc]]
2124
2125          _op .byte 0x08 "DW_LLE_start_length"
2126
2127          # Start and end of the address range.
2128          _op .${_debug_loclists_addr_size}byte $start "start"
2129          _op .uleb128 $length "length"
2130
2131          # Length of location description.
2132          set locdesc_start_label ".Lloclists_table_${_debug_loclists_table_count}_list_${_debug_loclists_list_count}_locdesc_${_debug_loclists_locdesc_count}_start"
2133          set locdesc_end_label ".Lloclists_table_${_debug_loclists_table_count}_list_${_debug_loclists_list_count}_locdesc_${_debug_loclists_locdesc_count}_end"
2134          _op .uleb128 "$locdesc_end_label - $locdesc_start_label" "locdesc length"
2135
2136          define_label $locdesc_start_label
2137          set dwarf_version 5
2138          _location $locdesc $dwarf_version $_debug_loclists_addr_size $_debug_loclists_offset_size
2139          define_label $locdesc_end_label
2140
2141          incr _debug_loclists_locdesc_count
2142    }
2143
2144    # Emit a DW_LLE_start_end entry.
2145    #
2146    # This proc is meant to be used within proc _loclists_list's body.  It is
2147    # made available as `start_end` while inside proc _loclists_list's body.
2148
2149    proc _loclists_start_end { start end locdesc } {
2150          variable _debug_loclists_is_64_dwarf
2151          variable _debug_loclists_addr_size
2152          variable _debug_loclists_offset_size
2153          variable _debug_loclists_table_count
2154          variable _debug_loclists_list_count
2155          variable _debug_loclists_locdesc_count
2156
2157          set locdesc [uplevel [list subst $locdesc]]
2158
2159          _op .byte 0x07 "DW_LLE_start_end"
2160
2161          # Start and end of the address range.
2162          _op .${_debug_loclists_addr_size}byte $start "start"
2163          _op .${_debug_loclists_addr_size}byte $end "end"
2164
2165          # Length of location description.
2166          set locdesc_start_label ".Lloclists_table_${_debug_loclists_table_count}_list_${_debug_loclists_list_count}_locdesc_${_debug_loclists_locdesc_count}_start"
2167          set locdesc_end_label ".Lloclists_table_${_debug_loclists_table_count}_list_${_debug_loclists_list_count}_locdesc_${_debug_loclists_locdesc_count}_end"
2168          _op .uleb128 "$locdesc_end_label - $locdesc_start_label" "locdesc length"
2169
2170          define_label $locdesc_start_label
2171          set dwarf_version 5
2172          _location $locdesc $dwarf_version $_debug_loclists_addr_size $_debug_loclists_offset_size
2173          define_label $locdesc_end_label
2174
2175          incr _debug_loclists_locdesc_count
2176    }
2177
2178    # Emit a DW_LLE_base_address entry.
2179    proc _loclists_base_address {addr} {
2180          variable _debug_loclists_addr_size
2181          variable _debug_loclists_locdesc_count
2182          _op .byte 0x06 "DW_LLE_base_address"
2183          _op .${_debug_loclists_addr_size}byte $addr "base_address"
2184          incr _debug_loclists_locdesc_count
2185    }
2186
2187    # Emit a DWARF .debug_macro section.
2188    #
2189    # BODY must be Tcl code that emits the content of the section.  It is
2190    # evaluated in the caller's context.  The body can use the `unit` proc
2191    # (see `_macro_unit`) to generate macro units.
2192
2193    proc macro { body } {
2194          _section ".debug_macro"
2195
2196          with_override Dwarf::unit Dwarf::_macro_unit {
2197              uplevel $body
2198          }
2199    }
2200
2201    # Generate one macro unit.
2202    #
2203    # This proc is meant to be used within proc macro's body.  It is made
2204    # available as `unit` while inside proc macro's body.
2205    #
2206    # BODY must be Tcl code that emits the content of the unit.  It may call
2207    # procedures defined below, prefixed with `_macro_unit_`, to generate the
2208    # unit's content.  It is evaluated in the caller's context.
2209    #
2210    # The `is-64 true|false` options tells whether to use 64-bit DWARF instead
2211    # of 32-bit DWARF.  The default is 32-bit.
2212    #
2213    # If specified, the `debug-line-offset-label` option is the name of a label
2214    # to use for the unit header's `debug_line_offset` field value.  If
2215    # omitted, the unit header will not contain the `debug_line_offset` field.
2216
2217    proc _macro_unit { options body } {
2218          parse_options {
2219              {"is-64" "false"}
2220              {"debug-line-offset-label" ""}
2221          }
2222
2223          _op .2byte 5 "version"
2224
2225          # Flags:
2226          #
2227          #   offset_size_flag           = set if is-64 is true
2228          #   debug_line_offset_flag     = set if debug-line-offset-label is set
2229          #   opcode_operands_table_flag = 0
2230          set flags 0
2231
2232          if { ${is-64} } {
2233              set flags [expr $flags | 0x1]
2234          }
2235          variable _mu_offset_size
2236          set _mu_offset_size [expr ${is-64} ? 8 : 4]
2237
2238          if { ${debug-line-offset-label} != "" } {
2239              set flags [expr $flags | 0x2]
2240          }
2241
2242          _op .byte $flags "flags"
2243
2244          if { ${debug-line-offset-label} != "" } {
2245              _op_offset [expr ${is-64} ? 8 : 4] ${debug-line-offset-label} \
2246                    "debug_line offset"
2247          }
2248
2249          with_override Dwarf::define_strp Dwarf::_macro_unit_define_strp {
2250          with_override Dwarf::define Dwarf::_macro_unit_define {
2251          with_override Dwarf::start_file Dwarf::_macro_unit_start_file {
2252          with_override Dwarf::end_file Dwarf::_macro_unit_end_file {
2253              uplevel $body
2254          }}}}
2255
2256          _op .byte 0x0 "# End macro unit"
2257    }
2258
2259    # Emit a DW_MACRO_define entry.
2260
2261    proc _macro_unit_define { lineno text } {
2262          _op .byte 0x1 "DW_MACRO_define"
2263          _op .uleb128 $lineno "Line number"
2264          _op .asciz "\"$text\"" "Macro definition"
2265    }
2266
2267    # Emit a DW_MACRO_define_strp entry.
2268
2269    proc _macro_unit_define_strp { lineno text } {
2270          _op .byte 0x5 "DW_MACRO_define_strp"
2271          _op .uleb128 $lineno "Line number"
2272
2273          variable _strings
2274          variable _mu_offset_size
2275
2276          if {![info exists _strings($text)]} {
2277              set _strings($text) [new_label strp]
2278              _defer_output .debug_str {
2279                    define_label $_strings($text)
2280                    _op .ascii [_quote $text]
2281              }
2282          }
2283
2284          _op_offset $_mu_offset_size "$_strings($text)" "strp: $text"
2285    }
2286
2287    # Emit a DW_MACRO_start_file entry.
2288
2289    proc _macro_unit_start_file { lineno file_idx } {
2290          _op .byte 0x3 "DW_MACRO_start_file"
2291          _op .uleb128 $lineno
2292          _op .uleb128 $file_idx
2293    }
2294
2295    # Emit a DW_MACRO_end_file entry.
2296
2297    proc _macro_unit_end_file {} {
2298          _op .byte 0x4 "DW_MACRO_end_file"
2299    }
2300
2301    # Emit a DWARF .debug_line unit.
2302    # OPTIONS is a list with an even number of elements containing
2303    # option-name and option-value pairs.
2304    # Current options are:
2305    # is_64 0|1    - boolean indicating if you want to emit 64-bit DWARF
2306    #                default = 0 (32-bit)
2307    # version n    - DWARF version number to emit
2308    #                default = 4
2309    # addr_size n  - the size of addresses in bytes: 4, 8, or default
2310    #                default = default
2311    # seg_sel_size n
2312    #              - the size of segment selector_size in bytes:
2313    #                default = 0
2314    #
2315    # LABEL is the label of the current unit (which is probably
2316    # referenced by a DW_AT_stmt_list), or "" if there is no such
2317    # label.
2318    #
2319    # BODY is Tcl code that emits the parts which make up the body of
2320    # the line unit.  It is evaluated in the caller's context.  The
2321    # following commands are available for the BODY section:
2322    #
2323    #   include_dir "dirname" -- adds a new include directory
2324    #
2325    #   file_name "file.c" idx -- adds a new file name.  IDX is a
2326    #   1-based index referencing an include directory or 0 for
2327    #   current directory.
2328
2329    proc lines {options label body} {
2330          variable _line_count
2331          variable _line_include_dirs
2332          variable _line_file_names
2333          variable _line_header_finalized
2334          variable _line_header_end_label
2335          variable _line_unit_version
2336          variable _line_is_64
2337          variable _line_string_form
2338
2339          # Establish the defaults.
2340          set _line_is_64 0
2341          set _line_unit_version 4
2342          set _unit_addr_size default
2343          set _line_include_dirs {}
2344          set _line_file_names {}
2345          set _line_header_finalized 0
2346          set _default_is_stmt 1
2347          set _seg_sel_size 0
2348          #set _line_string_form string
2349          set _line_string_form line_strp
2350
2351          foreach { name value } $options {
2352              switch -exact -- $name {
2353                    is_64 { set _line_is_64 $value }
2354                    version { set _line_unit_version $value }
2355                    addr_size { set _unit_addr_size $value }
2356                    seg_sel_size { set _seg_sel_size $value }
2357                    default_is_stmt { set _default_is_stmt $value }
2358                    string_form { set _line_string_form $value }
2359                    default { error "unknown option $name" }
2360              }
2361          }
2362          if {$_unit_addr_size == "default"} {
2363              if {[is_64_target]} {
2364                    set _unit_addr_size 8
2365              } else {
2366                    set _unit_addr_size 4
2367              }
2368          }
2369
2370          set unit_num [incr _line_count]
2371
2372          set section ".debug_line"
2373          _section $section
2374
2375          if { "$label" != "" } {
2376              # Define the user-provided label at this point.
2377              $label:
2378          }
2379
2380          set unit_len_label [_compute_label "line${_line_count}_start"]
2381          set unit_end_label [_compute_label "line${_line_count}_end"]
2382          set header_len_label [_compute_label "line${_line_count}_header_start"]
2383          set _line_header_end_label [_compute_label "line${_line_count}_header_end"]
2384
2385          if {$_line_is_64} {
2386              _op .4byte 0xffffffff
2387              _op .8byte "$unit_end_label - $unit_len_label" "unit_length"
2388          } else {
2389              _op .4byte "$unit_end_label - $unit_len_label" "unit_length"
2390          }
2391
2392          define_label $unit_len_label
2393
2394          _op .2byte $_line_unit_version version
2395
2396          if { $_line_unit_version >= 5 } {
2397              _op .byte $_unit_addr_size "address_size"
2398              # Hardcode to 0 for now.
2399              _op .byte $_seg_sel_size "seg_sel_size"
2400          }
2401
2402          if {$_line_is_64} {
2403              _op .8byte "$_line_header_end_label - $header_len_label" "header_length"
2404          } else {
2405              _op .4byte "$_line_header_end_label - $header_len_label" "header_length"
2406          }
2407
2408          define_label $header_len_label
2409
2410          _op .byte 1 "minimum_instruction_length"
2411          if { $_line_unit_version >= 4 } {
2412              # Assume non-VLIW for now.
2413              _op .byte 1 "maximum_operations_per_instruction"
2414          }
2415          _op .byte $_default_is_stmt "default_is_stmt"
2416          _op .byte 1 "line_base"
2417          _op .byte 1 "line_range"
2418          _op .byte 12 "opcode_base"
2419
2420          # The standard_opcode_lengths table.  The number of arguments
2421          # for each of the standard opcodes.  Generating 11 entries here
2422          # matches the use of 12 in the opcode_base above.  These 10
2423          # entries match the 9 standard opcodes for DWARF2 plus
2424          # DW_LNS_prologue_end and DW_LNS_epilogue_begin from DWARF3.
2425          _op .byte 0 "standard opcode 1"
2426          _op .byte 1 "standard opcode 2"
2427          _op .byte 1 "standard opcode 3"
2428          _op .byte 1 "standard opcode 4"
2429          _op .byte 1 "standard opcode 5"
2430          _op .byte 0 "standard opcode 6"
2431          _op .byte 0 "standard opcode 7"
2432          _op .byte 0 "standard opcode 8"
2433          _op .byte 1 "standard opcode 9"
2434          _op .byte 0 "standard opcode 10"
2435          _op .byte 0 "standard opcode 11"
2436
2437          # Add a directory entry to the line table header's directory table.
2438          #
2439          # Return the index by which this entry can be referred to.
2440          proc include_dir {dirname} {
2441              variable _line_include_dirs
2442              lappend _line_include_dirs $dirname
2443
2444              if { $Dwarf::_line_unit_version >= 5 } {
2445                    return [expr [llength $_line_include_dirs] - 1]
2446              } else {
2447                    return [llength $_line_include_dirs]
2448              }
2449          }
2450
2451          # Add a file name entry to the line table header's file names table.
2452          #
2453          # Return the index by which this entry can be referred to.
2454          proc file_name {filename diridx} {
2455              variable _line_file_names
2456              lappend _line_file_names $filename $diridx
2457
2458              set nr_filenames [expr [llength $_line_file_names] / 2]
2459              if { $Dwarf::_line_unit_version >= 5 } {
2460                    return [expr $nr_filenames - 1]
2461              } else {
2462                    return $nr_filenames
2463              }
2464          }
2465
2466          proc _line_finalize_header {} {
2467              variable _line_header_finalized
2468              if { $_line_header_finalized } {
2469                    return
2470              }
2471              set _line_header_finalized 1
2472
2473              variable _line_include_dirs
2474              variable _line_file_names
2475
2476              variable _line_unit_version
2477              variable _line_is_64
2478              variable _line_string_form
2479              if { $_line_unit_version >= 5 } {
2480                    _op .byte 1 "directory_entry_format_count"
2481                    _op .uleb128 1 \
2482                        "directory_entry_format (content type code: DW_LNCT_path)"
2483                    switch $_line_string_form {
2484                        string {
2485                              _op .uleb128 0x08 \
2486                                  "directory_entry_format (form: DW_FORM_string)"
2487                        }
2488                        line_strp {
2489                              _op .uleb128 0x1f \
2490                                  "directory_entry_format (form: DW_FORM_line_strp)"
2491                        }
2492                    }
2493
2494                    set nr_dirs [llength $_line_include_dirs]
2495                    _op .byte $nr_dirs "directory_count"
2496
2497                    foreach dirname $_line_include_dirs {
2498                        switch $_line_string_form {
2499                              string {
2500                                  _op .ascii [_quote $dirname]
2501                              }
2502                              line_strp {
2503                                  declare_labels string_ptr
2504                                  _defer_output .debug_line_str {
2505                                        string_ptr:
2506                                        _op .ascii [_quote $dirname]
2507                                  }
2508                                  _op_offset [expr $_line_is_64 ? 8 : 4] $string_ptr
2509                              }
2510                        }
2511                    }
2512
2513                    _op .byte 2 "file_name_entry_format_count"
2514                    _op .uleb128 1 \
2515                        "file_name_entry_format (content type code: DW_LNCT_path)"
2516                    switch $_line_string_form {
2517                        string {
2518                              _op .uleb128 0x08 \
2519                                  "directory_entry_format (form: DW_FORM_string)"
2520                        }
2521                        line_strp {
2522                              _op .uleb128 0x1f \
2523                                  "directory_entry_format (form: DW_FORM_line_strp)"
2524                        }
2525                    }
2526                    _op .uleb128 2 \
2527                        "file_name_entry_format (content type code: DW_LNCT_directory_index)"
2528                    _op .uleb128 0x0f \
2529                        "file_name_entry_format (form: DW_FORM_udata)"
2530
2531                    set nr_files [expr [llength $_line_file_names] / 2]
2532                    _op .byte $nr_files "file_names_count"
2533
2534                    foreach { filename diridx } $_line_file_names {
2535                        switch $_line_string_form {
2536                              string {
2537                                  _op .ascii [_quote $filename]
2538                              }
2539                              line_strp {
2540                                  declare_labels string_ptr
2541                                  _defer_output .debug_line_str {
2542                                        string_ptr:
2543                                        _op .ascii [_quote $filename]
2544                                  }
2545                                  _op_offset [expr $_line_is_64 ? 8 : 4] $string_ptr
2546                              }
2547                        }
2548                        _op .uleb128 $diridx
2549                    }
2550              } else {
2551                    foreach dirname $_line_include_dirs {
2552                        _op .ascii [_quote $dirname]
2553                    }
2554
2555                    _op .byte 0 "Terminator (include_directories)"
2556
2557                    foreach { filename diridx } $_line_file_names {
2558                        _op .ascii [_quote $filename]
2559                        _op .sleb128 $diridx
2560                        _op .sleb128 0 "mtime"
2561                        _op .sleb128 0 "length"
2562                    }
2563
2564                    _op .byte 0 "Terminator (file_names)"
2565              }
2566
2567              set _line_include_dirs {}
2568              set _line_file_names {}
2569
2570              variable _line_header_end_label
2571              define_label $_line_header_end_label
2572          }
2573
2574          proc program { body } {
2575              variable _line_header_end_label
2576              variable _line
2577              variable _line_address_update
2578              variable _line_program_terminated
2579
2580
2581              set _line 1
2582              set _line_address_update 0
2583              set _line_program_terminated 0
2584
2585              _line_finalize_header
2586
2587              proc DW_LNE_set_address {addr} {
2588                    variable _line_address_update
2589                    set _line_address_update 1
2590                    variable _line_program_terminated
2591                    set _line_program_terminated 0
2592                    _op .byte 0
2593                    set start [new_label "set_address_start"]
2594                    set end [new_label "set_address_end"]
2595                    _op .uleb128 "${end} - ${start}"
2596                    define_label ${start}
2597                    _op .byte 2
2598                    if {[is_64_target]} {
2599                        _op .8byte ${addr}
2600                    } else {
2601                        _op .4byte ${addr}
2602                    }
2603                    define_label ${end}
2604              }
2605
2606              proc DW_LNE_end_sequence {} {
2607                    variable _line_address_update
2608                    if { $_line_address_update == 0 } {
2609                        error "Missing address update for end_sequence"
2610                    }
2611                    set _line_address_update 0
2612                    variable _line_program_terminated
2613                    set _line_program_terminated 1
2614                    variable _line
2615                    _op .byte 0
2616                    _op .uleb128 1
2617                    _op .byte 1
2618                    set _line 1
2619              }
2620
2621              proc DW_LNE_user { len opcode } {
2622                    variable _line_program_terminated
2623                    set _line_program_terminated 0
2624                    set DW_LNE_lo_usr 0x80
2625                    set DW_LNE_hi_usr 0xff
2626                    if { $DW_LNE_lo_usr <= $opcode
2627                         && $opcode <= $DW_LNE_hi_usr } {
2628                        _op .byte 0
2629                        _op .uleb128 $len
2630                        _op .byte $opcode
2631                        for {set i 1} {$i < $len} {incr i} {
2632                              _op .byte 0
2633                        }
2634                    } else {
2635                        error "unknown vendor specific extended opcode: $opcode"
2636                    }
2637              }
2638
2639              proc DW_LNS_copy {} {
2640                    variable _line_address_update
2641                    if { $_line_address_update == 0 } {
2642                        error "Missing address update for copy"
2643                    }
2644                    set _line_address_update 0
2645                    variable _line_program_terminated
2646                    set _line_program_terminated 0
2647                    _op .byte 1
2648              }
2649
2650              proc DW_LNS_negate_stmt {} {
2651                    variable _line_program_terminated
2652                    set _line_program_terminated 0
2653                    _op .byte 6
2654              }
2655
2656              proc DW_LNS_set_prologue_end {} {
2657                    variable _line_program_terminated
2658                    set _line_program_terminated 0
2659                    _op .byte 0x0a
2660              }
2661
2662              proc DW_LNS_set_epilogue_begin {} {
2663                    variable _line_program_terminated
2664                    set _line_program_terminated 0
2665                    _op .byte 0x0b
2666              }
2667
2668              proc DW_LNS_advance_pc {offset} {
2669                    variable _line_program_terminated
2670                    set _line_program_terminated 0
2671                    variable _line_address_update
2672                    set _line_address_update 1
2673                    _op .byte 2
2674                    _op .uleb128 ${offset}
2675              }
2676
2677              proc DW_LNS_advance_line {offset} {
2678                    variable _line_program_terminated
2679                    set _line_program_terminated 0
2680                    variable _line
2681                    _op .byte 3
2682                    _op .sleb128 ${offset}
2683                    set _line [expr $_line + $offset]
2684              }
2685
2686              # A pseudo line number program instruction, that can be used instead
2687              # of DW_LNS_advance_line.  Rather than writing:
2688              #   {DW_LNS_advance_line [expr $line1 - 1]}
2689              #   {DW_LNS_advance_line [expr $line2 - $line1]}
2690              #   {DW_LNS_advance_line [expr $line3 - $line2]}
2691              # we can just write:
2692              #   {line $line1}
2693              #   {line $line2}
2694              #   {line $line3}
2695              proc line {line} {
2696                    variable _line
2697                    set offset [expr $line - $_line]
2698                    DW_LNS_advance_line $offset
2699              }
2700
2701              proc DW_LNS_set_file {num} {
2702                    variable _line_program_terminated
2703                    set _line_program_terminated 0
2704                    _op .byte 4
2705                    _op .sleb128 ${num}
2706              }
2707
2708              uplevel $body
2709
2710              if { $_line_program_terminated == 0 } {
2711                    error "Missing end_seq"
2712              }
2713          }
2714
2715          uplevel $body
2716
2717          rename include_dir ""
2718          rename file_name ""
2719
2720          _line_finalize_header
2721
2722          define_label $unit_end_label
2723    }
2724
2725    # Emit a DWARF .debug_aranges entry.
2726
2727    proc arange { options arange_start arange_length } {
2728          parse_options {
2729              { comment "" }
2730              { seg_sel "" }
2731          }
2732
2733          if { $comment != "" } {
2734              # Wrap
2735              set comment " ($comment)"
2736          }
2737
2738          if { $seg_sel != "" } {
2739              variable _seg_size
2740              if { $_seg_size == 8 } {
2741                    set seg_op .8byte
2742              } elseif { $_seg_size == 4 } {
2743                    set seg_op .4byte
2744              } else {
2745                    error \
2746                        "Don't know how to handle segment selector size $_seg_size"
2747              }
2748              _op $seg_op $seg_sel "Address range segment selector$comment"
2749          }
2750
2751          variable _addr_size
2752          if { $_addr_size == 8 } {
2753              set addr_op .8byte
2754          } elseif { $_addr_size == 4 } {
2755              set addr_op .4byte
2756          }
2757
2758          _op $addr_op $arange_start "Address range start$comment"
2759          _op $addr_op $arange_length "Address range length$comment"
2760    }
2761
2762    # Emit a DWARF .debug_aranges unit.
2763    #
2764    # OPTIONS is a list with an even number of elements containing
2765    # option-name and option-value pairs.
2766    # Current options are:
2767    # is_64 0|1    - boolean indicating if you want to emit 64-bit DWARF
2768    #                default = 0 (32-bit)
2769    # cu_is_64 0|1 - boolean indicating if LABEL refers to a 64-bit DWARF CU
2770    #                default = 0 (32-bit)
2771    # section_version n
2772    #                - section version number to emit
2773    #                default = 2
2774    # seg_size n   - the size of the adress selector in bytes: 0, 4, or 8
2775    #                default = 0
2776    #
2777    # LABEL is the label of the corresponding CU.
2778    #
2779    # BODY is Tcl code that emits the parts which make up the body of
2780    # the aranges unit.  It is evaluated in the caller's context.  The
2781    # following commands are available for the BODY section:
2782    #
2783    #   arange [-c <comment>] [<segment selector>] <start> <length>
2784    #     -- adds an address range.
2785
2786    proc aranges { options label body } {
2787          variable _addr_size
2788          variable _seg_size
2789
2790          # Handle options.
2791          parse_options {
2792              { is_64 0 }
2793              { cu_is_64 0 }
2794              { section_version 2 }
2795              { seg_size 0 }
2796          }
2797          set _seg_size $seg_size
2798
2799          if { [is_64_target] } {
2800              set _addr_size 8
2801          } else {
2802              set _addr_size 4
2803          }
2804
2805          # Switch to .debug_aranges section.
2806          _section .debug_aranges
2807
2808          # Keep track of offset from start of section entry to determine
2809          # padding amount.
2810          set offset 0
2811
2812          # Initial length.
2813          declare_labels aranges_start aranges_end
2814          set length "$aranges_end - $aranges_start"
2815          set comment "Length"
2816          if { $is_64 } {
2817              _op .4byte 0xffffffff
2818              _op .8byte $length $comment
2819              incr offset 12
2820          } else {
2821              _op .4byte $length $comment
2822              incr offset 4
2823          }
2824
2825          # Start label.
2826          aranges_start:
2827
2828          # Section version.
2829          _op .2byte $section_version "Section version"
2830          incr offset 2
2831
2832          # Offset into .debug_info.
2833          upvar $label my_label
2834          if { $cu_is_64 } {
2835              _op .8byte $my_label "Offset into .debug_info"
2836              incr offset 8
2837          } else {
2838              _op .4byte $my_label "Offset into .debug_info"
2839              incr offset 4
2840          }
2841
2842          # Address size.
2843          _op .byte $_addr_size "Address size"
2844          incr offset
2845
2846          # Segment selector size.
2847          _op .byte $_seg_size "Segment selector size"
2848          incr offset
2849
2850          # Padding.
2851          set tuple_size [expr 2 * $_addr_size + $_seg_size]
2852          while { 1 } {
2853              if { [expr $offset % $tuple_size] == 0 } {
2854                    break
2855              }
2856              _op .byte 0 "Pad to $tuple_size byte boundary"
2857              incr offset
2858          }
2859
2860          # Range tuples.
2861          uplevel $body
2862
2863          # Terminator tuple.
2864          set comment "Terminator"
2865          if { $_seg_size == 0 } {
2866              arange {comment $comment} 0 0
2867          } else {
2868              arange {comment $comment seg_sel 0} 0 0
2869          }
2870
2871          # End label.
2872          aranges_end:
2873    }
2874
2875    # Emit a .debug_loc entry.
2876
2877    proc _loc_entry { start end location_description } {
2878          # Determine how to emit addresses.
2879          variable _addr_size
2880          if { $_addr_size == 8 } {
2881              set addr_op .8byte
2882          } elseif { $_addr_size == 4 } {
2883              set addr_op .4byte
2884          }
2885
2886          # Emit start and end address.
2887          _op $addr_op $start "Start address"
2888          _op $addr_op $end "End address"
2889
2890          declare_labels location_description_start
2891          declare_labels location_description_end
2892
2893          # Emit length of location description.
2894          set len "$location_description_end - $location_description_start"
2895          _op .2byte $len "Location description length"
2896
2897          # Tag start of location description.
2898          define_label $location_description_start
2899
2900          # Emit location description.
2901          variable _cu_version
2902          variable _cu_offset_size
2903          _location $location_description $_cu_version $_addr_size \
2904              $_cu_offset_size
2905
2906          # Tag end of location description.
2907          define_label $location_description_end
2908    }
2909
2910    # Emit a DWARF .debug_loc contribution.
2911    #
2912    # OPTIONS is a list with an even number of elements containing
2913    # option-name and option-value pairs.
2914    # Current options are:
2915    # cu_is_64 0|1 - boolean indicating if references from location
2916    #                descriptions refer to a 64-bit DWARF CU.
2917    #                default = 0 (32-bit)
2918    # cu_version n - section version of DWARF CU referenced from location
2919    #                descriptions.
2920    #                default = 4
2921    #
2922    # BODY is Tcl code that emits the parts which make up the body of
2923    # the debug_loc contribution.  It is evaluated in the caller's context.
2924    # The following command is available for the BODY section:
2925    #
2926    #   entry <start> <end> <location description>
2927    #     -- emit a .debug_loc entry
2928
2929    proc loc { options body } {
2930          # Handle options.
2931          parse_options {
2932              { cu_version 4 }
2933              { cu_is_64 0 }
2934          }
2935
2936          # Export for use in BODY.
2937          variable _addr_size
2938          if { [is_64_target] } {
2939              set _addr_size 8
2940          } else {
2941              set _addr_size 4
2942          }
2943          variable _cu_version
2944          set _cu_version $cu_version
2945          variable _cu_offset_size
2946          if { $cu_is_64 == 1 } {
2947              set _cu_offset_size 8
2948          } else {
2949              set _cu_offset_size 4
2950          }
2951
2952          # Switch to .debug_loc section.
2953          _section .debug_loc
2954
2955          # Introduce command 'entry'.
2956          with_override Dwarf::entry Dwarf::_loc_entry {
2957              # Emit entries.
2958              uplevel $body
2959          }
2960
2961          # Determine how to emit addresses.
2962          if { $_addr_size == 8 } {
2963              set addr_op .8byte
2964          } elseif { $_addr_size == 4 } {
2965              set addr_op .4byte
2966          }
2967
2968          # Emit <End of list>.
2969          set comment "<End of list>"
2970          _op $addr_op 0 "$comment (Part 1/2)"
2971          _op $addr_op 0 "$comment (Part 2/2)"
2972    }
2973
2974    proc _empty_array {name} {
2975          upvar $name the_array
2976
2977          catch {unset the_array}
2978          set the_array(_) {}
2979          unset the_array(_)
2980    }
2981
2982    # Emit a .gnu_debugaltlink section with the given file name and
2983    # build-id.  The buildid should be represented as a hexadecimal
2984    # string, like "ffeeddcc".
2985    proc gnu_debugaltlink {filename buildid} {
2986          _defer_output .gnu_debugaltlink {
2987              _op .ascii [_quote $filename]
2988              foreach {a b} [split $buildid {}] {
2989                    _op .byte 0x$a$b
2990              }
2991          }
2992    }
2993
2994    proc _note {type name hexdata} {
2995          set namelen [expr [string length $name] + 1]
2996
2997          # Name size.
2998          _op .4byte $namelen
2999          # Data size.
3000          _op .4byte [expr [string length $hexdata] / 2]
3001          # Type.
3002          _op .4byte $type
3003          # The name.
3004          _op .ascii [_quote $name]
3005          # Alignment.
3006          set align 2
3007          set total [expr {($namelen + (1 << $align) - 1) & -(1 << $align)}]
3008          for {set i $namelen} {$i < $total} {incr i} {
3009              _op .byte 0
3010          }
3011          # The data.
3012          foreach {a b} [split $hexdata {}] {
3013              _op .byte 0x$a$b
3014          }
3015    }
3016
3017    # Emit a note section holding the given build-id.
3018    proc build_id {buildid} {
3019          _defer_output {.note.gnu.build-id a note} {
3020              # From elf/common.h.
3021              set NT_GNU_BUILD_ID 3
3022
3023              _note $NT_GNU_BUILD_ID GNU $buildid
3024          }
3025    }
3026
3027    # Emit a dummy CU.
3028    proc dummy_cu {} {
3029          # Generate a CU with default options and empty body.
3030          cu {label dummy_cu} {
3031            compile_unit {}
3032          }
3033
3034          # Generate an .debug_aranges entry for the dummy CU.
3035          aranges {} dummy_cu {
3036          }
3037    }
3038
3039    # Emit a DWARF .debug_names section.
3040    #
3041    # OPTIONS is a list with an even number of elements containing
3042    # option-name and option-value pairs.
3043    # Current options are:
3044    # is_64 0|1 - boolean indicating if the section contains 64-bit DWARF.
3045    #             default = 0 (32-bit)
3046    # version n - section version.
3047    #             default = 5.
3048    #
3049    # BODY is Tcl code that emits the parts which make up the body of
3050    # the .debug_names section.  It is evaluated in the caller's context.
3051    # The following commands are available for the BODY section:
3052    #
3053    #   cu <cu-label>
3054    #     -- add a CU.
3055    #
3056    #   name <name> <tag> <cu> <hash>
3057    #     -- add a name.
3058
3059    proc debug_names { options body } {
3060          global decimal
3061
3062          parse_options {
3063              { is_64 0 }
3064              { version 5 }
3065          }
3066
3067          variable _debug_names_offset_size
3068          if { $is_64 == 1 } {
3069              set _debug_names_offset_size 8
3070          } else {
3071              set _debug_names_offset_size 4
3072          }
3073
3074          # Section start.
3075          set section ".debug_names"
3076          _section $section
3077
3078          # Header - initial length.
3079          declare_labels debug_names_start debug_names_end
3080          set length "$debug_names_end - $debug_names_start"
3081          set comment "Initial_length"
3082          if { $is_64 } {
3083              _op .4byte 0xffffffff
3084              _op .8byte $length $comment
3085          } else {
3086              _op .4byte $length $comment
3087          }
3088
3089          # Header - start label.
3090          debug_names_start:
3091
3092          # Header - version + padding.
3093          _op .2byte $version "Version"
3094          _op .2byte 0 "Padding"
3095
3096          # Parse the body.
3097          variable _debug_names_cus
3098          set _debug_names_cus []
3099          proc _debug_names_cu { cu } {
3100              variable _debug_names_cus
3101              lappend _debug_names_cus $cu
3102          }
3103       variable _debug_names_tus
3104       set _debug_names_tus []
3105       proc _debug_names_tu { tu } {
3106             variable _debug_names_tus
3107             lappend _debug_names_tus $tu
3108       }
3109          variable _debug_names
3110          set _debug_names []
3111          proc _debug_names_name { name tag cu hash } {
3112              variable _debug_names
3113              declare_labels entry_pool_offset
3114              lappend _debug_names [list $name $tag $cu $hash $entry_pool_offset]
3115          }
3116          with_override Dwarf::cu Dwarf::_debug_names_cu {
3117          with_override Dwarf::tu Dwarf::_debug_names_tu {
3118          with_override Dwarf::name Dwarf::_debug_names_name {
3119              uplevel $body
3120          }}}
3121
3122          # Header - CU / TU / foreign TU count.
3123          _op .4byte [llength $_debug_names_cus] "Comp_unit_count"
3124          _op .4byte [llength $_debug_names_tus] "Local_type_unit_count"
3125          _op .4byte 0 "Foreign_type_unit_count"
3126
3127          # Header - bucket count.
3128          _op .4byte 1 "Bucket_count"
3129
3130          # Header - name count.
3131          _op .4byte [llength $_debug_names] "Name_count"
3132
3133          # Header - abbreviation table size.
3134          declare_labels debug_names_abbrev_table_start \
3135              debug_names_abbrev_table_end
3136          set abbrev_table_size \
3137              "$debug_names_abbrev_table_end - $debug_names_abbrev_table_start"
3138          _op .4byte $abbrev_table_size "Abbrev_table_size"
3139
3140          # Header - augmentation string.
3141          _op .4byte 8 "Augmentation_string_size"
3142          _op .ascii [_quote GDB2] "Augmentation_string"
3143          _op .byte 0
3144          _op .byte 0
3145          _op .byte 0
3146
3147          # List of CUs.
3148          set comment "CU offset"
3149          foreach cu $_debug_names_cus {
3150              upvar $cu tmp
3151              if { $is_64 } {
3152                    _op .8byte $tmp $comment
3153              } else {
3154                    _op .4byte $tmp $comment
3155              }
3156          }
3157
3158          # List of Local TUs.
3159          set comment "TU offset"
3160          foreach tu $_debug_names_tus {
3161              upvar $tu tmp
3162              if { $is_64 } {
3163                    _op .8byte $tmp $comment
3164              } else {
3165                    _op .4byte $tmp $comment
3166              }
3167          }
3168
3169          # List of Foreign TUs.
3170          #
3171
3172          # Hash Lookup Table - array of buckets.
3173          _op .4byte 1 "bucket: hash array index 1"
3174
3175          # Hash Lookup Table - array of hashes.
3176          foreach idx $_debug_names {
3177              set name [lindex $idx 0]
3178              set hash [lindex $idx 3]
3179              _op .4byte $hash "hash: $name"
3180          }
3181
3182          # Name Table - array of string offsets.
3183          foreach idx $_debug_names {
3184              set name [lindex $idx 0]
3185
3186              variable _strings
3187              if {![info exists _strings($name)]} {
3188                    set _strings($name) [new_label strp]
3189                    _defer_output .debug_str {
3190                        define_label $_strings($name)
3191                        _op .ascii [_quote $name]
3192                    }
3193              }
3194
3195              _op_offset $_debug_names_offset_size $_strings($name) "name: $name"
3196          }
3197
3198          # Name Table - array of entry offsets.
3199          set base_label ""
3200          foreach idx $_debug_names {
3201              set name [lindex $idx 0]
3202              set label [lindex $idx 4]
3203              if { [string equal $base_label ""]} {
3204                    set base_label $label
3205              }
3206              _op_offset $_debug_names_offset_size "$label - $base_label" \
3207                    "entry pool offset: $name"
3208          }
3209
3210          # Abbreviations Table.
3211          debug_names_abbrev_table_start:
3212          set abbrev 1
3213          variable _constants
3214          foreach idx $_debug_names {
3215              set name [lindex $idx 0]
3216              set tag [lindex $idx 1]
3217              set cu [lindex $idx 2]
3218
3219              if { [regexp "^CU-($decimal)$" $cu dummy cu_index] } {
3220                    set attr_name compile_unit
3221                    set attr_val 1
3222              } elseif { [regexp "^TU-($decimal)$" $cu dummy cu_index] } {
3223                    set attr_name type_unit
3224                    set attr_val 2
3225              } else {
3226                    set cu_index [lsearch -exact $_debug_names_cus $cu]
3227                    if { $cu_index == -1 } {
3228                        set attr_name type_unit
3229                        set attr_val 2
3230                    } else {
3231                        set attr_name compile_unit
3232                        set attr_val 1
3233                    }
3234              }
3235
3236              _op .byte $abbrev "abbrev $abbrev"
3237              _op .uleb128 $_constants(DW_TAG_$tag) "DW_TAG_$tag"
3238              _op .byte $attr_val  "DW_IDX_$attr_name (attribute)"
3239              _op .byte 0x0f "DW_FORM_udata (form)"
3240              _op .byte 0  "abbrev terminator (attribute)"
3241              _op .byte 0  "abbrev terminator (form)"
3242              incr abbrev
3243          }
3244          _op .byte 0 "Abbreviations Table terminator"
3245          debug_names_abbrev_table_end:
3246
3247          # Entry Pool
3248          set abbrev 1
3249          foreach idx $_debug_names {
3250              set name [lindex $idx 0]
3251              set cu [lindex $idx 2]
3252              set label [lindex $idx 4]
3253
3254              if { [regexp "^CU-($decimal)$" $cu dummy cu_index] } {
3255                    set comment "$name: CU index"
3256              } elseif { [regexp "^TU-($decimal)$" $cu dummy cu_index] } {
3257                    set comment "$name: TU index"
3258              } else {
3259                    set cu_index [lsearch -exact $_debug_names_cus $cu]
3260                    if { $cu_index == -1 } {
3261                        set cu_index [lsearch -exact $_debug_names_tus $cu]
3262                        set comment "$name: TU index"
3263                    } else {
3264                        set comment "$name: CU index"
3265                    }
3266              }
3267              define_label $label
3268              _op .byte $abbrev "$name: abbrev"
3269              _op .uleb128 $cu_index $comment
3270              _op .byte 0 "$name: terminator"
3271              incr abbrev
3272          }
3273
3274          # Section end.
3275          debug_names_end:
3276    }
3277
3278    # The top-level interface to the DWARF assembler.
3279    # OPTIONS is a list with an even number of elements containing
3280    # option-name and option-value pairs.
3281    # Current options are:
3282    # filename <string>
3283    #           - the name of the file where the generated assembly
3284    #             code is written.
3285    #             default = "".
3286    # file_id <tcl channel identifier>
3287    #           - open file where the generated assemble core is written.
3288    #             default = "".
3289    #  add_dummy_cus <0|1>
3290    #           - Whether to add dummy CUs before and after the CUs
3291    #             added in the BODY.
3292    #             default = 1.
3293    # As a special case, if OPTIONS is a list of length 1, it's
3294    # interpreted as specifing the filename.
3295    # BODY is Tcl code to emit the assembly.  It is evaluated via
3296    # "eval" -- not uplevel as you might expect, because it is
3297    # important to run the body in the Dwarf namespace.
3298    #
3299    # A typical invocation is something like:
3300    #    Dwarf::assemble $file {
3301    #        cu 0 2 8 {
3302    #            compile_unit {
3303    #            ...
3304    #            }
3305    #        }
3306    #        cu 0 2 8 {
3307    #        ...
3308    #        }
3309    #    }
3310    proc assemble {options body} {
3311          variable _initialized
3312          variable _output_file
3313          variable _deferred_output
3314          variable _defer
3315          variable _label_num
3316          variable _strings
3317          variable _cu_count
3318          variable _line_count
3319          variable _line_header_end_label
3320          variable _debug_ranges_64_bit
3321          variable _debug_addr_index
3322
3323          if { [llength $options] == 1 } {
3324              set options [list filename [lindex $options 0]]
3325          }
3326
3327          parse_options {
3328              { filename "" }
3329              { file_id "" }
3330              { add_dummy_cus 1 }
3331          }
3332
3333          if {!$_initialized} {
3334              _read_constants
3335              set _initialized 1
3336          }
3337
3338          if { $file_id != "" } {
3339              set _output_file $file_id
3340          } else {
3341              set _output_file [open $filename w]
3342          }
3343
3344          set _cu_count -1
3345          _empty_array _deferred_output
3346          set _defer ""
3347          set _label_num 0
3348          _empty_array _strings
3349
3350          set _line_count 0
3351          set _debug_ranges_64_bit [is_64_target]
3352
3353          set _debug_addr_index 0
3354
3355          # Dummy CU at the start to ensure that the first CU in $body is not
3356          # the first in .debug_info.
3357          if { $add_dummy_cus } {
3358              dummy_cu
3359          }
3360
3361          with_shared_gdb {
3362              # Not "uplevel" here, because we want to evaluate in this
3363              # namespace.  This is somewhat bad because it means we can't
3364              # readily refer to outer variables.
3365              eval $body
3366          }
3367
3368          # Dummy CU at the end to ensure that the last CU in $body is not
3369          # the last in .debug_info.
3370          if { $add_dummy_cus } {
3371              dummy_cu
3372          }
3373
3374          _write_deferred_output
3375
3376          _section .note.GNU-stack "" progbits
3377
3378          if { $file_id == "" } {
3379              catch {close $_output_file}
3380          }
3381          set _output_file {}
3382    }
3383}
3384