diff -rup binutils.orig/bfd/elf32-i386.c binutils-2.30/bfd/elf32-i386.c --- binutils.orig/bfd/elf32-i386.c 2018-02-27 17:25:53.961140597 +0000 +++ binutils-2.30/bfd/elf32-i386.c 2018-02-27 17:27:14.115133477 +0000 @@ -383,7 +383,7 @@ elf_i386_rtype_to_howto (bfd *abfd, unsi { (*_bfd_error_handler) (_("%B: invalid relocation type %d"), abfd, (int) r_type); - indx = R_386_NONE; + return NULL; } /* PR 17512: file: 0f67f69d. */ if (elf_howto_table [indx].type != r_type) diff -rup binutils.orig/bfd/elf64-ppc.c binutils-2.30/bfd/elf64-ppc.c --- binutils.orig/bfd/elf64-ppc.c 2018-02-27 17:25:53.969140496 +0000 +++ binutils-2.30/bfd/elf64-ppc.c 2018-02-27 17:27:56.213604518 +0000 @@ -2516,9 +2516,12 @@ ppc64_elf_info_to_howto (bfd *abfd, arel { (*_bfd_error_handler) (_("%B: invalid relocation type %d"), abfd, (int) type); - type = R_PPC64_NONE; + cache_ptr->howto = NULL; } - cache_ptr->howto = ppc64_elf_howto_table[type]; + else + cache_ptr->howto = ppc64_elf_howto_table[type]; + if (cache_ptr->howto == NULL || cache_ptr->howto->name == NULL) + _bfd_error_handler (_("%B: invalid relocation type %d"), abfd, type); } /* Handle the R_PPC64_ADDR16_HA and similar relocs. */ diff -rup binutils.orig/bfd/elf64-s390.c binutils-2.30/bfd/elf64-s390.c --- binutils.orig/bfd/elf64-s390.c 2018-02-27 17:25:53.968140509 +0000 +++ binutils-2.30/bfd/elf64-s390.c 2018-02-27 17:28:24.632247443 +0000 @@ -372,9 +372,10 @@ elf_s390_info_to_howto (bfd *abfd ATTRIB { (*_bfd_error_handler) (_("%B: invalid relocation type %d"), abfd, (int) r_type); - r_type = R_390_NONE; + cache_ptr->howto = NULL; } - cache_ptr->howto = &elf_howto_table[r_type]; + else + cache_ptr->howto = &elf_howto_table[r_type]; } } diff -rup binutils.orig/bfd/elf64-x86-64.c binutils-2.30/bfd/elf64-x86-64.c --- binutils.orig/bfd/elf64-x86-64.c 2018-02-27 17:25:53.964140559 +0000 +++ binutils-2.30/bfd/elf64-x86-64.c 2018-02-27 17:29:12.554645307 +0000 @@ -284,7 +284,7 @@ elf_x86_64_rtype_to_howto (bfd *abfd, un { (*_bfd_error_handler) (_("%B: invalid relocation type %d"), abfd, (int) r_type); - r_type = R_X86_64_NONE; + return NULL; } i = r_type; } @@ -347,7 +347,6 @@ elf_x86_64_info_to_howto (bfd *abfd ATTR r_type = ELF32_R_TYPE (dst->r_info); cache_ptr->howto = elf_x86_64_rtype_to_howto (abfd, r_type); - BFD_ASSERT (r_type == cache_ptr->howto->type); } /* Support for core dump NOTE sections. */ diff -rup binutils.orig/bfd/elfcode.h binutils-2.30/bfd/elfcode.h --- binutils.orig/bfd/elfcode.h 2018-02-27 17:25:53.964140559 +0000 +++ binutils-2.30/bfd/elfcode.h 2018-02-27 17:26:57.234345581 +0000 @@ -1474,6 +1474,12 @@ elf_slurp_reloc_table_from_section (bfd (*ebd->elf_info_to_howto) (abfd, relent, &rela); else (*ebd->elf_info_to_howto_rel) (abfd, relent, &rela); + + if (relent->howto == NULL) + { + bfd_set_error (bfd_error_bad_value); + goto error_return; + } } if (allocated != NULL) diff -rup binutils.orig/binutils/objcopy.c binutils-2.30/binutils/objcopy.c --- binutils.orig/binutils/objcopy.c 2018-02-27 17:25:53.185150347 +0000 +++ binutils-2.30/binutils/objcopy.c 2018-02-27 17:30:05.806976202 +0000 @@ -3022,10 +3022,19 @@ copy_object (bfd *ibfd, bfd *obfd, const haven't been set yet. mark_symbols_used_in_relocations will ignore input sections which have no corresponding output section. */ + bfd_set_error (bfd_error_no_error); if (strip_symbols != STRIP_ALL) - bfd_map_over_sections (ibfd, - mark_symbols_used_in_relocations, - isympp); + { + bfd_map_over_sections (ibfd, + mark_symbols_used_in_relocations, + isympp); + if (bfd_get_error () != bfd_error_no_error) + { + status = 1; + return FALSE; + } + } + osympp = (asymbol **) xmalloc ((symcount + add_symbols + 1) * sizeof (asymbol *)); symcount = filter_symbols (ibfd, obfd, osympp, isympp, symcount); } diff -rup binutils.orig/binutils/testsuite/binutils-all/objcopy.exp binutils-2.27/binutils/testsuite/binutils-all/objcopy.exp --- binutils.orig/binutils/testsuite/binutils-all/objcopy.exp 2018-04-11 12:34:04.671683298 +0100 +++ binutils-2.27/binutils/testsuite/binutils-all/objcopy.exp 2018-04-11 12:36:50.053734109 +0100 @@ -1083,6 +1083,29 @@ if [is_elf_format] { } run_dump_test "strip-11" $extra_strip11 + if { [istarget "mips64*-*-openbsd*"] } { + set reloc_format mips64 + } elseif { [istarget "arm-*"] \ + || [istarget "d10v-*"] \ + || [istarget "dlx-*"] \ + || [istarget "i*86-*"] \ + || [istarget "i960-*"] \ + || [istarget "m681*-*"] \ + || [istarget "m68hc1*-*"] \ + || ([istarget "mips*-*"] \ + && ![istarget "mips64*-ps2-elf*"] \ + && ![istarget "*-*-irix6*"] \ + && ![istarget "mips64*-*-freebsd*"] \ + && ![istarget "mips64*-*-kfreebsd*-gnu"] \ + && ![istarget "mips64*-*-linux*"]) \ + || [istarget "score*-*"] \ + || [istarget "xgate-*"] } { + set reloc_format rel + } else { + set reloc_format rela + } + run_dump_test "strip-13" [list [list source strip-13${reloc_format}.s]] + if { [istarget "i*86-*"] || [istarget "x86_64-*-*"] } { # Check to make sure we don't strip a symbol named in relocations. set test "objcopy keeps symbols needed by relocs" diff -rup binutils.orig/binutils/testsuite/lib/utils-lib.exp binutils-2.27/binutils/testsuite/lib/utils-lib.exp --- binutils.orig/binutils/testsuite/lib/utils-lib.exp 2018-04-11 12:34:04.674683263 +0100 +++ binutils-2.27/binutils/testsuite/lib/utils-lib.exp 2018-04-11 12:54:56.097850613 +0100 @@ -1,4 +1,4 @@ -# Copyright (C) 1993-2016 Free Software Foundation, Inc. +# Copyright (C) 1993-2018 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 @@ -51,12 +51,17 @@ proc binutil_version { prog } { # default_binutils_run # run a program, returning the output # sets binutils_run_failed if the program does not exist +# sets binutils_run_status to the exit status of the program # proc default_binutils_run { prog progargs } { global binutils_run_failed + global binutils_run_status global host_triplet set binutils_run_failed 0 + if [info exists binutils_run_status] { + unset binutils_run_status + } if ![is_remote host] { if {[which $prog] == 0} then { @@ -83,6 +88,7 @@ proc default_binutils_run { prog progarg regsub -all "\\$" "$progargs" "\\$" progargs set state [remote_exec host $prog $progargs] + set binutils_run_status [lindex $state 0] set exec_output [prune_warnings [lindex $state 1]] if {![string match "" $exec_output]} then { send_log "$exec_output\n" @@ -127,7 +133,6 @@ proc default_binutils_assemble_flags { s } else { send_log "$exec_output\n" verbose "$exec_output" - perror "$source: assembly failed" return 0 } } @@ -214,6 +219,11 @@ proc exe_ext {} { # Assemble the file SOURCE.s. If omitted, this defaults to FILE.s. # This is useful if several .d files want to share a .s file. # +# dump: DUMP +# Match against DUMP.d. If omitted, this defaults to FILE.d. This +# is useful if several .d files differ by options only. Options are +# always read from FILE.d. +# # target: GLOBS... # Run this test only on a specified list of targets. More precisely, # each glob in the space-separated list is passed to "istarget"; if @@ -237,22 +247,22 @@ proc exe_ext {} { # # error: REGEX # An error with message matching REGEX must be emitted for the test -# to pass. The PROG, objdump, nm and objcopy options have no -# meaning and need not supplied if this is present. +# to pass. The DUMPPROG, addr2line, nm, objdump, readelf and size +# options have no meaning and need not supplied if this is present. +# Multiple "error" directives append to the expected error message. +# +# error_output: FILE +# Means the same as 'error', except the regular expression lines +# are contains in FILE. # # warning: REGEX -# Expect a gas warning matching REGEX. It is an error to issue -# both "error" and "warning". -# -# stderr: FILE -# FILE contains regexp lines to be matched against the diagnostic -# output of the assembler. This does not preclude the use of -# PROG, nm, objdump, or objcopy. -# -# error-output: FILE -# Means the same as 'stderr', but also indicates that the assembler -# is expected to exit unsuccessfully (therefore PROG, objdump, nm, -# and objcopy have no meaning and should not be supplied). +# Expect a warning matching REGEX. It is an error to issue both +# "error" and "warning". Multiple "warning" directives append to +# the expected linker warning message. +# +# warning_output: FILE +# Means the same as 'warning', except the regular expression +# lines are contains in FILE. # # Each option may occur at most once. # @@ -266,6 +276,7 @@ proc run_dump_test { name {extra_options global OBJDUMP NM OBJCOPY READELF STRIP global OBJDUMPFLAGS NMFLAGS OBJCOPYFLAGS READELFFLAGS STRIPFLAGS global ELFEDIT ELFEDITFLAGS + global binutils_run_status global host_triplet global env global copyfile @@ -299,6 +310,11 @@ proc run_dump_test { name {extra_options set opts(PROG) {} set opts(DUMPPROG) {} set opts(source) {} + set opts(dump) {} + set opts(error) {} + set opts(warning) {} + set opts(error_output) {} + set opts(warning_output) {} set opts(target) {} set opts(not-target) {} set opts(skip) {} @@ -317,12 +333,18 @@ proc run_dump_test { name {extra_options # directory. regsub -all "\\\$srcdir" "$opt_val" "$srcdir/$subdir" opt_val - if [string length $opts($opt_name)] { - perror "option $opt_name multiply set in $file.d" - unresolved $subdir/$name - return + switch -- $opt_name { + warning {} + error {} + default { + if [string length $opts($opt_name)] { + perror "option $opt_name multiply set in $file.d" + unresolved $subdir/$name + return + } + } } - set opts($opt_name) $opt_val + append opts($opt_name) $opt_val } foreach i $extra_options { @@ -340,7 +362,8 @@ proc run_dump_test { name {extra_options # add extra option to end of existing option, adding space # if necessary. - if [string length $opts($opt_name)] { + if { ![regexp "warning|error" $opt_name] + && [string length $opts($opt_name)] } { append opts($opt_name) " " } append opts($opt_name) $opt_val @@ -378,28 +401,35 @@ proc run_dump_test { name {extra_options } set dumpprogram "" - if { $opts(DUMPPROG) != "" } { - switch -- $opts(DUMPPROG) { - addr2line { set dumpprogram addr2line } - nm { set dumpprogram nm } - objdump { set dumpprogram objdump } - readelf { set dumpprogram readelf } - size { set dumpprogram size } - default { - perror "unrecognized dump program option $opts(DUMPPROG) in $file.d" - unresolved $testname - return } - } - } else { - # Guess which program to run, by seeing which option was specified. - foreach p {addr2line nm objdump readelf size} { - if {$opts($p) != ""} { - if {$dumpprogram != ""} { - perror "more than one possible dump program specified in $file.d" + # It's meaningless to require an output-testing method when we + # expect an error. + if { $opts(error) == "" && $opts(error_output) == "" } { + if { $opts(DUMPPROG) != "" } { + switch -- $opts(DUMPPROG) { + addr2line { set dumpprogram addr2line } + nm { set dumpprogram nm } + objdump { set dumpprogram objdump } + readelf { set dumpprogram readelf } + size { set dumpprogram size } + default { + perror "unrecognized dump program option $opts(DUMPPROG)\ + in $file.d" unresolved $testname return - } else { - set dumpprogram $p + } + } + } else { + # Guess which program to run, by seeing which option was specified. + foreach p {addr2line nm objdump readelf size} { + if {$opts($p) != ""} { + if {$dumpprogram != ""} { + perror "more than one possible dump program specified\ + in $file.d" + unresolved $testname + return + } else { + set dumpprogram $p + } } } } @@ -456,6 +486,12 @@ proc run_dump_test { name {extra_options set srcfile $srcdir/$subdir/$opts(source) } + if { $opts(dump) == "" } { + set dumpfile ${file}.d + } else { + set dumpfile $srcdir/$subdir/$opts(dump) + } + if { $opts(as) == "binary" } { while {[file type $srcfile] eq "link"} { set newfile [file readlink $srcfile] @@ -464,7 +500,8 @@ proc run_dump_test { name {extra_options } set srcfile $newfile } - file copy -force ${srcfile} $tempfile + # Make sure we copy the file if we are doing remote host testing. + remote_download host ${srcfile} $tempfile } else { set exec_output [binutils_assemble_flags ${srcfile} $tempfile $opts(as)] if [string match "" $exec_output] then { @@ -475,16 +512,95 @@ proc run_dump_test { name {extra_options } } + if { (($opts(warning) != "") && ($opts(error) != "")) \ + || (($opts(warning) != "") && ($opts(error_output) != "")) \ + || (($opts(warning) != "") && ($opts(warning_output) != "")) \ + || (($opts(error) != "") && ($opts(warning_output) != "")) \ + || (($opts(error) != "") && ($opts(error_output) != "")) \ + || (($opts(warning_output) != "") && ($opts(error_output) != "")) } { + perror "bad mix of warning, error, warning_output, and error_output\ + test-directives" + unresolved $testname + return + } + + set check_prog(source) "" + set check_prog(terminal) 0 + if { $opts(error) != "" \ + || $opts(warning) != "" \ + || $opts(error_output) != "" \ + || $opts(warning_output) != "" } { + + if { $opts(error) != "" || $opts(error_output) != "" } { + set check_prog(terminal) 1 + } else { + set check_prog(terminal) 0 + } + + if { $opts(error) != "" || $opts(warning) != "" } { + set check_prog(source) "regex" + if { $opts(error) != "" } { + set check_prog(regex) $opts(error) + } else { + set check_prog(regex) $opts(warning) + } + } else { + set check_prog(source) "file" + if { $opts(error_output) != "" } { + set check_prog(file) $opts(error_output) + } else { + set check_prog(file) $opts(warning_output) + } + } + } + set progopts1 $opts($program) eval set progopts \$[string toupper $program]FLAGS eval set binary \$[string toupper $program] set exec_output [binutils_run $binary "$progopts $progopts1 $tempfile $destopt ${copyfile}.o"] - if ![string match "" $exec_output] { - send_log "$exec_output\n" + set cmdret 0 + if [info exists binutils_run_status] { + set cmdret $binutils_run_status + } + + regsub "\n$" $exec_output "" exec_output + if { $cmdret != 0 || $exec_output != "" || $check_prog(source) != "" } { + set exitstat "succeeded" + if { $cmdret != 0 } { + set exitstat "failed" + } + + if { $check_prog(source) == "regex" } { + verbose -log "$exitstat with: <$exec_output>,\ + expected: <$check_prog(regex)>" + } elseif { $check_prog(source) == "file" } { + verbose -log "$exitstat with: <$exec_output>,\ + expected in file $check_prog(file)" + set_file_contents "tmpdir/prog.messages" "$exec_output" + } else { + verbose -log "$exitstat with: <$exec_output>, no expected output" + } + send_log -- "$exec_output\n" verbose "$exec_output" - fail $testname - return + + if { (($check_prog(source) == "") == ($exec_output == "")) \ + && (($cmdret == 0) == ($check_prog(terminal) == 0)) \ + && ((($check_prog(source) == "regex") \ + && ($check_prog(regex) == "") == ($exec_output == "") \ + && [regexp -- $check_prog(regex) $exec_output]) \ + || (($check_prog(source) == "file") \ + && (![regexp_diff "tmpdir/prog.messages" \ + "$srcdir/$subdir/$check_prog(file)"]))) } { + # We have the expected output from prog. + if { $check_prog(terminal) || $program == "" } { + pass $testname + return + } + } else { + fail $testname + return + } } set progopts1 $opts($dumpprogram) @@ -534,7 +650,7 @@ proc run_dump_test { name {extra_options } verbose_eval {[file_contents "tmpdir/dump.out"]} 3 - if { [regexp_diff "tmpdir/dump.out" "${file}.d"] } then { + if { [regexp_diff "tmpdir/dump.out" "${dumpfile}"] } then { fail $testname verbose "output is [file_contents "tmpdir/dump.out"]" 2 return --- /dev/null 2018-04-11 08:10:00.466225454 +0100 +++ binutils-2.27/binutils/testsuite/binutils-all/strip-13.d 2018-04-11 12:55:42.481306111 +0100 @@ -0,0 +1,10 @@ +#PROG: strip +#strip: -g +#error: \A[^\n]*: invalid relocation type 143\n +#error: [^\n]*: Bad value\Z +#not-target: h8300-* ip2k-* m6811-* m68hc11-* rx-* +# The H8300-*, IP2K and 68HC11 targets use 16-bit addressing, so `.dc.a' +# does not work for manual relocation data construction. +# The RX targets do not complain about unrecognised relocs, unless they +# are actually used +# (which is what should really happen with the other targets...) --- /dev/null 2018-04-11 08:10:00.466225454 +0100 +++ binutils-2.27/binutils/testsuite/binutils-all/strip-13mips64.s 2018-04-11 12:37:17.195412074 +0100 @@ -0,0 +1,14 @@ + .text +foo: + .dc.l 0x12345678 + + .section .rela.text + .dc.a 0 + .dc.l 0 + .dc.b 0, 0, 0, 0x8f + .dc.a 0x0000008f + + .dc.a 0 + .dc.l 0 + .dc.b 0, 0, 0, 0 + .dc.a 0 --- /dev/null 2018-04-11 08:10:00.466225454 +0100 +++ binutils-2.27/binutils/testsuite/binutils-all/strip-13rela.s 2018-04-11 12:37:17.195412074 +0100 @@ -0,0 +1,12 @@ + .text +foo: + .dc.l 0x12345678 + + .section .rela.text + .dc.a 0 + .dc.a 0x0000008f + .dc.a 0x0000008f + + .dc.a 0 + .dc.a 0 + .dc.a 0 --- /dev/null 2018-04-11 08:10:00.466225454 +0100 +++ binutils-2.27/binutils/testsuite/binutils-all/strip-13rel.s 2018-04-11 12:37:17.195412074 +0100 @@ -0,0 +1,10 @@ + .text +foo: + .dc.l 0x12345678 + + .section .rel.text + .dc.a 0 + .dc.a 0x0000008f + + .dc.a 0 + .dc.a 0 --- binutils.orig/bfd/elfnn-aarch64.c 2018-04-11 12:34:04.649683557 +0100 +++ binutils-2.27/bfd/elfnn-aarch64.c 2018-04-11 13:33:08.539305994 +0100 @@ -1977,6 +1977,8 @@ elfNN_aarch64_info_to_howto (bfd *abfd A r_type = ELFNN_R_TYPE (elf_reloc->r_info); bfd_reloc->howto = elfNN_aarch64_howto_from_type (r_type); + if (bfd_reloc->howto == NULL) + _bfd_error_handler (_("%B: invalid relocation type %d"), abfd, r_type); } static reloc_howto_type *