From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1062) id 75BF73857365; Fri, 24 Feb 2023 07:54:00 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 75BF73857365 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Alan Modra To: bfd-cvs@sourceware.org Subject: [binutils-gdb] PR30155, ld segfault in _bfd_nearby_section X-Act-Checkin: binutils-gdb X-Git-Author: Alan Modra X-Git-Refname: refs/heads/master X-Git-Oldrev: 50980ba351856dff75bb0743bfca62f4c3ab19ff X-Git-Newrev: 18e7a6587e3f111e9367ea707f9eb21acf4b9af7 Message-Id: <20230224075400.75BF73857365@sourceware.org> Date: Fri, 24 Feb 2023 07:54:00 +0000 (GMT) X-BeenThere: binutils-cvs@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Binutils-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 24 Feb 2023 07:54:00 -0000 https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3D18e7a6587e3f= 111e9367ea707f9eb21acf4b9af7 commit 18e7a6587e3f111e9367ea707f9eb21acf4b9af7 Author: Alan Modra Date: Thu Feb 23 18:23:12 2023 +1030 PR30155, ld segfault in _bfd_nearby_section =20 The segfault was a symptom of messing with the absolute section next field, confusing bfd_section_removed_from_list in linker.c:fix_syms. That's not all that was going wrong. The INSERT list of output sections was being inserted into itself, ie. lost from the main list of linker statements. =20 PR 30155 * ldlang.c (process_insert_statements): Handle pathological case of the insert script being inserted before the first output section statement in the default script. (output_prev_sec_find): Don't test section owner here. (insert_os_after): Change parameter to a list union pointer. (lang_insert_orphan): Test section owner here and adjust insert_os_after call. Diff: --- ld/ldlang.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++---------= ---- 1 file changed, 52 insertions(+), 13 deletions(-) diff --git a/ld/ldlang.c b/ld/ldlang.c index 2852a4222d3..295de015da9 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -1774,7 +1774,7 @@ output_prev_sec_find (lang_output_section_statement_t= ype *os) if (lookup->constraint < 0) continue; =20 - if (lookup->bfd_section !=3D NULL && lookup->bfd_section->owner !=3D= NULL) + if (lookup->bfd_section !=3D NULL) return lookup->bfd_section; } =20 @@ -1793,13 +1793,13 @@ output_prev_sec_find (lang_output_section_statement= _type *os) image symbols. */ =20 static lang_statement_union_type ** -insert_os_after (lang_output_section_statement_type *after) +insert_os_after (lang_statement_union_type *after) { lang_statement_union_type **where; lang_statement_union_type **assign =3D NULL; bool ignore_first; =20 - ignore_first =3D after =3D=3D (void *) lang_os_list.head; + ignore_first =3D after =3D=3D lang_os_list.head; =20 for (where =3D &after->header.next; *where !=3D NULL; @@ -1936,7 +1936,9 @@ lang_insert_orphan (asection *s, if (bfd_section =3D=3D NULL) bfd_section =3D output_prev_sec_find (after); =20 - if (bfd_section !=3D NULL && bfd_section !=3D snew) + if (bfd_section !=3D NULL + && bfd_section->owner !=3D NULL + && bfd_section !=3D snew) place->section =3D &bfd_section->next; } =20 @@ -2159,8 +2161,9 @@ lang_insert_orphan (asection *s, /* Place OS after AFTER if AFTER_NOTE is TRUE. */ if (place_after) { - lang_statement_union_type **where =3D insert_os_after (after); + lang_statement_union_type **where; =20 + where =3D insert_os_after ((lang_statement_union_type *) after); *add.tail =3D *where; *where =3D add.head; =20 @@ -4370,21 +4373,55 @@ process_insert_statements (lang_statement_union_typ= e **start) else link_info.output_bfd->section_last =3D first_sec->prev; /* Add back. */ - last_sec->next =3D sec->next; - if (sec->next !=3D NULL) - sec->next->prev =3D last_sec; + if (sec->owner =3D=3D NULL) + /* SEC is the absolute section, from the + first dummy output section statement. Add + back the sections we trimmed off to the + start of the bfd sections. */ + sec =3D NULL; + if (sec !=3D NULL) + last_sec->next =3D sec->next; + else + last_sec->next =3D link_info.output_bfd->sections; + if (last_sec->next !=3D NULL) + last_sec->next->prev =3D last_sec; else link_info.output_bfd->section_last =3D last_sec; first_sec->prev =3D sec; - sec->next =3D first_sec; + if (first_sec->prev !=3D NULL) + first_sec->prev->next =3D first_sec; + else + link_info.output_bfd->sections =3D first_sec; } } - - first_os =3D NULL; - last_os =3D NULL; } =20 - ptr =3D insert_os_after (where); + lang_statement_union_type *after =3D (void *) where; + if (where =3D=3D &lang_os_list.head->output_section_statement + && where->next =3D=3D first_os) + { + /* PR30155. Handle a corner case where the statement + list is something like the following: + . LOAD t.o + . .data 0x0000000000000000 0x0 + . [0x0000000000000000] b =3D . + . *(.data) + . .data 0x0000000000000000 0x0 t.o + . 0x0000000000000000 0x4 LONG 0x0 + . INSERT BEFORE .text.start + . [0x0000000000000004] a =3D . + . .text.start 0x0000000000000000 0x0 + . [0x0000000000000000] c =3D . + . OUTPUT(a.out elf64-x86-64) + Here we do not want to allow insert_os_after to + choose a point inside the list we are moving. + That would lose the list. Instead, let + insert_os_after work from the INSERT, which in this + particular example will result in inserting after + the assignment "a =3D .". */ + after =3D *s; + } + ptr =3D insert_os_after (after); /* Snip everything from the start of the list, up to and including the insert statement we are currently processing. */ first =3D *start; @@ -4395,6 +4432,8 @@ process_insert_statements (lang_statement_union_type = **start) statement_list.tail =3D s; *ptr =3D first; s =3D start; + first_os =3D NULL; + last_os =3D NULL; continue; } s =3D &(*s)->header.next;