forked from Imagelibrary/binutils-gdb
ppc: sanity check writing relocs
Check for output buffer overruns. * elf32-ppc.c (swap_reloc_out, count_and_swap_reloc_out): New functions. Use throughout file. * elf64-ppc.c (swap_reloc_out, count_and_swap_reloc_out): Likewise.
This commit is contained in:
@@ -6935,6 +6935,23 @@ is_insn_dq_form (unsigned int insn)
|
||||
&& (insn & 3) == 1));
|
||||
}
|
||||
|
||||
static bool
|
||||
swap_reloc_out (bfd *obfd, Elf_Internal_Rela *rel, bfd_byte *loc, asection *s)
|
||||
{
|
||||
if ((size_t) (loc - s->contents) >= s->size)
|
||||
return false;
|
||||
bfd_elf32_swap_reloca_out (obfd, rel, loc);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
count_and_swap_reloc_out (bfd *obfd, Elf_Internal_Rela *rel, asection *s)
|
||||
{
|
||||
bfd_byte *loc = s->contents;
|
||||
loc += s->reloc_count++ * sizeof (Elf32_External_Rela);
|
||||
return swap_reloc_out (obfd, rel, loc, s);
|
||||
}
|
||||
|
||||
/* The RELOCATE_SECTION function is called by the ELF backend linker
|
||||
to handle the relocations for a section.
|
||||
|
||||
@@ -7806,7 +7823,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
||||
: sym->st_shndx != SHN_ABS)))
|
||||
{
|
||||
asection *rsec = htab->elf.srelgot;
|
||||
bfd_byte * loc;
|
||||
|
||||
if (ifunc != NULL)
|
||||
{
|
||||
@@ -7825,11 +7841,9 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
||||
outrel.r_info = ELF32_R_INFO (indx, R_PPC_DTPMOD32);
|
||||
if (tls_ty == (TLS_TLS | TLS_GD))
|
||||
{
|
||||
loc = rsec->contents;
|
||||
loc += (rsec->reloc_count++
|
||||
* sizeof (Elf32_External_Rela));
|
||||
bfd_elf32_swap_reloca_out (output_bfd,
|
||||
&outrel, loc);
|
||||
BFD_ASSERT (count_and_swap_reloc_out (output_bfd,
|
||||
&outrel,
|
||||
rsec));
|
||||
outrel.r_offset += 4;
|
||||
outrel.r_info
|
||||
= ELF32_R_INFO (indx, R_PPC_DTPREL32);
|
||||
@@ -7856,10 +7870,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
||||
outrel.r_addend -= htab->elf.tls_sec->vma;
|
||||
}
|
||||
}
|
||||
loc = rsec->contents;
|
||||
loc += (rsec->reloc_count++
|
||||
* sizeof (Elf32_External_Rela));
|
||||
bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
|
||||
BFD_ASSERT (count_and_swap_reloc_out (output_bfd,
|
||||
&outrel, rsec));
|
||||
}
|
||||
|
||||
/* Init the .got section contents if we're not
|
||||
@@ -8089,7 +8101,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
||||
&& h->dyn_relocs != NULL))
|
||||
{
|
||||
int skip;
|
||||
bfd_byte *loc;
|
||||
asection *sreloc;
|
||||
long indx = 0;
|
||||
|
||||
@@ -8221,9 +8232,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
||||
if (sreloc == NULL)
|
||||
return false;
|
||||
|
||||
loc = sreloc->contents;
|
||||
loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela);
|
||||
bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
|
||||
BFD_ASSERT (count_and_swap_reloc_out (output_bfd, &outrel,
|
||||
sreloc));
|
||||
|
||||
if (skip == -1)
|
||||
goto copy_reloc;
|
||||
@@ -9573,7 +9583,8 @@ write_global_sym_plt (struct elf_link_hash_entry *h, void *inf)
|
||||
rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
|
||||
R_PPC_ADDR16_HA);
|
||||
rela.r_addend = got_offset;
|
||||
bfd_elf32_swap_reloca_out (info->output_bfd, &rela, loc);
|
||||
BFD_ASSERT (swap_reloc_out (info->output_bfd, &rela, loc,
|
||||
htab->srelplt2));
|
||||
loc += sizeof (Elf32_External_Rela);
|
||||
|
||||
/* Provide the @l relocation for the second instruction. */
|
||||
@@ -9583,7 +9594,8 @@ write_global_sym_plt (struct elf_link_hash_entry *h, void *inf)
|
||||
rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
|
||||
R_PPC_ADDR16_LO);
|
||||
rela.r_addend = got_offset;
|
||||
bfd_elf32_swap_reloca_out (info->output_bfd, &rela, loc);
|
||||
BFD_ASSERT (swap_reloc_out (info->output_bfd, &rela, loc,
|
||||
htab->srelplt2));
|
||||
loc += sizeof (Elf32_External_Rela);
|
||||
|
||||
/* Provide a relocation for the GOT entry corresponding to this
|
||||
@@ -9594,7 +9606,8 @@ write_global_sym_plt (struct elf_link_hash_entry *h, void *inf)
|
||||
rela.r_info = ELF32_R_INFO (htab->elf.hplt->indx,
|
||||
R_PPC_ADDR32);
|
||||
rela.r_addend = ent->plt.offset + 16;
|
||||
bfd_elf32_swap_reloca_out (info->output_bfd, &rela, loc);
|
||||
BFD_ASSERT (swap_reloc_out (info->output_bfd, &rela, loc,
|
||||
htab->srelplt2));
|
||||
}
|
||||
|
||||
/* VxWorks uses non-standard semantics for R_PPC_JMP_SLOT.
|
||||
@@ -9676,7 +9689,8 @@ write_global_sym_plt (struct elf_link_hash_entry *h, void *inf)
|
||||
if (h->type == STT_GNU_IFUNC && is_static_defined (h))
|
||||
htab->maybe_local_ifunc_resolver = 1;
|
||||
}
|
||||
bfd_elf32_swap_reloca_out (info->output_bfd, &rela, loc);
|
||||
BFD_ASSERT (swap_reloc_out (info->output_bfd, &rela,
|
||||
loc, relplt));
|
||||
}
|
||||
doneone = true;
|
||||
}
|
||||
@@ -9793,9 +9807,8 @@ ppc_finish_symbols (struct bfd_link_info *info)
|
||||
+ plt->output_offset
|
||||
+ plt->output_section->vma);
|
||||
rela.r_addend = val;
|
||||
loc = relplt->contents + (relplt->reloc_count++
|
||||
* sizeof (Elf32_External_Rela));
|
||||
bfd_elf32_swap_reloca_out (info->output_bfd, &rela, loc);
|
||||
BFD_ASSERT (count_and_swap_reloc_out (info->output_bfd, &rela,
|
||||
relplt));
|
||||
|
||||
p = (unsigned char *) htab->glink->contents + ent->glink_offset;
|
||||
write_glink_stub (NULL, ent, htab->elf.iplt, p, info);
|
||||
@@ -9879,7 +9892,6 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
|
||||
{
|
||||
asection *s;
|
||||
Elf_Internal_Rela rela;
|
||||
bfd_byte *loc;
|
||||
|
||||
/* This symbols needs a copy reloc. Set it up. */
|
||||
|
||||
@@ -9900,8 +9912,7 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
|
||||
rela.r_offset = SYM_VAL (h);
|
||||
rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_COPY);
|
||||
rela.r_addend = 0;
|
||||
loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
|
||||
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
|
||||
BFD_ASSERT (count_and_swap_reloc_out (output_bfd, &rela, s));
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
@@ -10105,7 +10116,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
|
||||
+ 2);
|
||||
rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_PPC_ADDR16_HA);
|
||||
rela.r_addend = 0;
|
||||
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
|
||||
BFD_ASSERT (swap_reloc_out (output_bfd, &rela, loc, htab->srelplt2));
|
||||
loc += sizeof (Elf32_External_Rela);
|
||||
|
||||
/* Output the @l relocation for the second instruction. */
|
||||
@@ -10114,7 +10125,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
|
||||
+ 6);
|
||||
rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_PPC_ADDR16_LO);
|
||||
rela.r_addend = 0;
|
||||
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
|
||||
BFD_ASSERT (swap_reloc_out (output_bfd, &rela, loc, htab->srelplt2));
|
||||
loc += sizeof (Elf32_External_Rela);
|
||||
|
||||
/* Fix up the remaining relocations. They may have the wrong
|
||||
|
||||
@@ -11569,6 +11569,24 @@ get_relocs (asection *sec, int count)
|
||||
return relocs;
|
||||
}
|
||||
|
||||
static bool
|
||||
swap_reloc_out (bfd *obfd, Elf_Internal_Rela *rel, bfd_byte *loc, asection *s)
|
||||
{
|
||||
if ((size_t) (loc - s->contents) >= s->size)
|
||||
return false;
|
||||
bfd_elf64_swap_reloca_out (obfd, rel, loc);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
count_and_swap_reloc_out (bfd *obfd, Elf_Internal_Rela *rel, asection *s)
|
||||
{
|
||||
bfd_byte *loc = s->contents;
|
||||
loc += s->reloc_count++ * sizeof (Elf64_External_Rela);
|
||||
return swap_reloc_out (obfd, rel, loc, s);
|
||||
}
|
||||
|
||||
|
||||
/* Convert the relocs R[0] thru R[-NUM_REL+1], which are all no-symbol
|
||||
forms, to the equivalent relocs against the global symbol given by
|
||||
STUB_ENTRY->H. */
|
||||
@@ -11847,7 +11865,6 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
||||
{
|
||||
/* Create a reloc for the branch lookup table entry. */
|
||||
Elf_Internal_Rela rela;
|
||||
bfd_byte *rl;
|
||||
|
||||
rela.r_offset = (br_entry->offset
|
||||
+ htab->brlt->output_offset
|
||||
@@ -11855,10 +11872,8 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
||||
rela.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE);
|
||||
rela.r_addend = targ;
|
||||
|
||||
rl = htab->relbrlt->contents;
|
||||
rl += (htab->relbrlt->reloc_count++
|
||||
* sizeof (Elf64_External_Rela));
|
||||
bfd_elf64_swap_reloca_out (htab->relbrlt->owner, &rela, rl);
|
||||
BFD_ASSERT (count_and_swap_reloc_out (htab->relbrlt->owner, &rela,
|
||||
htab->relbrlt));
|
||||
}
|
||||
else if (info->emitrelocations)
|
||||
{
|
||||
@@ -14652,9 +14667,8 @@ build_global_entry_stubs_and_plt (struct elf_link_hash_entry *h, void *inf)
|
||||
rela.r_offset = (plt->output_section->vma
|
||||
+ plt->output_offset
|
||||
+ ent->plt.offset);
|
||||
loc = relplt->contents + (relplt->reloc_count++
|
||||
* sizeof (Elf64_External_Rela));
|
||||
bfd_elf64_swap_reloca_out (info->output_bfd, &rela, loc);
|
||||
BFD_ASSERT (count_and_swap_reloc_out (info->output_bfd, &rela,
|
||||
relplt));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -14669,7 +14683,8 @@ build_global_entry_stubs_and_plt (struct elf_link_hash_entry *h, void *inf)
|
||||
/ PLT_ENTRY_SIZE (htab) * sizeof (Elf64_External_Rela)));
|
||||
if (h->type == STT_GNU_IFUNC && is_static_defined (h))
|
||||
htab->elf.ifunc_resolvers = true;
|
||||
bfd_elf64_swap_reloca_out (info->output_bfd, &rela, loc);
|
||||
BFD_ASSERT (swap_reloc_out (info->output_bfd, &rela,
|
||||
loc, htab->elf.srelplt));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14790,7 +14805,6 @@ write_plt_relocs_for_local_syms (struct bfd_link_info *info)
|
||||
Elf_Internal_Sym *sym;
|
||||
asection *sym_sec;
|
||||
asection *plt, *relplt;
|
||||
bfd_byte *loc;
|
||||
bfd_vma val;
|
||||
|
||||
if (!get_sym_h (NULL, &sym, &sym_sec, NULL, &local_syms,
|
||||
@@ -14822,7 +14836,7 @@ write_plt_relocs_for_local_syms (struct bfd_link_info *info)
|
||||
|
||||
if (relplt == NULL)
|
||||
{
|
||||
loc = plt->contents + ent->plt.offset;
|
||||
bfd_byte *loc = plt->contents + ent->plt.offset;
|
||||
bfd_put_64 (info->output_bfd, val, loc);
|
||||
if (htab->opd_abi)
|
||||
{
|
||||
@@ -14851,9 +14865,8 @@ write_plt_relocs_for_local_syms (struct bfd_link_info *info)
|
||||
rela.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE);
|
||||
}
|
||||
rela.r_addend = val;
|
||||
loc = relplt->contents + (relplt->reloc_count++
|
||||
* sizeof (Elf64_External_Rela));
|
||||
bfd_elf64_swap_reloca_out (info->output_bfd, &rela, loc);
|
||||
BFD_ASSERT (count_and_swap_reloc_out (info->output_bfd,
|
||||
&rela, relplt));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16991,11 +17004,9 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
outrel.r_info = ELF64_R_INFO (indx, R_PPC64_DTPMOD64);
|
||||
if (tls_type == (TLS_TLS | TLS_GD))
|
||||
{
|
||||
loc = relgot->contents;
|
||||
loc += (relgot->reloc_count++
|
||||
* sizeof (Elf64_External_Rela));
|
||||
bfd_elf64_swap_reloca_out (output_bfd,
|
||||
&outrel, loc);
|
||||
BFD_ASSERT (count_and_swap_reloc_out (output_bfd,
|
||||
&outrel,
|
||||
relgot));
|
||||
outrel.r_offset += 8;
|
||||
outrel.r_addend = orig_rel.r_addend;
|
||||
outrel.r_info
|
||||
@@ -17035,12 +17046,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
}
|
||||
if (!(info->enable_dt_relr
|
||||
&& ELF64_R_TYPE (outrel.r_info) == R_PPC64_RELATIVE))
|
||||
{
|
||||
loc = relgot->contents;
|
||||
loc += (relgot->reloc_count++
|
||||
* sizeof (Elf64_External_Rela));
|
||||
bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
|
||||
}
|
||||
BFD_ASSERT (count_and_swap_reloc_out (output_bfd,
|
||||
&outrel, relgot));
|
||||
}
|
||||
|
||||
/* Init the .got section contents here if we're not
|
||||
@@ -17526,12 +17533,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
if (sreloc == NULL)
|
||||
abort ();
|
||||
|
||||
if (sreloc->reloc_count * sizeof (Elf64_External_Rela)
|
||||
>= sreloc->size)
|
||||
abort ();
|
||||
loc = sreloc->contents;
|
||||
loc += sreloc->reloc_count++ * sizeof (Elf64_External_Rela);
|
||||
bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
|
||||
BFD_ASSERT (count_and_swap_reloc_out (output_bfd, &outrel,
|
||||
sreloc));
|
||||
}
|
||||
|
||||
if (!warned_dynamic
|
||||
@@ -18164,7 +18167,6 @@ ppc64_elf_finish_dynamic_symbol (bfd *output_bfd,
|
||||
/* This symbol needs a copy reloc. Set it up. */
|
||||
Elf_Internal_Rela rela;
|
||||
asection *srel;
|
||||
bfd_byte *loc;
|
||||
|
||||
if (h->dynindx == -1)
|
||||
abort ();
|
||||
@@ -18176,9 +18178,7 @@ ppc64_elf_finish_dynamic_symbol (bfd *output_bfd,
|
||||
srel = htab->elf.sreldynrelro;
|
||||
else
|
||||
srel = htab->elf.srelbss;
|
||||
loc = srel->contents;
|
||||
loc += srel->reloc_count++ * sizeof (Elf64_External_Rela);
|
||||
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
|
||||
BFD_ASSERT (count_and_swap_reloc_out (output_bfd, &rela, srel));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user