PARAMS ((bfd *, Elf_Internal_Note *));
static bfd_boolean elfcore_grok_netbsd_note
PARAMS ((bfd *, Elf_Internal_Note *));
+static bfd_boolean elfcore_grok_nto_gregs
+ PARAMS ((bfd *, Elf_Internal_Note *, pid_t));
+static bfd_boolean elfcore_grok_nto_status
+ PARAMS ((bfd *, Elf_Internal_Note *, pid_t *));
+static bfd_boolean elfcore_grok_nto_note
+ PARAMS ((bfd *, Elf_Internal_Note *));
/* Swap version information in and out. The version information is
currently size independent. If that ever changes, this code will
h ^= g;
}
}
- return h;
+ return h & 0xffffffff;
}
/* Read a specified number of bytes at a specified offset in an ELF
"SHT_NOBITS", "SHT_REL", "SHT_SHLIB", "SHT_DYNSYM",
};
-/* ELF relocs are against symbols. If we are producing relocateable
+/* ELF relocs are against symbols. If we are producing relocatable
output, and the reloc is against an external symbol, and nothing
has given us any additional addend, the resulting reloc will also
be against the same symbol. In such a case, we don't want to
all be done at final link time. Rather than put special case code
into bfd_perform_relocation, all the reloc types use this howto
function. It just short circuits the reloc if producing
- relocateable output against an external symbol. */
+ relocatable output against an external symbol. */
bfd_reloc_status_type
bfd_elf_generic_reloc (abfd,
case PT_PHDR: pt = "PHDR"; break;
case PT_TLS: pt = "TLS"; break;
case PT_GNU_EH_FRAME: pt = "EH_FRAME"; break;
+ case PT_GNU_STACK: pt = "STACK"; break;
default: sprintf (buf, "0x%lx", p->p_type); pt = buf; break;
}
fprintf (f, "%8s off 0x", pt);
bfd *abfd ATTRIBUTE_UNUSED;
struct bfd_link_info *info;
{
- if (info->hash->creator->flavour != bfd_target_elf_flavour)
+ if (! is_elf_hash_table (info))
return NULL;
return elf_hash_table (info)->needed;
}
bfd *abfd ATTRIBUTE_UNUSED;
struct bfd_link_info *info;
{
- if (info->hash->creator->flavour != bfd_target_elf_flavour)
+ if (! is_elf_hash_table (info))
return NULL;
return elf_hash_table (info)->runpath;
}
SHF_ALLOC is set, and this is a shared object, then we also
treat this section as a BFD section. We can not base the
decision purely on SHF_ALLOC, because that flag is sometimes
- set in a relocateable object file, which would confuse the
+ set in a relocatable object file, which would confuse the
linker. */
if ((hdr->sh_flags & SHF_ALLOC) != 0
&& (abfd->flags & DYNAMIC) != 0
case PT_PHDR:
return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "phdr");
+ case PT_GNU_EH_FRAME:
+ return _bfd_elf_make_section_from_phdr (abfd, hdr, index,
+ "eh_frame_hdr");
+
+ case PT_GNU_STACK:
+ return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "stack");
+
default:
/* Check for any processor-specific program segment types.
If no handler for them, default to making "segment" sections. */
rel_hdr->sh_entsize = (use_rela_p
? bed->s->sizeof_rela
: bed->s->sizeof_rel);
- rel_hdr->sh_addralign = bed->s->file_align;
+ rel_hdr->sh_addralign = 1 << bed->s->log_file_align;
rel_hdr->sh_flags = 0;
rel_hdr->sh_addr = 0;
rel_hdr->sh_size = 0;
this_hdr = &elf_section_data (asect)->this_hdr;
- this_hdr->sh_name = (unsigned long) _bfd_elf_strtab_add (elf_shstrtab (abfd),
- asect->name, FALSE);
- if (this_hdr->sh_name == (unsigned long) -1)
+ this_hdr->sh_name = (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd),
+ asect->name, FALSE);
+ if (this_hdr->sh_name == (unsigned int) -1)
{
*failedptr = TRUE;
return;
pm = &m->next;
}
+ if (elf_tdata (abfd)->stack_flags)
+ {
+ amt = sizeof (struct elf_segment_map);
+ m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
+ if (m == NULL)
+ goto error_return;
+ m->next = NULL;
+ m->p_type = PT_GNU_STACK;
+ m->p_flags = elf_tdata (abfd)->stack_flags;
+ m->p_flags_valid = 1;
+
+ *pm = m;
+ pm = &m->next;
+ }
+
free (sections);
sections = NULL;
/* Put !SEC_LOAD sections after SEC_LOAD ones. */
-#define TOEND(x) (((x)->flags & (SEC_LOAD|SEC_THREAD_LOCAL)) == 0)
+#define TOEND(x) (((x)->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) == 0)
if (TOEND (sec1))
{
&& (abfd->flags & D_PAGED) != 0)
p->p_align = bed->maxpagesize;
else if (m->count == 0)
- p->p_align = bed->s->file_align;
+ p->p_align = 1 << bed->s->log_file_align;
else
p->p_align = 0;
++segs;
}
+ if (elf_tdata (abfd)->stack_flags)
+ {
+ /* We need a PT_GNU_STACK segment. */
+ ++segs;
+ }
+
for (s = abfd->sections; s != NULL; s = s->next)
{
if ((s->flags & SEC_LOAD) != 0
}
/* Place the section headers. */
- off = align_file_position (off, bed->s->file_align);
+ off = align_file_position (off, 1 << bed->s->log_file_align);
i_ehdrp->e_shoff = off;
off += i_ehdrp->e_shnum * i_ehdrp->e_shentsize;
&& ! section->segment_mark)
/* Returns TRUE iff seg1 starts after the end of seg2. */
-#define SEGMENT_AFTER_SEGMENT(seg1, seg2) \
- (seg1->p_vaddr >= SEGMENT_END (seg2, seg2->p_vaddr))
-
- /* Returns TRUE iff seg1 and seg2 overlap. */
+#define SEGMENT_AFTER_SEGMENT(seg1, seg2, field) \
+ (seg1->field >= SEGMENT_END (seg2, seg2->field))
+
+ /* Returns TRUE iff seg1 and seg2 overlap. Segments overlap iff both
+ their VMA address ranges and their LMA address ranges overlap.
+ It is possible to have overlapping VMA ranges without overlapping LMA
+ ranges. RedBoot images for example can have both .data and .bss mapped
+ to the same VMA range, but with the .data section mapped to a different
+ LMA. */
#define SEGMENT_OVERLAPS(seg1, seg2) \
- (!(SEGMENT_AFTER_SEGMENT (seg1, seg2) \
- || SEGMENT_AFTER_SEGMENT (seg2, seg1)))
+ ( !(SEGMENT_AFTER_SEGMENT (seg1, seg2, p_vaddr) \
+ || SEGMENT_AFTER_SEGMENT (seg2, seg1, p_vaddr)) \
+ && !(SEGMENT_AFTER_SEGMENT (seg1, seg2, p_paddr) \
+ || SEGMENT_AFTER_SEGMENT (seg2, seg1, p_paddr)))
/* Initialise the segment mark field. */
for (section = ibfd->sections; section != NULL; section = section->next)
continue;
/* Compute how many sections might be placed into this segment. */
- section_count = 0;
- for (section = ibfd->sections; section != NULL; section = section->next)
+ for (section = ibfd->sections, section_count = 0;
+ section != NULL;
+ section = section->next)
if (INCLUDE_SECTION_IN_SEGMENT (section, segment, bed))
++section_count;
- /* Allocate a segment map big enough to contain all of the
- sections we have selected. */
+ /* Allocate a segment map big enough to contain
+ all of the sections we have selected. */
amt = sizeof (struct elf_segment_map);
amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
map = (struct elf_segment_map *) bfd_alloc (obfd, amt);
and possibly its LMA changed, and a new segment or segments will
have to be created to contain the other sections.
- 4. The sections have been moved, but not be the same amount.
+ 4. The sections have been moved, but not by the same amount.
In this case we can change the segment's LMA to match the LMA
of the first section and we will have to create a new segment
or segments to contain the other sections.
amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
map = (struct elf_segment_map *) bfd_alloc (obfd, amt);
if (map == NULL)
- return FALSE;
+ {
+ free (sections);
+ return FALSE;
+ }
/* Initialise the fields of the segment map. Set the physical
physical address to the LMA of the first section that has
if (map->p_paddr != 0)
break;
if (map == NULL)
- {
- for (map = map_first; map != NULL; map = map->next)
- map->p_paddr_valid = 0;
- }
+ for (map = map_first; map != NULL; map = map->next)
+ map->p_paddr_valid = 0;
elf_tdata (obfd)->segment_map = map_first;
symtab_hdr->sh_entsize = bed->s->sizeof_sym;
symtab_hdr->sh_size = symtab_hdr->sh_entsize * (symcount + 1);
symtab_hdr->sh_info = elf_num_locals (abfd) + 1;
- symtab_hdr->sh_addralign = bed->s->file_align;
+ symtab_hdr->sh_addralign = 1 << bed->s->log_file_align;
symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr;
symstrtab_hdr->sh_type = SHT_STRTAB;
amt = (bfd_size_type) (1 + symcount) * bed->s->sizeof_sym;
outbound_syms = bfd_alloc (abfd, amt);
if (outbound_syms == NULL)
- return FALSE;
+ {
+ _bfd_stringtab_free (stt);
+ return FALSE;
+ }
symtab_hdr->contents = (PTR) outbound_syms;
outbound_shndx = NULL;
amt = (bfd_size_type) (1 + symcount) * sizeof (Elf_External_Sym_Shndx);
outbound_shndx = bfd_zalloc (abfd, amt);
if (outbound_shndx == NULL)
- return FALSE;
+ {
+ _bfd_stringtab_free (stt);
+ return FALSE;
+ }
+
symtab_shndx_hdr->contents = outbound_shndx;
symtab_shndx_hdr->sh_type = SHT_SYMTAB_SHNDX;
symtab_shndx_hdr->sh_size = amt;
symtab_shndx_hdr->sh_entsize = sizeof (Elf_External_Sym_Shndx);
}
- /* now generate the data (for "contents") */
+ /* Now generate the data (for "contents"). */
{
/* Fill in zeroth symbol and swap it out. */
Elf_Internal_Sym sym;
syms[idx]->name,
TRUE, FALSE);
if (sym.st_name == (unsigned long) -1)
- return FALSE;
+ {
+ _bfd_stringtab_free (stt);
+ return FALSE;
+ }
}
type_ptr = elf_symbol_from (abfd, syms[idx]);
value += sec->output_offset;
sec = sec->output_section;
}
+
/* Don't add in the section vma for relocatable output. */
if (! relocatable_p)
value += sec->vma;
section of a symbol to be a section that is
actually in the output file. */
sec2 = bfd_get_section_by_name (abfd, sec->name);
- BFD_ASSERT (sec2 != 0);
+ if (sec2 == NULL)
+ {
+ _bfd_error_handler (_("\
+Unable to find equivalent output section for symbol '%s' from section '%s'"),
+ syms[idx]->name ? syms[idx]->name : "<Local sym>",
+ sec->name);
+ bfd_set_error (bfd_error_invalid_operation);
+ _bfd_stringtab_free (stt);
+ return FALSE;
+ }
+
shndx = _bfd_elf_section_from_bfd_section (abfd, sec2);
BFD_ASSERT (shndx != -1);
}
if (syms[idx]->section->flags & SEC_THREAD_LOCAL)
type = STT_TLS;
- /* Processor-specific types */
+ /* Processor-specific types. */
if (type_ptr != NULL
&& bed->elf_backend_get_symbol_type)
type = ((*bed->elf_backend_get_symbol_type)
return TRUE;
error_return:
- if (contents == NULL)
+ if (contents != NULL)
free (contents);
return FALSE;
}
#else
return TRUE;
#endif
+
+ case NT_AUXV:
+ {
+ asection *sect = bfd_make_section (abfd, ".auxv");
+
+ if (sect == NULL)
+ return FALSE;
+ sect->_raw_size = note->descsz;
+ sect->filepos = note->descpos;
+ sect->flags = SEC_HAS_CONTENTS;
+ sect->alignment_power = 1 + bfd_get_arch_size (abfd) / 32;
+
+ return TRUE;
+ }
}
}
/* NOTREACHED */
}
+static bfd_boolean
+elfcore_grok_nto_status (abfd, note, tid)
+ bfd *abfd;
+ Elf_Internal_Note *note;
+ pid_t *tid;
+{
+ void *ddata = note->descdata;
+ char buf[100];
+ char *name;
+ asection *sect;
+ short sig;
+ unsigned flags;
+
+ /* nto_procfs_status 'pid' field is at offset 0. */
+ elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, (bfd_byte *) ddata);
+
+ /* nto_procfs_status 'tid' field is at offset 4. Pass it back. */
+ *tid = bfd_get_32 (abfd, (bfd_byte *) ddata + 4);
+
+ /* nto_procfs_status 'flags' field is at offset 8. */
+ flags = bfd_get_32 (abfd, (bfd_byte *) ddata + 8);
+
+ /* nto_procfs_status 'what' field is at offset 14. */
+ if ((sig = bfd_get_16 (abfd, (bfd_byte *) ddata + 14)) > 0)
+ {
+ elf_tdata (abfd)->core_signal = sig;
+ elf_tdata (abfd)->core_lwpid = *tid;
+ }
+
+ /* _DEBUG_FLAG_CURTID (current thread) is 0x80. Some cores
+ do not come from signals so we make sure we set the current
+ thread just in case. */
+ if (flags & 0x00000080)
+ elf_tdata (abfd)->core_lwpid = *tid;
+
+ /* Make a ".qnx_core_status/%d" section. */
+ sprintf (buf, ".qnx_core_status/%d", *tid);
+
+ name = bfd_alloc (abfd, (bfd_size_type) strlen (buf) + 1);
+ if (name == NULL)
+ return FALSE;
+ strcpy (name, buf);
+
+ sect = bfd_make_section (abfd, name);
+ if (sect == NULL)
+ return FALSE;
+
+ sect->_raw_size = note->descsz;
+ sect->filepos = note->descpos;
+ sect->flags = SEC_HAS_CONTENTS;
+ sect->alignment_power = 2;
+
+ return (elfcore_maybe_make_sect (abfd, ".qnx_core_status", sect));
+}
+
+static bfd_boolean
+elfcore_grok_nto_gregs (abfd, note, tid)
+ bfd *abfd;
+ Elf_Internal_Note *note;
+ pid_t tid;
+{
+ char buf[100];
+ char *name;
+ asection *sect;
+
+ /* Make a ".reg/%d" section. */
+ sprintf (buf, ".reg/%d", tid);
+
+ name = bfd_alloc (abfd, (bfd_size_type) strlen (buf) + 1);
+ if (name == NULL)
+ return FALSE;
+ strcpy (name, buf);
+
+ sect = bfd_make_section (abfd, name);
+ if (sect == NULL)
+ return FALSE;
+
+ sect->_raw_size = note->descsz;
+ sect->filepos = note->descpos;
+ sect->flags = SEC_HAS_CONTENTS;
+ sect->alignment_power = 2;
+
+ /* This is the current thread. */
+ if (elf_tdata (abfd)->core_lwpid == tid)
+ return elfcore_maybe_make_sect (abfd, ".reg", sect);
+
+ return TRUE;
+}
+
+#define BFD_QNT_CORE_INFO 7
+#define BFD_QNT_CORE_STATUS 8
+#define BFD_QNT_CORE_GREG 9
+#define BFD_QNT_CORE_FPREG 10
+
+static bfd_boolean
+elfcore_grok_nto_note (abfd, note)
+ bfd *abfd;
+ Elf_Internal_Note *note;
+{
+ /* Every GREG section has a STATUS section before it. Store the
+ tid from the previous call to pass down to the next gregs
+ function. */
+ static pid_t tid = 1;
+
+ switch (note->type)
+ {
+ case BFD_QNT_CORE_INFO: return elfcore_make_note_pseudosection (abfd, ".qnx_core_info", note);
+ case BFD_QNT_CORE_STATUS: return elfcore_grok_nto_status (abfd, note, &tid);
+ case BFD_QNT_CORE_GREG: return elfcore_grok_nto_gregs (abfd, note, tid);
+ case BFD_QNT_CORE_FPREG: return elfcore_grok_prfpreg (abfd, note);
+ default: return TRUE;
+ }
+}
+
/* Function: elfcore_write_note
Inputs:
namesz = strlen (name) + 1;
bed = get_elf_backend_data (abfd);
- pad = -namesz & (bed->s->file_align - 1);
+ pad = -namesz & ((1 << bed->s->log_file_align) - 1);
}
newspace = sizeof (Elf_External_Note) - 1 + namesz + pad + size;
if (! elfcore_grok_netbsd_note (abfd, &in))
goto error;
}
+ else if (strncmp (in.namedata, "QNX", 3) == 0)
+ {
+ if (! elfcore_grok_nto_note (abfd, &in))
+ goto error;
+ }
else
{
if (! elfcore_grok_note (abfd, &in))
return offset;
}
}
+\f
+/* Create a new BFD as if by bfd_openr. Rather than opening a file,
+ reconstruct an ELF file by reading the segments out of remote memory
+ based on the ELF file header at EHDR_VMA and the ELF program headers it
+ points to. If not null, *LOADBASEP is filled in with the difference
+ between the VMAs from which the segments were read, and the VMAs the
+ file headers (and hence BFD's idea of each section's VMA) put them at.
+
+ The function TARGET_READ_MEMORY is called to copy LEN bytes from the
+ remote memory at target address VMA into the local buffer at MYADDR; it
+ should return zero on success or an `errno' code on failure. TEMPL must
+ be a BFD for an ELF target with the word size and byte order found in
+ the remote memory. */
+
+bfd *
+bfd_elf_bfd_from_remote_memory (templ, ehdr_vma, loadbasep, target_read_memory)
+ bfd *templ;
+ bfd_vma ehdr_vma;
+ bfd_vma *loadbasep;
+ int (*target_read_memory) PARAMS ((bfd_vma vma, char *myaddr, int len));
+{
+ return (*get_elf_backend_data (templ)->elf_backend_bfd_from_remote_memory)
+ (templ, ehdr_vma, loadbasep, target_read_memory);
+}