ld-r.exp   [plain text]


# Copyright 2005 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.  

if $tracelevel then {
        strace $tracelevel
        }

#
# This tests if for gdb's handling of files produced with
# ld -r.  There are two things being tested here.  In the
# -gfull -Wl,-Sp case, it's whether we properly get the BINCL/EINCL
# dependencies when we are reading out of a .o.  And for -gused
# it is whether the debug info survives the coalescing process.
#

set prms_id 0
set bug_id 0

proc do_tests {use_ld} {
    global srcdir objdir subdir gdb_prompt
    global debug_default_format_is_dwarf gdb_test_apple_dsym

    set ld_flags {}

    set test_name "ld-r testing"
    if {!$use_ld} {
	append test_name " - ar"
    }
    if {$debug_default_format_is_dwarf && $gdb_test_apple_dsym == 0} {
	append test_name " - debug info in .o files"
    }
    set testfile "test-ld-r"
    set ld_r_file "ld-r.o"

    set main "main"

    set fooName "foo"
    set barName "bar"

    # These two we build oddly...  
    set bazName "baz"
    set multName "multiplier"

    
    set binfile  "${objdir}/${subdir}/${testfile}"
    set additional_flags additional_flags=""
    
    # This is a bit complicated seeming.  What I want to make sure is that I have
    #  1) two "ld -r" .o files.
    #  2) nested BINCL/EINCL's
    #  3) two BINCL/EINCL's with the same filename but different hashes.

    foreach {src} {main foo foo-2 bar bar-2} {
	if  { [gdb_compile "$srcdir/$subdir/$src.cc" "$objdir/$subdir/$src.o" object [list debug $additional_flags c++]] != "" } {
	    gdb_suppress_entire_file "Testcase compile failed for $test_name, so all tests in this file will automatically fail."
	}
    }
    
    if  { [gdb_compile "$srcdir/$subdir/multiplier.cc" "$objdir/$subdir/multiplier.o" object [list debug $additional_flags c++]] != "" } {
	gdb_suppress_entire_file "Testcase compile failed for $test_name, so all tests in this file will automatically fail."
    }

    set additional_flags "additional_flags= -DUSE_LONG"

    if  { [gdb_compile "$srcdir/$subdir/multiplier.cc" "$objdir/$subdir/multiplier-long.o" object [list debug $additional_flags c++]] != "" } {
	gdb_suppress_entire_file "Testcase compile failed for $test_name, so all tests in this file will automatically fail."
    }

    foreach {src} {baz baz-2} {
	if  { [gdb_compile "$srcdir/$subdir/$src.cc" "$objdir/$subdir/$src.o" object [list debug $additional_flags c++]] != "" } {
	    gdb_suppress_entire_file "Testcase compile failed for $test_name, so all tests in this file will automatically fail."
	}
    }
    
    if {$use_ld} {
	set intermediate_obj $objdir/$subdir/ld-r.o
	set command "ld -r \"$objdir/$subdir/foo.o\" \"$objdir/$subdir/bar.o\" \"$objdir/$subdir/baz.o\" -o \"$intermediate_obj\""
    } else {
	set intermediate_obj $objdir/$subdir/ld-r.a
	file delete $intermediate_obj
	set command "ar -c -q \"$intermediate_obj\" \"$objdir/$subdir/foo.o\" \"$objdir/$subdir/bar.o\" \"$objdir/$subdir/baz.o\""
    }
    set status [remote_exec  host $command]
    if {[lindex $status 0] != 0} {
	puts [lindex $status 1]
	gdb_suppress_entire_file "Testcase ld -r failed for $test_name, so all tests in this file will automatically fail."
    }
    
    if {!$use_ld} {
	set command "ranlib \"$intermediate_obj\""
	
	set status [remote_exec  host $command]
	if {[lindex $status 0] != 0} {
	    puts [lindex $status 1]
	    gdb_suppress_entire_file "Testcase ld -r failed for $test_name, so all tests in this file will automatically fail."
	}
    }


    set command "ld -r \"$objdir/$subdir/foo-2.o\" \"$objdir/$subdir/bar-2.o\" \"$objdir/$subdir/baz-2.o\" -o \"$objdir/$subdir/ld-r-2.o\""
    set status [remote_exec  host $command]
    if {[lindex $status 0] != 0} {
	puts [lindex $status 1]
	gdb_suppress_entire_file "Testcase ld -r failed for $test_name, so all tests in this file will automatically fail."
    }
    
    set command "ld -r \"$objdir/$subdir/multiplier-long.o\" \"$objdir/$subdir/multiplier.o\" -o \"$objdir/$subdir/ld-r-3.o\""
    set status [remote_exec  host $command]
    if {[lindex $status 0] != 0} {
	puts [lindex $status 1]
	gdb_suppress_entire_file "Testcase ld -r failed for $test_name, so all tests in this file will automatically fail."
    }
    
    
    set additional_flags additional_flags=""
    if  { [gdb_compile "$objdir/$subdir/ld-r-2.o $objdir/$subdir/ld-r-3.o $objdir/$subdir/main.o $intermediate_obj" "${binfile}" executable [list debug $additional_flags c++]] != "" } {
	gdb_suppress_entire_file "Testcase compile failed for $test_name, so all tests in this file will automatically fail."
    }

    if [get_compiler_info ${binfile} "c++"] {
	return -1
    }
    
    
    
    # Start with a fresh gdb
    gdb_exit
    gdb_start
    gdb_reinitialize_dir $srcdir/$subdir
    gdb_file_cmd "${binfile}"
    
    send_gdb "set width 0\n"
    gdb_expect -re "$gdb_prompt $"
    
    # The order is a little tricky here for the -gfull -Wl,-Sp case.
    # foo.cc in the ld-r file actually has the BINCL/EINCL,
    # and the other files the EXCL.  We want to make sure we hit the one with the EXCL first, 
    # so we test that the debugger actually builds the dependency list correctly.

    gdb_test "break barFunc" "Breakpoint 1.*bar.cc.*" "First break at bar: $test_name"
    
    # Note, runto_main does delete_breakpoint, that's why we have to reset it below.
    if {![runto_main]} {
	fail "Running to main suppressing testcase"
	return -1
    }

    gdb_test "break fooFunc" "Breakpoint 3.*foo.cc.*" "Break at foo: $test_name"
    gdb_test "break barFunc" "Breakpoint 4.*bar.cc.*" "Break at bar: $test_name"
    gdb_test "break bazFunc" "Breakpoint 5.*baz.cc.*" "Break at baz: $test_name"

    foreach {break func value} {3 foo 4000 4 bar 25 5 baz 4000} {
        gdb_test "continue" "Continuing\\..*Breakpoint $break, ${func}Func.*$func.cc.*" "Hit breakpoint at ${func}Func: $test_name"
	gdb_test "ptype mine" "type = class MyBlubby \{\r\n.*private:\r\n.*use_me value;(\r\n.*)*" "ptype mine in ${func}Func: $test_name"
        gdb_test "finish" "Run till exit from \#0.*${func}Func.* at .*$func.cc.*\\r\\n.*in main.*main.cc.*\\r\\n.*\\r\\nValue returned is \\\$\[0-9\] = $value" "Finish from ${func}Func: $test_name"
    }

    gdb_test "break fooFunc2" "Breakpoint 6.*foo-2.cc.*" "Break at foo-2: $test_name"
    gdb_test "break bazFunc2" "Breakpoint 7.*baz-2.cc.*" "Break at baz-2: $test_name"
    
    gdb_test "continue" "Continuing\\..*Breakpoint 6, fooFunc2.*foo-2.cc.*" "Hit breakpoint at fooFunc2: $test_name"
    gdb_test "ptype multiplier" "type = long long int" "ptype in fooFunc2: $test_name"

    gdb_test "continue" "Continuing\\..*Breakpoint 7, bazFunc2.*baz-2.cc.*" "Hit breakpoint at bazFunc2: $test_name"
    gdb_test "ptype multiplier" "type = long int" "ptype in bazFunc2: $test_name"

    gdb_exit

    # If the debug info was left in the .o files, let's make sure our time
    # check is working correctly.

    if {$debug_default_format_is_dwarf == 1&& $gdb_test_apple_dsym == 0} {
	# Start with a fresh gdb
	gdb_exit
	gdb_start
	gdb_reinitialize_dir $srcdir/$subdir
	gdb_file_cmd "${binfile}"
	
       
	send_gdb "set width 0\n"
	gdb_expect -re "$gdb_prompt $"

	if {$use_ld == 0} {
	    # If this is the "ar" case, we have to rebuild the .a file as well,
	    # since we are using the time of the .o file in the archive, not the 
	    # archive time.

	    # First make sure we aren't fooled by the archive time changing:
	    set intermediate_obj $objdir/$subdir/ld-r.a

	    file mtime $intermediate_obj [clock seconds]
	    send_gdb "break barFunc\n"
	    gdb_expect {
		-re ".*warning: .o.*\[\r\n\].*$gdb_prompt" {
		    fail "No warning for just changing .a file timestamp: $test_name"
		}
		-re ".*Breakpoint 1.*bar.cc.*\[\r\n\].*$gdb_prompt" {
		    pass "No warning for just changing .a file timestamp: $test_name"
		}
		-re "$gdb_prompt $" {
		    fail "No warning for just changing .a file timestamp: $test_name"
		}
		timeout {
		    fail "No warning for just changing .a file timestamp: $test_name"
		}
	    }

	    # Now really alter the .o file in the archive and test again.
	    file mtime $objdir/$subdir/foo.o [clock seconds]
	    file delete $intermediate_obj
	    set command "ar -c -q \"$intermediate_obj\" \"$objdir/$subdir/foo.o\" \"$objdir/$subdir/bar.o\" \"$objdir/$subdir/baz.o\""
	    set status [remote_exec  host $command]
	    if {[lindex $status 0] != 0} {
		puts [lindex $status 1]
		fail "Could not rebuild .a file: $test_name"
	    }
	    gdb_test "break fooFunc" "(warning:.*\r\n)+Breakpoint 2.*foo.cc.*" "Got warnings for mismatched timestamp1: $test_name"

	} else {
	    file mtime $objdir/$subdir/ld-r.o [clock seconds]
	    if  { [gdb_compile "$srcdir/$subdir/foo.cc" "$objdir/$subdir/foo.o" object [list debug $additional_flags c++]] != "" } {
	        gdb_suppress_entire_file "Testcase compile failed for $test_name, so all tests in this file will automatically fail."
	    }
	    gdb_test "break fooFunc" "warning: .o file.*more recent than executable timestamp.*Breakpoint 1.*foo.cc.*" "Got warnings for mismatched timestamp2: $test_name"
	}
    }
}

do_tests 0
do_tests 1

return 0