1# Copyright 2012-2013 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
16standard_testfile
17
18if [build_executable ${testfile}.exp $testfile] {
19    return -1
20}
21
22# A wrapper for 'remote_exec host' that passes or fails a test.
23# Returns 0 if all went well, nonzero on failure.
24# TEST is the name of the test, other arguments are as for
25# remote_exec.
26proc run {test program args} {
27    verbose "cmdline is remote_exec host $program $args"
28    # remote_exec doesn't work properly if the output is set but the
29    # input is the empty string -- so replace an empty input with
30    # /dev/null.
31    if {[llength $args] > 1 && [lindex $args 1] == ""} {
32	set args [lreplace $args 1 1 "/dev/null"]
33    }
34    set result [eval remote_exec host [list $program] $args]
35    verbose "result is $result"
36    set status [lindex $result 0]
37    set output [lindex $result 1]
38    if {$status == 0} {
39 	pass $test
40 	return 0
41    } else {
42	fail $test
43	return -1
44    }
45}
46
47set pipeline_counter 0
48
49# Run a pipeline of processes through 'run'.
50# TEST is the base name of the test, it is modified and passed to 'run'.
51# Each subsequent argument is a list of the form {PROGRAM [ARG]...}.
52# It is passed to 'run'.  However, before being passed, if input and output
53# files are not specified in the list, then this proc provides them.
54# Each program in the pipeline takes its input from the previous
55# program's output.
56proc pipeline {test args} {
57    global pipeline_counter
58
59    set input_file {}
60    foreach arglist $args {
61	verbose "raw args are $arglist"
62
63	set program [lindex $arglist 0]
64	set arguments [lindex $arglist 1]
65	set input [lindex $arglist 2]
66	set output [lindex $arglist 3]
67
68	if {$input == ""} {
69	    set input $input_file
70	}
71	if {$output == ""} {
72	    set output [standard_output_file pipe.[pid].$pipeline_counter]
73	    incr pipeline_counter
74	}
75	verbose "cooked args are [list $program $arguments $input $output]"
76
77	if {[run "$test - invoke $program" $program $arguments \
78		 $input $output]} {
79	    return -1
80	}
81
82	set input_file $output
83    }
84    return 0
85}
86
87# Extract the dynamic symbols from the main binary, there is no need
88# to also have these in the normal symbol table.
89remote_file host delete ${binfile}.dynsyms
90if {[pipeline "nm -D" \
91	 [list [transform nm] "-D ${binfile} --format=posix --defined-only"] \
92	 [list awk "\\{print\\ \\\$1\\}"] \
93	 [list sort "" "" "${binfile}.dynsyms"]]} {
94    return -1
95}
96
97# Extract all the text (i.e. function) symbols from the debuginfo.
98# (Note that we actually also accept "D" symbols, for the benefit
99# of platforms like PowerPC64 that use function descriptors.)
100remote_file host delete ${binfile}.funcsyms
101if {[pipeline "nm" \
102	 [list [transform nm] "${binfile} --format=posix --defined-only"] \
103	 [list awk "\\{if(\\\$2==\"T\"||\\\$2==\"t\"||\\\$2==\"D\")print\\ \\\$1\\}"] \
104	 [list sort "" "" "${binfile}.funcsyms"]]} {
105    return -1
106}
107
108# Keep all the function symbols not already in the dynamic symbol
109# table.
110remote_file host delete ${binfile}.keep_symbols
111if {[run "comm" "comm" "-13 ${binfile}.dynsyms ${binfile}.funcsyms" "" \
112	 "${binfile}.keep_symbols"]} {
113    return -1
114}
115
116# Copy the full debuginfo, keeping only a minimal set of symbols and
117# removing some unnecessary sections.
118remote_file host delete ${binfile}.mini_debuginfo
119if {[run "objcopy 1" [transform objcopy] "-S --remove-section .gdb_index --remove-section .comment --keep-symbols=${binfile}.keep_symbols ${binfile} ${binfile}.mini_debuginfo"]} {
120    return -1
121}
122
123# GDB specific - we do not have split executable in advance.
124remote_file host delete ${binfile}.strip
125if {[run "strip" [transform strip] \
126	 "--strip-all -o ${binfile}.strip ${binfile}"]} {
127    return -1
128}
129
130# Separate full debug info into ${binfile}.debug.
131remote_file host delete ${binfile}.debug
132if {[run "copydebug" [transform objcopy] \
133	 "--only-keep-debug ${binfile} ${binfile}.debug"]} {
134    return -1
135}
136
137# Add the .gnu_debuglink section to the .gnu_debugdata file.
138# .gnu_debuglink is normally not present in the .gnu_debugdata section but in
139# some files there may be PT_NOTE with NT_GNU_BUILD_ID and GDB could look up
140# the .debug file from it.
141if {[run "addlink" [transform objcopy] \
142	 "--add-gnu-debuglink=${binfile}.debug ${binfile}.mini_debuginfo ${binfile}.mini_debuginfo-debuglink"]} {
143    return -1
144}
145
146# Inject the compressed data into the .gnu_debugdata section of the
147# original binary.
148remote_file host delete ${binfile}.mini_debuginfo-debuglink.xz
149if {[run "xz" "xz" "-k ${binfile}.mini_debuginfo-debuglink"]} {
150    return -1
151}
152remote_file host delete ${binfile}.test
153if {[run "objcopy 2" [transform objcopy] "--add-section .gnu_debugdata=${binfile}.mini_debuginfo-debuglink.xz ${binfile}.strip ${binfile}.test"]} {
154    return -1
155}
156
157clean_restart "$testfile.strip"
158
159gdb_test "p debugdata_function" \
160    {No symbol table is loaded\.  Use the "file" command\.} \
161    "no symtab"
162
163clean_restart "$testfile.test"
164
165if {$gdb_file_cmd_debug_info == "lzma"} {
166    unsupported "LZMA support not available in this gdb"
167} else {
168    gdb_test "p debugdata_function" \
169	{ = {<text variable, no debug info>} 0x[0-9a-f]+ <debugdata_function>} \
170	"have symtab"
171}
172
173# Be sure to test the 'close' method on the MiniDebugInfo BFD.
174if {[gdb_unload]} {
175    fail "unload MiniDebugInfo"
176} else {
177    pass "unload MiniDebugInfo"
178}
179
180gdb_exit
181