summaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.base/gnu-debugdata.exp
blob: 83abe57bd716b7cf27d9cba67520650bcc5af8b5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# Copyright 2012 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

standard_testfile

if [build_executable ${testfile}.exp $testfile] {
    return -1
}

# A wrapper for 'remote_exec host' that passes or fails a test.
# Returns 0 if all went well, nonzero on failure.
# TEST is the name of the test, other arguments are as for
# remote_exec.
proc run {test program args} {
    verbose "cmdline is remote_exec host $program $args"
    # remote_exec doesn't work properly if the output is set but the
    # input is the empty string -- so replace an empty input with
    # /dev/null.
    if {[llength $args] > 1 && [lindex $args 1] == ""} {
	set args [lreplace $args 1 1 "/dev/null"]
    }
    set result [eval remote_exec host [list $program] $args]
    verbose "result is $result"
    set status [lindex $result 0]
    set output [lindex $result 1]
    if {$status == 0} {
 	pass $test
 	return 0
    } else {
	fail $test
	return -1
    }
}

set pipeline_counter 0

# Run a pipeline of processes through 'run'.
# TEST is the base name of the test, it is modified and passed to 'run'.
# Each subsequent argument is a list of the form {PROGRAM [ARG]...}.
# It is passed to 'run'.  However, before being passed, if input and output
# files are not specified in the list, then this proc provides them.
# Each program in the pipeline takes its input from the previous
# program's output.
proc pipeline {test args} {
    global pipeline_counter

    set input_file {}
    foreach arglist $args {
	verbose "raw args are $arglist"

	set program [lindex $arglist 0]
	set arguments [lindex $arglist 1]
	set input [lindex $arglist 2]
	set output [lindex $arglist 3]

	if {$input == ""} {
	    set input $input_file
	}
	if {$output == ""} {
	    set output [standard_output_file pipe.[pid].$pipeline_counter]
	    incr pipeline_counter
	}
	verbose "cooked args are [list $program $arguments $input $output]"

	if {[run "$test - invoke $program" $program $arguments \
		 $input $output]} {
	    return -1
	}

	set input_file $output
    }
    return 0
}

# Extract the dynamic symbols from the main binary, there is no need
# to also have these in the normal symbol table.
remote_file host delete ${binfile}.dynsyms
if {[pipeline "nm -D" \
	 [list [transform nm] "-D ${binfile} --format=posix --defined-only"] \
	 [list awk "\\{print\\ \\\$1\\}"] \
	 [list sort "" "" "${binfile}.dynsyms"]]} {
    return -1
}

# Extract all the text (i.e. function) symbols from the debuginfo.
# (Note that we actually also accept "D" symbols, for the benefit
# of platforms like PowerPC64 that use function descriptors.)
remote_file host delete ${binfile}.funcsyms
if {[pipeline "nm" \
	 [list [transform nm] "${binfile} --format=posix --defined-only"] \
	 [list awk "\\{if(\\\$2==\"T\"||\\\$2==\"t\"||\\\$2==\"D\")print\\ \\\$1\\}"] \
	 [list sort "" "" "${binfile}.funcsyms"]]} {
    return -1
}

# Keep all the function symbols not already in the dynamic symbol
# table.
remote_file host delete ${binfile}.keep_symbols
if {[run "comm" "comm" "-13 ${binfile}.dynsyms ${binfile}.funcsyms" "" \
	 "${binfile}.keep_symbols"]} {
    return -1
}

# Copy the full debuginfo, keeping only a minimal set of symbols and
# removing some unnecessary sections.
remote_file host delete ${binfile}.mini_debuginfo
if {[run "objcopy 1" [transform objcopy] "-S --remove-section .gdb_index --remove-section .comment --keep-symbols=${binfile}.keep_symbols ${binfile} ${binfile}.mini_debuginfo"]} {
    return -1
}

# GDB specific - we do not have split executable in advance.
remote_file host delete ${binfile}.strip
if {[run "strip" [transform strip] \
	 "--strip-all -o ${binfile}.strip ${binfile}"]} {
    return -1
}

# Inject the compressed data into the .gnu_debugdata section of the
# original binary.
remote_file host delete ${binfile}.mini_debuginfo.xz
if {[run "xz" "xz" "${binfile}.mini_debuginfo"]} {
    return -1
}
remote_file host delete ${binfile}.test
if {[run "objcopy 2" [transform objcopy] "--add-section .gnu_debugdata=${binfile}.mini_debuginfo.xz ${binfile}.strip ${binfile}.test"]} {
    return -1
}

clean_restart "$testfile.strip"

gdb_test "p debugdata_function" \
    {No symbol table is loaded\.  Use the "file" command\.} \
    "no symtab"

clean_restart "$testfile.test"

if {$gdb_file_cmd_debug_info == "lzma"} {
    unsupported "LZMA support not available in this gdb"
} else {
    gdb_test "p debugdata_function" \
	{ = {<text variable, no debug info>} 0x[0-9a-f]+ <debugdata_function>} \
	"have symtab"
}

# Be sure to test the 'close' method on the MiniDebugInfo BFD.
if {[gdb_unload]} {
    fail "unload MiniDebugInfo"
} else {
    pass "unload MiniDebugInfo"
}

gdb_exit