lang_output_section_statement_type *
lang_output_section_find_by_flags (const asection *sec,
- lang_output_section_statement_type **exact)
+ lang_output_section_statement_type **exact,
+ lang_match_sec_type_func match_type)
{
lang_output_section_statement_type *first, *look, *found;
flagword flags;
if (look->bfd_section != NULL)
{
flags = look->bfd_section->flags;
- if (!bfd_match_sections_by_type (output_bfd,
- look->bfd_section,
- sec->owner, sec))
+ if (match_type && !match_type (output_bfd, look->bfd_section,
+ sec->owner, sec))
continue;
}
flags ^= sec->flags;
}
if (found != NULL)
{
- *exact = found;
+ if (exact != NULL)
+ *exact = found;
return found;
}
if (look->bfd_section != NULL)
{
flags = look->bfd_section->flags;
- if (!bfd_match_sections_by_type (output_bfd,
- look->bfd_section,
- sec->owner, sec))
+ if (match_type && !match_type (output_bfd, look->bfd_section,
+ sec->owner, sec))
continue;
}
flags ^= sec->flags;
| SEC_CODE | SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
found = look;
}
- return found;
}
-
- if (sec->flags & (SEC_READONLY | SEC_THREAD_LOCAL))
+ else if (sec->flags & (SEC_READONLY | SEC_THREAD_LOCAL))
{
/* .rodata can go after .text, .sdata2 after .rodata. */
for (look = first; look; look = look->next)
if (look->bfd_section != NULL)
{
flags = look->bfd_section->flags;
- if (!bfd_match_sections_by_type (output_bfd,
- look->bfd_section,
- sec->owner, sec))
+ if (match_type && !match_type (output_bfd, look->bfd_section,
+ sec->owner, sec))
continue;
}
flags ^= sec->flags;
&& !(look->flags & (SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
found = look;
}
- return found;
}
-
- if (sec->flags & SEC_SMALL_DATA)
+ else if (sec->flags & SEC_SMALL_DATA)
{
/* .sdata goes after .data, .sbss after .sdata. */
for (look = first; look; look = look->next)
if (look->bfd_section != NULL)
{
flags = look->bfd_section->flags;
- if (!bfd_match_sections_by_type (output_bfd,
- look->bfd_section,
- sec->owner, sec))
+ if (match_type && !match_type (output_bfd, look->bfd_section,
+ sec->owner, sec))
continue;
}
flags ^= sec->flags;
&& !(sec->flags & SEC_HAS_CONTENTS)))
found = look;
}
- return found;
}
-
- if (sec->flags & SEC_HAS_CONTENTS)
+ else if (sec->flags & SEC_HAS_CONTENTS)
{
/* .data goes after .rodata. */
for (look = first; look; look = look->next)
if (look->bfd_section != NULL)
{
flags = look->bfd_section->flags;
- if (!bfd_match_sections_by_type (output_bfd,
- look->bfd_section,
- sec->owner, sec))
+ if (match_type && !match_type (output_bfd, look->bfd_section,
+ sec->owner, sec))
continue;
}
flags ^= sec->flags;
| SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
found = look;
}
- return found;
}
-
- /* .bss goes last. */
- for (look = first; look; look = look->next)
+ else
{
- flags = look->flags;
- if (look->bfd_section != NULL)
+ /* .bss goes last. */
+ for (look = first; look; look = look->next)
{
- flags = look->bfd_section->flags;
- if (!bfd_match_sections_by_type (output_bfd,
- look->bfd_section,
- sec->owner, sec))
- continue;
+ flags = look->flags;
+ if (look->bfd_section != NULL)
+ {
+ flags = look->bfd_section->flags;
+ if (match_type && !match_type (output_bfd, look->bfd_section,
+ sec->owner, sec))
+ continue;
+ }
+ flags ^= sec->flags;
+ if (!(flags & SEC_ALLOC))
+ found = look;
}
- flags ^= sec->flags;
- if (!(flags & SEC_ALLOC))
- found = look;
}
- return found;
+ if (found || !match_type)
+ return found;
+
+ return lang_output_section_find_by_flags (sec, NULL, NULL);
}
/* Find the last output section before given output statement.
{
lang_statement_union_type **where;
lang_statement_union_type **assign = NULL;
+ bfd_boolean ignore_first;
/* Look for a suitable place for the new statement list.
The idea is to skip over anything that might be inside
a SECTIONS {} statement in a script, before we find
another output_section_statement. Assignments to "dot"
before an output section statement are assumed to
- belong to it. */
+ belong to it. An exception to this rule is made for
+ the first assignment to dot, otherwise we might put an
+ orphan before . = . + SIZEOF_HEADERS or similar
+ assignments that set the initial address. */
+
+ ignore_first = after == (&lang_output_section_statement.head
+ ->output_section_statement);
for (where = &after->header.next;
*where != NULL;
where = &(*where)->header.next)
ass = &(*where)->assignment_statement;
if (ass->exp->type.node_class != etree_assert
&& ass->exp->assign.dst[0] == '.'
- && ass->exp->assign.dst[1] == 0)
+ && ass->exp->assign.dst[1] == 0
+ && !ignore_first)
assign = where;
}
+ ignore_first = FALSE;
continue;
case lang_wild_statement_enum:
case lang_input_section_enum: