X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Fpdp11.c;h=d41aefca2b2f5c8e15e6f842700f8874fbda48f8;hb=refs%2Fheads%2Fconcurrent-displaced-stepping-2020-04-01;hp=4555b36d274cf5d228e8b06e3eefb3416d4a4f63;hpb=765cf5f623dbc2de8c8791bce9a29fcc3492436c;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/pdp11.c b/bfd/pdp11.c index 4555b36d27..d41aefca2b 100644 --- a/bfd/pdp11.c +++ b/bfd/pdp11.c @@ -255,6 +255,7 @@ reloc_howto_type howto_table_pdp11[] = /* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone */ HOWTO( 0, 0, 1, 16, FALSE, 0, complain_overflow_signed,0,"16", TRUE, 0x0000ffff,0x0000ffff, FALSE), HOWTO( 1, 0, 1, 16, TRUE, 0, complain_overflow_signed,0,"DISP16", TRUE, 0x0000ffff,0x0000ffff, FALSE), +HOWTO( 2, 0, 2, 32, FALSE, 0, complain_overflow_signed,0,"32", TRUE, 0x0000ffff,0x0000ffff, FALSE), }; #define TABLE_SIZE(TABLE) (sizeof(TABLE)/sizeof(TABLE[0])) @@ -276,6 +277,8 @@ NAME (aout, reloc_type_lookup) (bfd * abfd ATTRIBUTE_UNUSED, return &howto_table_pdp11[0]; case BFD_RELOC_16_PCREL: return &howto_table_pdp11[1]; + case BFD_RELOC_32: + return &howto_table_pdp11[2]; default: return NULL; } @@ -620,8 +623,11 @@ NAME (aout, some_aout_object_p) (bfd *abfd, sets the entry point, and that is likely to be non-zero for most systems. */ if (execp->a_entry != 0 - || (execp->a_entry >= obj_textsec(abfd)->vma - && execp->a_entry < obj_textsec(abfd)->vma + obj_textsec(abfd)->size)) + || (execp->a_entry >= obj_textsec (abfd)->vma + && execp->a_entry < (obj_textsec (abfd)->vma + + obj_textsec (abfd)->size) + && execp->a_trsize == 0 + && execp->a_drsize == 0)) abfd->flags |= EXEC_P; #ifdef STAT_FOR_EXEC else @@ -1238,7 +1244,7 @@ aout_get_external_symbols (bfd *abfd) syms = (struct external_nlist *) _bfd_malloc_and_read (abfd, count * EXTERNAL_NLIST_SIZE, count * EXTERNAL_NLIST_SIZE); - if (syms == NULL && count != 0) + if (syms == NULL) return FALSE; #endif @@ -1252,36 +1258,54 @@ aout_get_external_symbols (bfd *abfd) unsigned char string_chars[BYTES_IN_LONG]; bfd_size_type stringsize; char *strings; + bfd_size_type amt = BYTES_IN_LONG; /* Get the size of the strings. */ if (bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET) != 0 - || (bfd_bread ((void *) string_chars, (bfd_size_type) BYTES_IN_LONG, - abfd) != BYTES_IN_LONG)) + || bfd_bread ((void *) string_chars, amt, abfd) != amt) return FALSE; stringsize = H_GET_32 (abfd, string_chars); + if (stringsize == 0) + stringsize = 1; + else if (stringsize < BYTES_IN_LONG + || (size_t) stringsize != stringsize) + { + bfd_set_error (bfd_error_bad_value); + return FALSE; + } #ifdef USE_MMAP - if (! bfd_get_file_window (abfd, obj_str_filepos (abfd), stringsize, - &obj_aout_string_window (abfd), TRUE)) - return FALSE; - strings = (char *) obj_aout_string_window (abfd).data; -#else - strings = bfd_malloc (stringsize + 1); - if (strings == NULL) - return FALSE; - - /* Skip space for the string count in the buffer for convenience - when using indexes. */ - if (bfd_bread (strings + 4, stringsize - 4, abfd) != stringsize - 4) + if (stringsize >= BYTES_IN_LONG) { - free (strings); - return FALSE; + if (! bfd_get_file_window (abfd, obj_str_filepos (abfd), stringsize + 1, + &obj_aout_string_window (abfd), TRUE)) + return FALSE; + strings = (char *) obj_aout_string_window (abfd).data; } + else #endif + { + strings = (char *) bfd_malloc (stringsize + 1); + if (strings == NULL) + return FALSE; + + if (stringsize >= BYTES_IN_LONG) + { + /* Keep the string count in the buffer for convenience + when indexing with e_strx. */ + amt = stringsize - BYTES_IN_LONG; + if (bfd_bread (strings + BYTES_IN_LONG, amt, abfd) != amt) + { + free (strings); + return FALSE; + } + } + } /* Ensure that a zero index yields an empty string. */ strings[0] = '\0'; - strings[stringsize - 1] = 0; + /* Ensure that the string buffer is NUL terminated. */ + strings[stringsize] = 0; obj_aout_external_strings (abfd) = strings; obj_aout_external_string_size (abfd) = stringsize; @@ -1501,7 +1525,13 @@ NAME (aout, translate_symbol_table) (bfd *abfd, else if (x < strsize) in->symbol.name = str + x; else - return FALSE; + { + _bfd_error_handler + (_("%pB: invalid string offset %" PRIu64 " >= %" PRIu64), + abfd, (uint64_t) x, (uint64_t) strsize); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } in->symbol.value = GET_WORD (abfd, ext->e_value); /* TODO: is 0 a safe value here? */ @@ -1593,7 +1623,7 @@ NAME (aout, slurp_symbol_table) (bfd *abfd) /* Get the index of a string in a strtab, adding it if it is not already present. */ -static INLINE bfd_size_type +static inline bfd_size_type add_to_stringtab (bfd *abfd, struct bfd_strtab_hash *tab, const char *str, @@ -1831,10 +1861,12 @@ pdp11_aout_swap_reloc_in (bfd * abfd, local or global. */ r_extern = (reloc_entry & RTYPE) == REXT; - if (r_extern && r_index > symcount) + if (r_extern && r_index >= symcount) { /* We could arrange to return an error, but it might be useful - to see the file even if it is bad. */ + to see the file even if it is bad. FIXME: Of course this + means that objdump -r *doesn't* see the actual reloc, and + objcopy silently writes a different reloc. */ r_extern = 0; r_index = N_ABS; } @@ -1957,6 +1989,15 @@ NAME (aout, squirt_out_relocs) (bfd *abfd, asection *section) { bfd_byte *r; + if ((*generic)->howto == NULL + || (*generic)->sym_ptr_ptr == NULL) + { + bfd_set_error (bfd_error_invalid_operation); + _bfd_error_handler (_("%pB: attempt to write out " + "unknown reloc type"), abfd); + bfd_release (abfd, native); + return FALSE; + } r = native + (*generic)->address; pdp11_aout_swap_reloc_out (abfd, *generic, r); count--; @@ -2226,7 +2267,7 @@ NAME (aout, find_nearest_line) (bfd *abfd, char *buf; *filename_ptr = bfd_get_filename (abfd); - *functionname_ptr = 0; + *functionname_ptr = NULL; *line_ptr = 0; if (discriminator_ptr) *discriminator_ptr = 0; @@ -2254,7 +2295,10 @@ NAME (aout, find_nearest_line) (bfd *abfd, const char * symname; symname = q->symbol.name; - if (strcmp (symname + strlen (symname) - 2, ".o") == 0) + + if (symname != NULL + && strlen (symname) > 2 + && strcmp (symname + strlen (symname) - 2, ".o") == 0) { if (q->symbol.value > low_line_vma) { @@ -2286,7 +2330,7 @@ NAME (aout, find_nearest_line) (bfd *abfd, /* Look ahead to next symbol to check if that too is an N_SO. */ p++; if (*p == NULL) - break; + goto done; q = (aout_symbol_type *)(*p); if (q->type != (int) N_SO) goto next; @@ -2347,8 +2391,7 @@ NAME (aout, find_nearest_line) (bfd *abfd, else funclen = strlen (bfd_asymbol_name (func)); - if (adata (abfd).line_buf != NULL) - free (adata (abfd).line_buf); + free (adata (abfd).line_buf); if (filelen + funclen == 0) adata (abfd).line_buf = buf = NULL; else @@ -2365,9 +2408,17 @@ NAME (aout, find_nearest_line) (bfd *abfd, *filename_ptr = main_file_name; else { - sprintf (buf, "%s%s", directory_name, main_file_name); - *filename_ptr = buf; - buf += filelen + 1; + if (buf == NULL) + /* PR binutils/20891: In a corrupt input file both + main_file_name and directory_name can be empty... */ + * filename_ptr = NULL; + else + { + snprintf (buf, filelen + 1, "%s%s", directory_name, + main_file_name); + *filename_ptr = buf; + buf += filelen + 1; + } } } @@ -2376,6 +2427,12 @@ NAME (aout, find_nearest_line) (bfd *abfd, const char *function = func->name; char *colon; + if (buf == NULL) + { + /* PR binutils/20892: In a corrupt input file func can be empty. */ + * functionname_ptr = NULL; + return TRUE; + } /* The caller expects a symbol name. We actually have a function name, without the leading underscore. Put the underscore back in, so that the caller gets a symbol name. */ @@ -2415,7 +2472,7 @@ NAME (aout, bfd_free_cached_info) (bfd *abfd) if (bfd_get_format (abfd) != bfd_object) return TRUE; -#define BFCI_FREE(x) if (x != NULL) { free (x); x = NULL; } +#define BFCI_FREE(x) do { free (x); x = NULL; } while (0) BFCI_FREE (obj_aout_symbols (abfd)); #ifdef USE_MMAP @@ -2806,6 +2863,9 @@ aout_link_add_symbols (bfd *abfd, struct bfd_link_info *info) type = H_GET_8 (abfd, p->e_type); + /* PR 19629: Corrupt binaries can contain illegal string offsets. */ + if (GET_WORD (abfd, p->e_strx) >= obj_aout_external_string_size (abfd)) + return FALSE; name = strings + GET_WORD (abfd, p->e_strx); value = GET_WORD (abfd, p->e_value); flags = BSF_GLOBAL; @@ -2918,6 +2978,9 @@ aout_link_includes_newfunc (struct bfd_hash_entry *entry, return (struct bfd_hash_entry *) ret; } +/* Write out a symbol that was not associated with an a.out input + object. */ + static bfd_boolean aout_link_write_other_symbol (struct bfd_hash_entry *bh, void *data) { @@ -3302,8 +3365,15 @@ pdp11_aout_link_input_section (struct aout_final_link_info *flaginfo, r_extern = (r_type == REXT); howto_idx = r_pcrel; - BFD_ASSERT (howto_idx < TABLE_SIZE (howto_table_pdp11)); - howto = howto_table_pdp11 + howto_idx; + if (howto_idx < TABLE_SIZE (howto_table_pdp11)) + howto = howto_table_pdp11 + howto_idx; + else + { + _bfd_error_handler (_("%pB: unsupported relocation type"), + input_bfd); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } } if (relocatable) @@ -3914,26 +3984,14 @@ NAME (aout, final_link) (bfd *abfd, } } - if (aout_info.contents != NULL) - { - free (aout_info.contents); - aout_info.contents = NULL; - } - if (aout_info.relocs != NULL) - { - free (aout_info.relocs); - aout_info.relocs = NULL; - } - if (aout_info.symbol_map != NULL) - { - free (aout_info.symbol_map); - aout_info.symbol_map = NULL; - } - if (aout_info.output_syms != NULL) - { - free (aout_info.output_syms); - aout_info.output_syms = NULL; - } + free (aout_info.contents); + aout_info.contents = NULL; + free (aout_info.relocs); + aout_info.relocs = NULL; + free (aout_info.symbol_map); + aout_info.symbol_map = NULL; + free (aout_info.output_syms); + aout_info.output_syms = NULL; if (includes_hash_initialized) { bfd_hash_table_free (&aout_info.includes.root); @@ -3993,14 +4051,10 @@ NAME (aout, final_link) (bfd *abfd, return TRUE; error_return: - if (aout_info.contents != NULL) - free (aout_info.contents); - if (aout_info.relocs != NULL) - free (aout_info.relocs); - if (aout_info.symbol_map != NULL) - free (aout_info.symbol_map); - if (aout_info.output_syms != NULL) - free (aout_info.output_syms); + free (aout_info.contents); + free (aout_info.relocs); + free (aout_info.symbol_map); + free (aout_info.output_syms); if (includes_hash_initialized) bfd_hash_table_free (&aout_info.includes.root); return FALSE;