aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--Makefile.def4
-rw-r--r--Makefile.in13
-rw-r--r--libctf/ChangeLog17
-rw-r--r--libctf/Makefile.am35
-rw-r--r--libctf/Makefile.in113
-rw-r--r--libctf/testsuite/config/default.exp59
-rw-r--r--libctf/testsuite/lib/ctf-lib.exp409
-rw-r--r--libctf/testsuite/libctf-lookup/ambiguous-struct-A.c8
-rw-r--r--libctf/testsuite/libctf-lookup/ambiguous-struct-B.c5
-rw-r--r--libctf/testsuite/libctf-lookup/ambiguous-struct.c51
-rw-r--r--libctf/testsuite/libctf-lookup/ambiguous-struct.lk4
-rw-r--r--libctf/testsuite/libctf-lookup/enum-ctf.c8
-rw-r--r--libctf/testsuite/libctf-lookup/enum.c78
-rw-r--r--libctf/testsuite/libctf-lookup/enum.lk10
-rw-r--r--libctf/testsuite/libctf-lookup/lookup.exp43
16 files changed, 837 insertions, 26 deletions
diff --git a/ChangeLog b/ChangeLog
index 7e57a54..5831a32 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2021-01-05 Nick Alcock <nick.alcock@oracle.com>
+
+ * Makefile.def (libctf): No longer no_check. Checking depends on
+ all-ld.
+ * Makefile.in: Regenerated.
+
2021-01-05 Nick Clifton <nickc@redhat.com>
* libiberty: Sync with gcc. Bring in:
diff --git a/Makefile.def b/Makefile.def
index 089e70a..cc429aa 100644
--- a/Makefile.def
+++ b/Makefile.def
@@ -131,8 +131,7 @@ host_modules= { module= lto-plugin; bootstrap=true;
extra_make_flags='@extra_linker_plugin_flags@'; };
host_modules= { module= libcc1; extra_configure_flags=--enable-shared; };
host_modules= { module= gotools; };
-host_modules= { module= libctf; no_check=true;
- bootstrap=true; };
+host_modules= { module= libctf; bootstrap=true; };
target_modules = { module= libstdc++-v3;
bootstrap=true;
@@ -547,6 +546,7 @@ dependencies = { module=configure-libctf; on=all-bfd; };
dependencies = { module=configure-libctf; on=all-intl; };
dependencies = { module=configure-libctf; on=all-zlib; };
dependencies = { module=configure-libctf; on=all-libiconv; };
+dependencies = { module=check-libctf; on=all-ld; };
// The Makefiles in gdb and gdbserver pull in a file that configure
// generates in the gnulib directory, so distclean gnulib only after
diff --git a/Makefile.in b/Makefile.in
index fe34132..4fe7321 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -34761,6 +34761,12 @@ maybe-check-libctf:
maybe-check-libctf: check-libctf
check-libctf:
+ @: $(MAKE); $(unstage)
+ @r=`${PWD_COMMAND}`; export r; \
+ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \
+ $(HOST_EXPORTS) $(EXTRA_HOST_EXPORTS) \
+ (cd $(HOST_SUBDIR)/libctf && \
+ $(MAKE) $(FLAGS_TO_PASS) $(EXTRA_BOOTSTRAP_FLAGS) check)
@endif libctf
@@ -52366,6 +52372,13 @@ configure-stage3-libctf: maybe-all-stage3-libiconv
configure-stage4-libctf: maybe-all-stage4-libiconv
configure-stageprofile-libctf: maybe-all-stageprofile-libiconv
configure-stagefeedback-libctf: maybe-all-stagefeedback-libiconv
+check-libctf: maybe-all-ld
+check-stage1-libctf: maybe-all-stage1-ld
+check-stage2-libctf: maybe-all-stage2-ld
+check-stage3-libctf: maybe-all-stage3-ld
+check-stage4-libctf: maybe-all-stage4-ld
+check-stageprofile-libctf: maybe-all-stageprofile-ld
+check-stagefeedback-libctf: maybe-all-stagefeedback-ld
distclean-gnulib: maybe-distclean-gdb
distclean-gnulib: maybe-distclean-gdbserver
all-bison: maybe-all-build-texinfo
diff --git a/libctf/ChangeLog b/libctf/ChangeLog
index 7e4997e..42ca1c6 100644
--- a/libctf/ChangeLog
+++ b/libctf/ChangeLog
@@ -1,5 +1,22 @@
2021-01-05 Nick Alcock <nick.alcock@oracle.com>
+ * Makefile.am (EXPECT): New.
+ (RUNTEST): Likewise.
+ (RUNTESTFLAGS): Likewise.
+ (CC_FOR_TARGET): Likewise.
+ (check-DEJAGNU): Likewise.
+ (AUTOMAKE_OPTIONS): Add dejagnu.
+ * Makefile.in: Regenerated.
+ * testsuite/config/default.exp: New.
+ * testsuite/lib/ctf-lib.exp: Likewise.
+ * testsuite/libctf-lookup/enum.lk: New test.
+ * testsuite/libctf-lookup/enum-ctf.c: New CTF input.
+ * testsuite/libctf-lookup/enum.c: New lookup test.
+ * testsuite/libctf-lookup/ambiguous-struct*.c: New test.
+ * testsuite/libctf-lookup/lookup.exp: New.
+
+2021-01-05 Nick Alcock <nick.alcock@oracle.com>
+
* configure.ac (BFD_LIBADD): Remove.
(BFD_DEPENDENCIES): Likewise. Remove associated cases.
(SHARED_LIBADD): Rename to...
diff --git a/libctf/Makefile.am b/libctf/Makefile.am
index a66ccc1..3fe1994 100644
--- a/libctf/Makefile.am
+++ b/libctf/Makefile.am
@@ -19,7 +19,7 @@
ACLOCAL_AMFLAGS = -I .. -I ../config -I ../bfd
-AUTOMAKE_OPTIONS = foreign no-texinfo.tex
+AUTOMAKE_OPTIONS = dejagnu foreign no-texinfo.tex
# This is where we get zlib from. zlibdir is -L../zlib and zlibinc is
# -I../zlib, unless we were configured with --with-system-zlib, in which
@@ -54,3 +54,36 @@ libctf_la_LIBADD = ../bfd/libbfd.la $(libctf_nobfd_la_LIBADD)
libctf_la_CPPFLAGS = $(AM_CPPFLAGS) -DNOBFD=0
libctf_la_LDFLAGS = $(libctf_nobfd_la_LDFLAGS)
libctf_la_SOURCES = $(libctf_nobfd_la_SOURCES) ctf-open-bfd.c
+
+# Setup the testing framework, if you have one
+EXPECT = expect
+RUNTEST = runtest
+RUNTESTFLAGS =
+
+CC_FOR_TARGET = ` \
+ if [ -f $$r/../gcc/xgcc ] ; then \
+ if [ -f $$r/../newlib/Makefile ] ; then \
+ echo $$r/../gcc/xgcc -B$$r/../gcc/ -idirafter $$r/../newlib/targ-include -idirafter $${srcroot}/../newlib/libc/include -nostdinc; \
+ else \
+ echo $$r/../gcc/xgcc -B$$r/../gcc/; \
+ fi; \
+ else \
+ if [ "@host@" = "@target@" ] ; then \
+ echo $(CC); \
+ else \
+ echo gcc | sed '$(transform)'; \
+ fi; \
+ fi`
+
+check-DEJAGNU: site.exp
+ srcroot=`cd $(srcdir) && pwd`; export srcroot; \
+ r=`pwd`; export r; \
+ LC_ALL=C; export LC_ALL; \
+ EXPECT=$(EXPECT); export EXPECT; \
+ runtest=$(RUNTEST); \
+ if $(SHELL) -c "$$runtest --version" > /dev/null 2>&1; then \
+ $$runtest --tool $(DEJATOOL) --srcdir $${srcroot}/testsuite \
+ CC="$(CC_FOR_TARGET)" CFLAGS="$(CFLAGS) -I$(INCDIR) -I$(srcdir) -I$(builddir) -I$(builddir)/../bfd $(ZLIBINC)" \
+ CC_FOR_HOST="$(CC)" LIBS="$(LIBS)" $(RUNTESTFLAGS); \
+ else echo "WARNING: could not find \`runtest'" 1>&2; :;\
+ fi
diff --git a/libctf/Makefile.in b/libctf/Makefile.in
index 0ee67fc..c86ac7b 100644
--- a/libctf/Makefile.in
+++ b/libctf/Makefile.in
@@ -278,6 +278,8 @@ ETAGS = etags
CTAGS = ctags
CSCOPE = cscope
AM_RECURSIVE_TARGETS = cscope
+DEJATOOL = $(PACKAGE)
+RUNTESTDEFAULTFLAGS = --tool $$tool --srcdir $$srcdir
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \
$(top_srcdir)/../ar-lib $(top_srcdir)/../compile \
$(top_srcdir)/../config.guess $(top_srcdir)/../config.sub \
@@ -439,7 +441,7 @@ warn = @warn@
zlibdir = @zlibdir@
zlibinc = @zlibinc@
ACLOCAL_AMFLAGS = -I .. -I ../config -I ../bfd
-AUTOMAKE_OPTIONS = foreign no-texinfo.tex
+AUTOMAKE_OPTIONS = dejagnu foreign no-texinfo.tex
# This is where we get zlib from. zlibdir is -L../zlib and zlibinc is
# -I../zlib, unless we were configured with --with-system-zlib, in which
@@ -464,6 +466,26 @@ libctf_la_LIBADD = ../bfd/libbfd.la $(libctf_nobfd_la_LIBADD)
libctf_la_CPPFLAGS = $(AM_CPPFLAGS) -DNOBFD=0
libctf_la_LDFLAGS = $(libctf_nobfd_la_LDFLAGS)
libctf_la_SOURCES = $(libctf_nobfd_la_SOURCES) ctf-open-bfd.c
+
+# Setup the testing framework, if you have one
+EXPECT = expect
+RUNTEST = runtest
+RUNTESTFLAGS =
+CC_FOR_TARGET = ` \
+ if [ -f $$r/../gcc/xgcc ] ; then \
+ if [ -f $$r/../newlib/Makefile ] ; then \
+ echo $$r/../gcc/xgcc -B$$r/../gcc/ -idirafter $$r/../newlib/targ-include -idirafter $${srcroot}/../newlib/libc/include -nostdinc; \
+ else \
+ echo $$r/../gcc/xgcc -B$$r/../gcc/; \
+ fi; \
+ else \
+ if [ "@host@" = "@target@" ] ; then \
+ echo $(CC); \
+ else \
+ echo gcc | sed '$(transform)'; \
+ fi; \
+ fi`
+
all: config.h
$(MAKE) $(AM_MAKEFLAGS) all-am
@@ -966,6 +988,36 @@ cscopelist-am: $(am__tagged_files)
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
+site.exp: Makefile $(EXTRA_DEJAGNU_SITE_CONFIG)
+ @echo 'Making a new site.exp file ...'
+ @echo '## these variables are automatically generated by make ##' >site.tmp
+ @echo '# Do not edit here. If you wish to override these values' >>site.tmp
+ @echo '# edit the last section' >>site.tmp
+ @echo 'set srcdir "$(srcdir)"' >>site.tmp
+ @echo "set objdir `pwd`" >>site.tmp
+ @echo 'set build_alias "$(build_alias)"' >>site.tmp
+ @echo 'set build_triplet $(build_triplet)' >>site.tmp
+ @echo 'set host_alias "$(host_alias)"' >>site.tmp
+ @echo 'set host_triplet $(host_triplet)' >>site.tmp
+ @list='$(EXTRA_DEJAGNU_SITE_CONFIG)'; for f in $$list; do \
+ echo "## Begin content included from file $$f. Do not modify. ##" \
+ && cat `test -f "$$f" || echo '$(srcdir)/'`$$f \
+ && echo "## End content included from file $$f. ##" \
+ || exit 1; \
+ done >> site.tmp
+ @echo "## End of auto-generated content; you can edit from here. ##" >> site.tmp
+ @if test -f site.exp; then \
+ sed -e '1,/^## End of auto-generated content.*##/d' site.exp >> site.tmp; \
+ fi
+ @-rm -f site.bak
+ @test ! -f site.exp || mv site.exp site.bak
+ @mv site.tmp site.exp
+
+distclean-DEJAGNU:
+ -rm -f site.exp site.bak
+ -l='$(DEJATOOL)'; for tool in $$l; do \
+ rm -f $$tool.sum $$tool.log; \
+ done
distdir: $(DISTFILES)
$(am__remove_distdir)
@@ -1131,6 +1183,7 @@ distcleancheck: distclean
$(distcleancheck_listfiles) ; \
exit 1; } >&2
check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-DEJAGNU
check: check-am
all-am: Makefile $(LTLIBRARIES) $(HEADERS) config.h
installdirs:
@@ -1176,8 +1229,9 @@ distclean: distclean-am
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf ./$(DEPDIR)
-rm -f Makefile
-distclean-am: clean-am distclean-compile distclean-generic \
- distclean-hdr distclean-libtool distclean-tags
+distclean-am: clean-am distclean-DEJAGNU distclean-compile \
+ distclean-generic distclean-hdr distclean-libtool \
+ distclean-tags
dvi: dvi-am
@@ -1241,30 +1295,43 @@ ps-am:
uninstall-am: uninstall-includeHEADERS uninstall-libLTLIBRARIES
-.MAKE: all install-am install-strip
-
-.PHONY: CTAGS GTAGS TAGS all all-am am--refresh check check-am clean \
- clean-cscope clean-generic clean-libLTLIBRARIES clean-libtool \
- clean-noinstLTLIBRARIES cscope cscopelist-am ctags ctags-am \
- dist dist-all dist-bzip2 dist-gzip dist-lzip dist-shar \
- dist-tarZ dist-xz dist-zip distcheck distclean \
- distclean-compile distclean-generic distclean-hdr \
- distclean-libtool distclean-tags distcleancheck distdir \
- distuninstallcheck dvi dvi-am html html-am info info-am \
- install install-am install-data install-data-am install-dvi \
- install-dvi-am install-exec install-exec-am install-html \
- install-html-am install-includeHEADERS install-info \
- install-info-am install-libLTLIBRARIES install-man install-pdf \
- install-pdf-am install-ps install-ps-am install-strip \
- installcheck installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags tags-am uninstall uninstall-am uninstall-includeHEADERS \
- uninstall-libLTLIBRARIES
+.MAKE: all check-am install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--refresh check check-DEJAGNU \
+ check-am clean clean-cscope clean-generic clean-libLTLIBRARIES \
+ clean-libtool clean-noinstLTLIBRARIES cscope cscopelist-am \
+ ctags ctags-am dist dist-all dist-bzip2 dist-gzip dist-lzip \
+ dist-shar dist-tarZ dist-xz dist-zip distcheck distclean \
+ distclean-DEJAGNU distclean-compile distclean-generic \
+ distclean-hdr distclean-libtool distclean-tags distcleancheck \
+ distdir distuninstallcheck dvi dvi-am html html-am info \
+ info-am install install-am install-data install-data-am \
+ install-dvi install-dvi-am install-exec install-exec-am \
+ install-html install-html-am install-includeHEADERS \
+ install-info install-info-am install-libLTLIBRARIES \
+ install-man install-pdf install-pdf-am install-ps \
+ install-ps-am install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am uninstall-includeHEADERS uninstall-libLTLIBRARIES
.PRECIOUS: Makefile
+check-DEJAGNU: site.exp
+ srcroot=`cd $(srcdir) && pwd`; export srcroot; \
+ r=`pwd`; export r; \
+ LC_ALL=C; export LC_ALL; \
+ EXPECT=$(EXPECT); export EXPECT; \
+ runtest=$(RUNTEST); \
+ if $(SHELL) -c "$$runtest --version" > /dev/null 2>&1; then \
+ $$runtest --tool $(DEJATOOL) --srcdir $${srcroot}/testsuite \
+ CC="$(CC_FOR_TARGET)" CFLAGS="$(CFLAGS) -I$(INCDIR) -I$(srcdir) -I$(builddir) -I$(builddir)/../bfd $(ZLIBINC)" \
+ CC_FOR_HOST="$(CC)" LIBS="$(LIBS)" $(RUNTESTFLAGS); \
+ else echo "WARNING: could not find \`runtest'" 1>&2; :;\
+ fi
+
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
diff --git a/libctf/testsuite/config/default.exp b/libctf/testsuite/config/default.exp
new file mode 100644
index 0000000..d14f660
--- /dev/null
+++ b/libctf/testsuite/config/default.exp
@@ -0,0 +1,59 @@
+# Basic expect script for libctf lookup tests
+# Copyright (C) 1993-2021 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# This file 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+# Written by Jeffrey Wheat (cassidy@cygnus.com)
+#
+
+if ![info exists ld] then {
+ set ld [findfile $base_dir/../ld/ld-new $base_dir/../ld/ld-new [transform ld]]
+}
+
+if ![info exists as] then {
+ set as [findfile $base_dir/../gas/as-new $base_dir/../gas/as-new [transform as]]
+}
+
+remote_exec host "mkdir -p tmpdir"
+
+# Make symlinks from tmpdir/libctf to the linker and assembler in the
+# build tree, so that we can use a -B option to gcc to force it to use
+# the newly built linker and assembler.
+if {![file isdirectory tmpdir/libctf]} then {
+ catch "exec mkdir tmpdir/libctf" status
+ catch "exec ln -s ../../../ld/ld-new tmpdir/libctf/ld" status
+ catch "exec ln -s ld tmpdir/libctf/collect-ld" status
+ catch "exec ln -s ../../../gas/as-new tmpdir/libctf/as" status
+}
+set gcc_B_opt "-B[pwd]/tmpdir/libctf/"
+
+# The "make check" target in the Makefile passes in
+# "CC=$(CC_FOR_TARGET)". But, if the user invokes runtest directly,
+# these flags may not be set.
+if {![info exists CC]} {
+ set CC [find_gcc]
+}
+if {![info exists CC_FOR_HOST]} {
+ set CC_FOR_HOST $CC
+}
+if {![info exists CFLAGS]} {
+ set CFLAGS "-g -O2"
+}
+
+# load the utility procedures
+load_lib ctf-lib.exp
diff --git a/libctf/testsuite/lib/ctf-lib.exp b/libctf/testsuite/lib/ctf-lib.exp
new file mode 100644
index 0000000..796342b
--- /dev/null
+++ b/libctf/testsuite/lib/ctf-lib.exp
@@ -0,0 +1,409 @@
+# Support routines for libctf testsuite.
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# This file 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+proc load_common_lib { name } {
+ global srcdir
+ load_file $srcdir/../../binutils/testsuite/lib/$name
+}
+
+load_common_lib binutils-common.exp
+
+proc run_native_host_cmd { command } {
+ global link_output
+ global ld
+
+ verbose -log "$command"
+ set run_output ""
+ try {
+ set run_output [exec "sh" "-c" "$command" "2>@1"]
+ set status 0
+ } trap CHILDSTATUS {results options} {
+ set status [lindex [dict get $options -errorcode] 2]
+ set run_output $results
+ }
+ regsub "\n$" $run_output "" run_output
+ if { [lindex $status 0] != 0 && [string match "" $run_output] } then {
+ append run_output "child process exited abnormally"
+ }
+
+ if [string match "" $run_output] then {
+ return ""
+ }
+
+ verbose -log "$run_output"
+ return "$run_output"
+}
+
+proc run_host_cmd { prog command } {
+ global link_output
+ global gcc_B_opt
+ global gcc_ld_B_opt_tested
+ global ld
+
+ if { ![is_remote host] && [which "$prog"] == 0 } then {
+ perror "$prog does not exist"
+ return 0
+ }
+
+ # If we are compiling with gcc, we want to add gcc_B_opt to flags. However,
+ # if $prog already has -B options, which might be the case when running gcc
+ # out of a build directory, we want our -B options to come first.
+ set gccexe $prog
+ set gccparm [string first " " $gccexe]
+ set gccflags ""
+ if { $gccparm > 0 } then {
+ set gccflags [string range $gccexe $gccparm end]
+ set gccexe [string range $gccexe 0 $gccparm]
+ set prog $gccexe
+ }
+ set gccexe [string replace $gccexe 0 [string last "/" $gccexe] ""]
+ if {[string match "*cc*" $gccexe] || [string match "*++*" $gccexe]} then {
+ set gccflags "$gcc_B_opt $gccflags"
+ if {![info exists gcc_ld_B_opt_tested]} {
+ set gcc_ld_B_opt_tested 1
+ set ld_version_message [run_host_cmd "$ld" "--version"]
+ set gcc_ld_version_message [run_host_cmd "$prog" "$gccflags -Wl,--version"]
+ if {[string first $ld_version_message $gcc_ld_version_message] < 0} {
+ perror "************************************************************************"
+ perror "Your compiler driver ignores -B when choosing ld."
+ perror "You will not be testing the new ld in many of the following tests."
+ set gcc_ld_version [run_host_cmd "$prog" "$gccflags --print-prog-name=ld"]
+ if {![string match "" $gcc_ld_version] && ![string match "ld" $gcc_ld_version]} {
+ perror "It seems you will be testing $gcc_ld_version instead."
+ }
+ perror "************************************************************************"
+ }
+ }
+ }
+
+ verbose -log "$prog $gccflags $command"
+ set status [remote_exec host [concat sh -c [list "$prog $gccflags $command 2>&1"]] "" "/dev/null" "libctf.tmp"]
+ remote_upload host "libctf.tmp"
+ set run_output [file_contents "libctf.tmp"]
+ regsub "\n$" $run_output "" run_output
+ if { [lindex $status 0] != 0 && [string match "" $run_output] } then {
+ append run_output "child process exited abnormally"
+ }
+ remote_file build delete libctf.tmp
+ remote_file host delete libctf.tmp
+
+ if [string match "" $run_output] then {
+ return ""
+ }
+
+ verbose -log "$run_output"
+ return "$run_output"
+}
+
+proc run_host_cmd_yesno { prog command } {
+ global exec_output
+ global errcnt warncnt
+
+ set exec_output [prune_warnings [run_host_cmd "$prog" "$command"]]
+ # Ignore error and warning.
+ set errcnt 0
+ set warncnt 0
+ if [string match "" $exec_output] then {
+ return 1;
+ }
+ return 0;
+}
+
+# Return true if we can build a program with the compiler.
+# On some targets, CC might be defined, but libraries and startup
+# code might be missing or require special options that the ld test
+# harness doesn't know about.
+
+proc check_compiler_available { } {
+ global compiler_available_saved
+ global CC
+
+ if {![info exists compiler_available_saved]} {
+ if { [which $CC] == 0 } {
+ set compiler_available_saved 0
+ return 0
+ }
+
+ set flags ""
+ if [board_info [target_info name] exists cflags] {
+ append flags " [board_info [target_info name] cflags]"
+ }
+ if [board_info [target_info name] exists ldflags] {
+ append flags " [board_info [target_info name] ldflags]"
+ }
+
+ set basename "tmpdir/compiler[pid]"
+ set src ${basename}.c
+ set output ${basename}.out
+ set f [open $src "w"]
+ puts $f "int main (void)"
+ puts $f "{"
+ puts $f " return 0; "
+ puts $f "}"
+ close $f
+ if [is_remote host] {
+ set src [remote_download host $src]
+ }
+ set compiler_available_saved [run_host_cmd_yesno "$CC" "$flags $src -o $output"]
+ remote_file host delete $src
+ remote_file host delete $output
+ file delete $src
+ }
+ return $compiler_available_saved
+}
+
+# Compile and link a C source file for execution on the host.
+proc compile_link_one_host_cc { src output additional_args } {
+ global CC_FOR_HOST
+ global CFLAGS
+
+ return [run_native_host_cmd "./libtool --quiet --tag=CC --mode=link $CC_FOR_HOST $CFLAGS $src -o $output $additional_args" ]
+}
+
+# Compile a C source file, with the specified additional_flags.
+proc compile_one_cc { src output additional_flags } {
+ global CC
+ global CFLAGS
+
+ set flags ""
+ if [board_info [target_info name] exists cflags] {
+ append flags " [board_info [target_info name] cflags]"
+ }
+ if [board_info [target_info name] exists ldflags] {
+ append flags " [board_info [target_info name] ldflags]"
+ }
+
+ if [is_remote host] {
+ set src [remote_download host $src]
+ }
+ return [run_host_cmd "$CC" "$flags $CFLAGS $additional_flags $src -o $output"]
+}
+
+# run_lookup_test FILE
+#
+# Compile with the host compiler and link a .c file into a "lookup" binary, then
+# compile and optionally link together a bunch of .s or .c files with CTF info
+# and pass the name of the resulting binary to the "lookup" binary and check the
+# output. (If none is specified, the binary is expected to generate its own CTF
+# for testing purposes.)
+#
+# As with run_dump_test, this is all driven by a file (in this case, a .lk file)
+# beginning with zero or more option lines, which specify the names of the
+# lookup binary's source file, the source file(s) with CTF info to compile
+# together, and whether to link them. The optional lines have the syntax:
+#
+# # OPTION: VALUE
+#
+# OPTION is the name of some option, like "name" or "lookup", and
+# VALUE is OPTION's value. The valid options are described below.
+# Whitespace is ignored everywhere, except within VALUE. The option
+# list ends with the first line that doesn't match the above syntax.
+# However, a line within the options that begins with a #, but doesn't
+# have a recognizable option name followed by a colon, is considered a
+# comment and entirely ignored.
+#
+# The interesting options are:
+#
+# name: TEST-NAME
+# The name of this test, passed to DejaGNU's `pass' and `fail'
+# commands. If omitted, this defaults to FILE, the root of the
+# lookup .c file's name.
+#
+# lookup: SOURCE
+# Compile the file SOURCE.c. If omitted, the lookup source defaults
+# to FILE.c.
+#
+# source: SOURCE
+# Assemble the file SOURCE.c and pass it to the LOOKUP program.
+#
+# link:
+# If set, link the SOURCE together even if only one file is specified.
+#
+# link_flags:
+# If set, extra flags to pass to the linker.
+#
+# xfail: GLOB|PROC ...
+# This test is expected to fail on a specified list of targets.
+#
+# Each option may occur at most once unless otherwise mentioned.
+#
+# After the option lines come regexp lines. run_lookup_test calls
+# regexp_diff to compare the output of the lookup program against the
+# regexps in FILE.d.
+#
+proc run_lookup_test { name } {
+ global CC CFLAGS LIBS
+ global copyfile env runtests srcdir subdir verbose
+
+ if ![runtest_file_p $runtests $name] then {
+ return
+ }
+
+ if [string match "*/*" $name] {
+ set file $name
+ set name [file tail $name]
+ } else {
+ set file "$srcdir/$subdir/$name"
+ }
+
+ set opt_array [slurp_options "${file}.lk"]
+ if { $opt_array == -1 } {
+ perror "error reading options from $file.lk"
+ unresolved $subdir/$name
+ return
+ }
+ set run_ld 0
+ set opts(link) {}
+ set opts(link_flags) {}
+ set opts(lookup) {}
+ set opts(name) {}
+ set opts(source) {}
+ set opts(xfail) {}
+
+ foreach i $opt_array {
+ set opt_name [lindex $i 0]
+ set opt_val [lindex $i 1]
+ if { $opt_name == "" } {
+ set in_extra 1
+ continue
+ }
+ if ![info exists opts($opt_name)] {
+ perror "unknown option $opt_name in file $file.lk"
+ unresolved $subdir/$name
+ return
+ }
+
+ set opts($opt_name) [concat $opts($opt_name) $opt_val]
+ }
+
+ if { [llength $opts(lookup)] == 0 } {
+ set opts(lookup) "$file.c"
+ } else {
+ set opts(lookup) "[file dirname $file]/$opts(lookup)"
+ }
+
+ if { [llength $opts(name)] == 0 } {
+ set opts(name) $opts(lookup)
+ }
+
+ if { [llength $opts(link)] != 0
+ || [llength $opts(source)] > 1 } {
+ set run_ld 1
+ }
+
+ set testname $opts(name)
+ if { $opts(name) == "" } {
+ set testname "$subdir/$name"
+ }
+
+ # Compile and link the lookup program.
+ set comp_output [compile_link_one_host_cc $opts(lookup) "tmpdir/lookup" "libctf.la"]
+
+ if { $comp_output != ""} {
+ send_log "compilation of lookup program $opts(lookup) failed with <$comp_output>"
+ perror "compilation of lookup program $opts(lookup) failed"
+ fail $testname
+ return 0
+ }
+
+ # Compile the inputs and posibly link them together.
+
+ set lookup_output ""
+ if { [llength $opts(source)] > 0 } {
+ set lookup_flags ""
+ if { $run_ld } {
+ set lookup_output "tmpdir/out.so"
+ set lookup_flags "-gt -fPIC -shared $opts(link_flags)"
+ } else {
+ set lookup_output "tmpdir/out.o"
+ set lookup_flags "-gt -fPIC -c"
+ }
+ if [board_info [target_info name] exists cflags] {
+ append lookup_flags " [board_info [target_info name] cflags]"
+ }
+ if [board_info [target_info name] exists ldflags] {
+ append lookup_flags " [board_info [target_info name] ldflags]"
+ }
+ set src {}
+ foreach sfile $opts(source) {
+ if [is_remote host] {
+ lappend src [remote_download host [file join [file dirname $file] $sfile]]
+ } else {
+ lappend src [file join [file dirname $file] $sfile]
+ }
+ }
+
+ set comp_output [run_host_cmd "$CC" "$CFLAGS $lookup_flags [concat $src] -o $lookup_output"]
+
+ if { $comp_output != ""} {
+ send_log "compilation of CTF program [concat $src] failed with <$comp_output>"
+ fail $testname
+ return 0
+ }
+ }
+
+ # Time to setup xfailures.
+ foreach targ $opts(xfail) {
+ if [match_target $targ] {
+ setup_xfail "*-*-*"
+ break
+ }
+ }
+
+ # Invoke the lookup program on the outputs.
+
+ set results [run_host_cmd tmpdir/lookup $lookup_output]
+
+ set f [open "tmpdir/lookup.out" "w"]
+ puts $f $results
+ close $f
+
+ if { [regexp_diff "tmpdir/lookup.out" "${file}.lk"] } then {
+ fail $testname
+ if { $verbose == 2 } then { verbose "output is [file_contents tmpdir/lookup.out]" 2 }
+ return 0
+ }
+
+ pass $testname
+ return 0
+}
+
+# Returns true if the target compiler supports -gt
+proc check_ctf_available { } {
+ global ctf_available_saved
+
+ if {![info exists ctf_available_saved]} {
+ if { ![check_compiler_available] } {
+ set ctf_available_saved 0
+ } else {
+ set basename "tmpdir/ctf_available[pid]"
+ set src ${basename}.c
+ set output ${basename}.o
+ set f [open $src "w"]
+ puts $f "int main() { return 0; }"
+ close $f
+ set ctf_available_saved [compile_one_cc $src $output "-gt -c"]
+ remote_file host delete $src
+ remote_file host delete $output
+ file delete $src
+ }
+ }
+ return $ctf_available_saved
+}
diff --git a/libctf/testsuite/libctf-lookup/ambiguous-struct-A.c b/libctf/testsuite/libctf-lookup/ambiguous-struct-A.c
new file mode 100644
index 0000000..67047c4
--- /dev/null
+++ b/libctf/testsuite/libctf-lookup/ambiguous-struct-A.c
@@ -0,0 +1,8 @@
+struct A;
+struct B { struct A *a; };
+struct A { struct B b; long foo; long bar; struct B b2; };
+
+typedef struct A a_array[50];
+a_array *foo __attribute__((__used__));
+
+static struct A a __attribute ((__used__));
diff --git a/libctf/testsuite/libctf-lookup/ambiguous-struct-B.c b/libctf/testsuite/libctf-lookup/ambiguous-struct-B.c
new file mode 100644
index 0000000..95a9346
--- /dev/null
+++ b/libctf/testsuite/libctf-lookup/ambiguous-struct-B.c
@@ -0,0 +1,5 @@
+struct A;
+struct B { struct A *a; };
+struct A { struct B b; int foo; struct B b2; };
+
+static struct A a __attribute__((__used__));
diff --git a/libctf/testsuite/libctf-lookup/ambiguous-struct.c b/libctf/testsuite/libctf-lookup/ambiguous-struct.c
new file mode 100644
index 0000000..05b471e
--- /dev/null
+++ b/libctf/testsuite/libctf-lookup/ambiguous-struct.c
@@ -0,0 +1,51 @@
+/* Test ambiguous forward lookups post-deduplication.
+
+ This also makes sure that deduplication succeeds in this case and does not
+ throw spurious errors. */
+
+#include <ctf-api.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main (int argc, char *argv[])
+{
+ ctf_dict_t *fp;
+ ctf_archive_t *ctf;
+ ctf_id_t type;
+ ctf_arinfo_t ar;
+ int err;
+
+ if (argc != 2)
+ {
+ fprintf (stderr, "Syntax: %s PROGRAM\n", argv[0]);
+ exit(1);
+ }
+
+ if ((ctf = ctf_open (argv[1], NULL, &err)) == NULL)
+ goto open_err;
+ if ((fp = ctf_dict_open (ctf, NULL, &err)) == NULL)
+ goto open_err;
+
+ /* Dig out the array type and resolve its element type. */
+
+ if ((type = ctf_lookup_by_name (fp, "a_array") ) == CTF_ERR)
+ goto err;
+ if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
+ goto err;
+ if (ctf_array_info (fp, type, &ar) < 0)
+ goto err;
+ printf ("Kind of array element is %i\n", ctf_type_kind (fp, ar.ctr_contents));
+
+ ctf_dict_close (fp);
+ ctf_close (ctf);
+
+ return 0;
+
+ open_err:
+ fprintf (stderr, "%s: cannot open: %s\n", argv[0], ctf_errmsg (err));
+ return 1;
+ err:
+ fprintf (stderr, "Lookup failed: %s\n", ctf_errmsg (ctf_errno (fp)));
+ return 1;
+}
diff --git a/libctf/testsuite/libctf-lookup/ambiguous-struct.lk b/libctf/testsuite/libctf-lookup/ambiguous-struct.lk
new file mode 100644
index 0000000..84f296d
--- /dev/null
+++ b/libctf/testsuite/libctf-lookup/ambiguous-struct.lk
@@ -0,0 +1,4 @@
+# source: ambiguous-struct-A.c
+# source: ambiguous-struct-B.c
+# link: on
+Kind of array element is 9
diff --git a/libctf/testsuite/libctf-lookup/enum-ctf.c b/libctf/testsuite/libctf-lookup/enum-ctf.c
new file mode 100644
index 0000000..aa60d72
--- /dev/null
+++ b/libctf/testsuite/libctf-lookup/enum-ctf.c
@@ -0,0 +1,8 @@
+/* Looked up item by item. */
+enum e { ENUMSAMPLE_1 = 0, ENUMSAMPLE_2 = 1 };
+
+/* Looked up via both sorts of iterator in turn. */
+enum ie { IENUMSAMPLE_1 = -10, IENUMSAMPLE_2, IENUMSAMPLE_3 };
+
+enum e foo;
+enum ie bar;
diff --git a/libctf/testsuite/libctf-lookup/enum.c b/libctf/testsuite/libctf-lookup/enum.c
new file mode 100644
index 0000000..1804b23
--- /dev/null
+++ b/libctf/testsuite/libctf-lookup/enum.c
@@ -0,0 +1,78 @@
+#include <ctf-api.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static int
+print_enum (const char *name, int val, void *unused)
+{
+ printf ("iter test: %s has value %i\n", name, val);
+ return 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+ ctf_dict_t *fp;
+ ctf_archive_t *ctf;
+ ctf_id_t type;
+ const char *name;
+ ctf_next_t *i = NULL;
+ int val;
+ int err;
+
+ if (argc != 2)
+ {
+ fprintf (stderr, "Syntax: %s PROGRAM\n", argv[0]);
+ exit(1);
+ }
+
+ if ((ctf = ctf_open (argv[1], NULL, &err)) == NULL)
+ goto open_err;
+ if ((fp = ctf_dict_open (ctf, NULL, &err)) == NULL)
+ goto open_err;
+
+ /* Try getting some enum values by hand. */
+
+ if ((type = ctf_lookup_by_name (fp, "enum e") ) == CTF_ERR)
+ goto err;
+ if (ctf_enum_value (fp, type, "ENUMSAMPLE_1", &val) < 0)
+ goto err;
+ printf ("Enum e enumerand ENUMSAMPLE_1 has value %i\n", val);
+
+ if ((name = ctf_enum_name (fp, type, 1)) == NULL)
+ goto err;
+ printf ("Enum e enumerand %s has value 1\n", name);
+
+ /* Try getting some values using both sorts of iterator. */
+
+ if ((type = ctf_lookup_by_name (fp, "enum ie") ) == CTF_ERR)
+ goto err;
+
+ if ((ctf_enum_iter (fp, type, print_enum, NULL)) < 0)
+ goto ierr;
+
+ while ((name = ctf_enum_next (fp, type, &i, &val)) != NULL)
+ {
+ printf ("next test: %s has value %i\n", name, val);
+ }
+ if (ctf_errno (fp) != ECTF_NEXT_END)
+ goto nerr;
+
+ ctf_dict_close (fp);
+ ctf_close (ctf);
+
+ return 0;
+
+ open_err:
+ fprintf (stderr, "%s: cannot open: %s\n", argv[0], ctf_errmsg (err));
+ return 1;
+ err:
+ fprintf (stderr, "Lookup failed: %s\n", ctf_errmsg (ctf_errno (fp)));
+ return 1;
+ ierr:
+ fprintf (stderr, "_iter iteration failed: %s\n", ctf_errmsg (ctf_errno (fp)));
+ return 1;
+ nerr:
+ fprintf (stderr, "_next iteration failed: %s\n", ctf_errmsg (ctf_errno (fp)));
+ return 1;
+}
diff --git a/libctf/testsuite/libctf-lookup/enum.lk b/libctf/testsuite/libctf-lookup/enum.lk
new file mode 100644
index 0000000..0b2b157
--- /dev/null
+++ b/libctf/testsuite/libctf-lookup/enum.lk
@@ -0,0 +1,10 @@
+# source: enum-ctf.c
+# link: on
+Enum e enumerand ENUMSAMPLE_1 has value 0
+Enum e enumerand ENUMSAMPLE_2 has value 1
+iter test: IENUMSAMPLE_1 has value -10
+iter test: IENUMSAMPLE_2 has value -9
+iter test: IENUMSAMPLE_3 has value -8
+next test: IENUMSAMPLE_1 has value -10
+next test: IENUMSAMPLE_2 has value -9
+next test: IENUMSAMPLE_3 has value -8
diff --git a/libctf/testsuite/libctf-lookup/lookup.exp b/libctf/testsuite/libctf-lookup/lookup.exp
new file mode 100644
index 0000000..51ad257
--- /dev/null
+++ b/libctf/testsuite/libctf-lookup/lookup.exp
@@ -0,0 +1,43 @@
+# Copyright (C) 2021 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# 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, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+if ![is_elf_format] {
+ unsupported "CTF needs bfd changes to be emitted on non-ELF"
+ return 0
+}
+
+if {[info exists env(LC_ALL)]} {
+ set old_lc_all $env(LC_ALL)
+}
+set env(LC_ALL) "C"
+
+set ctf_test_list [lsort [glob -nocomplain $srcdir/$subdir/*.lk]]
+
+foreach ctf_test $ctf_test_list {
+ verbose [file rootname $ctf_test]
+ verbose running lookup test on $ctf_test
+ run_lookup_test [file rootname $ctf_test]
+}
+
+if {[info exists old_lc_all]} {
+ set env(LC_ALL) $old_lc_all
+} else {
+ unset env(LC_ALL)
+}