# Copyright 2002-2013 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".


set testfile "gcore"
set srcfile  ${testfile}.c
set binfile  ${objdir}/${subdir}/${testfile}

if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
     untested gcore.exp
     return -1
}

# Start with a fresh gdb.

gdb_exit
gdb_start
gdb_reinitialize_dir $srcdir/$subdir
gdb_load ${binfile}

# Does this gdb support gcore?
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.exp
    return -1
}

proc capture_command_output { command prefix } {
    global gdb_prompt
    global expect_out

    set output_string ""
    gdb_test_multiple "$command" "capture_command_output for $command" {
	-re "${command}\[\r\n\]+${prefix}(.*)\[\r\n\]+$gdb_prompt $" {
	    set output_string $expect_out(1,string)
	}
    }
    return $output_string
}

gdb_test "break terminal_func" "Breakpoint .* at .*${srcfile}, line .*" \
	"set breakpoint at terminal_func"

gdb_test "continue" "Breakpoint .* terminal_func.*" \
	"continue to terminal_func"

set print_prefix ".\[0123456789\]* = "

set pre_corefile_backtrace [capture_command_output "backtrace" ""]
set pre_corefile_regs [capture_command_output "info registers" ""]
set pre_corefile_allregs [capture_command_output "info all-reg" ""]
set pre_corefile_sysregs [capture_command_output "info reg system" ""]
set pre_corefile_static_array \
	[capture_command_output "print static_array" "$print_prefix"]
set pre_corefile_uninit_array \
	[capture_command_output "print un_initialized_array" "$print_prefix"]
set pre_corefile_heap_string \
	[capture_command_output "print heap_string" "$print_prefix"]
set pre_corefile_local_array \
	[capture_command_output "print array_func::local_array" "$print_prefix"]
set pre_corefile_extern_array \
	[capture_command_output "print extern_array" "$print_prefix"]

set corefile "${objdir}/${subdir}/gcore.test"
set core_supported [gdb_gcore_cmd "$corefile" "save a corefile"]
if {!$core_supported} {
  return -1
}

# Now restart gdb and load the corefile.
gdb_exit
gdb_start
gdb_reinitialize_dir $srcdir/$subdir
gdb_load ${binfile}

set core_loaded [gdb_core_cmd "$corefile" "re-load generated corefile"]
if { $core_loaded == -1 } {
    # No use proceeding from here.
    return
}

gdb_test_sequence "where" "where in corefile" {
    "\[\r\n\]+#0 .* terminal_func \\(\\) at "
    "\[\r\n\]+#1 .* array_func \\(\\) at "
    "\[\r\n\]+#2 .* factorial_func \\(value=1\\) at "
    "\[\r\n\]+#3 .* factorial_func \\(value=2\\) at "
    "\[\r\n\]+#4 .* factorial_func \\(value=3\\) at "
    "\[\r\n\]+#5 .* factorial_func \\(value=4\\) at "
    "\[\r\n\]+#6 .* factorial_func \\(value=5\\) at "
    "\[\r\n\]+#7 .* factorial_func \\(value=6\\) at "
    "\[\r\n\]+#8 .* main \\(.*\\) at "
}

set post_corefile_regs [capture_command_output "info registers" ""]
if ![string compare $pre_corefile_regs $post_corefile_regs] then {
    pass "corefile restored general registers"
} else {
    fail "corefile restored general registers"
}

set post_corefile_allregs [capture_command_output "info all-reg" ""]
if ![string compare $pre_corefile_allregs $post_corefile_allregs] then {
    pass "corefile restored all registers"
} else {
    fail "corefile restored all registers"
}

set post_corefile_sysregs [capture_command_output "info reg system" ""]
if ![string compare $pre_corefile_sysregs $post_corefile_sysregs] then {
    pass "corefile restored system registers"
} else {
    fail "corefile restored system registers"
}

set post_corefile_extern_array \
	[capture_command_output "print extern_array" "$print_prefix"]
if ![string compare $pre_corefile_extern_array $post_corefile_extern_array]  {
    pass "corefile restored extern array"
} else {
    fail "corefile restored extern array"
}

set post_corefile_static_array \
	[capture_command_output "print static_array" "$print_prefix"]
if ![string compare $pre_corefile_static_array $post_corefile_static_array]  {
    pass "corefile restored static array"
} else {
    fail "corefile restored static array"
}

set post_corefile_uninit_array \
	[capture_command_output "print un_initialized_array" "$print_prefix"]
if ![string compare $pre_corefile_uninit_array $post_corefile_uninit_array]  {
    pass "corefile restored un-initialized array"
} else {
    fail "corefile restored un-initialized array"
}

set post_corefile_heap_string \
	[capture_command_output "print heap_string" "$print_prefix"]
if ![string compare $pre_corefile_heap_string $post_corefile_heap_string]  {
    pass "corefile restored heap array"
} else {
    fail "corefile restored heap array"
}

set post_corefile_local_array \
	[capture_command_output "print array_func::local_array" "$print_prefix"]
if ![string compare $pre_corefile_local_array $post_corefile_local_array]  {
    pass "corefile restored stack array"
} else {
    fail "corefile restored stack array"
}

set post_corefile_backtrace [capture_command_output "backtrace" ""]
if ![string compare $pre_corefile_backtrace $post_corefile_backtrace]  {
    pass "corefile restored backtrace"
} else {
    fail "corefile restored backtrace"
}
