* PR18452, ld allows overlapping sections
@ 2016-04-08 14:13 Alan Modra
0 siblings, 0 replies; 2+ messages in thread
From: Alan Modra @ 2016-04-08 14:13 UTC (permalink / raw)
To: binutils
This changes the way overlays are detected, enabling the new VMA check
in lang_check_section_addresses in a lot more cases. The previous
patch didn't fix the testcase in the PR, due to me being over-cautious
and not wanting to trigger warnings for unusual overlays. I figure
that if people do write really weird overlay scripts, then they can
probably work out how to invoke ld with --no-check-sections.
PR 18452
* ldlang.c (maybe_overlays): Delete.
(lang_size_sections_1): Remove code setting maybe_overlays.
(lang_check_section_addresses): Instead detect overlays by
exact match of section VMAs here. Fix memory leak.
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 5fbea3f..1947efc 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -75,7 +75,6 @@ static lang_statement_list_type **stat_save_ptr = &stat_save[0];
static struct unique_sections *unique_section_list;
static struct asneeded_minfo *asneeded_list_head;
static unsigned int opb_shift = 0;
-static bfd_boolean maybe_overlays = FALSE;
/* Forward declarations. */
static void exp_init_os (etree_type *);
@@ -4742,6 +4741,7 @@ lang_check_section_addresses (void)
bfd_vma p_start = 0;
bfd_vma p_end = 0;
lang_memory_region_type *m;
+ bfd_boolean overlays;
if (bfd_count_sections (link_info.output_bfd) <= 1)
return;
@@ -4763,11 +4763,14 @@ lang_check_section_addresses (void)
}
if (count <= 1)
- return;
+ {
+ free (sections);
+ return;
+ }
qsort (sections, count, sizeof (*sections), sort_sections_by_lma);
- /* First check sections LMAs. There should be no overlap of LMAs on
+ /* First check section LMAs. There should be no overlap of LMAs on
loadable sections, even with overlays. */
for (p = NULL, i = 0; i < count; i++)
{
@@ -4797,11 +4800,28 @@ lang_check_section_addresses (void)
}
}
- /* Now check sections VMAs if no overlays were detected. */
- if (!maybe_overlays)
+ /* If any non-zero size allocated section (excluding tbss) starts at
+ exactly the same VMA as another such section, then we have
+ overlays. Overlays generated by the OVERLAY keyword will have
+ this property. It is possible to intentionally generate overlays
+ that fail this test, but it would be unusual. */
+ qsort (sections, count, sizeof (*sections), sort_sections_by_vma);
+ overlays = FALSE;
+ p_start = sections[0].sec->vma;
+ for (i = 1; i < count; i++)
{
- qsort (sections, count, sizeof (*sections), sort_sections_by_vma);
+ s_start = sections[i].sec->vma;
+ if (p_start == s_start)
+ {
+ overlays = TRUE;
+ break;
+ }
+ p_start = s_start;
+ }
+ /* Now check section VMAs if no overlays were detected. */
+ if (!overlays)
+ {
for (p = NULL, i = 0; i < count; i++)
{
s = sections[i].sec;
@@ -4835,7 +4855,6 @@ lang_check_section_addresses (void)
if (m->had_full_message)
einfo (_("%X%P: region `%s' overflowed by %ld bytes\n"),
m->name_list.name, (long)(m->current - (m->origin + m->length)));
-
}
/* Make sure the new address is within the region. We explicitly permit the
@@ -5149,18 +5168,6 @@ lang_size_sections_1
if (bfd_is_abs_section (os->bfd_section) || os->ignored)
break;
- if (r->last_os != NULL
- && !IGNORE_SECTION (os->bfd_section)
- && os->bfd_section->size != 0)
- {
- asection *last;
-
- last = r->last_os->output_section_statement.bfd_section;
- if (dot + TO_ADDR (os->bfd_section->size) > last->vma
- && dot < last->vma + TO_ADDR (last->size))
- maybe_overlays = TRUE;
- }
-
/* Keep track of normal sections using the default
lma region. We use this to set the lma for
following sections. Overlays or other linker
--
Alan Modra
Australia Development Lab, IBM
^ permalink raw reply [flat|nested] 2+ messages in thread
* PR18452, ld allows overlapping sections
@ 2016-03-30 7:34 Alan Modra
0 siblings, 0 replies; 2+ messages in thread
From: Alan Modra @ 2016-03-30 7:34 UTC (permalink / raw)
To: binutils
PR 18452
* ldlang.c (maybe_overlays): New static var.
(lang_size_sections_1): Set it here.
(struct check_sec): New.
(sort_sections_by_lma): Adjust for array of structs.
(sort_sections_by_vma): New function.
(lang_check_section_addresses): Check both LMA and VMA for overlap.
* testsuite/ld-scripts/rgn-over7.d: Adjust.
diff --git a/ld/ldlang.c b/ld/ldlang.c
index b369f99..cb6aab6 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -68,6 +68,7 @@ static lang_statement_list_type *stat_save[10];
static lang_statement_list_type **stat_save_ptr = &stat_save[0];
static struct unique_sections *unique_section_list;
static struct asneeded_minfo *asneeded_list_head;
+static bfd_boolean maybe_overlays = FALSE;
/* Forward declarations. */
static void exp_init_os (etree_type *);
@@ -4677,17 +4678,39 @@ size_input_section
return dot;
}
+struct check_sec
+{
+ asection *sec;
+ bfd_boolean warned;
+};
+
static int
sort_sections_by_lma (const void *arg1, const void *arg2)
{
- const asection *sec1 = *(const asection **) arg1;
- const asection *sec2 = *(const asection **) arg2;
+ const asection *sec1 = ((const struct check_sec *) arg1)->sec;
+ const asection *sec2 = ((const struct check_sec *) arg2)->sec;
- if (bfd_section_lma (sec1->owner, sec1)
- < bfd_section_lma (sec2->owner, sec2))
+ if (sec1->lma < sec2->lma)
return -1;
- else if (bfd_section_lma (sec1->owner, sec1)
- > bfd_section_lma (sec2->owner, sec2))
+ else if (sec1->lma > sec2->lma)
+ return 1;
+ else if (sec1->id < sec2->id)
+ return -1;
+ else if (sec1->id > sec2->id)
+ return 1;
+
+ return 0;
+}
+
+static int
+sort_sections_by_vma (const void *arg1, const void *arg2)
+{
+ const asection *sec1 = ((const struct check_sec *) arg1)->sec;
+ const asection *sec2 = ((const struct check_sec *) arg2)->sec;
+
+ if (sec1->vma < sec2->vma)
+ return -1;
+ else if (sec1->vma > sec2->vma)
return 1;
else if (sec1->id < sec2->id)
return -1;
@@ -4712,66 +4735,90 @@ static void
lang_check_section_addresses (void)
{
asection *s, *p;
- asection **sections, **spp;
- unsigned int count;
+ struct check_sec *sections;
+ size_t i, count;
bfd_vma s_start;
bfd_vma s_end;
- bfd_vma p_start;
- bfd_vma p_end;
- bfd_size_type amt;
+ bfd_vma p_start = 0;
+ bfd_vma p_end = 0;
lang_memory_region_type *m;
if (bfd_count_sections (link_info.output_bfd) <= 1)
return;
- amt = bfd_count_sections (link_info.output_bfd) * sizeof (asection *);
- sections = (asection **) xmalloc (amt);
+ count = bfd_count_sections (link_info.output_bfd);
+ sections = XNEWVEC (struct check_sec, count);
/* Scan all sections in the output list. */
count = 0;
for (s = link_info.output_bfd->sections; s != NULL; s = s->next)
{
- /* Only consider loadable sections with real contents. */
- if (!(s->flags & SEC_LOAD)
- || !(s->flags & SEC_ALLOC)
+ if (IGNORE_SECTION (s)
|| s->size == 0)
continue;
- sections[count] = s;
+ sections[count].sec = s;
+ sections[count].warned = FALSE;
count++;
}
if (count <= 1)
return;
- qsort (sections, (size_t) count, sizeof (asection *),
- sort_sections_by_lma);
-
- spp = sections;
- s = *spp++;
- s_start = s->lma;
- s_end = s_start + TO_ADDR (s->size) - 1;
- for (count--; count; count--)
- {
- /* We must check the sections' LMA addresses not their VMA
- addresses because overlay sections can have overlapping VMAs
- but they must have distinct LMAs. */
- p = s;
- p_start = s_start;
- p_end = s_end;
- s = *spp++;
- s_start = s->lma;
- s_end = s_start + TO_ADDR (s->size) - 1;
-
- /* Look for an overlap. We have sorted sections by lma, so we
- know that s_start >= p_start. Besides the obvious case of
- overlap when the current section starts before the previous
- one ends, we also must have overlap if the previous section
- wraps around the address space. */
- if (s_start <= p_end
- || p_end < p_start)
- einfo (_("%X%P: section %s loaded at [%V,%V] overlaps section %s loaded at [%V,%V]\n"),
- s->name, s_start, s_end, p->name, p_start, p_end);
+ qsort (sections, count, sizeof (*sections), sort_sections_by_lma);
+
+ /* First check sections LMAs. There should be no overlap of LMAs on
+ loadable sections, even with overlays. */
+ for (p = NULL, i = 0; i < count; i++)
+ {
+ s = sections[i].sec;
+ if ((s->flags & SEC_LOAD) != 0)
+ {
+ s_start = s->lma;
+ s_end = s_start + TO_ADDR (s->size) - 1;
+
+ /* Look for an overlap. We have sorted sections by lma, so
+ we know that s_start >= p_start. Besides the obvious
+ case of overlap when the current section starts before
+ the previous one ends, we also must have overlap if the
+ previous section wraps around the address space. */
+ if (p != NULL
+ && (s_start <= p_end
+ || p_end < p_start))
+ {
+ einfo (_("%X%P: section %s LMA [%V,%V]"
+ " overlaps section %s LMA [%V,%V]\n"),
+ s->name, s_start, s_end, p->name, p_start, p_end);
+ sections[i].warned = TRUE;
+ }
+ p = s;
+ p_start = s_start;
+ p_end = s_end;
+ }
+ }
+
+ /* Now check sections VMAs if no overlays were detected. */
+ if (!maybe_overlays)
+ {
+ qsort (sections, count, sizeof (*sections), sort_sections_by_vma);
+
+ for (p = NULL, i = 0; i < count; i++)
+ {
+ s = sections[i].sec;
+ s_start = s->vma;
+ s_end = s_start + TO_ADDR (s->size) - 1;
+
+ if (p != NULL
+ && !sections[i].warned
+ && (s_start <= p_end
+ || p_end < p_start))
+ einfo (_("%X%P: section %s VMA [%V,%V]"
+ " overlaps section %s VMA [%V,%V]\n"),
+ s->name, s_start, s_end, p->name, p_start, p_end);
+ p = s;
+ p_start = s_start;
+ p_end = s_end;
+ }
}
free (sections);
@@ -5102,6 +5149,18 @@ lang_size_sections_1
if (bfd_is_abs_section (os->bfd_section) || os->ignored)
break;
+ if (r->last_os != NULL
+ && !IGNORE_SECTION (os->bfd_section)
+ && os->bfd_section->size != 0)
+ {
+ asection *last;
+
+ last = r->last_os->output_section_statement.bfd_section;
+ if (dot + TO_ADDR (os->bfd_section->size) > last->vma
+ && dot < last->vma + TO_ADDR (last->size))
+ maybe_overlays = TRUE;
+ }
+
/* Keep track of normal sections using the default
lma region. We use this to set the lma for
following sections. Overlays or other linker
diff --git a/ld/testsuite/ld-scripts/rgn-over7.d b/ld/testsuite/ld-scripts/rgn-over7.d
index 50bd6af..74abb5c 100644
--- a/ld/testsuite/ld-scripts/rgn-over7.d
+++ b/ld/testsuite/ld-scripts/rgn-over7.d
@@ -1,7 +1,7 @@
# name: rgn-over7
# source: rgn-over.s
# ld: -T rgn-over7.t -Map tmpdir/rgn-over7.map
-# error: \A[^ \n]*?ld[^:\n]*?: [^\n]*?section `\.text' will not fit in region `r1'\n[^ \n]*?ld[^:\n]*?: section \.data loaded at \[0+1008,0+1013\] overlaps section \.text loaded at \[0+1000,0+100b\]\n[^ \n]*?ld[^:\n]*?: region `r1' overflowed by 4 bytes\Z
+# error: \A[^ \n]*?ld[^:\n]*?: [^\n]*?section `\.text' will not fit in region `r1'\n[^ \n]*?ld[^:\n]*?: section \.data LMA \[0+1008,0+1013\] overlaps section \.text LMA \[0+1000,0+100b\]\n[^ \n]*?ld[^:\n]*?: region `r1' overflowed by 4 bytes\Z
Discarded input sections
#...
--
Alan Modra
Australia Development Lab, IBM
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2016-04-08 14:13 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-04-08 14:13 PR18452, ld allows overlapping sections Alan Modra
-- strict thread matches above, loose matches on Subject: below --
2016-03-30 7:34 Alan Modra
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).