* ld-srec/srec.exp: Add setup_xfail calls for i[345]86-*-aout*.
authorIan Lance Taylor <ian@airs.com>
Mon, 27 Nov 1995 19:39:09 +0000 (19:39 +0000)
committerIan Lance Taylor <ian@airs.com>
Mon, 27 Nov 1995 19:39:09 +0000 (19:39 +0000)
* ld-srec/sr1.c (V_SPILL, V_FILL): Define.
* ld-srec/sr3.cc: Likewise.

ld/testsuite/ChangeLog
ld/testsuite/ld-srec/sr1.c [new file with mode: 0644]
ld/testsuite/ld-srec/sr3.cc [new file with mode: 0644]
ld/testsuite/ld-srec/srec.exp [new file with mode: 0644]

index 8430fdf2424259d53693b7fafc362079ceb0355a..6f93cb83448c186a06f77c7089f2484812de0270 100644 (file)
@@ -1,3 +1,10 @@
+Mon Nov 27 14:36:11 1995  Ian Lance Taylor  <ian@cygnus.com>
+
+       * ld-srec/srec.exp: Add setup_xfail calls for i[345]86-*-aout*.
+
+       * ld-srec/sr1.c (V_SPILL, V_FILL): Define.
+       * ld-srec/sr3.cc: Likewise.
+
 Tue Nov 21 16:05:53 1995  Ian Lance Taylor  <ian@cygnus.com>
 
        * ld-empic/empic.exp: Update for changes in objdump output.
