# Copyright (C) 2003-2021 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/>.
#

# Tests for shared object file relocation. If two shared objects have
# the same load address (actually, overlapping load spaces), one of
# them gets relocated at load-time. Check that gdb gets the right
# values for the debugging and minimal symbols.

if {[skip_shlib_tests]} {
    return 0
}

#
# This file uses shreloc.c, shreloc1.c and shreloc2.c
#


standard_testfile .c shreloc1.c shreloc2.c

set srcfile $srcdir/$subdir/$srcfile
set lib1src $srcdir/$subdir/$srcfile2
set lib2src $srcdir/$subdir/$srcfile3
set binfile [standard_output_file $testfile]
set lib1_sl [standard_output_file shreloc1.sl]
set lib2_sl [standard_output_file shreloc2.sl]

if [get_compiler_info] {
    return -1
}

set lib_opts "debug"
set exec_opts [list debug shlib=$lib1_sl shlib=$lib2_sl]

if {([istarget "*pc-cygwin"] || [istarget "*pc-mingw32"]) } {
    lappend lib_opts "ldflags=-Wl,--image-base,0x04000000"
}

if [test_compiler_info "xlc-*"] {

    # IBM's xlc compiler does not add static variables to the ELF symbol 
    # table by default.  We need this option to make the variables show 
    # up in "maint print msymbols". 

    lappend lib_opts "additional_flags=-qstatsym"

}

if { [gdb_compile_shlib $lib1src $lib1_sl $lib_opts] != ""} {
    untested "could not build $lib1_sl."
    return -1
} elseif { [gdb_compile_shlib $lib2src $lib2_sl $lib_opts] != ""} {
    untested "could not build $lib1_s2."
    return -1
} elseif { [gdb_compile $srcfile $binfile executable $exec_opts] != ""} {
    untested "could not build $binfile."
    return -1
}

# Start with a fresh gdb.

clean_restart $binfile
gdb_load_shlib $lib1_sl
gdb_load_shlib $lib2_sl

# Load up the shared objects
if ![runto_main] then {
    return 0
}

#
# Check debugging symbol relocations
#

# Check extern function for relocation
set fn_1_addr [get_var_address fn_1]
set fn_2_addr [get_var_address fn_2]

if { "${fn_1_addr}" == "${fn_2_addr}" } {
  fail "relocated extern functions have different addresses"
} else {
  pass "relocated extern functions have different addresses"
}

# Check extern var for relocation
set extern_var_1_addr [get_var_address extern_var_1]
set extern_var_2_addr [get_var_address extern_var_2]

if { "${extern_var_1_addr}" == "${extern_var_2_addr}" } {
  fail "relocated extern variables have different addresses"
} else {
  pass "relocated extern variables have different addresses"
}

# Check static var for relocation
set static_var_1_addr [get_var_address static_var_1]
set static_var_2_addr [get_var_address static_var_2]

if { "${static_var_1_addr}" == "${static_var_2_addr}" } {
  fail "relocated static variables have different addresses"
} else {
  pass "relocated static variables have different addresses"
}

#
# Check minimal symbol relocations
#

proc send_gdb_discard { command } {
    # Send a command to gdb and discard output up to the next prompt

    global gdb_prompt

    # Discard output
    gdb_test_multiple "${command}" "${command}" {
	-re ".*\[\r\n]+${gdb_prompt} $" {
	    return 1
	}
	timeout {
	    fail "{$command} (timeout)"
	    return 0
	}
    }
}

proc get_msym_addrs { var msymfile } {
    # Extract the list of values for symbols matching var in the
    # minimal symbol output file

    global gdb_prompt hex
    set result ""

    send_gdb "shell grep -E \" ${var}(\[ \t\]+.*)?\$\" ${msymfile}\n"

    while 1 {
	gdb_expect {
	    -re "\[\[\]\[ 0-9\]+\] . (${hex}) ${var}(\[ \t\]+\[^\r\n\]*)?\[\r\n\]+" {
		set result [concat $result $expect_out(1,string)]
	    }

	    -re "$gdb_prompt $" {
		pass "get_msym_addrs ${var}"
		return "${result}"
	    }

	    -re "\[^\r\n\]*\[\r\n\]+" {
		# Skip
	    }

	    timeout {
		fail "get_msym_addrs ${var} (timeout)"
		return -1
	    }
	}
    }
}

proc check_same {var msymfile} {
    # Check that the minimal symbol values matching var are the same

    set len [llength [lsort -unique [get_msym_addrs "${var}" "${msymfile}"]]]

    if { $len == 1 } {
	return 1
    } else {
	return 0
    }
}

proc check_different {var msymfile} {
    # Check that the minimal symbol values matching var are different

    set addr_list [lsort [get_msym_addrs "${var}" "${msymfile}"]]
    set prev ""

    if { [llength ${addr_list}] < 2 } {
	return 0
    }

    foreach addr ${addr_list} {
	if { ${prev} == ${addr} } {
	  return 0
	}
	set prev ${addr}
    }

    return 1
}

if [is_remote host] {
    set msymfile shreloc.txt
} else {
    set msymfile [standard_output_file shreloc.txt]
}

if [send_gdb_discard "maint print msymbols ${msymfile}"] {
    if {[check_different "static_var_\[12\]" "${msymfile}"]} {
	pass "(msymbol) relocated static vars have different addresses"
    } else {
	fail "(msymbol) relocated static vars have different addresses"
    }

    if {[check_different "extern_var_\[12\]" "${msymfile}"]} {
	pass "(msymbol) relocated extern vars have different addresses"
    } else {
	fail "(msymbol) relocated extern vars have different addresses"
    }

    if {[check_different "fn_\[12\]" "${msymfile}"]} {
	pass "(msymbol) relocated functions have different addresses"
    } else {
	fail "(msymbol) relocated functions have different addresses"
    }
}

if {([istarget "*pc-cygwin"] || [istarget "*pc-mingw32"]) } {
    #
    # We know the names of some absolute symbols included in the
    # portable-executable (DLL) format. Check that they didn't get
    # relocated.
    #
    # A better approach would be include absolute symbols via the assembler.
    #
    if {[check_same "_minor_os_version__" "${msymfile}"]} {
	pass "absolute symbols not relocated"
    } else {
	fail "absolute symbols not relocated"
    }
}
