2012-11-26 19:23:56 +00:00
|
|
|
# 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"
|
2012-11-29 20:53:24 +00:00
|
|
|
set status [lindex $result 0]
|
|
|
|
set output [lindex $result 1]
|
2012-11-26 19:23:56 +00:00
|
|
|
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"
|
2012-11-29 20:53:24 +00:00
|
|
|
|
|
|
|
set program [lindex $arglist 0]
|
|
|
|
set arguments [lindex $arglist 1]
|
|
|
|
set input [lindex $arglist 2]
|
|
|
|
set output [lindex $arglist 3]
|
2012-11-26 19:23:56 +00:00
|
|
|
|
|
|
|
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.
|
|
|
|
remote_file host delete ${binfile}.funcsyms
|
|
|
|
if {[pipeline "nm" \
|
|
|
|
[list [transform nm] "${binfile} --format=posix --defined-only"] \
|
|
|
|
[list awk "\\{if(\\\$2==\"T\"||\\\$2==\"t\")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
|