diff --git a/ld/testsuite/ld-srec/sr1.c b/ld/testsuite/ld-srec/sr1.c
new file mode 100644 (file)
index 0000000..cfa5887
--- /dev/null
@@ -0,0 +1,37 @@
+/* This file is compiled and linked into the S-record format.  */
+
+extern int e1;
+extern int e2;
+int i;
+int j = 1;
+static int k;
+static int l = 1;
+static char ab[] = "This is a string constant";
+
+extern int fn1 ();
+extern int fn2 ();
+
+int
+main ()
+{
+  fn1 (ab);
+  fn2 ("static string constant");
+  return e1 + e2 + i + j + k + l;
+}
+
+int
+__main ()
+{
+}
+
+/* V_SPILL and V_FILL are used by a29k-amd-udi.  */
+
+int
+V_SPILL ()
+{
+}
+
+int
+V_FILL ()
+{
+}
diff --git a/ld/testsuite/ld-srec/sr3.cc b/ld/testsuite/ld-srec/sr3.cc
new file mode 100644 (file)
index 0000000..800b46b
--- /dev/null
@@ -0,0 +1,92 @@
+// This file is compiled and linked into the S-record format.
+
+#define FOO_MSG_LEN 80
+
+class Foo {
+    static int foos;
+    int i;
+    const len = FOO_MSG_LEN;
+    char message[len];
+public:
+    static void init_foo ();
+    static int nb_foos() { return foos; }
+    Foo();
+    Foo( char* message);
+    Foo(const Foo&);
+    Foo & operator= (const Foo&);
+    ~Foo ();
+};
+
+static Foo static_foo( "static_foo");
+
+int
+main ()
+{
+  Foo automatic_foo( "automatic_foo");
+  return 0;
+}
+
+extern "C" {
+int
+__main ()
+{
+}
+
+int
+__builtin_delete ()
+{
+}
+
+int
+__builtin_new ()
+{
+}
+
+/* V_SPILL and V_FILL are used by a29k-amd-udi.  */
+
+int
+V_SPILL ()
+{
+}
+
+int
+V_FILL ()
+{
+}
+}
+
+int Foo::foos = 0;
+
+void Foo::init_foo ()
+{
+  foos = 80;
+}
+
+Foo::Foo ()
+{
+  i = ++foos;
+}
+
+Foo::Foo (char* msg)
+{
+  i = ++foos;
+}
+
+Foo::Foo (const Foo& foo)
+{
+  i = ++foos;
+  for (int k = 0; k < FOO_MSG_LEN; k++)
+    message[k] = foo.message[k];
+}
+
+Foo& Foo::operator= (const Foo& foo)
+{
+  for (int k = 0; k < FOO_MSG_LEN; k++)
+    message[k] = foo.message[k];
+  return *this;
+}
+
+Foo::~Foo ()
+{
+  foos--;
+}
diff --git a/ld/testsuite/ld-srec/srec.exp b/ld/testsuite/ld-srec/srec.exp
new file mode 100644 (file)
index 0000000..b6d633d
--- /dev/null
@@ -0,0 +1,300 @@
+# Test linking directly to S-records.
+# By Ian Lance Taylor, Cygnus Support.
+# Public domain.
+
+# Get the offset from an S-record line to the start of the data.
+
+proc srec_off { l } {
+    if [string match "S1*" $l] {
+       return 8
+    } else { if [string match "S2*" $l] {
+       return 10
+    } else { if [string match "S3*" $l] {
+       return 12
+    } else {
+       return -1
+    } } }
+}
+
+# See if an S-record line contains only zero data.
+
+proc srec_zero { l } {
+    if [string match "S\[0789\]*" $l] {
+       return 1
+    }
+
+    # Strip the address and checksum.
+    if [string match "S\[123\]*" $l] {
+       set l [string range $l [srec_off $l] [expr [string length $l] - 3]]
+    } else {
+       return 0
+    }
+
+    # The rest must be zero.
+    return [string match "" [string trim $l "0"]]
+}
+
+# Get the address of an S-record line.
+
+proc srec_addr { l } {
+    if [string match "S\[123\]*" $l] {
+       set addr [string range $l 4 [expr [srec_off $l] - 1]]
+    } else {
+       return -1
+    }
+
+    return "0x$addr"
+}
+
+# Get the number of data bytes in an S-record line.
+
+proc srec_len { l } {
+    if ![string match "S\[123\]*" $l] {
+       return 0
+    }
+
+    return [expr "0x[string range $l 2 3]" - ([srec_off $l] - 4) / 2 - 1]
+}
+
+# Extract bytes from an S-record line.
+
+proc srec_extract { l start len } {
+    set off [srec_off $l]
+    set rlen [srec_len $l]
+    set stop [expr $start + $len]
+    if { $stop > $rlen } {
+       set stop [expr $rlen]
+    }
+    set start [expr $start * 2 + $off]
+    set stop [expr $stop * 2 + $off - 1]
+    return [string range $l $start $stop]
+}
+
+# See if a range of bytes in an S-record line is all zeroes.
+
+proc srec_zero_range { l start len } {
+    return [string match "" [string trim [srec_extract $l $start $len] "0"]]
+}
+
+# Trim an S-record line such that the specified number of bytes remain
+# at the end.
+
+proc srec_trim { l leave } {
+    set off [srec_off $l]
+    set addr [srec_addr $l]
+    set len [srec_len $l]
+
+    if { $leave >= $len } {
+       return $l
+    }
+
+    set s1 [string range $l 0 1]
+    set s2 [format "%02x" [expr ($off - 4) / 2 + $leave + 1]]
+    set s3 [format "%0[expr $off - 4]x" [expr $addr + $len - $leave]]
+    set s4 [string range $l [expr [string length $l] - ($leave * 2) - 2] end]
+    set s "${s1}${s2}${s3}${s4}"
+
+    verbose "srec_trim { '$l' $leave } returning '$s'" 2
+
+    return $s
+}
+
+# Report failure when comparing S-record lines
+
+proc srec_compare_fail { which l1 l2 } {
+    send_log "comparison failure $which:\n$l1\n$l2\n"
+    verbose "comparison failure $which:\n$l1\n$l2"
+}
+
+# Compare S-record files.  We don't want to fuss about things like
+# extra zeroes.  Note that BFD always sorts S-records by address.
+
+proc srec_compare { f1 f2 } {
+    set e1 [gets $f1 l1]
+    set e2 [gets $f2 l2]
+
+    while { $e1 != -1 } {
+       set l1 [string trimright $l1 "\r\n"]
+       set l2 [string trimright $l2 "\r\n"]
+       if { $e2 == -1 } {
+           # If l1 contains data, it must be zero.
+           if ![srec_zero $l1] {
+               send_log "data after EOF: $l1\n"
+               verbose "data after EOF: $l1"
+               return 0
+           }
+       } else { if { [string compare $l1 $l2] == 0 } {
+           set e1 [gets $f1 l1]
+           set e2 [gets $f2 l2]
+       } else { if { [srec_zero $l1] } {
+           set e1 [gets $f1 l1]
+       } else { if { [srec_zero $l2] } {
+           set e2 [gets $f2 l2]
+       } else {
+           # The strings are not the same, and neither is all zeroes.
+           set a1 [srec_addr $l1]
+           set n1 [srec_len $l1]
+           set a2 [srec_addr $l2]
+           set n2 [srec_len $l2]
+
+           if { $a1 < $a2 && ![srec_zero_range $l1 0 [expr $a2 - $a1]] } {
+               verbose "$a1 $a2 [srec_extract $l1 0 [expr $a2 - $a1]]" 2
+               srec_compare_fail 1 $l1 $l2
+               return 0
+           }
+           if { $a2 < $a1 && ![srec_zero_range $l2 0 [expr $a1 - $a2]] } {
+               srec_compare_fail 2 $l1 $l2
+               return 0
+           }
+
+           # Here we know that any initial data in both lines is
+           # zero.  Now make sure that any overlapping data matches.
+           if { $a1 < $a2 } {
+               set os1 [expr $a2 - $a1]
+               set os2 0
+           } else {
+               set os1 0
+               set os2 [expr $a1 - $a2]
+           }
+           if { $a1 + $n1 < $a2 + $n2 } {
+               set ol [expr $n1 - $os1]
+           } else {
+               set ol [expr $n2 - $os2]
+           }
+
+           set x1 [srec_extract $l1 $os1 $ol]
+           set x2 [srec_extract $l2 $os2 $ol]
+           if { [string compare $x1 $x2] != 0 } {
+               verbose "$os1 $ol $x1" 2
+               verbose "$os2 $ol $x2" 2
+               srec_compare_fail 3 $l1 $l2
+               return 0
+           }
+
+           # These strings match.  Trim the data from the larger
+           # string, read a new copy of the smaller string, and
+           # continue.
+           if { $a1 + $n1 < $a2 + $n2 } {
+               set l2 [srec_trim $l2 [expr ($a2 + $n2) - ($a1 + $n1)]]
+               set e1 [gets $f1 l1]
+           } else { if { $a1 + $n1 > $a2 + $n2 } {
+               set l1 [srec_trim $l1 [expr ($a1 + $n1) - ($a2 + $n2)]]
+               set e2 [gets $f2 l2]
+           } else {
+               set e1 [gets $f1 l1]
+               set e2 [gets $f2 l2]
+           } }
+       } } } }
+    }
+
+    # We've reached the end of the first file.  The remainder of the
+    # second file must contain only zeroes.
+    while { $e2 != -1 } {
+       set l2 [string trimright $l2 "\r\n"]
+       if ![srec_zero $l2] {
+           send_log "data after EOF: $l2\n"
+           verbose "data after EOF: $l2"
+           return 0
+       }
+       set e2 [gets $f2 l2]
+    }
+
+    return 1
+}
+
+# Link twice, objcopy, and compare
+
+proc run_srec_test { test objs } {
+    global ld
+    global objcopy
+    global sizeof_headers
+    global host_triplet
+
+    # If the linker script uses SIZEOF_HEADERS, use a -Ttext argument
+    # to force both the normal link and the S-record link to be put in
+    # the same place.  We don't always use -Ttext because it interacts
+    # poorly with a.out.
+
+    if { $sizeof_headers } {
+       set targ "-Ttext 0x1000"
+    } else {
+       set targ ""
+    }
+
+    if { ![ld_simple_link $ld tmpdir/sr1 "$targ $objs"] \
+        || ![ld_simple_link $ld tmpdir/sr2.sr "$targ -oformat srec $objs"] } {
+       fail $test
+       return
+    }
+
+    send_log "$objcopy -O srec tmpdir/sr1 tmpdir/sr1.sr\n"
+    verbose "$objcopy -O srec tmpdir/sr1 tmpdir/sr1.sr"
+    catch "exec $objcopy -O srec tmpdir/sr1 tmpdir/sr1.sr" exec_output
+    set exec_output [prune_system_crud $host_triplet $exec_output]
+    if ![string match "" $exec_output] {
+       send_log "$exec_output\n"
+       verbose "$exec_output"
+       unresolved $test
+       return
+    }
+
+    set f1 [open tmpdir/sr1.sr r]
+    set f2 [open tmpdir/sr2.sr r]
+    if [srec_compare $f1 $f2] {
+       pass $test
+    } else {
+       fail $test
+    }
+    close $f1
+    close $f2
+}
+
+set test1 "S-records"
+set test2 "S-records with constructors"
+
+# See whether the default linker script uses SIZEOF_HEADERS.
+catch "exec $ld --verbose" exec_output
+set sizeof_headers [string match "*SIZEOF_HEADERS*" $exec_output]
+
+# First test linking a C program.  We don't require any libraries.  We
+# link it normally, and objcopy to the S-record format, and then link
+# directly to the S-record format, and require that the two files
+# contain the same data.
+
+if { [which $CC] == 0 } {
+    untested $test1
+    untested $test2
+    return
+}
+
+if { ![ld_compile $CC $srcdir/$subdir/sr1.c tmpdir/sr1.o] \
+     || ![ld_compile $CC $srcdir/$subdir/sr2.c tmpdir/sr2.o] } {
+    unresolved $test1
+    unresolved $test2
+    return
+}
+
+# The i386-aout target is confused: the linker does not put the
+# sections where objdump finds them.  I don't know which is wrong.
+setup_xfail "i[345]86-*-aout*"
+
+run_srec_test $test1 "tmpdir/sr1.o tmpdir/sr2.o"
+
+# Now try linking a C++ program with global constructors and
+# destructors.  Note that since we are not linking against any
+# libraries, this program won't actually work or anything.
+
+if { [which $CXX] == 0 } {
+    untested $test2
+    return
+}
+
+if ![ld_compile "$CXX $CXXFLAGS -fgnu-linker" $srcdir/$subdir/sr3.cc tmpdir/sr3.o] {
+    unresolved $test2
+    return
+}
+
+# See above.
+setup_xfail "i[345]86-*-aout*"
+
+run_srec_test $test2 "tmpdir/sr3.o"