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