* [RFC/WIP] unit test for separate debug info
@ 2003-11-07 20:03 Elena Zannoni
2003-11-07 20:39 ` Kevin Buettner
0 siblings, 1 reply; 8+ messages in thread
From: Elena Zannoni @ 2003-11-07 20:03 UTC (permalink / raw)
To: gdb-patches; +Cc: mec
It took a while, but I think I have this working, at least on my
machine. The real problem is that RedHat is using another process to
get separate debug info files from executables. I was able to get that
working pretty quickly in a testcase, but ran into a bit of a problem
in doing that with the binutils tools, and then got sidetracked.
Anyway, here is what I did. I used the break.exp and break.c files as
templates. I actually cloned break.exp and added fiddling with the
separate debug info. Break.exp is usually a decent smoke test for gdb.
No need to clone break.c. (BTW, should cloned files retain the original
copyright years?)
I also added a couple of procedures to gdb.exp to do the files
manipulations. I believe I got some of them from an old posting from
Jimb (I'll go check), But they were mostly rewritten.
I have 2 different ways to generate the separate debug info files, one
for binutils and one for elfutils (for the RH case). The one for elfutils
is included in the RedHat gdb rpm, i can post that too, if people are
interested, but probably it should remain Red Hat specific, especially
since I cannot seem to find a decent way to use one or the other,
other than see if one fails.
Anyway, this needs some pounding by Michael, I think. There probably
are improvements/changes that could be made. This is why it's not a
formal RFA yet.
elena
Index: gdb.exp
===================================================================
RCS file: /cvs/uberbaum/gdb/testsuite/lib/gdb.exp,v
retrieving revision 1.37
diff -u -p -r1.37 gdb.exp
--- gdb.exp 1 May 2003 01:09:51 -0000 1.37
+++ gdb.exp 7 Nov 2003 19:36:09 -0000
@@ -1840,3 +1840,68 @@ proc gdb_skip_bogus_test { msg } {
return 0;
}
+# Return the name of the file in which we should stor EXEC's separated
+# debug info.
+proc separate_debug_filename { exec } {
+
+ # In a .debug subdirectory off the same directory where the testcase
+ # executable is going to be. Something like:
+ # <your-path>/gdb/testsuite/gdb.base/.debug/blah.debug.
+ # This is the default location where gdb expects to find the debug info fil
e.
+ set exec_dir [file dirname $exec]
+ set exec_file [file tail $exec]
+ set debug_dir [file join $exec_dir ".debug"]
+ set debug_file [file join $debug_dir "${exec_file}.debug"]
+
+ return $debug_file
+}
+
+
+proc gdb_gnu_strip_debug { dest } {
+
+ set debug_file [separate_debug_filename $dest]
+ set strip_to_file_program /home/ezannoni/uberbaum/installed/bin/strip
+ set objcopy_program /home/ezannoni/uberbaum/installed/bin/objcopy
+
+ # Make sure the directory that will hold the separated debug
+ # info actually exists.
+ set debug_dir [file dirname $debug_file]
+ if {! [file isdirectory $debug_dir]} {
+ file mkdir $debug_dir
+ }
+
+ set debug_link [file tail $debug_file]
+ set stripped_file "${dest}.stripped"
+
+ # Get rid of the debug info, and store result in stripped_file
+ # something like gdb/testsuite/gdb.base/blah.stripped.
+ set result [catch "exec $strip_to_file_program --strip-debug ${dest} -o ${stripped_file}" output]
+ verbose "result is $result"
+ verbose "output is $output"
+ if {$result == 1} {
+ return 1
+ }
+
+ # Get rid of everything but the debug info, and store result in debug_file
+ # This will be in the .debug subdirectory, see above.
+ set result [catch "exec $strip_to_file_program --only-keep-debug ${dest} -o ${debug_file}" output]
+ verbose "result is $result"
+ verbose "output is $output"
+ if {$result == 1} {
+ return 1
+ }
+
+ # Link the two previous output files together, adding the .gnu_debuglink
+ # section to the stripped_file, containing a pointer to the debug_file,
+ # save the new file in dest.
+ # This will be the regular executable filename, in the usual location.
+ set result [catch "exec $objcopy_program --add-gnu-debuglink=${debug_file} ${stripped_file} ${dest}" output]
+ verbose "result is $result"
+ verbose "output is $output"
+ if {$result == 1} {
+ return 1
+ }
+
+ return 0
+}
+
# Copyright 1988, 1990, 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2002, 2003
# 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 2 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, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# Please email any bugs, comments, and/or additions to this file to:
# bug-gdb@prep.ai.mit.edu
# Modified to test gdb's handling of separate debug info files.
# Based on break.exp, written by Rob Savoye. (rob@cygnus.com)
if $tracelevel then {
strace $tracelevel
}
#
# test running programs
#
set prms_id 0
set bug_id 0
set testfile "break"
set srcfile ${testfile}.c
set binfile ${objdir}/${subdir}/${testfile}
if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-w}] != "" } {
gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
}
if [gdb_gnu_strip_debug $binfile] {
unsupported "no separate debug info handling"
return -1
}
gdb_exit
gdb_start
gdb_reinitialize_dir $srcdir/$subdir
gdb_load ${binfile}
if [target_info exists gdb_stub] {
gdb_step_for_stub;
}
#
# test simple breakpoint setting commands
#
# Test deleting all breakpoints when there are none installed,
# GDB should not prompt for confirmation.
# Note that gdb-init.exp provides a "delete_breakpoints" proc
# for general use elsewhere.
send_gdb "delete breakpoints\n"
gdb_expect {
-re "Delete all breakpoints.*$" {
send_gdb "y\n"
gdb_expect {
-re "$gdb_prompt $" {
fail "Delete all breakpoints when none (unexpected prompt)"
}
timeout { fail "Delete all breakpoints when none (timeout after unexpected prompt)" }
}
}
-re ".*$gdb_prompt $" { pass "Delete all breakpoints when none" }
timeout { fail "Delete all breakpoints when none (timeout)" }
}
#
# test break at function
#
gdb_test "break main" \
"Breakpoint.*at.* file .*$srcfile, line.*" \
"breakpoint function"
#
# test break at quoted function
#
gdb_test "break \"marker2\"" \
"Breakpoint.*at.* file .*$srcfile, line.*" \
"breakpoint quoted function"
#
# test break at function in file
#
gdb_test "break $srcfile:factorial" \
"Breakpoint.*at.* file .*$srcfile, line.*" \
"breakpoint function in file"
#
# test break at line number
#
# Note that the default source file is the last one whose source text
# was printed. For native debugging, before we've executed the
# program, this is the file containing main, but for remote debugging,
# it's wherever the processor was stopped when we connected to the
# board. So, to be sure, we do a list command.
#
gdb_test "list main" \
".*main \\(argc, argv, envp\\).*" \
"use `list' to establish default source file"
gdb_test "break 79" \
"Breakpoint.*at.* file .*$srcfile, line 79\\." \
"breakpoint line number"
#
# test duplicate breakpoint
#
gdb_test "break 79" \
"Note: breakpoint \[0-9\]+ also set at pc.*Breakpoint \[0-9\]+ at.* file .*$srcfile, line 79\\." \
"breakpoint duplicate"
#
# test break at line number in file
#
gdb_test "break $srcfile:85" \
"Breakpoint.*at.* file .*$srcfile, line 85\\." \
"breakpoint line number in file"
#
# Test putting a break at the start of a multi-line if conditional.
# Verify the breakpoint was put at the start of the conditional.
#
gdb_test "break multi_line_if_conditional" \
"Breakpoint.*at.* file .*$srcfile, line 109\\." \
"breakpoint at start of multi line if conditional"
gdb_test "break multi_line_while_conditional" \
"Breakpoint.*at.* file .*$srcfile, line 124\\." \
"breakpoint at start of multi line while conditional"
#
# check to see what breakpoints are set
#
if [target_info exists gdb_stub] {
set main_line 72
} else {
set main_line 75
}
gdb_test "info break" \
"Num Type\[ \]+Disp Enb Address\[ \]+What.*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$main_line.*
\[0-9\]+\[\t \]+breakpoint keep y.* in marker2 at .*$srcfile:4\[49\].*
\[0-9\]+\[\t \]+breakpoint keep y.* in factorial at .*$srcfile:96.*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:79.*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:79.*
\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:85.*
\[0-9\]+\[\t \]+breakpoint keep y.* in multi_line_if_conditional at .*$srcfile:109.*
\[0-9\]+\[\t \]+breakpoint keep y.* in multi_line_while_conditional at .*$srcfile:124" \
"breakpoint info"
# FIXME: The rest of this test doesn't work with anything that can't
# handle arguments.
# Huh? There doesn't *appear* to be anything that passes arguments
# below.
if [istarget "mips-idt-*"] then {
return
}
#
# run until the breakpoint at main is hit. For non-stubs-using targets.
#
if ![target_info exists use_gdb_stub] {
if [istarget "*-*-vxworks*"] then {
send_gdb "run vxmain \"2\"\n"
set timeout 120
verbose "Timeout is now $timeout seconds" 2
} else {
send_gdb "run\n"
}
gdb_expect {
-re "The program .* has been started already.*y or n. $" {
send_gdb "y\n"
exp_continue
}
-re "Starting program.*Breakpoint \[0-9\]+,.*main .*argc.*argv.* at .*$srcfile:75.*75\[\t \]+if .argc.* \{.*$gdb_prompt $"\
{ pass "run until function breakpoint" }
-re ".*$gdb_prompt $" { fail "run until function breakpoint" }
timeout { fail "run until function breakpoint (timeout)" }
}
} else {
if ![target_info exists gdb_stub] {
gdb_test continue ".*Continuing\\..*Breakpoint \[0-9\]+, main \\(argc=.*, argv=.*, envp=.*\\) at .*$srcfile:75.*75\[\t \]+if .argc.*\{.*" "stub continue"
}
}
#
# run until the breakpoint at a line number
#
gdb_test continue "Continuing\\..*Breakpoint \[0-9\]+, main \\(argc=.*, argv=.*, envp=.*\\) at .*$srcfile:79.*79\[\t \]+printf.*factorial.*" \
"run until breakpoint set at a line number"
#
# Run until the breakpoint set in a function in a file
#
for {set i 6} {$i >= 1} {incr i -1} {
gdb_test continue "Continuing\\..*Breakpoint \[0-9\]+, factorial \\(value=$i\\) at .*$srcfile:96.*96\[\t \]+.*if .value > 1. \{.*" \
"run until file:function($i) breakpoint"
}
#
# Run until the breakpoint set at a quoted function
#
gdb_test continue "Continuing\\..*Breakpoint \[0-9\]+, (0x\[0-9a-f\]+ in )?marker2 \\(a=43\\) at .*$srcfile:4\[49\].*" \
"run until quoted breakpoint"
#
# run until the file:function breakpoint at a line number in a file
#
gdb_test continue "Continuing\\..*Breakpoint \[0-9\]+, main \\(argc=.*, argv=.*, envp=.*\\) at .*$srcfile:85.*85\[\t \]+argc = \\(argc == 12345\\);.*" \
"run until file:linenum breakpoint"
# Test break at offset +1
gdb_test "break +1" \
"Breakpoint.*at.* file .*$srcfile, line 86\\." \
"breakpoint offset +1"
# Check to see if breakpoint is hit when stepped onto
gdb_test "step" \
".*Breakpoint \[0-9\]+, main \\(argc=.*, argv=.*, envp=.*\\) at .*$srcfile:86.*86\[\t \]+return argc;" \
"step onto breakpoint"
#
# delete all breakpoints so we can start over, course this can be a test too
#
delete_breakpoints
#
# test temporary breakpoint at function
#
gdb_test "tbreak main" "Breakpoint.*at.* file .*$srcfile, line.*" "Temporary breakpoint function"
#
# test break at function in file
#
gdb_test "tbreak $srcfile:factorial" "Breakpoint.*at.* file .*$srcfile, line.*" \
"Temporary breakpoint function in file"
#
# test break at line number
#
send_gdb "tbreak 79\n"
gdb_expect {
-re "Breakpoint.*at.* file .*$srcfile, line 79.*$gdb_prompt $" { pass "Temporary breakpoint line number #1" }
-re ".*$gdb_prompt $" { pass "Temporary breakpoint line number #1" }
timeout { fail "breakpoint line number #1 (timeout)" }
}
gdb_test "tbreak 75" "Breakpoint.*at.* file .*$srcfile, line 75.*" "Temporary breakpoint line number #2"
#
# test break at line number in file
#
send_gdb "tbreak $srcfile:85\n"
gdb_expect {
-re "Breakpoint.*at.* file .*$srcfile, line 85.*$gdb_prompt $" { pass "Temporary breakpoint line number in file #1" }
-re ".*$gdb_prompt $" { pass "Temporary breakpoint line number in file #1" }
timeout { fail "Temporary breakpoint line number in file #1 (timeout)" }
}
gdb_test "tbreak $srcfile:81" "Breakpoint.*at.* file .*$srcfile, line 81.*" "Temporary breakpoint line number in file #2"
#
# check to see what breakpoints are set (temporary this time)
#
gdb_test "info break" "Num Type.*Disp Enb Address.*What.*\[\r\n\]
\[0-9\]+\[\t \]+breakpoint del.*y.*in main at .*$srcfile:$main_line.*\[\r\n\]
\[0-9\]+\[\t \]+breakpoint del.*y.*in factorial at .*$srcfile:96.*\[\r\n\]
\[0-9\]+\[\t \]+breakpoint del.*y.*in main at .*$srcfile:79.*\[\r\n\]
\[0-9\]+\[\t \]+breakpoint del.*y.*in main at .*$srcfile:75.*\[\r\n\]
\[0-9\]+\[\t \]+breakpoint del.*y.*in main at .*$srcfile:85.*\[\r\n\]
\[0-9\]+\[\t \]+breakpoint del.*y.*in main at .*$srcfile:81.*" \
"Temporary breakpoint info"
#***********
# Verify that catchpoints for fork, vfork and exec don't trigger
# inappropriately. (There are no calls to those system functions
# in this test program.)
#
if ![runto_main] then { fail "break tests suppressed" }
send_gdb "catch\n"
gdb_expect {
-re "Catch requires an event name.*$gdb_prompt $"\
{pass "catch requires an event name"}
-re "$gdb_prompt $"\
{fail "catch requires an event name"}
timeout {fail "(timeout) catch requires an event name"}
}
set name "set catch fork, never expected to trigger"
send_gdb "catch fork\n"
gdb_expect {
-re "Catchpoint \[0-9\]* .fork..*$gdb_prompt $"
{pass $name}
-re "Catch of fork not yet implemented.*$gdb_prompt $"
{pass $name}
-re "$gdb_prompt $"
{fail $name}
timeout {fail "(timeout) $name"}
}
set name "set catch vfork, never expected to trigger"
send_gdb "catch vfork\n"
# If we are on HP-UX 10.20, we expect an error message to be
# printed if we type "catch vfork" at the gdb gdb_prompt. This is
# because on HP-UX 10.20, we cannot catch vfork events.
if [istarget "hppa*-hp-hpux10.20"] then {
gdb_expect {
-re "Catch of vfork events not supported on HP-UX 10.20..*$gdb_prompt $"
{pass $name}
-re "$gdb_prompt $"
{fail $name}
timeout {fail "(timeout) $name"}
}
} else {
gdb_expect {
-re "Catchpoint \[0-9\]* .vfork..*$gdb_prompt $"
{pass $name}
-re "Catch of vfork not yet implemented.*$gdb_prompt $"
{pass $name}
-re "$gdb_prompt $"
{fail $name}
timeout {fail "(timeout) $name"}
}
}
set name "set catch exec, never expected to trigger"
send_gdb "catch exec\n"
gdb_expect {
-re "Catchpoint \[0-9\]* .exec..*$gdb_prompt $"
{pass $name}
-re "Catch of exec not yet implemented.*$gdb_prompt $"
{pass $name}
-re "$gdb_prompt $" {fail $name}
timeout {fail "(timeout) $name"}
}
# Verify that GDB responds gracefully when asked to set a breakpoint
# on a nonexistent source line.
#
send_gdb "break 999\n"
gdb_expect {
-re "No line 999 in file .*$gdb_prompt $"\
{pass "break on non-existent source line"}
-re "$gdb_prompt $"\
{fail "break on non-existent source line"}
timeout {fail "(timeout) break on non-existent source line"}
}
# Run to the desired default location. If not positioned here, the
# tests below don't work.
#
gdb_test "until 79" "main .* at .*:79.*" "until 79"
# Verify that GDB allows one to just say "break", which is treated
# as the "default" breakpoint. Note that GDB gets cute when printing
# the informational message about other breakpoints at the same
# location. We'll hit that bird with this stone too.
#
send_gdb "break\n"
gdb_expect {
-re "Breakpoint \[0-9\]*.*$gdb_prompt $"\
{pass "break on default location, 1st time"}
-re "$gdb_prompt $"\
{fail "break on default location, 1st time"}
timeout {fail "(timeout) break on default location, 1st time"}
}
send_gdb "break\n"
gdb_expect {
-re "Note: breakpoint \[0-9\]* also set at .*Breakpoint \[0-9\]*.*$gdb_prompt $"\
{pass "break on default location, 2nd time"}
-re "$gdb_prompt $"\
{fail "break on default location, 2nd time"}
timeout {fail "(timeout) break on default location, 2nd time"}
}
send_gdb "break\n"
gdb_expect {
-re "Note: breakpoints \[0-9\]* and \[0-9\]* also set at .*Breakpoint \[0-9\]*.*$gdb_prompt $"\
{pass "break on default location, 3rd time"}
-re "$gdb_prompt $"\
{fail "break on default location, 3rd time"}
timeout {fail "(timeout) break on default location, 3rd time"}
}
send_gdb "break\n"
gdb_expect {
-re "Note: breakpoints \[0-9\]*, \[0-9\]* and \[0-9\]* also set at .*Breakpoint \[0-9\]*.*$gdb_prompt $"\
{pass "break on default location, 4th time"}
-re "$gdb_prompt $"\
{fail "break on default location, 4th time"}
timeout {fail "(timeout) break on default location, 4th time"}
}
# Verify that a "silent" breakpoint can be set, and that GDB is indeed
# "silent" about its triggering.
#
if ![runto_main] then { fail "break tests suppressed" }
send_gdb "break 79\n"
gdb_expect {
-re "Breakpoint (\[0-9\]*) at .*, line 79.*$gdb_prompt $"\
{pass "set to-be-silent break 79"}
-re "$gdb_prompt $"\
{fail "set to-be-silent break 79"}
timeout {fail "(timeout) set to-be-silent break 79"}
}
send_gdb "commands $expect_out(1,string)\n"
send_gdb "silent\n"
send_gdb "end\n"
gdb_expect {
-re ".*$gdb_prompt $"\
{pass "set silent break 79"}
timeout {fail "(timeout) set silent break 79"}
}
send_gdb "info break $expect_out(1,string)\n"
gdb_expect {
-re "\[0-9\]*\[ \t\]*breakpoint.*:79\r\n\[ \t\]*silent.*$gdb_prompt $"\
{pass "info silent break 79"}
-re "$gdb_prompt $"\
{fail "info silent break 79"}
timeout {fail "(timeout) info silent break 79"}
}
send_gdb "continue\n"
gdb_expect {
-re "Continuing.\r\n$gdb_prompt $"\
{pass "hit silent break 79"}
-re "$gdb_prompt $"\
{fail "hit silent break 79"}
timeout {fail "(timeout) hit silent break 79"}
}
send_gdb "bt\n"
gdb_expect {
-re "#0 main .* at .*:79.*$gdb_prompt $"\
{pass "stopped for silent break 79"}
-re "$gdb_prompt $"\
{fail "stopped for silent break 79"}
timeout {fail "(timeout) stopped for silent break 79"}
}
# Verify that GDB can at least parse a breakpoint with the
# "thread" keyword. (We won't attempt to test here that a
# thread-specific breakpoint really triggers appropriately.
# The gdb.threads subdirectory contains tests for that.)
#
send_gdb "break 80 thread 999\n"
gdb_expect {
-re "Unknown thread 999.*$gdb_prompt $"\
{pass "thread-specific breakpoint on non-existent thread disallowed"}
-re "$gdb_prompt $"\
{fail "thread-specific breakpoint on non-existent thread disallowed"}
timeout {fail "(timeout) thread-specific breakpoint on non-existent thread disallowed"}
}
send_gdb "break 80 thread foo\n"
gdb_expect {
-re "Junk after thread keyword..*$gdb_prompt $"\
{pass "thread-specific breakpoint on bogus thread ID disallowed"}
-re "$gdb_prompt $"\
{fail "thread-specific breakpoint on bogus thread ID disallowed"}
timeout {fail "(timeout) thread-specific breakpoint on bogus thread ID disallowed"}
}
# Verify that GDB responds gracefully to a breakpoint command with
# trailing garbage.
#
send_gdb "break 80 foo\n"
gdb_expect {
-re "Junk at end of arguments..*$gdb_prompt $"\
{pass "breakpoint with trailing garbage disallowed"}
-re "$gdb_prompt $"\
{fail "breakpoint with trailing garbage disallowed"}
timeout {fail "(timeout) breakpoint with trailing garbage disallowed"}
}
# Verify that GDB responds gracefully to a "clear" command that has
# no matching breakpoint. (First, get us off the current source line,
# which we know has a breakpoint.)
#
send_gdb "next\n"
gdb_expect {
-re ".*$gdb_prompt $"\
{pass "step over breakpoint"}
timeout {fail "(timeout) step over breakpoint"}
}
send_gdb "clear 81\n"
gdb_expect {
-re "No breakpoint at 81..*$gdb_prompt $"\
{pass "clear line has no breakpoint disallowed"}
-re "$gdb_prompt $"\
{fail "clear line has no breakpoint disallowed"}
timeout {fail "(timeout) clear line has no breakpoint disallowed"}
}
send_gdb "clear\n"
gdb_expect {
-re "No breakpoint at this line..*$gdb_prompt $"\
{pass "clear current line has no breakpoint disallowed"}
-re "$gdb_prompt $"\
{fail "clear current line has no breakpoint disallowed"}
timeout {fail "(timeout) clear current line has no breakpoint disallowed"}
}
# Verify that we can set and clear multiple breakpoints.
#
# We don't test that it deletes the correct breakpoints. We do at
# least test that it deletes more than one breakpoint.
#
gdb_test "break marker3" "Breakpoint.*at.*" "break marker3 #1"
gdb_test "break marker3" "Breakpoint.*at.*" "break marker3 #2"
gdb_test "clear marker3" {Deleted breakpoints [0-9]+ [0-9]+.*}
# Verify that a breakpoint can be set via a convenience variable.
#
send_gdb "set \$foo=81\n"
gdb_expect {
-re "$gdb_prompt $"\
{pass "set convenience variable \$foo to 81"}
timeout {fail "(timeout) set convenience variable \$foo to 81"}
}
send_gdb "break \$foo\n"
gdb_expect {
-re "Breakpoint (\[0-9\]*) at .*, line 81.*$gdb_prompt $"\
{pass "set breakpoint via convenience variable"}
-re "$gdb_prompt $"\
{fail "set breakpoint via convenience variable"}
timeout {fail "(timeout) set breakpoint via convenience variable"}
}
# Verify that GDB responds gracefully to an attempt to set a
# breakpoint via a convenience variable whose type is not integer.
#
send_gdb "set \$foo=81.5\n"
gdb_expect {
-re "$gdb_prompt $"\
{pass "set convenience variable \$foo to 81.5"}
timeout {fail "(timeout) set convenience variable \$foo to 81.5"}
}
send_gdb "break \$foo\n"
gdb_expect {
-re "Convenience variables used in line specs must have integer values..*$gdb_prompt $"\
{pass "set breakpoint via non-integer convenience variable disallowed"}
-re "$gdb_prompt $"\
{fail "set breakpoint via non-integer convenience variable disallowed"}
timeout {fail "(timeout) set breakpoint via non-integer convenience variable disallowed"}
}
# Verify that we can set and trigger a breakpoint in a user-called function.
#
send_gdb "break marker2\n"
gdb_expect {
-re "Breakpoint (\[0-9\]*) at .*, line 4\[49\].*$gdb_prompt $"\
{pass "set breakpoint on to-be-called function"}
-re "$gdb_prompt $"\
{fail "set breakpoint on to-be-called function"}
timeout {fail "(timeout) set breakpoint on to-be-called function"}
}
send_gdb "print marker2(99)\n"
gdb_expect {
-re "The program being debugged stopped while in a function called from GDB.\r\nWhen the function .marker2. is done executing, GDB will silently\r\nstop .instead of continuing to evaluate the expression containing\r\nthe function call...*$gdb_prompt $"\
{pass "hit breakpoint on called function"}
-re "$gdb_prompt $"\
{fail "hit breakpoint on called function"}
timeout {fail "(timeout) hit breakpoint on called function"}
}
# As long as we're stopped (breakpointed) in a called function,
# verify that we can successfully backtrace & such from here.
#
# In this and the following test, the _sr4export check apparently is needed
# for hppa*-*-hpux.
#
send_gdb "bt\n"
gdb_expect {
-re "#0\[ \t\]*($hex in )?marker2.*:4\[49\]\r\n#1.*_sr4export.*$gdb_prompt $"\
{pass "backtrace while in called function"}
-re "#0\[ \t\]*($hex in )?marker2.*:4\[49\]\r\n#1.*function called from gdb.*$gdb_prompt $"\
{pass "backtrace while in called function"}
-re "$gdb_prompt $"\
{fail "backtrace while in called function"}
timeout {fail "(timeout) backtrace while in called function"}
}
# Return from the called function. For remote targets, it's important to do
# this before runto_main, which otherwise may silently stop on the dummy
# breakpoint inserted by GDB at the program's entry point.
#
send_gdb "finish\n"
gdb_expect {
-re "Run till exit from .*marker2.* at .*4\[49\]\r\n.* in _sr4export.*$gdb_prompt $"\
{pass "finish from called function"}
-re "Run till exit from .*marker2.* at .*4\[49\]\r\n.*function called from gdb.*$gdb_prompt $"\
{pass "finish from called function"}
-re "Run till exit from .*marker2.* at .*4\[49\]\r\n.*Value returned.*$gdb_prompt $"\
{pass "finish from called function"}
-re "$gdb_prompt $"\
{fail "finish from called function"}
timeout {fail "(timeout) finish from called function"}
}
# Verify that GDB responds gracefully to a "finish" command with
# arguments.
#
if ![runto_main] then { fail "break tests suppressed" }
send_gdb "finish 123\n"
gdb_expect {
-re "The \"finish\" command does not take any arguments.\r\n$gdb_prompt $"\
{pass "finish with arguments disallowed"}
-re "$gdb_prompt $"\
{fail "finish with arguments disallowed"}
timeout {fail "(timeout) finish with arguments disallowed"}
}
# Verify that GDB responds gracefully to a request to "finish" from
# the outermost frame. On a stub that never exits, this will just
# run to the stubs routine, so we don't get this error... Thus the
# second condition.
#
send_gdb "finish\n"
gdb_expect {
-re "\"finish\" not meaningful in the outermost frame.\r\n$gdb_prompt $"\
{pass "finish from outermost frame disallowed"}
-re "Run till exit from.*\r\n$gdb_prompt $" {
pass "finish from outermost frame disallowed"
}
-re "$gdb_prompt $"\
{fail "finish from outermost frame disallowed"}
timeout {fail "(timeout) finish from outermost frame disallowed"}
}
# Verify that we can explicitly ask GDB to stop on all shared library
# events, and that it does so.
#
if [istarget "hppa*-*-hpux*"] then {
if ![runto_main] then { fail "break tests suppressed" }
send_gdb "set stop-on-solib-events 1\n"
gdb_expect {
-re "$gdb_prompt $"\
{pass "set stop-on-solib-events"}
timeout {fail "(timeout) set stop-on-solib-events"}
}
send_gdb "run\n"
gdb_expect {
-re ".*Start it from the beginning.*y or n. $"\
{send_gdb "y\n"
gdb_expect {
-re ".*Stopped due to shared library event.*$gdb_prompt $"\
{pass "triggered stop-on-solib-events"}
-re "$gdb_prompt $"\
{fail "triggered stop-on-solib-events"}
timeout {fail "(timeout) triggered stop-on-solib-events"}
}
}
-re "$gdb_prompt $"\
{fail "rerun for stop-on-solib-events"}
timeout {fail "(timeout) rerun for stop-on-solib-events"}
}
send_gdb "set stop-on-solib-events 0\n"
gdb_expect {
-re "$gdb_prompt $"\
{pass "reset stop-on-solib-events"}
timeout {fail "(timeout) reset stop-on-solib-events"}
}
}
# Hardware breakpoints are unsupported on HP-UX. Verify that GDB
# gracefully responds to requests to create them.
#
if [istarget "hppa*-*-hpux*"] then {
if ![runto_main] then { fail "break tests suppressed" }
send_gdb "hbreak\n"
gdb_expect {
-re "No hardware breakpoint support in the target.*$gdb_prompt $"\
{pass "hw breaks disallowed"}
-re "$gdb_prompt $"\
{fail "hw breaks disallowed"}
timeout {fail "(timeout) hw breaks disallowed"}
}
send_gdb "thbreak\n"
gdb_expect {
-re "No hardware breakpoint support in the target.*$gdb_prompt $"\
{pass "temporary hw breaks disallowed"}
-re "$gdb_prompt $"\
{fail "temporary hw breaks disallowed"}
timeout {fail "(timeout) temporary hw breaks disallowed"}
}
}
#********
#
# Test "next" over recursive function call.
#
proc test_next_with_recursion {} {
global gdb_prompt
global decimal
global binfile
if [target_info exists use_gdb_stub] {
# Reload the program.
delete_breakpoints
gdb_load ${binfile};
} else {
# FIXME: should be using runto
gdb_test "kill" "" "kill program" "Kill the program being debugged.*y or n. $" "y"
delete_breakpoints
}
gdb_test "break factorial" "Breakpoint $decimal at .*" "break at factorial"
# Run until we call factorial with 6
if [istarget "*-*-vxworks*"] then {
send_gdb "run vxmain \"6\"\n"
} else {
gdb_run_cmd
}
gdb_expect {
-re "Break.* factorial .value=6. .*$gdb_prompt $" {}
-re ".*$gdb_prompt $" {
fail "run to factorial(6)";
gdb_suppress_tests;
}
timeout { fail "run to factorial(6) (timeout)" ; gdb_suppress_tests }
}
# Continue until we call factorial recursively with 5.
if [gdb_test "continue" \
"Continuing.*Break.* factorial .value=5. .*" \
"continue to factorial(5)"] then { gdb_suppress_tests }
# Do a backtrace just to confirm how many levels deep we are.
if [gdb_test "backtrace" \
"#0\[ \t\]+ factorial .value=5..*" \
"backtrace from factorial(5)"] then { gdb_suppress_tests }
# Now a "next" should position us at the recursive call, which
# we will be performing with 4.
if [gdb_test "next" \
".* factorial .value - 1.;.*" \
"next to recursive call"] then { gdb_suppress_tests }
# Disable the breakpoint at the entry to factorial by deleting them all.
# The "next" should run until we return to the next line from this
# recursive call to factorial with 4.
# Buggy versions of gdb will stop instead at the innermost frame on
# the line where we are trying to "next" to.
delete_breakpoints
if [istarget "mips*tx39-*"] {
set timeout 60
}
# We used to set timeout here for all other targets as well. This
# is almost certainly wrong. The proper timeout depends on the
# target system in use, and how we communicate with it, so there
# is no single value appropriate for all targets. The timeout
# should be established by the Dejagnu config file(s) for the
# board, and respected by the test suite.
#
# For example, if I'm running GDB over an SSH tunnel talking to a
# portmaster in California talking to an ancient 68k board running
# a crummy ROM monitor (a situation I can only wish were
# hypothetical), then I need a large timeout. But that's not the
# kind of knowledge that belongs in this file.
gdb_test next "\[0-9\]*\[\t \]+return \\(value\\);.*" \
"next over recursive call"
# OK, we should be back in the same stack frame we started from.
# Do a backtrace just to confirm.
set result [gdb_test "backtrace" \
"#0\[ \t\]+ factorial .value=120.*\r\n#1\[ \t\]+ \[0-9a-fx\]+ in factorial .value=6..*" \
"backtrace from factorial(5.1)"]
if { $result != 0 } { gdb_suppress_tests }
if [target_info exists gdb,noresults] { gdb_suppress_tests }
gdb_continue_to_end "recursive next test"
gdb_stop_suppressing_tests;
}
test_next_with_recursion
#********
# build a new file with optimization enabled so that we can try breakpoints
# on targets with optimized prologues
set binfileo2 ${objdir}/${subdir}/${testfile}o2
if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfileo2}" executable {debug additional_flags="-O2" }] != "" } {
gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
}
if [get_compiler_info ${binfileo2}] {
return -1
}
gdb_exit
gdb_start
gdb_reinitialize_dir $srcdir/$subdir
gdb_load ${binfileo2}
if [target_info exists gdb_stub] {
gdb_step_for_stub;
}
#
# test break at function
#
gdb_test "break main" \
"Breakpoint.*at.* file .*$srcfile, line.*" \
"breakpoint function, optimized file"
#
# test break at function
#
gdb_test "break marker4" \
"Breakpoint.*at.* file .*$srcfile, line.*" \
"breakpoint small function, optimized file"
#
# run until the breakpoint at main is hit. For non-stubs-using targets.
#
if ![target_info exists use_gdb_stub] {
if [istarget "*-*-vxworks*"] then {
send_gdb "run vxmain \"2\"\n"
set timeout 120
verbose "Timeout is now $timeout seconds" 2
} else {
send_gdb "run\n"
}
gdb_expect {
-re "The program .* has been started already.*y or n. $" {
send_gdb "y\n"
exp_continue
}
-re "Starting program.*Breakpoint \[0-9\]+,.*main .*argc.*argv.* at .*$srcfile:75.*75\[\t \]+if .argc.* \{.*$gdb_prompt $"\
{ pass "run until function breakpoint, optimized file" }
-re "Starting program.*Breakpoint \[0-9\]+,.*main .*argc.*argv.* at .*$gdb_prompt $"\
{ pass "run until function breakpoint, optimized file (code motion)" }
-re ".*$gdb_prompt $" { fail "run until function breakpoint, optimized file" }
timeout { fail "run until function breakpoint, optimized file (timeout)" }
}
} else {
if ![target_info exists gdb_stub] {
gdb_test continue ".*Continuing\\..*Breakpoint \[0-9\]+, main \\(argc=.*, argv=.*, envp=.*\\) at .*$srcfile:75.*75\[\t \]+if .argc.*\{.*" "stub continue, optimized file"
}
}
#
# run until the breakpoint at a small function
#
#
# Add a second pass pattern. The behavior differs here between stabs
# and dwarf for one-line functions. Stabs preserves two line symbols
# (one before the prologue and one after) with the same line number,
# but dwarf regards these as duplicates and discards one of them.
# Therefore the address after the prologue (where the breakpoint is)
# has no exactly matching line symbol, and GDB reports the breakpoint
# as if it were in the middle of a line rather than at the beginning.
send_gdb "continue\n"
gdb_expect {
-re "Breakpoint $decimal, marker4 \\(d=177601976\\) at .*$srcfile:51\[\r\n\]+51\[\t \]+void marker4.*" {
pass "run until breakpoint set at small function, optimized file"
}
-re "Breakpoint $decimal, $hex in marker4 \\(d=177601976\\) at .*$srcfile:51\[\r\n\]+51\[\t \]+void marker4.*" {
pass "run until breakpoint set at small function, optimized file"
}
-re "Breakpoint $decimal, marker4 \\(d=177601976\\) at .*$srcfile:46\[\r\n\]+46\[\t \]+void marker4.*" {
# marker4() is defined at line 46 when compiled with -DPROTOTYPES
pass "run until breakpoint set at small function, optimized file (line 46)"
}
-re ".*$gdb_prompt " {
fail "run until breakpoint set at small function, optimized file"
}
timeout {
fail "run until breakpoint set at small function, optimized file (timeout)"
}
}
# Reset the default arguments for VxWorks
if [istarget "*-*-vxworks*"] {
set timeout 10
verbose "Timeout is now $timeout seconds" 2
send_gdb "set args main\n"
gdb_expect -re ".*$gdb_prompt $" {}
}
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [RFC/WIP] unit test for separate debug info
2003-11-07 20:03 [RFC/WIP] unit test for separate debug info Elena Zannoni
@ 2003-11-07 20:39 ` Kevin Buettner
0 siblings, 0 replies; 8+ messages in thread
From: Kevin Buettner @ 2003-11-07 20:39 UTC (permalink / raw)
To: Elena Zannoni, gdb-patches; +Cc: mec
On Nov 7, 3:03pm, Elena Zannoni wrote:
> Anyway, here is what I did. I used the break.exp and break.c files as
> templates. I actually cloned break.exp and added fiddling with the
> separate debug info. Break.exp is usually a decent smoke test for gdb.
> No need to clone break.c.
Prior to cloning, it'd be nice if break.exp could be converted to use
gdb_get_line_number instead of containing explicit references to line
numbers in break.c.
> (BTW, should cloned files retain the original
> copyright years?)
I think so.
Kevin
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFC/WIP] unit test for separate debug info
@ 2003-11-07 20:21 Michael Elizabeth Chastain
0 siblings, 0 replies; 8+ messages in thread
From: Michael Elizabeth Chastain @ 2003-11-07 20:21 UTC (permalink / raw)
To: ezannoni, gdb-patches
> (BTW, should cloned files retain the original copyright years?)
I believe so.
> Anyway, this needs some pounding by Michael, I think. There probably
> are improvements/changes that could be made.
Okay, I'll jump on it!
Michael C
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFC/WIP] unit test for separate debug info
@ 2003-11-08 1:28 Michael Elizabeth Chastain
2003-11-11 16:26 ` Elena Zannoni
0 siblings, 1 reply; 8+ messages in thread
From: Michael Elizabeth Chastain @ 2003-11-08 1:28 UTC (permalink / raw)
To: ezannoni, gdb-patches
I gave it some proof-reading but did not try running it yet.
The idea looks okay to me.
For documentation, it would help to just have a list of files at the top:
gdb.base/break original executable
gdb.base/break.stripped stripped executable
gdb.base/break.sym debug symbols
gdb.base/break.debuglink output of --add-gnu-debuglink
(Hmmm, my list of files does not have any .debug directory!)
Human beings are good at reading examples and extrapolating
from them, and not as good at handling explicit meta-variables.
I would really like break.debuglink to be a separate file from the
original file. If somebody is debugging this process, it's much better
to have each file be unique.
In gdb_gnu_strip_debug, what are the final values of "strip_to_file_program"
and "objcopy_program" going to be? I am hoping that they will just be
set strip_to_file_program strip
set objcopy_program objcopy
Well, actually that works only for natives, crosses need more work.
I would say, leave the elfutils case out for now.
Michael C
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFC/WIP] unit test for separate debug info
2003-11-08 1:28 Michael Elizabeth Chastain
@ 2003-11-11 16:26 ` Elena Zannoni
0 siblings, 0 replies; 8+ messages in thread
From: Elena Zannoni @ 2003-11-11 16:26 UTC (permalink / raw)
To: Michael Elizabeth Chastain; +Cc: ezannoni, gdb-patches
Michael Elizabeth Chastain writes:
> I gave it some proof-reading but did not try running it yet.
>
> The idea looks okay to me.
>
> For documentation, it would help to just have a list of files at the top:
>
> gdb.base/break original executable
> gdb.base/break.stripped stripped executable
> gdb.base/break.sym debug symbols
> gdb.base/break.debuglink output of --add-gnu-debuglink
>
> (Hmmm, my list of files does not have any .debug directory!)
>
> Human beings are good at reading examples and extrapolating
> from them, and not as good at handling explicit meta-variables.
>
Indeed. The comments must be misleading, because the names of the
files you listed above are not the correct ones. So I'll add such a comment.
The files are
gdb.base/break-->original executable
gdb.base/break.stripped-->stripped exec
gdb.base/.debug/break.debug-->debuginfo only
gdb.base/break-->original exec minus debug symbols plus link to the .debug file
> I would really like break.debuglink to be a separate file from the
> original file. If somebody is debugging this process, it's much better
> to have each file be unique.
At first thought I'd say no, because that's not what you'll encounter
in practice. You would be testing something different. Close but
different. I.e. original executable name == name of final executable.
Indeed if you get a RedHat distro, you get all stripped binaries, but
their names are the usual ones. However, on second thought it may work
anyway. I'll play with it.
>
> In gdb_gnu_strip_debug, what are the final values of "strip_to_file_program"
> and "objcopy_program" going to be? I am hoping that they will just be
>
> set strip_to_file_program strip
> set objcopy_program objcopy
>
yes. I had to tweak them in order to pick up the copies that had the
features, the ones installed on the systems were too old. Note the
failure mode as well. It produces an unsupported. For the RedHat case,
it would pick up eu-strip (but in reality the whole procedure is
different anyway).
> Well, actually that works only for natives, crosses need more work.
>
yes. I am not planning on doing that right now. I guess I should make
the test work only for natives.
> I would say, leave the elfutils case out for now.
>
yep.
> Michael C
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFC/WIP] unit test for separate debug info
@ 2003-11-11 21:19 Michael Elizabeth Chastain
2003-11-11 21:22 ` Daniel Jacobowitz
2003-11-12 14:44 ` Elena Zannoni
0 siblings, 2 replies; 8+ messages in thread
From: Michael Elizabeth Chastain @ 2003-11-11 21:19 UTC (permalink / raw)
To: ezannoni; +Cc: gdb-patches
Hi Elena,
mec> gdb.base/break original executable
mec> gdb.base/break.stripped stripped executable
mec> gdb.base/break.sym debug symbols
mec> gdb.base/break.debuglink output of --add-gnu-debuglink
eza> gdb.base/break-->original executable
eza> gdb.base/break.stripped-->stripped exec
eza> gdb.base/.debug/break.debug-->debuginfo only
eza> gdb.base/break-->original exec minus debug symbols plus link to the .debug file
Ah, I was mixing two things together. I definitely prefer the doco
in the format above. That's one thing. I was also adding in my own
preferences for the file names. That's a different thing.
I like gdb.base/break.sym or gdb.base/break.debug a lot more than
gdb.base/.debug/break.debug. That keeps all the files parallel
instead of some files inside a dot directory.
mec> I would really like break.debuglink to be a separate file from the
mec> original file. If somebody is debugging this process, it's much better
mec> to have each file be unique.
eza> At first thought I'd say no, because that's not what you'll encounter
eza> in practice. You would be testing something different. Close but
eza> different.
I see your point. And I see that you see my point. :) I guess
I'm on your side now. It's important to test what people actually do.
Although if I were building these things as end user of gcc/binutils/gdb,
I would build:
break.full # full debugging info
break.stripped # stripped executable
break.sym # symbols
break.ship # break.full - symbols + link to break.sym
break # copy of break.ship
Oh, yeah, I also like the MS-DOS convention of 'break.exe'
and I would like to change Unix to do that also. So I have
weird taste.
Michael C
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFC/WIP] unit test for separate debug info
2003-11-11 21:19 Michael Elizabeth Chastain
@ 2003-11-11 21:22 ` Daniel Jacobowitz
2003-11-12 14:44 ` Elena Zannoni
1 sibling, 0 replies; 8+ messages in thread
From: Daniel Jacobowitz @ 2003-11-11 21:22 UTC (permalink / raw)
To: Michael Elizabeth Chastain; +Cc: ezannoni, gdb-patches
On Tue, Nov 11, 2003 at 04:19:24PM -0500, Michael Elizabeth Chastain wrote:
> Hi Elena,
>
> mec> gdb.base/break original executable
> mec> gdb.base/break.stripped stripped executable
> mec> gdb.base/break.sym debug symbols
> mec> gdb.base/break.debuglink output of --add-gnu-debuglink
>
> eza> gdb.base/break-->original executable
> eza> gdb.base/break.stripped-->stripped exec
> eza> gdb.base/.debug/break.debug-->debuginfo only
> eza> gdb.base/break-->original exec minus debug symbols plus link to the .debug file
>
> Ah, I was mixing two things together. I definitely prefer the doco
> in the format above. That's one thing. I was also adding in my own
> preferences for the file names. That's a different thing.
>
> I like gdb.base/break.sym or gdb.base/break.debug a lot more than
> gdb.base/.debug/break.debug. That keeps all the files parallel
> instead of some files inside a dot directory.
The dot directory is special - GDB knows to search $dir/.debug/ for
these files, and that's how it will be used in the real world. I
believe it's usually:
/usr/lib/libfoo.so
/usr/lib/.debug/libfoo.so
> break.full # full debugging info
> break.stripped # stripped executable
> break.sym # symbols
> break.ship # break.full - symbols + link to break.sym
> break # copy of break.ship
Sure, you might build them that way. But you wouldn't ship/install
them that way.
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFC/WIP] unit test for separate debug info
2003-11-11 21:19 Michael Elizabeth Chastain
2003-11-11 21:22 ` Daniel Jacobowitz
@ 2003-11-12 14:44 ` Elena Zannoni
1 sibling, 0 replies; 8+ messages in thread
From: Elena Zannoni @ 2003-11-12 14:44 UTC (permalink / raw)
To: Michael Elizabeth Chastain; +Cc: ezannoni, gdb-patches
Michael Elizabeth Chastain writes:
> Hi Elena,
>
> Ah, I was mixing two things together. I definitely prefer the doco
> in the format above. That's one thing. I was also adding in my own
> preferences for the file names. That's a different thing.
>
I agree with you about the comment needing to be more explicit.
> I like gdb.base/break.sym or gdb.base/break.debug a lot more than
> gdb.base/.debug/break.debug. That keeps all the files parallel
> instead of some files inside a dot directory.
>
Can't do this one. This is the way that gdb is doing the search, the
default configuration is such that it looks into the .debug
subdirectory. However, you bring up another valid point, which is
that there is a command in gdb that allows you to change the default
location of the debug files. And I forgot to add that to the test. I
think I'll do the default location, then move/copy the .debug file and
test the gdb command that changes the location.
>
> I see your point. And I see that you see my point. :) I guess
> I'm on your side now. It's important to test what people actually do.
> Although if I were building these things as end user of gcc/binutils/gdb,
> I would build:
>
> break.full # full debugging info
> break.stripped # stripped executable
> break.sym # symbols
> break.ship # break.full - symbols + link to break.sym
> break # copy of break.ship
>
yes, true. But the distros are coming out with the weird name scheme.
In reality it doesn't make much of a difference. I can change the name
of the final executable in the testcase, and I tried that, no difference.
> Oh, yeah, I also like the MS-DOS convention of 'break.exe'
> and I would like to change Unix to do that also. So I have
> weird taste.
>
er....
elena
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2003-11-12 14:44 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-11-07 20:03 [RFC/WIP] unit test for separate debug info Elena Zannoni
2003-11-07 20:39 ` Kevin Buettner
2003-11-07 20:21 Michael Elizabeth Chastain
2003-11-08 1:28 Michael Elizabeth Chastain
2003-11-11 16:26 ` Elena Zannoni
2003-11-11 21:19 Michael Elizabeth Chastain
2003-11-11 21:22 ` Daniel Jacobowitz
2003-11-12 14:44 ` Elena Zannoni
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox