1 # Expect script for creating PDB files when linking.
2 # Copyright (C) 2022-2024 Free Software Foundation, Inc.
4 # This file is part of the GNU Binutils.
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 if {![istarget i*86-*-mingw*]
22 && ![istarget i*86-*-cygwin*]
23 && ![istarget i*86-*-winnt]
24 && ![istarget i*86-*-pe]
25 && ![istarget x86_64-*-mingw*]
26 && ![istarget x86_64-*-pe*]
27 && ![istarget x86_64-*-cygwin]
28 && ![istarget aarch64-*-mingw*]
29 && ![istarget aarch64-*-pe*]} {
33 proc get_pdb_name { pe } {
36 set exec_output [run_host_cmd "$OBJDUMP" "-p $pe"]
38 if ![regexp -line "^\\(format RSDS signature (\[0-9a-fA-F\]{32}) age 1 pdb (.*)\\)$" $exec_output full sig pdb] {
45 proc get_pdb_guid { pe } {
48 set exec_output [run_host_cmd "$OBJDUMP" "-p $pe"]
50 if ![regexp -line "^\\(format RSDS signature (\[0-9a-fA-F\]{32}) age 1 pdb (.*)\\)$" $exec_output full sig pdb] {
57 proc check_pdb_info_stream { pdb guid } {
60 set exec_output [run_host_cmd "$ar" "x --output tmpdir $pdb 0001"]
62 if ![string match "" $exec_output] {
66 set fi [open tmpdir/0001]
67 fconfigure $fi -translation binary
72 binary scan $data i version
74 if { $version != 20000404 } {
79 # skip signature (timestamp)
85 binary scan $data i age
94 set data [read $fi 16]
95 binary scan $data H2H2H2H2H2H2H2H2H* guid1 guid2 guid3 guid4 guid5 guid6 guid7 guid8 guid9
97 set data "$guid4$guid3$guid2$guid1$guid6$guid5$guid8$guid7$guid9"
99 if { $data ne $guid } {
106 set data [read $fi 4]
107 binary scan $data i names_length
108 read $fi $names_length
110 # read number of names entries
112 set data [read $fi 4]
113 binary scan $data i num_entries
115 # skip number of buckets
118 # skip present bitmap
120 set data [read $fi 4]
121 binary scan $data i bitmap_length
122 read $fi [expr $bitmap_length * 4]
124 # skip deleted bitmap
126 set data [read $fi 4]
127 binary scan $data i bitmap_length
128 read $fi [expr $bitmap_length * 4]
131 read $fi [expr $num_entries * 8]
136 # read second version
138 set data [read $fi 4]
139 binary scan $data i version2
141 if { $version2 != 20140508 } {
151 proc check_type_stream { pdb stream } {
154 set exec_output [run_host_cmd "$ar" "x --output tmpdir $pdb $stream"]
156 if ![string match "" $exec_output] {
160 set fi [open tmpdir/$stream]
161 fconfigure $fi -translation binary
165 set data [read $fi 4]
166 binary scan $data i version
168 if { $version != 20040203 } {
175 set data [read $fi 4]
176 binary scan $data i header_size
178 if { $header_size != 0x38 } {
183 # skip type_index_begin and type_index_end
186 # read type_record_bytes
188 set data [read $fi 4]
189 binary scan $data i type_record_bytes
193 # check stream length
195 set stream_length [file size tmpdir/$stream]
197 if { $stream_length != [ expr $header_size + $type_record_bytes ] } {
204 proc check_dbi_stream { pdb } {
207 set exec_output [run_host_cmd "$ar" "x --output tmpdir $pdb 0003"]
209 if ![string match "" $exec_output] {
213 set fi [open tmpdir/0003]
214 fconfigure $fi -translation binary
218 set data [read $fi 4]
219 binary scan $data i signature
221 if { $signature != -1 } {
228 set data [read $fi 4]
229 binary scan $data i version
231 if { $version != 19990903 } {
238 set data [read $fi 4]
239 binary scan $data i age
249 # read substream sizes
251 set data [read $fi 4]
252 binary scan $data i mod_info_size
254 set data [read $fi 4]
255 binary scan $data i section_contribution_size
257 set data [read $fi 4]
258 binary scan $data i section_map_size
260 set data [read $fi 4]
261 binary scan $data i source_info_size
263 set data [read $fi 4]
264 binary scan $data i type_server_map_size
266 # skip MFC type server index
269 set data [read $fi 4]
270 binary scan $data i optional_dbg_header_size
272 set data [read $fi 4]
273 binary scan $data i ec_substream_size
277 # check stream length
279 set stream_length [file size tmpdir/0003]
281 if { $stream_length != [expr 0x40 + $mod_info_size + $section_contribution_size + $section_map_size + $source_info_size + $type_server_map_size + $optional_dbg_header_size + $ec_substream_size] } {
288 proc get_section_stream_index { pdb } {
291 set exec_output [run_host_cmd "$ar" "x --output tmpdir $pdb 0003"]
293 if ![string match "" $exec_output] {
297 set fi [open tmpdir/0003]
298 fconfigure $fi -translation binary
303 # read substream sizes
305 set data [read $fi 4]
306 binary scan $data i mod_info_size
308 set data [read $fi 4]
309 binary scan $data i section_contribution_size
311 set data [read $fi 4]
312 binary scan $data i section_map_size
314 set data [read $fi 4]
315 binary scan $data i source_info_size
317 set data [read $fi 4]
318 binary scan $data i type_server_map_size
320 # skip type server index
323 set data [read $fi 4]
324 binary scan $data i optional_dbg_header_size
326 if { $optional_dbg_header_size < 12 } {
332 seek $fi [expr 12 + $mod_info_size + $section_contribution_size + $section_map_size + $source_info_size + $type_server_map_size + 10] current
334 set data [read $fi 2]
335 binary scan $data s section_stream_index
339 return $section_stream_index
342 proc check_section_stream { img pdb } {
345 # read sections stream
347 set index [get_section_stream_index $pdb]
349 if { $index == -1 } {
353 set index_str [format "%04x" $index]
355 set exec_output [run_host_cmd "$ar" "x --output tmpdir $pdb $index_str"]
357 if ![string match "" $exec_output] {
361 set stream_length [file size tmpdir/$index_str]
363 set fi [open tmpdir/$index_str]
364 fconfigure $fi -translation binary
366 set stream_data [read $fi $stream_length]
370 # read sections from PE file
373 fconfigure $fi -translation binary
377 set data [read $fi 4]
378 binary scan $data i pe_offset
380 # read number of sections
381 seek $fi [expr $pe_offset + 6]
382 set data [read $fi 2]
383 binary scan $data s num_sections
385 # read size of optional header
387 set data [read $fi 2]
388 binary scan $data s opt_header_size
390 # read section headers
391 seek $fi [expr $opt_header_size + 2] current
392 set section_data [read $fi [expr $num_sections * 40]]
398 if { $stream_data ne $section_data} {
405 proc get_publics_stream_index { pdb } {
408 set exec_output [run_host_cmd "$ar" "x --output tmpdir $pdb 0003"]
410 if ![string match "" $exec_output] {
414 set fi [open tmpdir/0003]
415 fconfigure $fi -translation binary
420 # read substream sizes
422 set data [read $fi 2]
423 binary scan $data s index
430 proc get_sym_record_stream_index { pdb } {
433 set exec_output [run_host_cmd "$ar" "x --output tmpdir $pdb 0003"]
435 if ![string match "" $exec_output] {
439 set fi [open tmpdir/0003]
440 fconfigure $fi -translation binary
445 # read substream sizes
447 set data [read $fi 2]
448 binary scan $data s index
455 proc check_publics_stream { pdb } {
461 set publics_index [get_publics_stream_index $pdb]
463 if { $publics_index == -1 } {
467 set index_str [format "%04x" $publics_index]
469 set exec_output [run_host_cmd "$ar" "x --output tmpdir $pdb $index_str"]
471 if ![string match "" $exec_output] {
475 set exp [file_contents "$srcdir/$subdir/pdb1-publics.d"]
476 set got [run_host_cmd "$objdump" "-s --target=binary tmpdir/$index_str"]
477 if ![string match $exp $got] {
481 set sym_record_index [get_sym_record_stream_index $pdb]
483 if { $sym_record_index == -1 } {
487 set index_str [format "%04x" $sym_record_index]
489 set exec_output [run_host_cmd "$ar" "x --output tmpdir $pdb $index_str"]
491 if ![string match "" $exec_output] {
495 set exp [file_contents "$srcdir/$subdir/pdb1-sym-record.d"]
496 set got [run_host_cmd "$objdump" "-s --target=binary tmpdir/$index_str"]
497 if ![string match $exp $got] {
510 if ![ld_assemble $as $srcdir/$subdir/pdb1.s tmpdir/pdb1.o] {
511 unsupported "Build pdb1.o"
515 if ![ld_link $ld "tmpdir/pdb1.exe" "--pdb=tmpdir/pdb1.pdb --gc-sections -e foo tmpdir/pdb1.o"] {
516 fail "Could not create a PE image with a PDB file"
520 if ![string equal [get_pdb_name "tmpdir/pdb1.exe"] "pdb1.pdb"] {
521 fail "PDB filename not found in CodeView debug info"
525 pass "PDB filename present in CodeView debug info"
527 if [check_pdb_info_stream tmpdir/pdb1.pdb [get_pdb_guid "tmpdir/pdb1.exe"]] {
528 pass "Valid PDB info stream"
530 fail "Invalid PDB info stream"
533 if [check_type_stream tmpdir/pdb1.pdb "0002"] {
534 pass "Valid TPI stream"
536 fail "Invalid TPI stream"
539 if [check_type_stream tmpdir/pdb1.pdb "0004"] {
540 pass "Valid IPI stream"
542 fail "Invalid IPI stream"
545 if [check_dbi_stream tmpdir/pdb1.pdb] {
546 pass "Valid DBI stream"
548 fail "Invalid DBI stream"
551 if [check_section_stream tmpdir/pdb1.exe tmpdir/pdb1.pdb] {
552 pass "Valid section stream"
554 fail "Invalid section stream"
557 if [check_publics_stream tmpdir/pdb1.pdb] {
558 pass "Valid publics stream"
560 fail "Invalid publics stream"
564 proc test_mod_info { mod_info } {
565 # check filenames in mod_info
569 set obj1 [string range $mod_info $off [expr [string first \000 $mod_info $off] - 1]]
570 incr off [expr [string length $obj1] + 1]
572 set ar1 [string range $mod_info $off [expr [string first \000 $mod_info $off] - 1]]
573 incr off [expr [string length $ar1] + 1]
575 if [string match "*pdb2a.o" $obj1] {
576 pass "Correct name for first object file"
578 fail "Incorrect name for first object file"
581 if [string equal $obj1 $ar1] {
582 pass "Correct archive name for first object file"
584 fail "Incorrect archive name for first object file"
587 if { [expr $off % 4] != 0 } {
588 set off [expr $off + 4 - ($off % 4)]
593 set obj2 [string range $mod_info $off [expr [string first \000 $mod_info $off] - 1]]
594 incr off [expr [string length $obj2] + 1]
596 set ar2 [string range $mod_info $off [expr [string first \000 $mod_info $off] - 1]]
597 incr off [expr [string length $ar2] + 1]
599 if [string match "*pdb2b.o" $obj2] {
600 pass "Correct name for second object file"
602 fail "Incorrect name for second object file"
605 if [string match "*pdb2b.a" $ar2] {
606 pass "Correct archive name for second object file"
608 fail "Incorrect archive name for second object file"
611 if { [expr $off % 4] != 0 } {
612 set off [expr $off + 4 - ($off % 4)]
617 set obj3 [string range $mod_info $off [expr [string first \000 $mod_info $off] - 1]]
618 incr off [expr [string length $obj3] + 1]
620 set ar3 [string range $mod_info $off [expr [string first \000 $mod_info $off] - 1]]
621 incr off [expr [string length $ar3] + 1]
623 if [string equal $obj3 "* Linker *"] {
624 pass "Correct name for dummy object file"
626 fail "Incorrect name for dummy object file"
629 if [string equal $ar3 ""] {
630 pass "Correct archive name for dummy object file"
632 fail "Incorrect archive name for dummy object file"
636 proc test_section_contrib { section_contrib } {
641 set fi [open tmpdir/pdb2-sc w]
642 fconfigure $fi -translation binary
643 puts -nonewline $fi $section_contrib
646 set exp [file_contents "$srcdir/$subdir/pdb2-section-contrib.d"]
647 set got [run_host_cmd "$objdump" "-s --target=binary tmpdir/pdb2-sc"]
649 if [string equal $exp $got] {
650 pass "Correct section contribution substream"
652 fail "Incorrect section contribution substream"
663 if ![ld_assemble $as $srcdir/$subdir/pdb2a.s tmpdir/pdb2a.o] {
664 unsupported "Build pdb2a.o"
668 if ![ld_assemble $as $srcdir/$subdir/pdb2b.s tmpdir/pdb2b.o] {
669 unsupported "Build pdb2b.o"
673 set exec_output [run_host_cmd "$ar" "cr tmpdir/pdb2b.a tmpdir/pdb2b.o"]
675 if ![string match "" $exec_output] {
676 unsupported "Create pdb2b.a"
680 if ![ld_link $ld "tmpdir/pdb2.exe" "--pdb=tmpdir/pdb2.pdb --gc-sections -e foo tmpdir/pdb2a.o tmpdir/pdb2b.a"] {
681 unsupported "Create PE image with PDB file"
685 set exec_output [run_host_cmd "$ar" "x --output tmpdir tmpdir/pdb2.pdb 0003"]
687 if ![string match "" $exec_output] {
691 set fi [open tmpdir/0003]
692 fconfigure $fi -translation binary
696 set data [read $fi 4]
697 binary scan $data i mod_info_size
699 set data [read $fi 4]
700 binary scan $data i section_contrib_size
704 set mod_info [read $fi $mod_info_size]
705 set section_contrib [read $fi $section_contrib_size]
709 test_mod_info $mod_info
710 test_section_contrib $section_contrib
713 proc find_named_stream { pdb name } {
716 set exec_output [run_host_cmd "$ar" "x --output tmpdir $pdb 0001"]
718 if ![string match "" $exec_output] {
722 set fi [open tmpdir/0001]
723 fconfigure $fi -translation binary
727 set data [read $fi 4]
728 binary scan $data i string_len
730 set strings [read $fi $string_len]
734 while {[string first \000 $strings $string_off] != -1 } {
735 set str [string range $strings $string_off [expr [string first \000 $strings $string_off] - 1]]
737 if { $str eq $name } {
741 incr string_off [expr [string length $str] + 1]
744 if { [string length $strings] == $string_off } { # string not found
749 set data [read $fi 4]
750 binary scan $data i num_entries
754 set data [read $fi 4]
755 binary scan $data i present_bitmap_len
757 seek $fi [expr $present_bitmap_len * 4] current
759 set data [read $fi 4]
760 binary scan $data i deleted_bitmap_len
762 seek $fi [expr $deleted_bitmap_len * 4] current
764 for {set i 0} {$i < $num_entries} {incr i} {
765 set data [read $fi 4]
766 binary scan $data i offset
768 if { $offset == $string_off } {
769 set data [read $fi 4]
770 binary scan $data i value
792 if ![ld_assemble $as $srcdir/$subdir/pdb-strings1.s tmpdir/pdb-strings1.o] {
793 unsupported "Build pdb-strings1.o"
797 if ![ld_assemble $as $srcdir/$subdir/pdb-strings2.s tmpdir/pdb-strings2.o] {
798 unsupported "Build pdb-strings2.o"
802 if ![ld_link $ld "tmpdir/pdb-strings.exe" "--pdb=tmpdir/pdb-strings.pdb tmpdir/pdb-strings1.o tmpdir/pdb-strings2.o"] {
803 unsupported "Create PE image with PDB file"
807 set index [find_named_stream "tmpdir/pdb-strings.pdb" "/names"]
810 fail "Could not find /names stream"
813 pass "Found /names stream"
816 set index_str [format "%04x" $index]
818 set exec_output [run_host_cmd "$ar" "x --output tmpdir tmpdir/pdb-strings.pdb $index_str"]
820 if ![string match "" $exec_output] {
824 set exp [file_contents "$srcdir/$subdir/pdb-strings.d"]
825 set got [run_host_cmd "$objdump" "-s --target=binary tmpdir/$index_str"]
827 if ![string match $exp $got] {
828 fail "Strings table was not as expected"
830 pass "Strings table was as expected"
834 proc extract_c13_info { pdb mod_info } {
837 binary scan [string range $mod_info 34 35] s module_sym_stream
838 binary scan [string range $mod_info 36 39] i sym_byte_size
839 binary scan [string range $mod_info 40 43] i c11_byte_size
840 binary scan [string range $mod_info 44 47] i c13_byte_size
842 set index_str [format "%04x" $module_sym_stream]
844 set exec_output [run_host_cmd "$ar" "x --output tmpdir $pdb $index_str"]
846 if ![string match "" $exec_output] {
850 set fi [open tmpdir/$index_str]
851 fconfigure $fi -translation binary
853 seek $fi [expr $sym_byte_size + $c11_byte_size]
855 set data [read $fi $c13_byte_size]
870 if ![ld_assemble $as $srcdir/$subdir/pdb3a.s tmpdir/pdb3a.o] {
871 unsupported "Build pdb3a.o"
875 if ![ld_assemble $as $srcdir/$subdir/pdb3b.s tmpdir/pdb3b.o] {
876 unsupported "Build pdb3b.o"
880 if ![ld_link $ld "tmpdir/pdb3.exe" "--pdb=tmpdir/pdb3.pdb --gc-sections -e main tmpdir/pdb3a.o tmpdir/pdb3b.o"] {
881 unsupported "Create PE image with PDB file"
885 # read relevant bits from DBI stream
887 set exec_output [run_host_cmd "$ar" "x --output tmpdir tmpdir/pdb3.pdb 0003"]
889 if ![string match "" $exec_output] {
890 fail "Could not extract DBI stream"
893 pass "Extracted DBI stream"
896 set fi [open tmpdir/0003]
897 fconfigure $fi -translation binary
901 # read substream sizes
903 set data [read $fi 4]
904 binary scan $data i mod_info_size
906 set data [read $fi 4]
907 binary scan $data i section_contribution_size
909 set data [read $fi 4]
910 binary scan $data i section_map_size
912 set data [read $fi 4]
913 binary scan $data i source_info_size
917 set mod_info [read $fi $mod_info_size]
919 seek $fi [expr $section_contribution_size + $section_map_size] current
921 set source_info [read $fi $source_info_size]
925 # check source info substream
927 set fi [open tmpdir/pdb3-source-info w]
928 fconfigure $fi -translation binary
929 puts -nonewline $fi $source_info
932 set exp [file_contents "$srcdir/$subdir/pdb3-source-info.d"]
933 set got [run_host_cmd "$objdump" "-s --target=binary tmpdir/pdb3-source-info"]
935 if [string match $exp $got] {
936 pass "Correct source info substream"
938 fail "Incorrect source info substream"
941 # check C13 info in first module
943 set c13_info [extract_c13_info "tmpdir/pdb3.pdb" [string range $mod_info 0 63]]
945 set fi [open tmpdir/pdb3-c13-info1 w]
946 fconfigure $fi -translation binary
947 puts -nonewline $fi $c13_info
950 set exp [file_contents "$srcdir/$subdir/pdb3-c13-info1.d"]
951 set got [run_host_cmd "$objdump" "-s --target=binary tmpdir/pdb3-c13-info1"]
953 if [string match $exp $got] {
954 pass "Correct C13 info for first module"
956 fail "Incorrect C13 info for first module"
959 # check C13 info in second module
961 set fn1_end [string first \000 $mod_info 64]
962 set fn2_end [string first \000 $mod_info [expr $fn1_end + 1]]
964 set off [expr $fn2_end + 1]
966 if { [expr $off % 4] != 0 } {
967 set off [expr $off + 4 - ($off % 4)]
970 set c13_info [extract_c13_info "tmpdir/pdb3.pdb" [string range $mod_info $off [expr $off + 63]]]
972 set fi [open tmpdir/pdb3-c13-info2 w]
973 fconfigure $fi -translation binary
974 puts -nonewline $fi $c13_info
977 set exp [file_contents "$srcdir/$subdir/pdb3-c13-info2.d"]
978 set got [run_host_cmd "$objdump" "-s --target=binary tmpdir/pdb3-c13-info2"]
980 if [string match $exp $got] {
981 pass "Correct C13 info for second module"
983 fail "Incorrect C13 info for second module"
995 if ![ld_assemble $as $srcdir/$subdir/pdb-types1a.s tmpdir/pdb-types1a.o] {
996 unsupported "Build pdb-types1a.o"
1000 if ![ld_assemble $as $srcdir/$subdir/pdb-types1b.s tmpdir/pdb-types1b.o] {
1001 unsupported "Build pdb-types1b.o"
1005 if ![ld_link $ld "tmpdir/pdb-types1.exe" "--pdb=tmpdir/pdb-types1.pdb tmpdir/pdb-types1a.o tmpdir/pdb-types1b.o"] {
1006 unsupported "Create PE image with PDB file"
1010 set exec_output [run_host_cmd "$ar" "x --output tmpdir tmpdir/pdb-types1.pdb 0002"]
1012 if ![string match "" $exec_output] {
1013 fail "Could not extract TPI stream"
1016 pass "Extracted TPI stream"
1019 # check values in TPI header, and save anything interesting
1021 set fi [open tmpdir/0002]
1022 fconfigure $fi -translation binary
1026 set data [read $fi 4]
1027 binary scan $data i first_type
1029 if { $first_type != 0x1000 } {
1030 fail "Incorrect first type value in TPI stream."
1032 pass "Correct first type value in TPI stream."
1035 set data [read $fi 4]
1036 binary scan $data i end_type
1038 # end_type is one greater than the last type in the stream
1039 if { $end_type != 0x102c } {
1040 fail "Incorrect end type value in TPI stream."
1042 pass "Correct end type value in TPI stream."
1045 set data [read $fi 4]
1046 binary scan $data i type_list_size
1048 set data [read $fi 2]
1049 binary scan $data s hash_stream_index
1053 set data [read $fi 4]
1054 binary scan $data i hash_size
1056 if { $hash_size != 4 } {
1057 fail "Incorrect hash size in TPI stream."
1059 pass "Correct hash size in TPI stream."
1062 set data [read $fi 4]
1063 binary scan $data i num_buckets
1065 if { $num_buckets != 0x3ffff } {
1066 fail "Incorrect number of buckets in TPI stream."
1068 pass "Correct number of buckets in TPI stream."
1071 set data [read $fi 4]
1072 binary scan $data i hash_list_offset
1074 set data [read $fi 4]
1075 binary scan $data i hash_list_size
1077 set data [read $fi 4]
1078 binary scan $data i skip_list_offset
1080 set data [read $fi 4]
1081 binary scan $data i skip_list_size
1085 set type_list [read $fi $type_list_size]
1089 set fi [open tmpdir/pdb-types1-typelist w]
1090 fconfigure $fi -translation binary
1091 puts -nonewline $fi $type_list
1096 set exp [file_contents "$srcdir/$subdir/pdb-types1-typelist.d"]
1097 set got [run_host_cmd "$objdump" "-s --target=binary tmpdir/pdb-types1-typelist"]
1098 if ![string match $exp $got] {
1099 fail "Incorrect type list in TPI stream."
1101 pass "Correct type list in TPI stream."
1104 # extract hash list and skip list
1106 set index_str [format "%04x" $hash_stream_index]
1108 set exec_output [run_host_cmd "$ar" "x --output tmpdir tmpdir/pdb-types1.pdb $index_str"]
1110 if ![string match "" $exec_output] {
1111 fail "Could not extract TPI hash stream."
1113 pass "Extracted TPI hash stream."
1116 set fi [open tmpdir/$index_str]
1117 fconfigure $fi -translation binary
1119 seek $fi $hash_list_offset
1120 set hash_list [read $fi $hash_list_size]
1122 seek $fi $skip_list_offset
1123 set skip_list [read $fi $skip_list_size]
1129 set fi [open tmpdir/pdb-types1-hashlist w]
1130 fconfigure $fi -translation binary
1131 puts -nonewline $fi $hash_list
1134 set exp [file_contents "$srcdir/$subdir/pdb-types1-hashlist.d"]
1135 set got [run_host_cmd "$objdump" "-s --target=binary tmpdir/pdb-types1-hashlist"]
1136 if ![string match $exp $got] {
1137 fail "Incorrect hash list in TPI stream."
1139 pass "Correct hash list in TPI stream."
1144 set fi [open tmpdir/pdb-types1-skiplist w]
1145 fconfigure $fi -translation binary
1146 puts -nonewline $fi $skip_list
1149 set exp [file_contents "$srcdir/$subdir/pdb-types1-skiplist.d"]
1150 set got [run_host_cmd "$objdump" "-s --target=binary tmpdir/pdb-types1-skiplist"]
1151 if ![string match $exp $got] {
1152 fail "Incorrect skip list in TPI stream."
1154 pass "Correct skip list in TPI stream."
1166 if ![ld_assemble $as $srcdir/$subdir/pdb-types2a.s tmpdir/pdb-types2a.o] {
1167 unsupported "Build pdb-types2a.o"
1171 if ![ld_assemble $as $srcdir/$subdir/pdb-types2b.s tmpdir/pdb-types2b.o] {
1172 unsupported "Build pdb-types2b.o"
1176 if ![ld_link $ld "tmpdir/pdb-types2.exe" "--pdb=tmpdir/pdb-types2.pdb tmpdir/pdb-types2a.o tmpdir/pdb-types2b.o"] {
1177 unsupported "Create PE image with PDB file"
1181 set exec_output [run_host_cmd "$ar" "x --output tmpdir tmpdir/pdb-types2.pdb 0004"]
1183 if ![string match "" $exec_output] {
1184 fail "Could not extract IPI stream"
1187 pass "Extracted IPI stream"
1190 # check values in IPI header, and save anything interesting
1192 set fi [open tmpdir/0004]
1193 fconfigure $fi -translation binary
1197 set data [read $fi 4]
1198 binary scan $data i first_type
1200 if { $first_type != 0x1000 } {
1201 fail "Incorrect first type value in IPI stream."
1203 pass "Correct first type value in IPI stream."
1206 set data [read $fi 4]
1207 binary scan $data i end_type
1209 # end_type is one greater than the last type in the stream
1210 if { $end_type != 0x100f } {
1211 fail "Incorrect end type value in IPI stream."
1213 pass "Correct end type value in IPI stream."
1216 set data [read $fi 4]
1217 binary scan $data i type_list_size
1219 set data [read $fi 2]
1220 binary scan $data s hash_stream_index
1224 set data [read $fi 4]
1225 binary scan $data i hash_size
1227 if { $hash_size != 4 } {
1228 fail "Incorrect hash size in IPI stream."
1230 pass "Correct hash size in IPI stream."
1233 set data [read $fi 4]
1234 binary scan $data i num_buckets
1236 if { $num_buckets != 0x3ffff } {
1237 fail "Incorrect number of buckets in IPI stream."
1239 pass "Correct number of buckets in IPI stream."
1242 set data [read $fi 4]
1243 binary scan $data i hash_list_offset
1245 set data [read $fi 4]
1246 binary scan $data i hash_list_size
1248 set data [read $fi 4]
1249 binary scan $data i skip_list_offset
1251 set data [read $fi 4]
1252 binary scan $data i skip_list_size
1256 set type_list [read $fi $type_list_size]
1260 set fi [open tmpdir/pdb-types2-typelist w]
1261 fconfigure $fi -translation binary
1262 puts -nonewline $fi $type_list
1267 set exp [file_contents "$srcdir/$subdir/pdb-types2-typelist.d"]
1268 set got [run_host_cmd "$objdump" "-s --target=binary tmpdir/pdb-types2-typelist"]
1269 if ![string match $exp $got] {
1270 fail "Incorrect type list in IPI stream."
1272 pass "Correct type list in IPI stream."
1275 # extract hash list and skip list
1277 set index_str [format "%04x" $hash_stream_index]
1279 set exec_output [run_host_cmd "$ar" "x --output tmpdir tmpdir/pdb-types2.pdb $index_str"]
1281 if ![string match "" $exec_output] {
1282 fail "Could not extract IPI hash stream."
1284 pass "Extracted IPI hash stream."
1287 set fi [open tmpdir/$index_str]
1288 fconfigure $fi -translation binary
1290 seek $fi $hash_list_offset
1291 set hash_list [read $fi $hash_list_size]
1293 seek $fi $skip_list_offset
1294 set skip_list [read $fi $skip_list_size]
1300 set fi [open tmpdir/pdb-types2-hashlist w]
1301 fconfigure $fi -translation binary
1302 puts -nonewline $fi $hash_list
1305 set exp [file_contents "$srcdir/$subdir/pdb-types2-hashlist.d"]
1306 set got [run_host_cmd "$objdump" "-s --target=binary tmpdir/pdb-types2-hashlist"]
1307 if ![string match $exp $got] {
1308 fail "Incorrect hash list in IPI stream."
1310 pass "Correct hash list in IPI stream."
1315 set fi [open tmpdir/pdb-types2-skiplist w]
1316 fconfigure $fi -translation binary
1317 puts -nonewline $fi $skip_list
1320 set exp [file_contents "$srcdir/$subdir/pdb-types2-skiplist.d"]
1321 set got [run_host_cmd "$objdump" "-s --target=binary tmpdir/pdb-types2-skiplist"]
1322 if ![string match $exp $got] {
1323 fail "Incorrect skip list in IPI stream."
1325 pass "Correct skip list in IPI stream."
1337 if ![ld_assemble $as $srcdir/$subdir/pdb-types3a.s tmpdir/pdb-types3a.o] {
1338 unsupported "Build pdb-types3a.o"
1342 if ![ld_assemble $as $srcdir/$subdir/pdb-types3b.s tmpdir/pdb-types3b.o] {
1343 unsupported "Build pdb-types3b.o"
1347 if ![ld_link $ld "tmpdir/pdb-types3.exe" "--pdb=tmpdir/pdb-types3.pdb tmpdir/pdb-types3a.o tmpdir/pdb-types3b.o"] {
1348 unsupported "Create PE image with PDB file"
1352 set exec_output [run_host_cmd "$ar" "x --output tmpdir tmpdir/pdb-types3.pdb 0004"]
1354 if ![string match "" $exec_output] {
1355 fail "Could not extract IPI stream"
1358 pass "Extracted IPI stream"
1361 set fi [open tmpdir/0004]
1362 fconfigure $fi -translation binary
1366 set data [read $fi 4]
1367 binary scan $data i type_list_size
1369 set data [read $fi 2]
1370 binary scan $data s hash_stream_index
1374 set data [read $fi 4]
1375 binary scan $data i hash_list_offset
1377 set data [read $fi 4]
1378 binary scan $data i hash_list_size
1380 set data [read $fi 4]
1381 binary scan $data i skip_list_offset
1383 set data [read $fi 4]
1384 binary scan $data i skip_list_size
1388 set type_list [read $fi $type_list_size]
1392 set fi [open tmpdir/pdb-types3-typelist w]
1393 fconfigure $fi -translation binary
1394 puts -nonewline $fi $type_list
1399 set exp [file_contents "$srcdir/$subdir/pdb-types3-typelist.d"]
1400 set got [run_host_cmd "$objdump" "-s --target=binary tmpdir/pdb-types3-typelist"]
1401 if ![string match $exp $got] {
1402 fail "Incorrect type list in IPI stream."
1404 pass "Correct type list in IPI stream."
1407 # extract hash list and skip list
1409 set index_str [format "%04x" $hash_stream_index]
1411 set exec_output [run_host_cmd "$ar" "x --output tmpdir tmpdir/pdb-types3.pdb $index_str"]
1413 if ![string match "" $exec_output] {
1414 fail "Could not extract IPI hash stream."
1416 pass "Extracted IPI hash stream."
1419 set fi [open tmpdir/$index_str]
1420 fconfigure $fi -translation binary
1422 seek $fi $hash_list_offset
1423 set hash_list [read $fi $hash_list_size]
1425 seek $fi $skip_list_offset
1426 set skip_list [read $fi $skip_list_size]
1432 set fi [open tmpdir/pdb-types3-hashlist w]
1433 fconfigure $fi -translation binary
1434 puts -nonewline $fi $hash_list
1437 set exp [file_contents "$srcdir/$subdir/pdb-types3-hashlist.d"]
1438 set got [run_host_cmd "$objdump" "-s --target=binary tmpdir/pdb-types3-hashlist"]
1439 if ![string match $exp $got] {
1440 fail "Incorrect hash list in IPI stream."
1442 pass "Correct hash list in IPI stream."
1447 set fi [open tmpdir/pdb-types3-skiplist w]
1448 fconfigure $fi -translation binary
1449 puts -nonewline $fi $skip_list
1452 set exp [file_contents "$srcdir/$subdir/pdb-types3-skiplist.d"]
1453 set got [run_host_cmd "$objdump" "-s --target=binary tmpdir/pdb-types3-skiplist"]
1454 if ![string match $exp $got] {
1455 fail "Incorrect skip list in IPI stream."
1457 pass "Correct skip list in IPI stream."
1469 if ![ld_assemble $as $srcdir/$subdir/pdb-syms1a.s tmpdir/pdb-syms1a.o] {
1470 unsupported "Build pdb-syms1a.o"
1474 if ![ld_assemble $as $srcdir/$subdir/pdb-syms1b.s tmpdir/pdb-syms1b.o] {
1475 unsupported "Build pdb-syms1b.o"
1479 if ![ld_link $ld "tmpdir/pdb-syms1.exe" "--pdb=tmpdir/pdb-syms1.pdb tmpdir/pdb-syms1a.o tmpdir/pdb-syms1b.o"] {
1480 unsupported "Create PE image with PDB file"
1484 # get index of globals stream and records stream
1486 set exec_output [run_host_cmd "$ar" "x --output tmpdir tmpdir/pdb-syms1.pdb 0003"]
1488 if ![string match "" $exec_output] {
1489 fail "Could not extract DBI stream"
1492 pass "Extracted DBI stream"
1495 set fi [open tmpdir/0003]
1496 fconfigure $fi -translation binary
1499 set data [read $fi 2]
1500 binary scan $data s globals_index
1503 set data [read $fi 2]
1504 binary scan $data s records_index
1507 set data [read $fi 4]
1508 binary scan $data i mod_info_size
1511 set mod_info [read $fi $mod_info_size]
1515 # get index of first and second module streams
1517 binary scan [string range $mod_info 34 35] s mod1_index
1521 set obj1 [string range $mod_info $off [expr [string first \000 $mod_info $off] - 1]]
1522 incr off [expr [string length $obj1] + 1]
1524 set ar1 [string range $mod_info $off [expr [string first \000 $mod_info $off] - 1]]
1525 incr off [expr [string length $ar1] + 1]
1527 if { [expr $off % 4] != 0 } {
1528 set off [expr $off + 4 - ($off % 4)]
1533 binary scan [string range $mod_info $off [expr $off + 1]] s mod2_index
1535 # check globals stream
1537 set index_str [format "%04x" $globals_index]
1539 set exec_output [run_host_cmd "$ar" "x --output tmpdir tmpdir/pdb-syms1.pdb $index_str"]
1541 if ![string match "" $exec_output] {
1542 fail "Could not extract globals stream"
1545 pass "Extracted globals stream"
1548 set exp [file_contents "$srcdir/$subdir/pdb-syms1-globals.d"]
1549 set got [run_host_cmd "$objdump" "-s --target=binary tmpdir/$index_str"]
1551 if [string match $exp $got] {
1552 pass "Correct globals stream"
1554 fail "Incorrect globals stream"
1557 # check records stream
1559 set index_str [format "%04x" $records_index]
1561 set exec_output [run_host_cmd "$ar" "x --output tmpdir tmpdir/pdb-syms1.pdb $index_str"]
1563 if ![string match "" $exec_output] {
1564 fail "Could not extract records stream"
1567 pass "Extracted records stream"
1570 set exp [file_contents "$srcdir/$subdir/pdb-syms1-records.d"]
1571 set got [run_host_cmd "$objdump" "-s --target=binary tmpdir/$index_str"]
1573 if [string match $exp $got] {
1574 pass "Correct records stream"
1576 fail "Incorrect records stream"
1579 # check symbols in first module
1581 set index_str [format "%04x" $mod1_index]
1583 set exec_output [run_host_cmd "$ar" "x --output tmpdir tmpdir/pdb-syms1.pdb $index_str"]
1585 if ![string match "" $exec_output] {
1586 fail "Could not extract first module's symbols"
1589 pass "Extracted first module's symbols"
1592 set exp [file_contents "$srcdir/$subdir/pdb-syms1-symbols1.d"]
1593 set got [run_host_cmd "$objdump" "-s --target=binary tmpdir/$index_str"]
1595 if [string match $exp $got] {
1596 pass "Correct symbols in first module's stream"
1598 fail "Incorrect symbols in first module's stream"
1601 # check symbols in second module
1603 set index_str [format "%04x" $mod2_index]
1605 set exec_output [run_host_cmd "$ar" "x --output tmpdir tmpdir/pdb-syms1.pdb $index_str"]
1607 if ![string match "" $exec_output] {
1608 fail "Could not extract second module's symbols"
1611 pass "Extracted second module's symbols"
1614 set exp [file_contents "$srcdir/$subdir/pdb-syms1-symbols2.d"]
1615 set got [run_host_cmd "$objdump" "-s --target=binary tmpdir/$index_str"]
1617 if [string match $exp $got] {
1618 pass "Correct symbols in second module's stream"
1620 fail "Incorrect symbols in second module's stream"
1632 if ![ld_assemble $as $srcdir/$subdir/pdb-syms2.s tmpdir/pdb-syms2.o] {
1633 unsupported "Build pdb-syms2.o"
1637 if ![ld_link $ld "tmpdir/pdb-syms2.exe" "--pdb=tmpdir/pdb-syms2.pdb tmpdir/pdb-syms2.o"] {
1638 unsupported "Create PE image with PDB file"
1642 # get index of module stream
1644 set exec_output [run_host_cmd "$ar" "x --output tmpdir tmpdir/pdb-syms2.pdb 0003"]
1646 if ![string match "" $exec_output] {
1647 fail "Could not extract DBI stream"
1650 pass "Extracted DBI stream"
1653 set fi [open tmpdir/0003]
1654 fconfigure $fi -translation binary
1657 set data [read $fi 4]
1658 binary scan $data i mod_info_size
1661 set mod_info [read $fi $mod_info_size]
1665 binary scan [string range $mod_info 34 35] s module_index
1667 # check module records
1669 set index_str [format "%04x" $module_index]
1671 set exec_output [run_host_cmd "$ar" "x --output tmpdir tmpdir/pdb-syms2.pdb $index_str"]
1673 if ![string match "" $exec_output] {
1674 fail "Could not extract module symbols"
1677 pass "Extracted module symbols"
1680 set exp [file_contents "$srcdir/$subdir/pdb-syms2-symbols1.d"]
1681 set got [run_host_cmd "$objdump" "-s --target=binary tmpdir/$index_str"]
1683 if [string match $exp $got] {
1684 pass "Correct symbols in module stream"
1686 fail "Incorrect symbols in module stream"
1689 # check linker symbols
1693 set obj1 [string range $mod_info $off [expr [string first \000 $mod_info $off] - 1]]
1694 incr off [expr [string length $obj1] + 1]
1696 set ar1 [string range $mod_info $off [expr [string first \000 $mod_info $off] - 1]]
1697 incr off [expr [string length $ar1] + 1]
1699 if { [expr $off % 4] != 0 } {
1700 set off [expr $off + 4 - ($off % 4)]
1705 binary scan [string range $mod_info $off [expr $off + 1]] s linker_syms_index
1707 set index_str [format "%04x" $linker_syms_index]
1709 set exec_output [run_host_cmd "$ar" "x --output tmpdir tmpdir/pdb-syms2.pdb $index_str"]
1711 if ![string match "" $exec_output] {
1712 fail "Could not extract linker symbols"
1715 pass "Extracted linker symbols"
1718 set syms [file_contents "tmpdir/$index_str"]
1723 binary scan [string range $syms $off [expr $off + 1]] s sym_len
1724 binary scan [string range $syms [expr $off + 2] [expr $off + 3]] s sym_type
1726 if { $sym_type != 0x1101 } {
1727 fail "First linker symbol was not S_OBJNAME"
1729 pass "First linker symbol was S_OBJNAME"
1731 set linker_fn [string range $syms [expr $off + 8] [expr [string first \000 $syms [expr $off + 8]] - 1]]
1733 if ![string equal $linker_fn "* Linker *"] {
1734 fail "Incorrect linker object name"
1736 pass "Correct linker object name"
1740 incr off [expr $sym_len + 2]
1744 binary scan [string range $syms $off [expr $off + 1]] s sym_len
1745 binary scan [string range $syms [expr $off + 2] [expr $off + 3]] s sym_type
1747 if { $sym_type != 0x113c } {
1748 fail "Second linker symbol was not S_COMPILE3"
1750 pass "Second linker symbol was S_COMPILE3"
1753 incr off [expr $sym_len + 2]
1757 binary scan [string range $syms $off [expr $off + 1]] s sym_len
1758 binary scan [string range $syms [expr $off + 2] [expr $off + 3]] s sym_type
1760 if { $sym_type != 0x113d } {
1761 fail "Third linker symbol was not S_ENVBLOCK"
1763 pass "Third linker symbol was S_ENVBLOCK"