# Copyright 2002, 2003, 2004, 2007, 2008, 2009, 2010, 2011
# 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/>.

# This file was written by Michael Snyder (msnyder@redhat.com)
# This is a test for the gdb command "generate-core-file".

if $tracelevel then {
	strace $tracelevel
}

# Single-threaded test case
set testfile "gcore-thread"
set srcfile  pthreads.c
set objfile  ${objdir}/${subdir}/${testfile}.o
set binfile  ${objdir}/${subdir}/${testfile}
set corefile ${objdir}/${subdir}/${testfile}.test
set core0file ${objdir}/${subdir}/${testfile}0.test

if [istarget "*-*-linux"] then {
    set target_cflags "-D_MIT_POSIX_THREADS"
} else {
    set target_cflags ""
}

# Attempt to prevent -Wl,-z,relro which happens by default at least on
# Kubuntu-10.10.  Due to PR corefiles/11804 will then GDB be unable to find
# libpthread, therefore libthread_db will not fail as expected
# on the test `zeroed-threads cannot be listed'.

set opts [list debug "incdir=${objdir}"]
if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${objfile}" object $opts] != ""
    || ([gdb_compile_pthreads "${objfile}" "${binfile}" executable [concat $opts {additional_flags=-Wl,-z,norelro}] ] != ""
        && [gdb_compile_pthreads "${objfile}" "${binfile}" executable $opts] != "") } {
    return -1
}

# Now we can proceed with the real testing.

# Start with a fresh gdb.

clean_restart ${testfile}

# regexp for "horizontal" text (i.e. doesn't include newline or
# carriage return)
set horiz "\[^\n\r\]*"

# regexp for newline
set nl "\[\r\n\]+"

set timeout 30

gdb_test_multiple "help gcore" "help gcore" {
    -re "Undefined command: .gcore.*$gdb_prompt $" {
	# gcore command not supported -- nothing to test here.
	unsupported "gdb does not support gcore on this target"
	return -1;
    }
    -re "Save a core file .*$gdb_prompt $" {
	pass "help gcore"
    }
}

if { ! [ runto_main ] } then {
    untested gcore-thread.exp
    return -1
}

gdb_test_multiple "info threads" "threads are supported" {
    -re ".* main .*$gdb_prompt $" {
	# OK, threads are supported.
    }
    -re "${nl}$gdb_prompt $" {
	unsupported "gdb does not support threads on this target"
	return -1;
    }
}

# Make sure thread 1 is running
delete_breakpoints
gdb_breakpoint "thread1"
gdb_test "continue" "Continuing.*Breakpoint.* thread1 .*" "thread 1 is running"

# Make sure thread 2 is running
delete_breakpoints
gdb_breakpoint "thread2"
gdb_test "continue" "Continuing.*Breakpoint.* thread2 .*" "thread 2 is running"

set escapedfilename [string_to_regexp $corefile]
# Drop corefile
set core_supported 0
gdb_test_multiple "gcore $corefile" "save a corefile" \
{
  -re "Saved corefile ${escapedfilename}\[\r\n\]+$gdb_prompt $" {
    pass "save a corefile"
    global core_supported
    set core_supported 1
  }
  -re "Can't create a corefile\[\r\n\]+$gdb_prompt $" {
    unsupported "save a corefile"
  }
}

if {!$core_supported} {
  return -1
}


# Test the uninitialized thread list.
# Provide the case of glibc td_thr_get_info handling of:
# /* Special case for the main thread before initialization.  */

foreach symbol {__stack_user stack_used} {
    set test "clear ${symbol}.next"
    gdb_test_multiple "p *(void **) &${symbol} = 0" $test {
	-re " = \\(void \\*\\) 0x0\r\n$gdb_prompt $" {
	    pass $test
	}
	-re "No symbol \"${symbol}\" in current context\\.\r\n$gdb_prompt $" {
	    xfail $test
	    # Do not do the verification.
	    set core0file ""
	}
    }
}

if {"$core0file" != ""} {
    gdb_test "gcore $core0file" "Saved corefile .*" "save a zeroed-threads corefile"
}


# Now restart gdb and load the corefile.
clean_restart ${testfile}

proc load_core { corefile } {
    global gdb_prompt
    global libthread_db_seen

    set libthread_db_seen 0
    gdb_test_multiple "core $corefile" \
	"re-load generated corefile" {
	    -re "\\\[Thread debugging using \[^ \r\n\]* enabled\\\]\r\n" {
		set libthread_db_seen 1
		exp_continue
	    }
	    -re " is not a core dump:.*\r\n$gdb_prompt $" {
		fail "re-load generated corefile (bad file format)"
		# No use proceeding from here.
		return 0;
	    }
	    -re ": No such file or directory.*\r\n$gdb_prompt $" {
		fail "re-load generated corefile (file not found)"
		# No use proceeding from here.
		return 0;
	    }
	    -re "Couldn't find .* registers in core file.*\r\n$gdb_prompt $" {
		fail "re-load generated corefile (incomplete note section)"
	    }
	    -re "Core was generated by .*\r\n$gdb_prompt $" {
		pass "re-load generated corefile"
	    }
	}
    return 1
}

if ![load_core $corefile] {
    return
}

# FIXME: now what can we test about the thread state?
# We do not know for certain that there should be at least 
# three threads, because who knows what kind of many-to-one
# mapping various OS's may do?  Let's assume that there must
# be at least two threads:

gdb_test "info threads" ".*${nl}  2 ${horiz}${nl}\\* 1 .*" \
	"corefile contains at least two threads"

# One thread in the corefile should be in the "thread2" function.

gdb_test "info threads" ".* thread2 .*" \
	"a corefile thread is executing thread2"

# The thread2 thread should be marked as the current thread.

gdb_test "info threads" ".*${nl}\\* ${horiz} thread2 .*" \
	"thread2 is current thread in corefile"


# Test the uninitialized thread list.

if {"$core0file" != "" && [load_core $core0file]} {
    set test "zeroed-threads cannot be listed"

    if {!$libthread_db_seen} {
	verbose -log "No libthread_db loaded - -Wl,-z,relro compilation?"
	xfail $test
    } else {
	gdb_test "info threads" "Cannot find new threads: .*" $test
    }
}
