+2015-01-05 Nick Clifton <nickc@redhat.com>
+
+ PR binutils/17512
+ * archive.c (do_slurp_bsd_armap): Make sure that the parsed sized
+ is at least big enough for the header to be read.
+ * elf32-i386.c (elf_i386_get_plt_sym_val): Skip unknown relocs.
+ * mach-o.c (bfd_mach_o_get_synthetic_symtab): Add range checks.
+ (bfd_mach_o_read_command): Prevetn duplicate error messages about
+ unrecognized commands.
+ * syms.c (_bfd_stab_section_find_nearest_line): Add range checks
+ when indexing into the string table.
+
2015-01-01 Alan Modra <amodra@gmail.com>
Update year range in copyright notice of all files.
parsed_size = mapdata->parsed_size;
free (mapdata);
/* PR 17512: file: 883ff754. */
- if (parsed_size == 0)
+ /* PR 17512: file: 0458885f. */
+ if (parsed_size < 4)
return FALSE;
raw_armap = (bfd_byte *) bfd_zalloc (abfd, parsed_size);
{
long reloc_index;
- if (p->howto->type != R_386_JUMP_SLOT
- && p->howto->type != R_386_IRELATIVE)
+ if (p->howto == NULL /* PR 17512: file: bc9d6cf5. */
+ || (p->howto->type != R_386_JUMP_SLOT
+ && p->howto->type != R_386_IRELATIVE))
continue;
reloc_index = H_GET_32 (abfd, (plt_contents + plt_offset
for (isym = isymbuf + 1, sym = symbase; isym < isymend; isym++, sym++)
{
memcpy (&sym->internal_elf_sym, isym, sizeof (Elf_Internal_Sym));
- sym->symbol.the_bfd = abfd;
+ sym->symbol.the_bfd = abfd;
sym->symbol.name = bfd_elf_sym_name (abfd, hdr, isym, NULL);
-
sym->symbol.value = isym->st_value;
if (isym->st_shndx == SHN_UNDEF)
bfd_mach_o_dysymtab_command *dysymtab = mdata->dysymtab;
bfd_mach_o_symtab_command *symtab = mdata->symtab;
asymbol *s;
+ char * s_start;
+ char * s_end;
unsigned long count, i, j, n;
size_t size;
char *names;
char *nul_name;
+ const char stub [] = "$stub";
*ret = NULL;
/* Stop now if no symbols or no indirect symbols. */
- if (dysymtab == NULL || symtab == NULL || symtab->symbols == NULL)
- return 0;
-
- if (dysymtab->nindirectsyms == 0)
+ if (dysymtab == NULL || dysymtab->nindirectsyms == 0
+ || symtab == NULL || symtab->symbols == NULL)
return 0;
/* We need to allocate a bfd symbol for every indirect symbol and to
for (j = 0; j < count; j++)
{
+ const char * strng;
unsigned int isym = dysymtab->indirect_syms[j];
/* Some indirect symbols are anonymous. */
- if (isym < symtab->nsyms && symtab->symbols[isym].symbol.name)
- size += strlen (symtab->symbols[isym].symbol.name) + sizeof ("$stub");
+ if (isym < symtab->nsyms && (strng = symtab->symbols[isym].symbol.name))
+ /* PR 17512: file: f5b8eeba. */
+ size += strnlen (strng, symtab->strsize - (strng - symtab->strtab)) + sizeof (stub);
}
- s = *ret = (asymbol *) bfd_malloc (size);
+ s_start = bfd_malloc (size);
+ s = *ret = (asymbol *) s_start;
if (s == NULL)
return -1;
names = (char *) (s + count);
nul_name = names;
*names++ = 0;
+ s_end = s_start + size;
n = 0;
for (i = 0; i < mdata->nsects; i++)
last = first + bfd_mach_o_section_get_nbr_indirect (abfd, sec);
addr = sec->addr;
entry_size = bfd_mach_o_section_get_entry_size (abfd, sec);
+
+ /* PR 17512: file: 08e15eec. */
+ if (first >= count || last >= count || first > last)
+ goto fail;
+
for (j = first; j < last; j++)
{
unsigned int isym = dysymtab->indirect_syms[j];
+ /* PR 17512: file: 04d64d9b. */
+ if (((char *) s) + sizeof (* s) > s_end)
+ goto fail;
+
s->flags = BSF_GLOBAL | BSF_SYNTHETIC;
s->section = sec->bfdsection;
s->value = addr - sec->addr;
s->name = names;
len = strlen (sym);
+ /* PR 17512: file: 47dfd4d2. */
+ if (names + len >= s_end)
+ goto fail;
memcpy (names, sym, len);
names += len;
- memcpy (names, "$stub", sizeof ("$stub"));
- names += sizeof ("$stub");
+ /* PR 17512: file: 18f340a4. */
+ if (names + sizeof (stub) >= s_end)
+ goto fail;
+ memcpy (names, stub, sizeof (stub));
+ names += sizeof (stub);
}
else
s->name = nul_name;
}
return n;
+
+ fail:
+ free (s_start);
+ * ret = NULL;
+ return -1;
}
void
return FALSE;
break;
default:
- (*_bfd_error_handler)(_("%B: unknown load command 0x%lx"),
- abfd, (unsigned long) command->type);
- break;
+ {
+ static bfd_boolean unknown_set = FALSE;
+ static unsigned long unknown_command = 0;
+
+ /* Prevent reams of error messages when parsing corrupt binaries. */
+ if (!unknown_set)
+ unknown_set = TRUE;
+ else if (command->type == unknown_command)
+ break;
+ unknown_command = command->type;
+
+ (*_bfd_error_handler)(_("%B: unknown load command 0x%lx"),
+ abfd, (unsigned long) command->type);
+ break;
+ }
}
return TRUE;
*minisymsp = syms;
*sizep = sizeof (asymbol *);
+
return symcount;
error_return:
{
nul_fun = stab;
nul_str = str;
+ if (file_name >= (char *) info->strs + strsize)
+ file_name = NULL;
if (stab + STABSIZE + TYPEOFF < info->stabs + stabsize
&& *(stab + STABSIZE + TYPEOFF) == (bfd_byte) N_SO)
{
directory_name = file_name;
file_name = ((char *) str
+ bfd_get_32 (abfd, stab + STRDXOFF));
+ if (file_name >= (char *) info->strs + strsize)
+ file_name = NULL;
}
}
break;
case N_SOL:
/* The name of an include file. */
file_name = (char *) str + bfd_get_32 (abfd, stab + STRDXOFF);
+ /* PR 17512: file: 0c680a1f. */
+ if (file_name >= (char *) info->strs + strsize)
+ file_name = NULL;
break;
case N_FUN:
function_name = (char *) str + bfd_get_32 (abfd, stab + STRDXOFF);
if (function_name == (char *) str)
continue;
+ if (function_name >= (char *) info->strs + strsize)
+ function_name = NULL;
nul_fun = NULL;
info->indextable[i].val = bfd_get_32 (abfd, stab + VALOFF);
if (val <= offset)
{
file_name = (char *) str + bfd_get_32 (abfd, stab + STRDXOFF);
+ if (file_name >= (char *) info->strs + strsize)
+ file_name = NULL;
*pline = 0;
}
break;
+2015-01-05 Nick Clifton <nickc@redhat.com>
+
+ PR binutils/17512
+ * nm.c (print_symbol): Add 'is_synthetic' parameter. Use it to
+ help initialize the info.elfinfo field.
+ (print_size_symbols): Add 'synth_count' parameter. Use it to set
+ the is_synthetic parameter when calling print_symbol.
+ (print_symbols): Likewise.
+ (display_rel_file): Pass synth_count to printing function.
+ (display_archive): Break loop if the last archive displayed
+ matches the current archive.
+ * size.c (display_archive): Likewise.
+
2015-01-05 Nick Clifton <nickc@redhat.com>
PR binutils/17531
/* Print a single symbol. */
static void
-print_symbol (bfd *abfd, asymbol *sym, bfd_vma ssize, bfd *archive_bfd)
+print_symbol (bfd * abfd,
+ asymbol * sym,
+ bfd_vma ssize,
+ bfd * archive_bfd,
+ bfd_boolean is_synthetic)
{
symbol_info syminfo;
struct extended_symbol_info info;
format->print_symbol_filename (archive_bfd, abfd);
bfd_get_symbol_info (abfd, sym, &syminfo);
+
info.sinfo = &syminfo;
info.ssize = ssize;
- if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
- info.elfinfo = (elf_symbol_type *) sym;
- else
- info.elfinfo = NULL;
+ /* Synthetic symbols do not have a full elf_symbol_type set of data available. */
+ info.elfinfo = is_synthetic ? NULL : elf_symbol_from (abfd, sym);
+
format->print_symbol_info (&info, abfd);
if (line_numbers)
/* Print the symbols when sorting by size. */
static void
-print_size_symbols (bfd *abfd, bfd_boolean is_dynamic,
- struct size_sym *symsizes, long symcount,
- bfd *archive_bfd)
+print_size_symbols (bfd * abfd,
+ bfd_boolean is_dynamic,
+ struct size_sym * symsizes,
+ long symcount,
+ long synth_count,
+ bfd * archive_bfd)
{
asymbol *store;
- struct size_sym *from, *fromend;
+ struct size_sym *from;
+ struct size_sym *fromend;
+ struct size_sym *fromsynth;
store = bfd_make_empty_symbol (abfd);
if (store == NULL)
from = symsizes;
fromend = from + symcount;
+ fromsynth = symsizes + (symcount - synth_count);
+
for (; from < fromend; from++)
{
asymbol *sym;
if (sym == NULL)
bfd_fatal (bfd_get_filename (abfd));
- print_symbol (abfd, sym, from->size, archive_bfd);
+ print_symbol (abfd, sym, from->size, archive_bfd, from >= fromsynth);
}
}
\f
-/* Print the symbols. If ARCHIVE_BFD is non-NULL, it is the archive
- containing ABFD. */
+/* Print the symbols of ABFD that are held in MINISYMS.
+
+ If ARCHIVE_BFD is non-NULL, it is the archive containing ABFD.
+
+ SYMCOUNT is the number of symbols in MINISYMS and SYNTH_COUNT
+ is the number of these that are synthetic. Synthetic symbols,
+ if any are present, always come at the end of the MINISYMS.
+
+ SIZE is the size of a symbol in MINISYMS. */
static void
-print_symbols (bfd *abfd, bfd_boolean is_dynamic, void *minisyms, long symcount,
- unsigned int size, bfd *archive_bfd)
+print_symbols (bfd * abfd,
+ bfd_boolean is_dynamic,
+ void * minisyms,
+ long symcount,
+ long synth_count,
+ unsigned int size,
+ bfd * archive_bfd)
{
asymbol *store;
- bfd_byte *from, *fromend;
+ bfd_byte *from;
+ bfd_byte *fromend;
+ bfd_byte *fromsynth;
store = bfd_make_empty_symbol (abfd);
if (store == NULL)
from = (bfd_byte *) minisyms;
fromend = from + symcount * size;
+ fromsynth = (bfd_byte *) minisyms + ((symcount - synth_count) * size);
+
for (; from < fromend; from += size)
{
asymbol *sym;
if (sym == NULL)
bfd_fatal (bfd_get_filename (abfd));
- print_symbol (abfd, sym, (bfd_vma) 0, archive_bfd);
+ print_symbol (abfd, sym, (bfd_vma) 0, archive_bfd, from >= fromsynth);
}
}
display_rel_file (bfd *abfd, bfd *archive_bfd)
{
long symcount;
+ long synth_count = 0;
void *minisyms;
unsigned int size;
struct size_sym *symsizes;
non_fatal (_("%s: no symbols"), bfd_get_filename (abfd));
return;
}
-
+
if (show_synthetic && size == sizeof (asymbol *))
{
asymbol *synthsyms;
- long synth_count;
asymbol **static_syms = NULL;
asymbol **dyn_syms = NULL;
long static_count = 0;
bfd_fatal (bfd_get_filename (abfd));
}
}
+
synth_count = bfd_get_synthetic_symtab (abfd, static_count, static_syms,
dyn_count, dyn_syms, &synthsyms);
if (synth_count > 0)
}
if (! sort_by_size)
- print_symbols (abfd, dynamic, minisyms, symcount, size, archive_bfd);
+ print_symbols (abfd, dynamic, minisyms, symcount, synth_count, size, archive_bfd);
else
- print_size_symbols (abfd, dynamic, symsizes, symcount, archive_bfd);
+ print_size_symbols (abfd, dynamic, symsizes, symcount, synth_count, archive_bfd);
free (minisyms);
free (symsizes);
bfd_close (last_arfile);
lineno_cache_bfd = NULL;
lineno_cache_rel_bfd = NULL;
+ if (arfile == last_arfile)
+ return;
}
last_arfile = arfile;
}
print_value (abfd, SYM_SIZE (info));
else
print_value (abfd, SYM_VALUE (info));
-
if (print_size && SYM_SIZE (info))
{
printf (" ");
display_bfd (arfile);
if (last_arfile != NULL)
- bfd_close (last_arfile);
+ {
+ bfd_close (last_arfile);
+
+ /* PR 17512: file: a244edbc. */
+ if (last_arfile == arfile)
+ return;
+ }
+
last_arfile = arfile;
}