aboutsummaryrefslogtreecommitdiff
path: root/gold
diff options
context:
space:
mode:
Diffstat (limited to 'gold')
-rw-r--r--gold/ChangeLog15
-rw-r--r--gold/script-sections.cc28
-rw-r--r--gold/testsuite/Makefile.am9
-rw-r--r--gold/testsuite/Makefile.in44
-rw-r--r--gold/testsuite/script_test_12.t63
-rw-r--r--gold/testsuite/script_test_12a.c75
-rw-r--r--gold/testsuite/script_test_12b.c3
-rw-r--r--gold/testsuite/script_test_12i.t63
8 files changed, 298 insertions, 2 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index d66f292..f5f3817 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,18 @@
+2015-06-03 Cary Coutant <ccoutant@gmail.com>
+
+ PR gold/15370
+ * script-sections.cc
+ (Output_section_element_input::set_section_addresses): When there
+ are several patterns with no sort spec, put all sections in the same
+ bin.
+ * testsuite/Makefile.am (script_test_12): New testcase.
+ (script_test_12i): New testcase.
+ * testsuite/Makefile.in: Regenerate.
+ * testsuite/script_test_12.t: New test linker script.
+ * testsuite/script_test_12i.t: New test linker script.
+ * testsuite/script_test_12a.c: New test source file.
+ * testsuite/script_test_12b.c: New test source file.
+
2015-06-02 Cary Coutant <ccoutant@gmail.com>
* nacl.h (Sniff_file): Switch parameters to get_view to get an
diff --git a/gold/script-sections.cc b/gold/script-sections.cc
index 9ff0fee..4f29c08 100644
--- a/gold/script-sections.cc
+++ b/gold/script-sections.cc
@@ -1555,9 +1555,33 @@ Output_section_element_input::set_section_addresses(
// We build a list of sections which match each
// Input_section_pattern.
+ // If none of the patterns specify a sort option, we throw all
+ // matching input sections into a single bin, in the order we
+ // find them. Otherwise, we put matching input sections into
+ // a separate bin for each pattern, and sort each one as
+ // specified. Thus, an input section spec like this:
+ // *(.foo .bar)
+ // will group all .foo and .bar sections in the order seen,
+ // whereas this:
+ // *(.foo) *(.bar)
+ // will group all .foo sections followed by all .bar sections.
+ // This matches Gnu ld behavior.
+
+ // Things get really weird, though, when you add a sort spec
+ // on some, but not all, of the patterns, like this:
+ // *(SORT_BY_NAME(.foo) .bar)
+ // We do not attempt to match Gnu ld behavior in this case.
+
typedef std::vector<std::vector<Input_section_info> > Matching_sections;
size_t input_pattern_count = this->input_section_patterns_.size();
- if (input_pattern_count == 0)
+ bool any_patterns_with_sort = false;
+ for (size_t i = 0; i < input_pattern_count; ++i)
+ {
+ const Input_section_pattern& isp(this->input_section_patterns_[i]);
+ if (isp.sort != SORT_WILDCARD_NONE)
+ any_patterns_with_sort = true;
+ }
+ if (input_pattern_count == 0 || !any_patterns_with_sort)
input_pattern_count = 1;
Matching_sections matching_sections(input_pattern_count);
@@ -1620,6 +1644,8 @@ Output_section_element_input::set_section_addresses(
++p;
else
{
+ if (!any_patterns_with_sort)
+ i = 0;
matching_sections[i].push_back(isi);
p = input_sections->erase(p);
}
diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am
index fff941e..0ae99bd 100644
--- a/gold/testsuite/Makefile.am
+++ b/gold/testsuite/Makefile.am
@@ -1661,6 +1661,15 @@ script_test_11_r.o: gcctestdir/ld $(srcdir)/script_test_11.t script_test_11.o
script_test_11.o: script_test_11.c
$(COMPILE) -c -g -o $@ $<
+# Test difference between "*(a b)" and "*(a) *(b)" in input section spec.
+check_PROGRAMS += script_test_12
+script_test_12: gcctestdir/ld $(srcdir)/script_test_12.t script_test_12a.o script_test_12b.o
+ $(LINK) -Bgcctestdir/ -Wl,-T,$(srcdir)/script_test_12.t script_test_12a.o script_test_12b.o
+
+check_PROGRAMS += script_test_12i
+script_test_12i: gcctestdir/ld $(srcdir)/script_test_12i.t script_test_12a.o script_test_12b.o
+ $(LINK) -Bgcctestdir/ -Wl,-T,$(srcdir)/script_test_12i.t script_test_12a.o script_test_12b.o
+
# Test --dynamic-list, --dynamic-list-data, --dynamic-list-cpp-new,
# and --dynamic-list-cpp-typeinfo
diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in
index ad29bd1..5228650 100644
--- a/gold/testsuite/Makefile.in
+++ b/gold/testsuite/Makefile.in
@@ -240,6 +240,8 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
# Test scripts with a relocatable link.
# The -g option is necessary to trigger a bug where a section
# declared in a script file is assigned a non-zero starting address.
+
+# Test difference between "*(a b)" and "*(a) *(b)" in input section spec.
@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_32 = many_sections_test \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ many_sections_r_test initpri1 \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ initpri2 initpri3a \
@@ -259,6 +261,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_3 \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ tls_phdrs_script_test \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ tls_script_test script_test_11 \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_12 script_test_12i \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ dynamic_list_2 \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ thin_archive_test_1 \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ thin_archive_test_2
@@ -924,6 +927,8 @@ libgoldtest_a_OBJECTS = $(am_libgoldtest_a_OBJECTS)
@GCC_TRUE@@NATIVE_LINKER_TRUE@ tls_phdrs_script_test$(EXEEXT) \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ tls_script_test$(EXEEXT) \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_11$(EXEEXT) \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_12$(EXEEXT) \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_12i$(EXEEXT) \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ dynamic_list_2$(EXEEXT) \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ thin_archive_test_1$(EXEEXT) \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ thin_archive_test_2$(EXEEXT)
@@ -1660,6 +1665,20 @@ script_test_11_DEPENDENCIES = libgoldtest.a ../libgold.a \
../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1)
+script_test_12_SOURCES = script_test_12.c
+script_test_12_OBJECTS = script_test_12.$(OBJEXT)
+script_test_12_LDADD = $(LDADD)
+script_test_12_DEPENDENCIES = libgoldtest.a ../libgold.a \
+ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+script_test_12i_SOURCES = script_test_12i.c
+script_test_12i_OBJECTS = script_test_12i.$(OBJEXT)
+script_test_12i_LDADD = $(LDADD)
+script_test_12i_DEPENDENCIES = libgoldtest.a ../libgold.a \
+ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
@GCC_TRUE@@NATIVE_LINKER_TRUE@am_script_test_2_OBJECTS = \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_2.$(OBJEXT) \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_2a.$(OBJEXT) \
@@ -2059,7 +2078,8 @@ SOURCES = $(libgoldtest_a_SOURCES) basic_pic_test.c basic_pie_test.c \
$(protected_2_SOURCES) $(relro_now_test_SOURCES) \
$(relro_script_test_SOURCES) $(relro_strip_test_SOURCES) \
$(relro_test_SOURCES) $(script_test_1_SOURCES) \
- script_test_11.c $(script_test_2_SOURCES) script_test_3.c \
+ script_test_11.c script_test_12.c script_test_12i.c \
+ $(script_test_2_SOURCES) script_test_3.c \
$(searched_file_test_SOURCES) start_lib_test.c \
$(thin_archive_test_1_SOURCES) $(thin_archive_test_2_SOURCES) \
$(tls_phdrs_script_test_SOURCES) $(tls_pic_test_SOURCES) \
@@ -3577,6 +3597,18 @@ script_test_1$(EXEEXT): $(script_test_1_OBJECTS) $(script_test_1_DEPENDENCIES)
@NATIVE_LINKER_FALSE@script_test_11$(EXEEXT): $(script_test_11_OBJECTS) $(script_test_11_DEPENDENCIES)
@NATIVE_LINKER_FALSE@ @rm -f script_test_11$(EXEEXT)
@NATIVE_LINKER_FALSE@ $(LINK) $(script_test_11_OBJECTS) $(script_test_11_LDADD) $(LIBS)
+@GCC_FALSE@script_test_12$(EXEEXT): $(script_test_12_OBJECTS) $(script_test_12_DEPENDENCIES)
+@GCC_FALSE@ @rm -f script_test_12$(EXEEXT)
+@GCC_FALSE@ $(LINK) $(script_test_12_OBJECTS) $(script_test_12_LDADD) $(LIBS)
+@NATIVE_LINKER_FALSE@script_test_12$(EXEEXT): $(script_test_12_OBJECTS) $(script_test_12_DEPENDENCIES)
+@NATIVE_LINKER_FALSE@ @rm -f script_test_12$(EXEEXT)
+@NATIVE_LINKER_FALSE@ $(LINK) $(script_test_12_OBJECTS) $(script_test_12_LDADD) $(LIBS)
+@GCC_FALSE@script_test_12i$(EXEEXT): $(script_test_12i_OBJECTS) $(script_test_12i_DEPENDENCIES)
+@GCC_FALSE@ @rm -f script_test_12i$(EXEEXT)
+@GCC_FALSE@ $(LINK) $(script_test_12i_OBJECTS) $(script_test_12i_LDADD) $(LIBS)
+@NATIVE_LINKER_FALSE@script_test_12i$(EXEEXT): $(script_test_12i_OBJECTS) $(script_test_12i_DEPENDENCIES)
+@NATIVE_LINKER_FALSE@ @rm -f script_test_12i$(EXEEXT)
+@NATIVE_LINKER_FALSE@ $(LINK) $(script_test_12i_OBJECTS) $(script_test_12i_LDADD) $(LIBS)
script_test_2$(EXEEXT): $(script_test_2_OBJECTS) $(script_test_2_DEPENDENCIES)
@rm -f script_test_2$(EXEEXT)
$(script_test_2_LINK) $(script_test_2_OBJECTS) $(script_test_2_LDADD) $(LIBS)
@@ -3880,6 +3912,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/relro_test_main.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script_test_1.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script_test_11.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script_test_12.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script_test_12i.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script_test_2.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script_test_2a.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script_test_2b.Po@am__quote@
@@ -4620,6 +4654,10 @@ tls_script_test.log: tls_script_test$(EXEEXT)
@p='tls_script_test$(EXEEXT)'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
script_test_11.log: script_test_11$(EXEEXT)
@p='script_test_11$(EXEEXT)'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
+script_test_12.log: script_test_12$(EXEEXT)
+ @p='script_test_12$(EXEEXT)'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
+script_test_12i.log: script_test_12i$(EXEEXT)
+ @p='script_test_12i$(EXEEXT)'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
dynamic_list_2.log: dynamic_list_2$(EXEEXT)
@p='dynamic_list_2$(EXEEXT)'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
thin_archive_test_1.log: thin_archive_test_1$(EXEEXT)
@@ -5617,6 +5655,10 @@ uninstall-am:
@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld -r -o $@ -T $(srcdir)/script_test_11.t script_test_11.o
@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_11.o: script_test_11.c
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -g -o $@ $<
+@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_12: gcctestdir/ld $(srcdir)/script_test_12.t script_test_12a.o script_test_12b.o
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ -Wl,-T,$(srcdir)/script_test_12.t script_test_12a.o script_test_12b.o
+@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_12i: gcctestdir/ld $(srcdir)/script_test_12i.t script_test_12a.o script_test_12b.o
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ -Wl,-T,$(srcdir)/script_test_12i.t script_test_12a.o script_test_12b.o
@GCC_TRUE@@NATIVE_LINKER_TRUE@dynamic_list: basic_test.o gcctestdir/ld $(srcdir)/dynamic_list.t
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ basic_test.o \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ -Wl,--dynamic-list $(srcdir)/dynamic_list.t \
diff --git a/gold/testsuite/script_test_12.t b/gold/testsuite/script_test_12.t
new file mode 100644
index 0000000..f7e0116
--- /dev/null
+++ b/gold/testsuite/script_test_12.t
@@ -0,0 +1,63 @@
+/* script_test_12.t -- linker script test 12 for gold
+
+ Copyright (C) 2008-2015 Free Software Foundation, Inc.
+ Written by Cary Coutant <ccoutant@gmail.com>.
+
+ This file is part of gold.
+
+ 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. */
+
+interleaved = 0;
+
+SECTIONS
+{
+ . = 0x400000 + SIZEOF_HEADERS;
+
+ .interp : { *(.interp) }
+ .note : { *(.note .note.*) }
+ .rel.dyn : { *(.rel.dyn) }
+ .rela.dyn : { *(.rela.dyn) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text : { *(.text) }
+ .fini : { *(.fini) }
+ .rodata : { *(.rodata .rodata.*) }
+ .eh_frame_hdr : { *(.eh_frame_hdr) }
+ .eh_frame : { *(.eh_frame) }
+
+ . = DATA_SEGMENT_ALIGN(0x1000, 0x1000);
+
+ .init_array : {
+ __init_array_start = .;
+ *(.init_array);
+ __init_array_end = .;
+ }
+ .fini_array : { *(.fini_array) }
+ .jcr : { *(.jcr) }
+ .dynamic : { *(.dynamic) }
+ .got : { *(.got) }
+ .got.plt : { *(.got.plt) }
+ .data : { *(.data) }
+ .test : {
+ test_array_start = .;
+ *(.x1 .x2 .x3);
+ test_array_end = .;
+ }
+ .bss : { *(.bss) }
+
+}
diff --git a/gold/testsuite/script_test_12a.c b/gold/testsuite/script_test_12a.c
new file mode 100644
index 0000000..6540027
--- /dev/null
+++ b/gold/testsuite/script_test_12a.c
@@ -0,0 +1,75 @@
+/* script_test_12a.c -- a test case for gold
+
+ Copyright (C) 2015 Free Software Foundation, Inc.
+ Written by Cary Coutant <ccoutant@gmail.com>.
+
+ This file is part of gold.
+
+ 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.
+
+ This tests linker script behavior, that gold distinguishes correctly
+ between
+ *(.x1) *(.x2) *(.x3)
+ and
+ *(.x1 .x2 .x3)
+ in an input section spec. In the first case, the output section
+ should contain all .x1 sections, followed by all .x2 sections,
+ then all .x3 sections; i.e.:
+ script_test_12a.o(.x1)
+ script_test_12b.o(.x1)
+ script_test_12a.o(.x2)
+ script_test_12b.o(.x2)
+ script_test_12a.o(.x3)
+ script_test_12b.o(.x3)
+
+ In the second case, the output section should interleave the
+ .x1, .x2, and .x3 sections in the order seen; i.e.:
+ script_test_12a.o(.x1)
+ script_test_12a.o(.x2)
+ script_test_12a.o(.x3)
+ script_test_12b.o(.x1)
+ script_test_12b.o(.x2)
+ script_test_12b.o(.x3)
+
+ The linker scripts set the absolute symbol INTERLEAVED, which we
+ test here to determine which ordering to expect. The scripts also
+ define the symbols test_array_start and test_array_end.
+*/
+
+extern int test_array_start;
+extern int test_array_end;
+extern char interleaved;
+
+int
+main(void)
+{
+ int last = 0;
+ int *p;
+ long should_be_interleaved = (long)&interleaved;
+ int mask = (should_be_interleaved == 1 ? 0x7f : 0xff);
+ for (p = &test_array_start; p < &test_array_end; ++p)
+ {
+ int next = *p & mask;
+ if (next <= last)
+ return 1;
+ last = next;
+ }
+ return 0;
+}
+
+int a1[] __attribute((section(".x1"))) = { 0x01, 0x02, 0x03, 0x04 };
+int a2[] __attribute((section(".x2"))) = { 0x11, 0x12, 0x13, 0x14};
+int a3[] __attribute((section(".x3"))) = { 0x21, 0x22, 0x23, 0x24 };
diff --git a/gold/testsuite/script_test_12b.c b/gold/testsuite/script_test_12b.c
new file mode 100644
index 0000000..a69866e
--- /dev/null
+++ b/gold/testsuite/script_test_12b.c
@@ -0,0 +1,3 @@
+int b1[] __attribute((section(".x1"))) = { 0x85, 0x86, 0x87, 0x88 };
+int b2[] __attribute((section(".x2"))) = { 0x95, 0x96, 0x97, 0x98 };
+int b3[] __attribute((section(".x3"))) = { 0xa5, 0xa6, 0xa7, 0xa8 };
diff --git a/gold/testsuite/script_test_12i.t b/gold/testsuite/script_test_12i.t
new file mode 100644
index 0000000..d4ef91c
--- /dev/null
+++ b/gold/testsuite/script_test_12i.t
@@ -0,0 +1,63 @@
+/* script_test_12i.t -- linker script test 12 for gold, with interleaved sections
+
+ Copyright (C) 2008-2015 Free Software Foundation, Inc.
+ Written by Cary Coutant <ccoutant@gmail.com>.
+
+ This file is part of gold.
+
+ 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. */
+
+interleaved = 1;
+
+SECTIONS
+{
+ . = 0x400000 + SIZEOF_HEADERS;
+
+ .interp : { *(.interp) }
+ .note : { *(.note .note.*) }
+ .rel.dyn : { *(.rel.dyn) }
+ .rela.dyn : { *(.rela.dyn) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text : { *(.text) }
+ .fini : { *(.fini) }
+ .rodata : { *(.rodata .rodata.*) }
+ .eh_frame_hdr : { *(.eh_frame_hdr) }
+ .eh_frame : { *(.eh_frame) }
+
+ . = DATA_SEGMENT_ALIGN(0x1000, 0x1000);
+
+ .init_array : {
+ __init_array_start = .;
+ *(.init_array);
+ __init_array_end = .;
+ }
+ .fini_array : { *(.fini_array) }
+ .jcr : { *(.jcr) }
+ .dynamic : { *(.dynamic) }
+ .got : { *(.got) }
+ .got.plt : { *(.got.plt) }
+ .data : { *(.data) }
+ .test : {
+ test_array_start = .;
+ *(.x1) *(.x2) *(.x3)
+ test_array_end = .;
+ }
+ .bss : { *(.bss) }
+
+}