From: "H.J. Lu" <hjl.tools@gmail.com>
To: Dave Korn <dave.korn.cygwin@gmail.com>
Cc: "binutils@sourceware.org" <binutils@sourceware.org>
Subject: Re: [PATCH,trunk+2.21.1] Fix link order problem with LD plugin API.
Date: Sat, 29 Jan 2011 02:01:00 -0000 [thread overview]
Message-ID: <AANLkTik6PH6WTFq_yRy1ceLwOu0u+t_LuRv4wyCCwgsk@mail.gmail.com> (raw)
In-Reply-To: <AANLkTino6tHjPdxZAaixhPfJKEX-mLeH8KaA5GkmDRFn@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 4268 bytes --]
On Fri, Jan 28, 2011 at 5:45 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Fri, Jan 28, 2011 at 5:48 PM, Dave Korn <dave.korn.cygwin@gmail.com> wrote:
>>
>> Hi list,
>>
>> This patch updates the existing plugin API in LD to correct the effective
>> link order of the files added by the plugin. (It does not deal with the need
>> for pass-throughs; that is a separate and orthogonal issue that I will tackle
>> in a subsequent patch. I hope that the combination of these two fixes should
>> address all the same issues HJ's two-stage linking approach was designed to fix.)
>>
>> At the moment added files and libraries are simply concatenated onto the end
>> of the statement list. This is more-or-less the same as adding them onto the
>> end of the command-line; this means that their contributions get merged into
>> sections after all the non-IR files, including in particular crtend.o. That's
>> pretty serious when it results in something like this:
>>
>>> .eh_frame 0x00404000 0x200
>>> *(.eh_frame)
>>> .eh_frame 0x00404000 0x58 /gnu/gcc/obj-clean-r169274/gcc/testsuite/g++/../../crtbegin.o
>>> .eh_frame 0x00404058 0x5c /gnu/gcc/obj-clean-r169274/gcc/testsuite/g++/../../crtend.o
>>> .eh_frame 0x004040b4 0x68 /win/c/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ccF5bqWv.lto.o
>>
>> because it breaks EH!
>>
>> The attached patch doesn't implement two-stage linking, but takes the
>> approach Cary described(*) in GOLD:
>>
>>> On 03/12/2010 18:46, Cary Coutant wrote:
>>>
>>>> I should have remembered that I already dealt with this problem long
>>>> ago -- gold defers the layout of all real objects that follow the
>>>> first claimed IR file until after the replacement files have been laid
>>>> out. With respect to physical layout of the sections, this effectively
>>>> makes the link order equivalent to putting the replacement files in
>>>> the place of the first IR file. No "endcap" option is necessary.
>>
>> In LD, there's nothing to "defer", as layout hasn't begun yet. All we need
>> to do is add the replacement files into the middle of the existing statement
>> list, immediately after the first claimed IR file. Complicated only slightly
>> by the fact that there are in fact three separate singly-linked chains through
>> the list of statements, that's what this patch does, and it results in the
>> correct result:
>>
>>> .eh_frame 0x00404000 0x200
>>> *(.eh_frame)
>>> .eh_frame 0x00404000 0x58 /gnu/gcc/obj-clean-r169274/gcc/testsuite/g++/../../crtbegin.o
>>> .eh_frame 0x00404058 0x68 /win/c/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ccfuGGNR.lto.o
>>> .eh_frame 0x004040c0 0x5c /gnu/gcc/obj-clean-r169274/gcc/testsuite/g++/../../crtend.o
>>
>> ld/ChangeLog:
>>
>> 2011-01-29 Dave Korn <dave.korn.cygwin@gmail.com>
>>
>> * ldlang.c (lang_process): After adding and opening new input files
>> passed from plugin, splice them into correct place in statement list
>> chains to preserve critical link order.
>> (lang_list_insert_after): New helper function.
>> (lang_list_remove_tail): Likewise.
>>
>> Built and tested on i686-pc-cygwin. I'm running a subset of the G++/GCC
>> testsuites to sanity-check it as well, and I'll put it through a cycle or two
>> on one of the cfarm machines while I'm at it.
>>
>
> On hjl/lto-mixed branch, I added a dozen LTO tests. They are tested
> if GCC supports LTO. You should try your ld changes on those new
> LTO tests. You can ignore those mixed IR failures. But other LTO tests
> should pass. I can post a patch for LTO testcases if you want.
>
Here is the new LTO tests. The current LD in CVS failed:
FAIL: LTO 2
FAIL: ld-plugin/lto-4r-a
FAIL: ld-plugin/lto-4r-b
FAIL: ld-plugin/lto-4r-c
FAIL: ld-plugin/lto-4r-d
FAIL: LTO 3 symbol
FAIL: LTO 5 symbol
FAIL: LTO 4a
FAIL: LTO 4c
FAIL: LTO 4d
FAIL: LTO 10
FAIL: LTO 8
You can ignore
FAIL: ld-plugin/lto-4r-a
FAIL: ld-plugin/lto-4r-b
FAIL: ld-plugin/lto-4r-c
FAIL: ld-plugin/lto-4r-d
FAIL: LTO 3 symbol
FAIL: LTO 5 symbol
FAIL: LTO 4a
FAIL: LTO 4c
FAIL: LTO 4d
FAIL: LTO 10
But all other tests should pass.
--
H.J.
[-- Attachment #2: ld-lto-test-1.patch --]
[-- Type: text/plain, Size: 32482 bytes --]
diff --git a/ld/testsuite/ld-plugin/dummy.c b/ld/testsuite/ld-plugin/dummy.c
new file mode 100644
index 0000000..5c03287
--- /dev/null
+++ b/ld/testsuite/ld-plugin/dummy.c
@@ -0,0 +1 @@
+/* An empty file. */
diff --git a/ld/testsuite/ld-plugin/dummy.s b/ld/testsuite/ld-plugin/dummy.s
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/ld/testsuite/ld-plugin/dummy.s
@@ -0,0 +1 @@
+
diff --git a/ld/testsuite/ld-plugin/func1p.c b/ld/testsuite/ld-plugin/func1p.c
new file mode 100644
index 0000000..917dcbb
--- /dev/null
+++ b/ld/testsuite/ld-plugin/func1p.c
@@ -0,0 +1,8 @@
+extern int retval;
+
+int
+__attribute__ ((visibility ("protected")))
+func1 (void)
+{
+ return retval;
+}
diff --git a/ld/testsuite/ld-plugin/func2.c b/ld/testsuite/ld-plugin/func2.c
new file mode 100644
index 0000000..d233fcf
--- /dev/null
+++ b/ld/testsuite/ld-plugin/func2.c
@@ -0,0 +1,7 @@
+
+extern int retval;
+
+int func2 (void)
+{
+ return retval;
+}
diff --git a/ld/testsuite/ld-plugin/func2i.c b/ld/testsuite/ld-plugin/func2i.c
new file mode 100644
index 0000000..00d7cdd
--- /dev/null
+++ b/ld/testsuite/ld-plugin/func2i.c
@@ -0,0 +1,8 @@
+extern int retval;
+
+int
+__attribute__ ((visibility ("internal")))
+func2 (void)
+{
+ return retval;
+}
diff --git a/ld/testsuite/ld-plugin/func3h.c b/ld/testsuite/ld-plugin/func3h.c
new file mode 100644
index 0000000..525de63
--- /dev/null
+++ b/ld/testsuite/ld-plugin/func3h.c
@@ -0,0 +1,8 @@
+extern int retval;
+
+int
+__attribute__ ((visibility ("hidden")))
+func3 (void)
+{
+ return retval;
+}
diff --git a/ld/testsuite/ld-plugin/lto-10.out b/ld/testsuite/ld-plugin/lto-10.out
new file mode 100644
index 0000000..ce01362
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-10.out
@@ -0,0 +1 @@
+hello
diff --git a/ld/testsuite/ld-plugin/lto-10a.c b/ld/testsuite/ld-plugin/lto-10a.c
new file mode 100644
index 0000000..93d57b5
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-10a.c
@@ -0,0 +1,6 @@
+extern int foo(void);
+
+int main(void)
+{
+ return foo();
+}
diff --git a/ld/testsuite/ld-plugin/lto-10b.c b/ld/testsuite/ld-plugin/lto-10b.c
new file mode 100644
index 0000000..507055b
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-10b.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+int foo(void)
+{
+ printf ("hello\n");
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/lto-10r.d b/ld/testsuite/ld-plugin/lto-10r.d
new file mode 100644
index 0000000..689e6ec
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-10r.d
@@ -0,0 +1,7 @@
+#ld: -r tmpdir/lto-10a.o tmpdir/lto-10b.o
+#source: dummy.s
+#nm: -p
+
+#...
+[0-9a-f]+ C __gnu_lto_v.*
+#pass
diff --git a/ld/testsuite/ld-plugin/lto-11.out b/ld/testsuite/ld-plugin/lto-11.out
new file mode 100644
index 0000000..899682a
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-11.out
@@ -0,0 +1,2 @@
+Hello from foo!
+Hello from bar!
diff --git a/ld/testsuite/ld-plugin/lto-11a.c b/ld/testsuite/ld-plugin/lto-11a.c
new file mode 100644
index 0000000..5193972
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-11a.c
@@ -0,0 +1,9 @@
+extern void foo(void);
+extern void bar(void);
+
+int main(void)
+{
+ foo();
+ bar();
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/lto-11b.c b/ld/testsuite/ld-plugin/lto-11b.c
new file mode 100644
index 0000000..62d61ec
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-11b.c
@@ -0,0 +1,6 @@
+extern int printf(const char *, ...);
+
+void foo(void)
+{
+ printf("Hello from %s!\n", __FUNCTION__);
+}
diff --git a/ld/testsuite/ld-plugin/lto-11c.c b/ld/testsuite/ld-plugin/lto-11c.c
new file mode 100644
index 0000000..8cd40b9
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-11c.c
@@ -0,0 +1,6 @@
+extern int printf(const char *, ...);
+
+void bar(void)
+{
+ printf("Hello from %s!\n", __FUNCTION__);
+}
diff --git a/ld/testsuite/ld-plugin/lto-12.out b/ld/testsuite/ld-plugin/lto-12.out
new file mode 100644
index 0000000..d86bac9
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-12.out
@@ -0,0 +1 @@
+OK
diff --git a/ld/testsuite/ld-plugin/lto-12a.c b/ld/testsuite/ld-plugin/lto-12a.c
new file mode 100644
index 0000000..30ff3d9
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-12a.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+extern int value;
+
+int
+main (int argc, char **argv)
+{
+ int n = 10 * (argc + 1);
+ char *p = malloc (n);
+ __builtin_memcpy (p, argv[0], n);
+ if (value != -1)
+ abort ();
+ printf ("OK\n");
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/lto-12b.c b/ld/testsuite/ld-plugin/lto-12b.c
new file mode 100644
index 0000000..c2b00e4
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-12b.c
@@ -0,0 +1 @@
+int value = -1;
diff --git a/ld/testsuite/ld-plugin/lto-12c.c b/ld/testsuite/ld-plugin/lto-12c.c
new file mode 100644
index 0000000..ecd1bd4
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-12c.c
@@ -0,0 +1,15 @@
+#include <string.h>
+
+extern int value;
+
+void *memcpy(void *dest, const void *src, size_t n)
+{
+ char *d = (char *) dest;
+ const char *s = (const char *) src;
+
+ while (n--)
+ *d++ = *s++;
+
+ value = 1;
+ return dest;
+}
diff --git a/ld/testsuite/ld-plugin/lto-13.out b/ld/testsuite/ld-plugin/lto-13.out
new file mode 100644
index 0000000..3bd1f0e
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-13.out
@@ -0,0 +1,2 @@
+foo
+bar
diff --git a/ld/testsuite/ld-plugin/lto-13a.c b/ld/testsuite/ld-plugin/lto-13a.c
new file mode 100644
index 0000000..5193972
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-13a.c
@@ -0,0 +1,9 @@
+extern void foo(void);
+extern void bar(void);
+
+int main(void)
+{
+ foo();
+ bar();
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/lto-13b.c b/ld/testsuite/ld-plugin/lto-13b.c
new file mode 100644
index 0000000..7c87a5e
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-13b.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+void
+bar (void)
+{
+ printf ("bar\n");
+}
diff --git a/ld/testsuite/ld-plugin/lto-13c.c b/ld/testsuite/ld-plugin/lto-13c.c
new file mode 100644
index 0000000..4859019
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-13c.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+void
+foo (void)
+{
+ printf ("foo\n");
+}
diff --git a/ld/testsuite/ld-plugin/lto-1a.c b/ld/testsuite/ld-plugin/lto-1a.c
new file mode 100644
index 0000000..b775d0a
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-1a.c
@@ -0,0 +1,4 @@
+unsigned long long bar (unsigned long long y)
+{
+ return 30 / y;
+}
diff --git a/ld/testsuite/ld-plugin/lto-1b.c b/ld/testsuite/ld-plugin/lto-1b.c
new file mode 100644
index 0000000..8a961ef
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-1b.c
@@ -0,0 +1,8 @@
+extern unsigned long long bar (unsigned long long);
+
+int
+main (int argc, char **argv)
+{
+ unsigned long long d = bar ((unsigned long long) (argc + 1));
+ return d;
+}
diff --git a/ld/testsuite/ld-plugin/lto-2.c b/ld/testsuite/ld-plugin/lto-2.c
new file mode 100644
index 0000000..f0eacf4
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-2.c
@@ -0,0 +1,11 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+int
+main (int argc, char **argv)
+{
+ int d = atoi (argv[1]);
+ printf ("%f\n", sin (d));
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/lto-3.d b/ld/testsuite/ld-plugin/lto-3.d
new file mode 100644
index 0000000..c3a9a16
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-3.d
@@ -0,0 +1,4 @@
+#failif
+#...
+[0-9a-f]+ T foo
+#...
diff --git a/ld/testsuite/ld-plugin/lto-3.out b/ld/testsuite/ld-plugin/lto-3.out
new file mode 100644
index 0000000..a69f8f3
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-3.out
@@ -0,0 +1,2 @@
+hello foo
+hello bar
diff --git a/ld/testsuite/ld-plugin/lto-3a.c b/ld/testsuite/ld-plugin/lto-3a.c
new file mode 100644
index 0000000..5193972
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-3a.c
@@ -0,0 +1,9 @@
+extern void foo(void);
+extern void bar(void);
+
+int main(void)
+{
+ foo();
+ bar();
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/lto-3b.c b/ld/testsuite/ld-plugin/lto-3b.c
new file mode 100644
index 0000000..c24f6d4
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-3b.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+void foo(void)
+{
+ printf ("hello foo\n");
+}
diff --git a/ld/testsuite/ld-plugin/lto-3c.c b/ld/testsuite/ld-plugin/lto-3c.c
new file mode 100644
index 0000000..95b3bc0
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-3c.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+void bar(void)
+{
+ printf ("hello bar\n");
+}
diff --git a/ld/testsuite/ld-plugin/lto-3r.d b/ld/testsuite/ld-plugin/lto-3r.d
new file mode 100644
index 0000000..1d1befe
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-3r.d
@@ -0,0 +1,7 @@
+#ld: -r tmpdir/lto-3b.o
+#source: dummy.s
+#nm: -p
+
+#...
+[0-9a-f]+ C __gnu_lto_v.*
+#pass
diff --git a/ld/testsuite/ld-plugin/lto-4.out b/ld/testsuite/ld-plugin/lto-4.out
new file mode 100644
index 0000000..8d8cc92
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-4.out
@@ -0,0 +1,2 @@
+hello bar
+hello foo
diff --git a/ld/testsuite/ld-plugin/lto-4a.c b/ld/testsuite/ld-plugin/lto-4a.c
new file mode 100644
index 0000000..2d07cf5
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-4a.c
@@ -0,0 +1,7 @@
+extern void foo(void);
+
+int main(void)
+{
+ foo();
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/lto-4b.c b/ld/testsuite/ld-plugin/lto-4b.c
new file mode 100644
index 0000000..bb4a68b
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-4b.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+
+extern void bar (void);
+
+void foo(void)
+{
+ bar ();
+ printf ("hello foo\n");
+}
diff --git a/ld/testsuite/ld-plugin/lto-4c.c b/ld/testsuite/ld-plugin/lto-4c.c
new file mode 100644
index 0000000..317e6fc
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-4c.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+void bar (void)
+{
+ printf ("hello bar\n");
+}
diff --git a/ld/testsuite/ld-plugin/lto-4r-a.d b/ld/testsuite/ld-plugin/lto-4r-a.d
new file mode 100644
index 0000000..c618cff
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-4r-a.d
@@ -0,0 +1,7 @@
+#ld: -r tmpdir/lto-4a.o tmpdir/lto-4b.o tmpdir/lto-4c.o
+#source: dummy.s
+#objdump: -h
+
+#...
+.* .gnu_object_only.*
+#pass
diff --git a/ld/testsuite/ld-plugin/lto-4r-b.d b/ld/testsuite/ld-plugin/lto-4r-b.d
new file mode 100644
index 0000000..07d71cb
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-4r-b.d
@@ -0,0 +1,7 @@
+#ld: -r tmpdir/lto-4a.o tmpdir/lto-4b.o
+#source: dummy.s
+#objdump: -h
+
+#...
+.* .gnu_object_only.*
+#pass
diff --git a/ld/testsuite/ld-plugin/lto-4r-c.d b/ld/testsuite/ld-plugin/lto-4r-c.d
new file mode 100644
index 0000000..ada50c0
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-4r-c.d
@@ -0,0 +1,7 @@
+#ld: -r tmpdir/lto-4r-b.o tmpdir/lto-4c.o
+#source: dummy.s
+#objdump: -h
+
+#...
+.* .gnu_object_only.*
+#pass
diff --git a/ld/testsuite/ld-plugin/lto-4r-d.d b/ld/testsuite/ld-plugin/lto-4r-d.d
new file mode 100644
index 0000000..d4c5852
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-4r-d.d
@@ -0,0 +1,7 @@
+#ld: -r --whole-archive tmpdir/liblto-4.a
+#source: dummy.s
+#objdump: -h
+
+#...
+.* .gnu_object_only.*
+#pass
diff --git a/ld/testsuite/ld-plugin/lto-5.d b/ld/testsuite/ld-plugin/lto-5.d
new file mode 100644
index 0000000..c3a9a16
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-5.d
@@ -0,0 +1,4 @@
+#failif
+#...
+[0-9a-f]+ T foo
+#...
diff --git a/ld/testsuite/ld-plugin/lto-5.out b/ld/testsuite/ld-plugin/lto-5.out
new file mode 100644
index 0000000..dfbb215
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-5.out
@@ -0,0 +1 @@
+hello foo
diff --git a/ld/testsuite/ld-plugin/lto-5a.c b/ld/testsuite/ld-plugin/lto-5a.c
new file mode 100644
index 0000000..2d07cf5
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-5a.c
@@ -0,0 +1,7 @@
+extern void foo(void);
+
+int main(void)
+{
+ foo();
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/lto-5b.c b/ld/testsuite/ld-plugin/lto-5b.c
new file mode 100644
index 0000000..c24f6d4
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-5b.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+void foo(void)
+{
+ printf ("hello foo\n");
+}
diff --git a/ld/testsuite/ld-plugin/lto-5r.d b/ld/testsuite/ld-plugin/lto-5r.d
new file mode 100644
index 0000000..43e9a5c
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-5r.d
@@ -0,0 +1,7 @@
+#ld: -r tmpdir/lto-5a.o tmpdir/lto-5b.o
+#source: dummy.s
+#nm: -p
+
+#...
+[0-9a-f]+ C __gnu_lto_v.*
+#pass
diff --git a/ld/testsuite/ld-plugin/lto-6.c b/ld/testsuite/ld-plugin/lto-6.c
new file mode 100644
index 0000000..749e4e0
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-6.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+
+extern char _etext[];
+
+int main(void)
+{
+ printf ("%p: %d\n", _etext, _etext[0]);
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/lto-7.out b/ld/testsuite/ld-plugin/lto-7.out
new file mode 100644
index 0000000..d86bac9
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-7.out
@@ -0,0 +1 @@
+OK
diff --git a/ld/testsuite/ld-plugin/lto-7a.c b/ld/testsuite/ld-plugin/lto-7a.c
new file mode 100644
index 0000000..d277a43
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-7a.c
@@ -0,0 +1,14 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+int foo = -1;
+
+extern void bar ();
+
+int
+main (int argc, char **argv)
+{
+ bar ();
+ printf ("OK\n");
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/lto-7b.c b/ld/testsuite/ld-plugin/lto-7b.c
new file mode 100644
index 0000000..1798130
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-7b.c
@@ -0,0 +1,8 @@
+extern int foo;
+
+static void
+__attribute__ ((unused, constructor))
+set_foo (void)
+{
+ foo = 30;
+}
diff --git a/ld/testsuite/ld-plugin/lto-7c.c b/ld/testsuite/ld-plugin/lto-7c.c
new file mode 100644
index 0000000..5236f57
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-7c.c
@@ -0,0 +1,9 @@
+extern int foo;
+extern int foo2;
+
+static void
+__attribute__ ((unused, constructor))
+set_foo (void)
+{
+ foo = foo2;
+}
diff --git a/ld/testsuite/ld-plugin/lto-7d.c b/ld/testsuite/ld-plugin/lto-7d.c
new file mode 100644
index 0000000..7fc1ff1
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-7d.c
@@ -0,0 +1,11 @@
+#include <stdlib.h>
+
+extern int foo;
+int foo2 = 2;
+
+void
+bar (void)
+{
+ if (foo != 30)
+ abort ();
+}
diff --git a/ld/testsuite/ld-plugin/lto-8.out b/ld/testsuite/ld-plugin/lto-8.out
new file mode 100644
index 0000000..35c5d69
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-8.out
@@ -0,0 +1 @@
+baz: 42
diff --git a/ld/testsuite/ld-plugin/lto-8a.c b/ld/testsuite/ld-plugin/lto-8a.c
new file mode 100644
index 0000000..6901fb3
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-8a.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+
+void baz(int i)
+{
+ printf ("baz: %d\n", i);
+}
+
+int main(void)
+{
+ foo(42);
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/lto-8b.c b/ld/testsuite/ld-plugin/lto-8b.c
new file mode 100644
index 0000000..3b6db5f
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-8b.c
@@ -0,0 +1,14 @@
+extern int bar(void) __attribute__((__visibility__("hidden"), __const__));
+extern void baz(int);
+
+void foo(char c)
+{
+ int i;
+
+ if (bar())
+ i = c;
+ else
+ i = c;
+
+ baz(i);
+}
diff --git a/ld/testsuite/ld-plugin/lto-9.cc b/ld/testsuite/ld-plugin/lto-9.cc
new file mode 100644
index 0000000..2a4dcde
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-9.cc
@@ -0,0 +1,9 @@
+struct Foooo {
+ virtual ~Foooo () { }
+};
+
+int main(void)
+{
+ Foooo t;
+ return 0;
+}
diff --git a/ld/testsuite/ld-plugin/lto-9.d b/ld/testsuite/ld-plugin/lto-9.d
new file mode 100644
index 0000000..4b5bcf8
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto-9.d
@@ -0,0 +1,4 @@
+#failif
+#...
+[0-9a-f]+ . .*Foooo::Foooo.*
+#...
diff --git a/ld/testsuite/ld-plugin/lto.exp b/ld/testsuite/ld-plugin/lto.exp
new file mode 100644
index 0000000..0c49cec
--- /dev/null
+++ b/ld/testsuite/ld-plugin/lto.exp
@@ -0,0 +1,233 @@
+# Expect script for ld-plugin LTO tests
+# Copyright 2011
+# 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.
+
+# These tests require plugin and LTO.
+if { ![check_plugin_api_available]
+ || ![check_lto_available] } {
+ return
+}
+
+# Simple LTO tests and generate input files for complex LTO tests.
+set lto_link_tests {
+ {"LTO 1"
+ "-O2 -flto -fuse-linker-plugin" "-flto -fuse-linker-plugin"
+ {lto-1a.c lto-1b.c} {} "lto-1.exe"}
+ {"Build libdummy.a 2"
+ "" "-O2 -flto -fuse-linker-plugin"
+ {lto-2.c} {} "libdummy.a"}
+ {"LTO 2"
+ "-static -O2 -flto -fuse-linker-plugin tmpdir/lto-2.o -lm" ""
+ {dummy.c} {} "lto-2.exe"}
+ {"Build libdummy.a 3a"
+ "" "-flto"
+ {lto-3a.c} {} "libdummy.a"}
+ {"Build libdummy.a 3c"
+ "" "-O2"
+ {lto-3c.c} {} "libdummy.a"}
+ {"Build liblto-3.a"
+ "" "-flto"
+ {lto-3b.c} {} "liblto-3.a"}
+ {"Build libdummy.a 4a"
+ "" "-flto"
+ {lto-4a.c} {} "libdummy.a"}
+ {"Build libdummy.a 4b"
+ "" "-O2"
+ {lto-4b.c} {} "libdummy.a"}
+ {"Build libdummy.a 4c"
+ "" "-O2"
+ {lto-4c.c} {} "libdummy.a"}
+ {"Build libdummy.a 5a"
+ "" "-flto"
+ {lto-5a.c} {} "libdummy.a"}
+ {"Build libdummy.a 5b"
+ "" "-flto"
+ {lto-5b.c} {} "libdummy.a"}
+ {"LTO 6"
+ "-O2 -flto -fuse-linker-plugin" ""
+ {lto-6.c} {} "lto-6.exe" "c"}
+ {"Build libdummy.a PR ld/12365"
+ "" "-flto -O2"
+ {pr12365a.c pr12365b.c pr12365c.c} {} "libdummy.a"}
+ {"Build libdummy.a 9"
+ "" "-O2 -flto"
+ {lto-9.cc} {} "libdummy.a"}
+ {"Build libdummy.a 10a"
+ "" "-O2"
+ {lto-10a.c} {} "libdummy.a"}
+ {"Build libdummy.a 10b"
+ "" "-O2 -flto"
+ {lto-10b.c} {} "libdummy.a"}
+ {"Build libdummy.a 11a"
+ "" "-O -flto"
+ {lto-11a.c} {} "libdummy.a"}
+ {"Build libdummy.a 11b"
+ "" "-O -flto"
+ {lto-11b.c} {} "libdummy.a"}
+ {"Build libdummy.a 11c"
+ "" "-O"
+ {lto-11c.c} {} "libdummy.a"}
+ {"Build liblto-12.a"
+ "" "-O2 -flto"
+ {lto-12c.c} {} "liblto-12.a"}
+ {"Build libdummy.a 12"
+ "" "-O2 -flto"
+ {lto-12a.c lto-12b.c} {} "libdummy.a"}
+ {"Build libdummy.a 13"
+ "" "-O2 -flto"
+ {lto-13a.c lto-13b.c} {} "libdummy.a"}
+ {"Build liblto-13.a"
+ "" "-O2"
+ {lto-13c.c} {} "liblto-13.a"}
+}
+
+# Generate input files for complex LTO tests for ELF.
+set lto_link_elf_tests {
+ {"Build libdummy.a 7"
+ "" "-flto -O2"
+ {lto-7a.c lto-7b.c lto-7c.c} {} "libdummy.a"}
+ {"Build liblto-7.so"
+ "-shared" "-O2 -fpic"
+ {lto-7d.c} {} "liblto-7.so" "c"}
+ {"Build libdummy.a 8a"
+ "" "-O2"
+ {lto-8a.c} {} "libdummy.a"}
+ {"Build libdummy.a 8b"
+ "" "-flto -O2"
+ {lto-8b.c} {} "libdummy.a"}
+}
+
+# Check final symbols in executables.
+set lto_link_symbol_tests {
+ {"LTO 3 symbol"
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-3a.o tmpdir/lto-3c.o tmpdir/liblto-3.a" ""
+ {dummy.c} {{"nm" {} "lto-3.d"}} "lto-3.exe" "c"}
+ {"LTO 5 symbol"
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-5.o" ""
+ {dummy.c} {{"nm" {} "lto-5.d"}} "lto-5.exe" "c"}
+ {"LTO 9 symbol"
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-9.o" ""
+ {dummy.c} {{"nm" {-C} "lto-9.d"}} "lto-9.exe" "c++"}
+}
+
+# LTO run-time tests.
+set lto_run_tests {
+ {"LTO 3a"
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-3a.o tmpdir/lto-3c.o tmpdir/liblto-3.a" ""
+ {dummy.c} "lto-3b.exe" "lto-3.out" "" "c"}
+ {"LTO 3b"
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-3a.o tmpdir/lto-3c.o tmpdir/lto-3.o" ""
+ {dummy.c} "lto-3c.exe" "lto-3.out" "" "c"}
+ {"LTO 3c"
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-3a.o tmpdir/lto-3c.o -Wl,--whole-archive tmpdir/liblto-3.a -Wl,--no-whole-archive tmpdir/liblto-3.a" ""
+ {dummy.c} "lto-3d.exe" "lto-3.out" "" "c"}
+ {"LTO 4a"
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-4r-a.o" ""
+ {dummy.c} "lto-4a.exe" "lto-4.out" "" "c"}
+ {"LTO 4c"
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-4r-c.o" ""
+ {dummy.c} "lto-4c.exe" "lto-4.out" "" "c"}
+ {"LTO 4d"
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-4r-d.o" ""
+ {dummy.c} "lto-4d.exe" "lto-4.out" "" "c"}
+ {"LTO 5"
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-5.o" ""
+ {dummy.c} "lto-5.exe" "lto-5.out" "" "c"}
+ {"LTO 10"
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-10.o" ""
+ {dummy.c} "lto-10.exe" "lto-10.out" "" "c"}
+ {"LTO 11"
+ "-O -flto -fuse-linker-plugin tmpdir/liblto-11.a" ""
+ {dummy.c} "lto-11.exe" "lto-11.out" "" "c"}
+ {"LTO 12a"
+ "-O -flto -fuse-linker-plugin tmpdir/lto-12a.o tmpdir/liblto-12.a tmpdir/lto-12b.o" ""
+ {dummy.c} "lto-12a.exe" "lto-12.out" "" "c"}
+ {"LTO 12b"
+ "-O -flto -fuse-linker-plugin tmpdir/lto-12a.o tmpdir/lto-12b.o tmpdir/liblto-12.a" ""
+ {dummy.c} "lto-12b.exe" "lto-12.out" "" "c"}
+ {"LTO 13"
+ "-O -flto -fuse-linker-plugin tmpdir/lto-13a.o tmpdir/liblto-13.a tmpdir/lto-13b.o" ""
+ {dummy.c} "lto-13.exe" "lto-13.out" "" "c"}
+}
+
+# LTO run-time tests for ELF
+set lto_run_elf_tests {
+ {"LTO 7"
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-7b.o tmpdir/lto-7c.o tmpdir/lto-7a.o tmpdir/liblto-7.so" ""
+ {dummy.c} "lto-7.exe" "lto-7.out" "" "c"}
+ {"LTO 8"
+ "-O2 -flto -fuse-linker-plugin tmpdir/lto-8b.o tmpdir/lto-8a.o" ""
+ {dummy.c} "lto-8.exe" "lto-8.out" "" "c"}
+}
+
+run_cc_link_tests $lto_link_tests
+
+if { [is_elf_format] } {
+ run_cc_link_tests $lto_link_elf_tests
+}
+
+set testname "Build liblto-4.a"
+remote_file host delete "tmpdir/liblto-4.a"
+set catch_output [run_host_cmd "$ar" "rc tmpdir/liblto-4.a tmpdir/lto-4a.o tmpdir/lto-4b.o tmpdir/lto-4c.o"]
+if {![string match "" $catch_output]} {
+ unresolved $testname
+ return
+}
+
+set testname "Build liblto-11.a"
+remote_file host delete "tmpdir/liblto-11.a"
+set catch_output [run_host_cmd "$ar" "rc tmpdir/liblto-11.a tmpdir/lto-11a.o tmpdir/lto-11b.o tmpdir/lto-11c.o"]
+if {![string match "" $catch_output]} {
+ unresolved $testname
+ return
+}
+
+# Check exported LTO linker errors.
+set testname "PR ld/12365"
+set exec_output [run_host_cmd "$CC" "-O2 -flto -fuse-linker-plugin tmpdir/pr12365a.o tmpdir/pr12365b.o tmpdir/pr12365c.o"]
+if { [ regexp "undefined reference to `my_bcopy'" $exec_output ] } {
+ pass $testname
+} {
+ fail $testname
+}
+
+# Run "ld -r" to generate inputs for complex LTO tests.
+run_dump_test "lto-3r"
+remote_exec host "mv" "tmpdir/dump tmpdir/lto-3.o"
+run_dump_test "lto-4r-a"
+remote_exec host "mv" "tmpdir/dump tmpdir/lto-4r-a.o"
+run_dump_test "lto-4r-b"
+remote_exec host "mv" "tmpdir/dump tmpdir/lto-4r-b.o"
+run_dump_test "lto-4r-c"
+remote_exec host "mv" "tmpdir/dump tmpdir/lto-4r-c.o"
+run_dump_test "lto-4r-d"
+remote_exec host "mv" "tmpdir/dump tmpdir/lto-4r-d.o"
+run_dump_test "lto-5r"
+remote_exec host "mv" "tmpdir/dump tmpdir/lto-5.o"
+run_dump_test "lto-10r"
+remote_exec host "mv" "tmpdir/dump tmpdir/lto-10.o"
+
+run_cc_link_tests $lto_link_symbol_tests
+
+run_ld_link_exec_tests [] $lto_run_tests
+
+if { [is_elf_format] } {
+ run_ld_link_exec_tests [] $lto_run_elf_tests
+}
diff --git a/ld/testsuite/ld-plugin/plugin-7.d b/ld/testsuite/ld-plugin/plugin-7.d
index 75f25e0..ee7a6eb 100644
--- a/ld/testsuite/ld-plugin/plugin-7.d
+++ b/ld/testsuite/ld-plugin/plugin-7.d
@@ -19,7 +19,8 @@ tv\[16\]: LDPT_OPTION 'registerallsymbolsread'
tv\[17\]: LDPT_OPTION 'registercleanup'
tv\[18\]: LDPT_OPTION 'claim:tmpdir/func.o'
tv\[19\]: LDPT_OPTION 'sym:_?func::0:0:0'
-tv\[20\]: LDPT_NULL value 0x0 \(0\)
+tv\[20\]: LDPT_OPTION 'add:tmpdir/func.o'
+tv\[21\]: LDPT_NULL value 0x0 \(0\)
#...
hook called: claim_file tmpdir/main.o \[@0/.* not claimed
hook called: claim_file tmpdir/func.o \[@0/.* CLAIMED
diff --git a/ld/testsuite/ld-plugin/plugin-8.d b/ld/testsuite/ld-plugin/plugin-8.d
index e72b039..a4db899 100644
--- a/ld/testsuite/ld-plugin/plugin-8.d
+++ b/ld/testsuite/ld-plugin/plugin-8.d
@@ -21,7 +21,9 @@ tv\[18\]: LDPT_OPTION 'claim:tmpdir/func.o'
tv\[19\]: LDPT_OPTION 'sym:_?func::0:0:0'
tv\[20\]: LDPT_OPTION 'sym:_?func2::0:0:0'
tv\[21\]: LDPT_OPTION 'dumpresolutions'
-tv\[22\]: LDPT_NULL value 0x0 \(0\)
+tv\[22\]: LDPT_OPTION 'add:tmpdir/func.o'
+tv\[23\]: LDPT_OPTION 'add:tmpdir/func2.o'
+tv\[24\]: LDPT_NULL value 0x0 \(0\)
#...
hook called: claim_file tmpdir/main.o \[@0/.* not claimed
hook called: claim_file tmpdir/func.o \[@0/.* CLAIMED
diff --git a/ld/testsuite/ld-plugin/plugin-9.d b/ld/testsuite/ld-plugin/plugin-9.d
index b74f4a6..a4db899 100644
--- a/ld/testsuite/ld-plugin/plugin-9.d
+++ b/ld/testsuite/ld-plugin/plugin-9.d
@@ -22,7 +22,8 @@ tv\[19\]: LDPT_OPTION 'sym:_?func::0:0:0'
tv\[20\]: LDPT_OPTION 'sym:_?func2::0:0:0'
tv\[21\]: LDPT_OPTION 'dumpresolutions'
tv\[22\]: LDPT_OPTION 'add:tmpdir/func.o'
-tv\[23\]: LDPT_NULL value 0x0 \(0\)
+tv\[23\]: LDPT_OPTION 'add:tmpdir/func2.o'
+tv\[24\]: LDPT_NULL value 0x0 \(0\)
#...
hook called: claim_file tmpdir/main.o \[@0/.* not claimed
hook called: claim_file tmpdir/func.o \[@0/.* CLAIMED
diff --git a/ld/testsuite/ld-plugin/plugin.exp b/ld/testsuite/ld-plugin/plugin.exp
index 8952f1d..fd0f939 100644
--- a/ld/testsuite/ld-plugin/plugin.exp
+++ b/ld/testsuite/ld-plugin/plugin.exp
@@ -70,6 +70,7 @@ set plugin_nm_output ""
if { $can_compile && \
(![ld_compile "$CC $CFLAGS" $srcdir/$subdir/main.c tmpdir/main.o] \
|| ![ld_compile "$CC $CFLAGS" $srcdir/$subdir/func.c tmpdir/func.o] \
+ || ![ld_compile "$CC $CFLAGS" $srcdir/$subdir/func2.c tmpdir/func2.o] \
|| ![ld_compile "$CC $CFLAGS" $srcdir/$subdir/text.c tmpdir/text.o]) } {
# Defer fail until we have list of tests set.
set failed_compile 1
@@ -108,12 +109,15 @@ set plugin_tests [list \
[list "plugin claimfile replace symbol" "-plugin $plugin_path $regclm \
$regas $regcln -plugin-opt claim:tmpdir/func.o \
-plugin-opt sym:${_}func::0:0:0 \
+ -plugin-opt add:tmpdir/func.o \
$testobjfiles $libs" "" "" {{ld plugin-7.d}} "main.x" ] \
[list "plugin claimfile resolve symbol" "-plugin $plugin_path $regclm \
$regas $regcln -plugin-opt claim:tmpdir/func.o \
-plugin-opt sym:${_}func::0:0:0 \
-plugin-opt sym:${_}func2::0:0:0 \
-plugin-opt dumpresolutions \
+ -plugin-opt add:tmpdir/func.o \
+ -plugin-opt add:tmpdir/func2.o \
$testobjfiles $libs" "" "" {{ld plugin-8.d}} "main.x" ] \
[list "plugin claimfile replace file" "-plugin $plugin_path $regclm \
$regas $regcln -plugin-opt claim:tmpdir/func.o \
@@ -121,6 +125,7 @@ set plugin_tests [list \
-plugin-opt sym:${_}func2::0:0:0 \
-plugin-opt dumpresolutions \
-plugin-opt add:tmpdir/func.o \
+ -plugin-opt add:tmpdir/func2.o \
$testobjfiles $libs" "" "" {{ld plugin-9.d}} "main.x" ] \
]
@@ -152,6 +157,10 @@ set plugin_extra_elf_tests [list \
-plugin-opt sym:${_}func2::0:2:0 \
-plugin-opt sym:${_}func3::0:3:0 \
-plugin-opt dumpresolutions \
+ -plugin-opt add:tmpdir/func.o \
+ -plugin-opt add:tmpdir/func1p.o \
+ -plugin-opt add:tmpdir/func2i.o \
+ -plugin-opt add:tmpdir/func3h.o \
$testobjfiles $libs" "" "" {{ld plugin-ignore.d} \
{readelf -s plugin-vis-1.d}} "main.x" ] \
]
@@ -170,7 +179,10 @@ if { !$can_compile || $failed_compile } {
run_ld_link_tests $plugin_tests
-if { [is_elf_format] } {
+if { [is_elf_format] \
+ && [ld_compile "$CC $CFLAGS" $srcdir/$subdir/func1p.c tmpdir/func1p.o] \
+ && [ld_compile "$CC $CFLAGS" $srcdir/$subdir/func2i.c tmpdir/func2i.o] \
+ && [ld_compile "$CC $CFLAGS" $srcdir/$subdir/func3h.c tmpdir/func3h.o] } {
run_ld_link_tests $plugin_extra_elf_tests
}
diff --git a/ld/testsuite/ld-plugin/pr12365a.c b/ld/testsuite/ld-plugin/pr12365a.c
new file mode 100644
index 0000000..a9bb6c6
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr12365a.c
@@ -0,0 +1,25 @@
+extern void abort(void);
+extern void main_test (void);
+extern void abort (void);
+int inside_main;
+
+int
+main ()
+{
+ inside_main = 1;
+ main_test ();
+ inside_main = 0;
+ return 0;
+}
+
+/* When optimizing, all the constant cases should have been
+ constant folded, so no calls to link_error should remain.
+ In any case, link_error should not be called. */
+
+#ifndef __OPTIMIZE__
+void
+link_error (void)
+{
+ abort ();
+}
+#endif
diff --git a/ld/testsuite/ld-plugin/pr12365b.c b/ld/testsuite/ld-plugin/pr12365b.c
new file mode 100644
index 0000000..3e86e06
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr12365b.c
@@ -0,0 +1,47 @@
+#define ASMNAME(cname) ASMNAME2 (__USER_LABEL_PREFIX__, cname)
+#define ASMNAME2(prefix, cname) STRING (prefix) cname
+#define STRING(x) #x
+
+typedef __SIZE_TYPE__ size_t;
+extern void abort (void);
+extern void *memcpy (void *, const void *, size_t)
+ __asm (ASMNAME ("my_memcpy"));
+extern void bcopy (const void *, void *, size_t)
+ __asm (ASMNAME ("my_bcopy"));
+extern void *memset (void *, int, size_t)
+ __asm (ASMNAME ("my_memset"));
+extern void bzero (void *, size_t)
+ __asm (ASMNAME ("my_bzero"));
+extern int memcmp (const void *, const void *, size_t);
+
+struct A { char c[32]; } a = { "foobar" };
+char x[64] = "foobar", y[64];
+int i = 39, j = 6, k = 4;
+
+extern int inside_main;
+
+void
+main_test (void)
+{
+ struct A b = a;
+ struct A c = { { 'x' } };
+
+ inside_main = 1;
+
+ if (memcmp (b.c, x, 32) || c.c[0] != 'x' || memcmp (c.c + 1, x + 32, 31))
+ abort ();
+ if (__builtin_memcpy (y, x, i) != y || memcmp (x, y, 64))
+ abort ();
+ if (memcpy (y + 6, x, j) != y + 6
+ || memcmp (x, y, 6) || memcmp (x, y + 6, 58))
+ abort ();
+ if (__builtin_memset (y + 2, 'X', k) != y + 2
+ || memcmp (y, "foXXXXfoobar", 13))
+ abort ();
+ bcopy (y + 1, y + 2, 6);
+ if (memcmp (y, "fooXXXXfobar", 13))
+ abort ();
+ __builtin_bzero (y + 4, 2);
+ if (memcmp (y, "fooX\0\0Xfobar", 13))
+ abort ();
+}
diff --git a/ld/testsuite/ld-plugin/pr12365c.c b/ld/testsuite/ld-plugin/pr12365c.c
new file mode 100644
index 0000000..2edd0ff
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr12365c.c
@@ -0,0 +1,79 @@
+extern void abort (void);
+extern int inside_main;
+typedef __SIZE_TYPE__ size_t;
+
+#define TEST_ABORT if (inside_main) abort()
+
+void *
+my_memcpy (void *d, const void *s, size_t n)
+{
+ char *dst = (char *) d;
+ const char *src = (const char *) s;
+ while (n--)
+ *dst++ = *src++;
+ return (char *) d;
+}
+
+void
+my_bcopy (const void *s, void *d, size_t n)
+{
+ char *dst = (char *) d;
+ const char *src = (const char *) s;
+ if (src >= dst)
+ while (n--)
+ *dst++ = *src++;
+ else
+ {
+ dst += n;
+ src += n;
+ while (n--)
+ *--dst = *--src;
+ }
+}
+
+void *
+my_memset (void *d, int c, size_t n)
+{
+ char *dst = (char *) d;
+ while (n--)
+ *dst++ = c;
+ return (char *) d;
+}
+
+void
+my_bzero (void *d, size_t n)
+{
+ char *dst = (char *) d;
+ while (n--)
+ *dst++ = '\0';
+}
+
+void *
+memcpy (void *d, const void *s, size_t n)
+{
+ void *result = my_memcpy (d, s, n);
+ TEST_ABORT;
+ return result;
+}
+
+void
+bcopy (const void *s, void *d, size_t n)
+{
+ my_bcopy (s, d, n);
+ TEST_ABORT;
+}
+
+void *
+memset (void *d, int c, size_t n)
+{
+ void *result = my_memset (d, c, n);
+ TEST_ABORT;
+ return result;
+}
+
+void
+bzero (void *d, size_t n)
+{
+ my_bzero (d, n);
+ TEST_ABORT;
+}
diff --git a/ld/testsuite/lib/ld-lib.exp b/ld/testsuite/lib/ld-lib.exp
index 48e9635..74bad74 100644
--- a/ld/testsuite/lib/ld-lib.exp
+++ b/ld/testsuite/lib/ld-lib.exp
@@ -1461,6 +1461,34 @@ proc check_plugin_api_available { } {
return $plugin_api_available_saved
}
+# Returns true if the target compiler supports LTO
+proc check_lto_available { } {
+ global lto_available_saved
+ global CC
+ if {![info exists lto_available_saved]} {
+ # Check if gcc supports -flto -fuse-linker-plugin
+ if { [which $CC] == 0 } {
+ set lto_available_saved 0
+ return 0
+ }
+ set basename "lto"
+ set src ${basename}[pid].c
+ set output ${basename}[pid].s
+ set f [open $src "w"]
+ puts $f ""
+ close $f
+ set status [remote_exec host $CC "-S -flto -fuse-linker-plugin $src -o $output"]
+ if { [lindex $status 0] == 0 } {
+ set lto_available_saved 1
+ } else {
+ set lto_available_saved 0
+ }
+ file delete $src
+ file delete $output
+ }
+ return $lto_available_saved
+}
+
# Check if the assembler supports CFI statements.
proc check_as_cfi { } {
next prev parent reply other threads:[~2011-01-29 2:01 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-01-29 1:23 Dave Korn
2011-01-29 1:45 ` H.J. Lu
2011-01-29 2:01 ` H.J. Lu [this message]
2011-01-29 2:05 ` H.J. Lu
2011-01-29 2:11 ` Dave Korn
2011-01-29 2:45 ` H.J. Lu
2011-01-29 2:59 ` Dave Korn
2011-01-29 4:11 ` Dave Korn
2011-01-29 4:41 ` H.J. Lu
2011-01-31 1:57 ` [PATCH,take 2,trunk+2.21.1] " Dave Korn
2011-02-03 5:12 ` Alan Modra
2011-02-03 5:44 ` Dave Korn
2011-02-03 13:28 ` Alan Modra
2011-02-05 1:56 ` Alan Modra
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=AANLkTik6PH6WTFq_yRy1ceLwOu0u+t_LuRv4wyCCwgsk@mail.gmail.com \
--to=hjl.tools@gmail.com \
--cc=binutils@sourceware.org \
--cc=dave.korn.cygwin@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).