non-bss input sections to bss output sections, or emit data
to a bss output section via a linker script. */
(*_bfd_error_handler)
- (_("section `%A' type changed to PROGBITS"), asect);
+ (_("warning: section `%A' type changed to PROGBITS"), asect);
this_hdr->sh_type = sh_type;
}
return segs * bed->s->sizeof_phdr;
}
+/* Find the segment that contains the output_section of section. */
+
+Elf_Internal_Phdr *
+_bfd_elf_find_segment_containing_section (bfd * abfd, asection * section)
+{
+ struct elf_segment_map *m;
+ Elf_Internal_Phdr *p;
+
+ for (m = elf_tdata (abfd)->segment_map,
+ p = elf_tdata (abfd)->phdr;
+ m != NULL;
+ m = m->next, p++)
+ {
+ int i;
+
+ for (i = m->count - 1; i >= 0; i--)
+ if (m->sections[i] == section)
+ return p;
+ }
+
+ return NULL;
+}
+
/* Create a mapping from a set of sections to a program segment. */
static struct elf_segment_map *
&& (section->lma + SECTION_SIZE (section, segment) \
<= SEGMENT_END (segment, base)))
- /* Special case: corefile "NOTE" section containing regs, prpsinfo etc. */
-#define IS_COREFILE_NOTE(p, s) \
+ /* Handle PT_NOTE segment. */
+#define IS_NOTE(p, s) \
(p->p_type == PT_NOTE \
- && bfd_get_format (ibfd) == bfd_core \
- && s->vma == 0 && s->lma == 0 \
+ && elf_section_type (s) == SHT_NOTE \
&& (bfd_vma) s->filepos >= p->p_offset \
&& ((bfd_vma) s->filepos + s->size \
<= p->p_offset + p->p_filesz))
+ /* Special case: corefile "NOTE" section containing regs, prpsinfo
+ etc. */
+#define IS_COREFILE_NOTE(p, s) \
+ (IS_NOTE (p, s) \
+ && bfd_get_format (ibfd) == bfd_core \
+ && s->vma == 0 \
+ && s->lma == 0)
+
/* The complicated case when p_vaddr is 0 is to handle the Solaris
linker, which generates a PT_INTERP section with p_vaddr and
p_memsz set to 0. */
A section will be included if:
1. It is within the address space of the segment -- we use the LMA
if that is set for the segment and the VMA otherwise,
- 2. It is an allocated segment,
+ 2. It is an allocated section or a NOTE section in a PT_NOTE
+ segment.
3. There is an output section associated with it,
4. The section has not already been allocated to a previous segment.
5. PT_GNU_STACK segments do not include any sections.
? IS_CONTAINED_BY_LMA (section, segment, segment->p_paddr) \
: IS_CONTAINED_BY_VMA (section, segment)) \
&& (section->flags & SEC_ALLOC) != 0) \
- || IS_COREFILE_NOTE (segment, section)) \
+ || IS_NOTE (segment, section)) \
&& segment->p_type != PT_GNU_STACK \
&& (segment->p_type != PT_TLS \
|| (section->flags & SEC_THREAD_LOCAL)) \
: segment->p_vaddr != section->vma) \
|| (strcmp (bfd_get_section_name (ibfd, section), ".dynamic") \
== 0)) \
- && ! section->segment_mark)
+ && !section->segment_mark)
/* If the output section of a section in the input segment is NULL,
it is removed from the corresponding output segment. */
}
/* Determine if this segment overlaps any previous segments. */
- for (j = 0, segment2 = elf_tdata (ibfd)->phdr; j < i; j++, segment2 ++)
+ for (j = 0, segment2 = elf_tdata (ibfd)->phdr; j < i; j++, segment2++)
{
bfd_signed_vma extra_length;
if (segment2->p_type != PT_LOAD
- || ! SEGMENT_OVERLAPS (segment, segment2))
+ || !SEGMENT_OVERLAPS (segment, segment2))
continue;
/* Merge the two segments together. */
{
/* Extend SEGMENT2 to include SEGMENT and then delete
SEGMENT. */
- extra_length =
- SEGMENT_END (segment, segment->p_vaddr)
- - SEGMENT_END (segment2, segment2->p_vaddr);
+ extra_length = (SEGMENT_END (segment, segment->p_vaddr)
+ - SEGMENT_END (segment2, segment2->p_vaddr));
if (extra_length > 0)
{
- segment2->p_memsz += extra_length;
+ segment2->p_memsz += extra_length;
segment2->p_filesz += extra_length;
}
{
/* Extend SEGMENT to include SEGMENT2 and then delete
SEGMENT2. */
- extra_length =
- SEGMENT_END (segment2, segment2->p_vaddr)
- - SEGMENT_END (segment, segment->p_vaddr);
+ extra_length = (SEGMENT_END (segment2, segment2->p_vaddr)
+ - SEGMENT_END (segment, segment->p_vaddr));
if (extra_length > 0)
{
- segment->p_memsz += extra_length;
+ segment->p_memsz += extra_length;
segment->p_filesz += extra_length;
}
/* The second scan attempts to assign sections to segments. */
for (i = 0, segment = elf_tdata (ibfd)->phdr;
i < num_segments;
- i ++, segment ++)
- {
- unsigned int section_count;
- asection ** sections;
- asection * output_section;
- unsigned int isec;
- bfd_vma matching_lma;
- bfd_vma suggested_lma;
- unsigned int j;
+ i++, segment++)
+ {
+ unsigned int section_count;
+ asection **sections;
+ asection *output_section;
+ unsigned int isec;
+ bfd_vma matching_lma;
+ bfd_vma suggested_lma;
+ unsigned int j;
bfd_size_type amt;
- asection * first_section;
+ asection *first_section;
+ bfd_boolean first_matching_lma;
+ bfd_boolean first_suggested_lma;
if (segment->p_type == PT_NULL)
continue;
/* Initialise the fields of the segment map. Default to
using the physical address of the segment in the input BFD. */
- map->next = NULL;
- map->p_type = segment->p_type;
- map->p_flags = segment->p_flags;
+ map->next = NULL;
+ map->p_type = segment->p_type;
+ map->p_flags = segment->p_flags;
map->p_flags_valid = 1;
/* If the first section in the input segment is removed, there is
and if it contains the program headers themselves. */
map->includes_filehdr = (segment->p_offset == 0
&& segment->p_filesz >= iehdr->e_ehsize);
-
map->includes_phdrs = 0;
- if (! phdr_included || segment->p_type != PT_LOAD)
+ if (!phdr_included || segment->p_type != PT_LOAD)
{
map->includes_phdrs =
(segment->p_offset <= (bfd_vma) iehdr->e_phoff
something. They are allowed by the ELF spec however, so only
a warning is produced. */
if (segment->p_type == PT_LOAD)
- (*_bfd_error_handler)
- (_("%B: warning: Empty loadable segment detected, is this intentional ?\n"),
- ibfd);
+ (*_bfd_error_handler) (_("%B: warning: Empty loadable segment"
+ " detected, is this intentional ?\n"),
+ ibfd);
map->count = 0;
*pointer_to_map = map;
isec = 0;
matching_lma = 0;
suggested_lma = 0;
+ first_matching_lma = TRUE;
+ first_suggested_lma = TRUE;
- for (j = 0, section = ibfd->sections;
+ for (section = ibfd->sections;
section != NULL;
section = section->next)
+ if (section == first_section)
+ break;
+
+ for (j = 0; section != NULL; section = section->next)
{
if (INCLUDE_SECTION_IN_SEGMENT (section, segment, bed))
{
output_section = section->output_section;
- sections[j ++] = section;
+ sections[j++] = section;
/* The Solaris native linker always sets p_paddr to 0.
We try to catch that case here, and set it to the
p_paddr be left as zero. */
if (segment->p_paddr == 0
&& segment->p_vaddr != 0
- && (! bed->want_p_paddr_set_to_zero)
+ && !bed->want_p_paddr_set_to_zero
&& isec == 0
&& output_section->lma != 0
- && (output_section->vma == (segment->p_vaddr
- + (map->includes_filehdr
- ? iehdr->e_ehsize
- : 0)
- + (map->includes_phdrs
- ? (iehdr->e_phnum
- * iehdr->e_phentsize)
- : 0))))
+ && output_section->vma == (segment->p_vaddr
+ + (map->includes_filehdr
+ ? iehdr->e_ehsize
+ : 0)
+ + (map->includes_phdrs
+ ? (iehdr->e_phnum
+ * iehdr->e_phentsize)
+ : 0)))
map->p_paddr = segment->p_vaddr;
/* Match up the physical address of the segment with the
LMA address of the output section. */
if (IS_CONTAINED_BY_LMA (output_section, segment, map->p_paddr)
|| IS_COREFILE_NOTE (segment, section)
- || (bed->want_p_paddr_set_to_zero &&
- IS_CONTAINED_BY_VMA (output_section, segment)))
+ || (bed->want_p_paddr_set_to_zero
+ && IS_CONTAINED_BY_VMA (output_section, segment)))
{
- if (matching_lma == 0 || output_section->lma < matching_lma)
- matching_lma = output_section->lma;
+ if (first_matching_lma || output_section->lma < matching_lma)
+ {
+ matching_lma = output_section->lma;
+ first_matching_lma = FALSE;
+ }
/* We assume that if the section fits within the segment
then it does not overlap any other section within that
segment. */
- map->sections[isec ++] = output_section;
+ map->sections[isec++] = output_section;
}
- else if (suggested_lma == 0)
- suggested_lma = output_section->lma;
+ else if (first_suggested_lma)
+ {
+ suggested_lma = output_section->lma;
+ first_suggested_lma = FALSE;
+ }
+
+ if (j == section_count)
+ break;
}
}
*pointer_to_map = map;
pointer_to_map = &map->next;
- if (matching_lma != map->p_paddr
+ if (!bed->want_p_paddr_set_to_zero
+ && matching_lma != map->p_paddr
&& !map->includes_filehdr && !map->includes_phdrs)
/* There is some padding before the first section in the
segment. So, we must account for that in the output
}
else
{
- if (matching_lma != 0)
+ if (!first_matching_lma)
{
/* At least one section fits inside the current segment.
Keep it, but modify its physical address to match the
{
map->count = 0;
suggested_lma = 0;
+ first_suggested_lma = TRUE;
/* Fill the current segment with sections that fit. */
for (j = 0; j < section_count; j++)
/* If the first section in a segment does not start at
the beginning of the segment, then something is
wrong. */
- if (output_section->lma !=
- (map->p_paddr
- + (map->includes_filehdr ? iehdr->e_ehsize : 0)
- + (map->includes_phdrs
- ? iehdr->e_phnum * iehdr->e_phentsize
- : 0)))
+ if (output_section->lma
+ != (map->p_paddr
+ + (map->includes_filehdr ? iehdr->e_ehsize : 0)
+ + (map->includes_phdrs
+ ? iehdr->e_phnum * iehdr->e_phentsize
+ : 0)))
abort ();
}
else
{
- asection * prev_sec;
+ asection *prev_sec;
prev_sec = map->sections[map->count - 1];
if ((BFD_ALIGN (prev_sec->lma + prev_sec->size,
maxpagesize)
< BFD_ALIGN (output_section->lma, maxpagesize))
- || ((prev_sec->lma + prev_sec->size)
+ || (prev_sec->lma + prev_sec->size
> output_section->lma))
{
- if (suggested_lma == 0)
- suggested_lma = output_section->lma;
+ if (first_suggested_lma)
+ {
+ suggested_lma = output_section->lma;
+ first_suggested_lma = FALSE;
+ }
continue;
}
sections[j] = NULL;
section->segment_mark = TRUE;
}
- else if (suggested_lma == 0)
- suggested_lma = output_section->lma;
+ else if (first_suggested_lma)
+ {
+ suggested_lma = output_section->lma;
+ first_suggested_lma = FALSE;
+ }
}
BFD_ASSERT (map->count > 0);
/* Initialise the fields of the segment map. Set the physical
physical address to the LMA of the first section that has
not yet been assigned. */
- map->next = NULL;
- map->p_type = segment->p_type;
- map->p_flags = segment->p_flags;
- map->p_flags_valid = 1;
- map->p_paddr = suggested_lma;
- map->p_paddr_valid = 1;
+ map->next = NULL;
+ map->p_type = segment->p_type;
+ map->p_flags = segment->p_flags;
+ map->p_flags_valid = 1;
+ map->p_paddr = suggested_lma;
+ map->p_paddr_valid = 1;
map->includes_filehdr = 0;
- map->includes_phdrs = 0;
+ map->includes_phdrs = 0;
}
}
while (isec < section_count);
#undef SECTION_SIZE
#undef IS_CONTAINED_BY_VMA
#undef IS_CONTAINED_BY_LMA
+#undef IS_NOTE
#undef IS_COREFILE_NOTE
#undef IS_SOLARIS_PT_INTERP
#undef IS_SECTION_IN_INPUT_SEGMENT
asection *section, *osec;
unsigned int i, num_segments;
Elf_Internal_Shdr *this_hdr;
+ const struct elf_backend_data *bed;
+
+ bed = get_elf_backend_data (ibfd);
+
+ /* Regenerate the segment map if p_paddr is set to 0. */
+ if (bed->want_p_paddr_set_to_zero)
+ goto rewrite;
/* Initialize the segment mark field. */
for (section = obfd->sections; section != NULL;
osym = elf_symbol_from (obfd, osymarg);
if (isym != NULL
+ && isym->internal_elf_sym.st_shndx != 0
&& osym != NULL
&& bfd_is_abs_section (isym->symbol.section))
{
names = (char *) (s + count);
p = relplt->relocation;
n = 0;
- for (i = 0; i < count; i++, s++, p++)
+ for (i = 0; i < count; i++, p++)
{
size_t len;
bfd_vma addr;
s->section = plt;
s->value = addr - plt->vma;
s->name = names;
+ s->udata.p = NULL;
len = strlen ((*p->sym_ptr_ptr)->name);
memcpy (names, (*p->sym_ptr_ptr)->name, len);
names += len;
memcpy (names, "@plt", sizeof ("@plt"));
names += sizeof ("@plt");
- ++n;
+ ++s, ++n;
}
return n;