TLS orphan section placement
Ensures TLS orphans are placed adjacent to existing TLS sections, and fixes places where the output_section_statement flags (which might not be set) were tested when bfd_section flags were available. * ldlang.c (lang_output_section_find_by_flags): Be careful to test look->bfd_section->flags if available rather than look->flags. Separate SEC_THREAD_LOCAL handling from SEC_READONLY loop, and rewrite.
This commit is contained in:
parent
3ba720c788
commit
d9d94ac86b
@ -1,3 +1,10 @@
|
||||
2014-01-24 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* ldlang.c (lang_output_section_find_by_flags): Be careful to
|
||||
test look->bfd_section->flags if available rather than
|
||||
look->flags. Separate SEC_THREAD_LOCAL handling from
|
||||
SEC_READONLY loop, and rewrite.
|
||||
|
||||
2014-01-22 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* ldlang.c (asneeded_list_head, asneeded_list_tail): New vars.
|
||||
|
134
ld/ldlang.c
134
ld/ldlang.c
@ -1495,7 +1495,7 @@ lang_output_section_find_by_flags (const asection *sec,
|
||||
lang_match_sec_type_func match_type)
|
||||
{
|
||||
lang_output_section_statement_type *first, *look, *found;
|
||||
flagword flags;
|
||||
flagword look_flags, sec_flags, differ;
|
||||
|
||||
/* We know the first statement on this list is *ABS*. May as well
|
||||
skip it. */
|
||||
@ -1503,21 +1503,22 @@ lang_output_section_find_by_flags (const asection *sec,
|
||||
first = first->next;
|
||||
|
||||
/* First try for an exact match. */
|
||||
sec_flags = sec->flags;
|
||||
found = NULL;
|
||||
for (look = first; look; look = look->next)
|
||||
{
|
||||
flags = look->flags;
|
||||
look_flags = look->flags;
|
||||
if (look->bfd_section != NULL)
|
||||
{
|
||||
flags = look->bfd_section->flags;
|
||||
look_flags = look->bfd_section->flags;
|
||||
if (match_type && !match_type (link_info.output_bfd,
|
||||
look->bfd_section,
|
||||
sec->owner, sec))
|
||||
continue;
|
||||
}
|
||||
flags ^= sec->flags;
|
||||
if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY
|
||||
| SEC_CODE | SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
|
||||
differ = look_flags ^ sec_flags;
|
||||
if (!(differ & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY
|
||||
| SEC_CODE | SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
|
||||
found = look;
|
||||
}
|
||||
if (found != NULL)
|
||||
@ -1527,115 +1528,144 @@ lang_output_section_find_by_flags (const asection *sec,
|
||||
return found;
|
||||
}
|
||||
|
||||
if ((sec->flags & SEC_CODE) != 0
|
||||
&& (sec->flags & SEC_ALLOC) != 0)
|
||||
if ((sec_flags & SEC_CODE) != 0
|
||||
&& (sec_flags & SEC_ALLOC) != 0)
|
||||
{
|
||||
/* Try for a rw code section. */
|
||||
for (look = first; look; look = look->next)
|
||||
{
|
||||
flags = look->flags;
|
||||
look_flags = look->flags;
|
||||
if (look->bfd_section != NULL)
|
||||
{
|
||||
flags = look->bfd_section->flags;
|
||||
look_flags = look->bfd_section->flags;
|
||||
if (match_type && !match_type (link_info.output_bfd,
|
||||
look->bfd_section,
|
||||
sec->owner, sec))
|
||||
continue;
|
||||
}
|
||||
flags ^= sec->flags;
|
||||
if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
|
||||
| SEC_CODE | SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
|
||||
differ = look_flags ^ sec_flags;
|
||||
if (!(differ & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
|
||||
| SEC_CODE | SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
|
||||
found = look;
|
||||
}
|
||||
}
|
||||
else if ((sec->flags & (SEC_READONLY | SEC_THREAD_LOCAL)) != 0
|
||||
&& (sec->flags & SEC_ALLOC) != 0)
|
||||
else if ((sec_flags & SEC_READONLY) != 0
|
||||
&& (sec_flags & SEC_ALLOC) != 0)
|
||||
{
|
||||
/* .rodata can go after .text, .sdata2 after .rodata. */
|
||||
for (look = first; look; look = look->next)
|
||||
{
|
||||
flags = look->flags;
|
||||
look_flags = look->flags;
|
||||
if (look->bfd_section != NULL)
|
||||
{
|
||||
flags = look->bfd_section->flags;
|
||||
look_flags = look->bfd_section->flags;
|
||||
if (match_type && !match_type (link_info.output_bfd,
|
||||
look->bfd_section,
|
||||
sec->owner, sec))
|
||||
continue;
|
||||
}
|
||||
flags ^= sec->flags;
|
||||
if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
|
||||
| SEC_READONLY | SEC_SMALL_DATA))
|
||||
|| (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
|
||||
| SEC_READONLY))
|
||||
&& !(look->flags & SEC_SMALL_DATA))
|
||||
|| (!(flags & (SEC_THREAD_LOCAL | SEC_ALLOC))
|
||||
&& (look->flags & SEC_THREAD_LOCAL)
|
||||
&& (!(flags & SEC_LOAD)
|
||||
|| (look->flags & SEC_LOAD))))
|
||||
differ = look_flags ^ sec_flags;
|
||||
if (!(differ & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
|
||||
| SEC_READONLY | SEC_SMALL_DATA))
|
||||
|| (!(differ & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
|
||||
| SEC_READONLY))
|
||||
&& !(look_flags & SEC_SMALL_DATA)))
|
||||
found = look;
|
||||
}
|
||||
}
|
||||
else if ((sec->flags & SEC_SMALL_DATA) != 0
|
||||
&& (sec->flags & SEC_ALLOC) != 0)
|
||||
else if ((sec_flags & SEC_THREAD_LOCAL) != 0
|
||||
&& (sec_flags & SEC_ALLOC) != 0)
|
||||
{
|
||||
/* .tdata can go after .data, .tbss after .tdata. Treat .tbss
|
||||
as if it were a loaded section, and don't use match_type. */
|
||||
bfd_boolean seen_thread_local = FALSE;
|
||||
|
||||
match_type = NULL;
|
||||
for (look = first; look; look = look->next)
|
||||
{
|
||||
look_flags = look->flags;
|
||||
if (look->bfd_section != NULL)
|
||||
look_flags = look->bfd_section->flags;
|
||||
|
||||
differ = look_flags ^ (sec_flags | SEC_LOAD | SEC_HAS_CONTENTS);
|
||||
if (!(differ & (SEC_THREAD_LOCAL | SEC_ALLOC)))
|
||||
{
|
||||
/* .tdata and .tbss must be adjacent and in that order. */
|
||||
if (!(look_flags & SEC_LOAD)
|
||||
&& (sec_flags & SEC_LOAD))
|
||||
/* ..so if we're at a .tbss section and we're placing
|
||||
a .tdata section stop looking and return the
|
||||
previous section. */
|
||||
break;
|
||||
found = look;
|
||||
seen_thread_local = TRUE;
|
||||
}
|
||||
else if (seen_thread_local)
|
||||
break;
|
||||
else if (!(differ & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD)))
|
||||
found = look;
|
||||
}
|
||||
}
|
||||
else if ((sec_flags & SEC_SMALL_DATA) != 0
|
||||
&& (sec_flags & SEC_ALLOC) != 0)
|
||||
{
|
||||
/* .sdata goes after .data, .sbss after .sdata. */
|
||||
for (look = first; look; look = look->next)
|
||||
{
|
||||
flags = look->flags;
|
||||
look_flags = look->flags;
|
||||
if (look->bfd_section != NULL)
|
||||
{
|
||||
flags = look->bfd_section->flags;
|
||||
look_flags = look->bfd_section->flags;
|
||||
if (match_type && !match_type (link_info.output_bfd,
|
||||
look->bfd_section,
|
||||
sec->owner, sec))
|
||||
continue;
|
||||
}
|
||||
flags ^= sec->flags;
|
||||
if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
|
||||
| SEC_THREAD_LOCAL))
|
||||
|| ((look->flags & SEC_SMALL_DATA)
|
||||
&& !(sec->flags & SEC_HAS_CONTENTS)))
|
||||
differ = look_flags ^ sec_flags;
|
||||
if (!(differ & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
|
||||
| SEC_THREAD_LOCAL))
|
||||
|| ((look_flags & SEC_SMALL_DATA)
|
||||
&& !(sec_flags & SEC_HAS_CONTENTS)))
|
||||
found = look;
|
||||
}
|
||||
}
|
||||
else if ((sec->flags & SEC_HAS_CONTENTS) != 0
|
||||
&& (sec->flags & SEC_ALLOC) != 0)
|
||||
else if ((sec_flags & SEC_HAS_CONTENTS) != 0
|
||||
&& (sec_flags & SEC_ALLOC) != 0)
|
||||
{
|
||||
/* .data goes after .rodata. */
|
||||
for (look = first; look; look = look->next)
|
||||
{
|
||||
flags = look->flags;
|
||||
look_flags = look->flags;
|
||||
if (look->bfd_section != NULL)
|
||||
{
|
||||
flags = look->bfd_section->flags;
|
||||
look_flags = look->bfd_section->flags;
|
||||
if (match_type && !match_type (link_info.output_bfd,
|
||||
look->bfd_section,
|
||||
sec->owner, sec))
|
||||
continue;
|
||||
}
|
||||
flags ^= sec->flags;
|
||||
if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
|
||||
| SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
|
||||
differ = look_flags ^ sec_flags;
|
||||
if (!(differ & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
|
||||
| SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
|
||||
found = look;
|
||||
}
|
||||
}
|
||||
else if ((sec->flags & SEC_ALLOC) != 0)
|
||||
else if ((sec_flags & SEC_ALLOC) != 0)
|
||||
{
|
||||
/* .bss goes after any other alloc section. */
|
||||
for (look = first; look; look = look->next)
|
||||
{
|
||||
flags = look->flags;
|
||||
look_flags = look->flags;
|
||||
if (look->bfd_section != NULL)
|
||||
{
|
||||
flags = look->bfd_section->flags;
|
||||
look_flags = look->bfd_section->flags;
|
||||
if (match_type && !match_type (link_info.output_bfd,
|
||||
look->bfd_section,
|
||||
sec->owner, sec))
|
||||
continue;
|
||||
}
|
||||
flags ^= sec->flags;
|
||||
if (!(flags & SEC_ALLOC))
|
||||
differ = look_flags ^ sec_flags;
|
||||
if (!(differ & SEC_ALLOC))
|
||||
found = look;
|
||||
}
|
||||
}
|
||||
@ -1644,11 +1674,11 @@ lang_output_section_find_by_flags (const asection *sec,
|
||||
/* non-alloc go last. */
|
||||
for (look = first; look; look = look->next)
|
||||
{
|
||||
flags = look->flags;
|
||||
look_flags = look->flags;
|
||||
if (look->bfd_section != NULL)
|
||||
flags = look->bfd_section->flags;
|
||||
flags ^= sec->flags;
|
||||
if (!(flags & SEC_DEBUGGING))
|
||||
look_flags = look->bfd_section->flags;
|
||||
differ = look_flags ^ sec_flags;
|
||||
if (!(differ & SEC_DEBUGGING))
|
||||
found = look;
|
||||
}
|
||||
return found;
|
||||
|
Loading…
Reference in New Issue
Block a user