X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Fopncls.c;h=c2a1d2fa4df13d649ac6a0c7545766105d800085;hb=refs%2Fheads%2Fconcurrent-displaced-stepping-2020-04-01;hp=8550623dfce024125defeaccb181a4387e5fe6a1;hpb=52b36c51e5bf6d7600fdc6ba115b170b0e78e31d;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/opncls.c b/bfd/opncls.c index 8550623dfc..c2a1d2fa4d 100644 --- a/bfd/opncls.c +++ b/bfd/opncls.c @@ -1,5 +1,5 @@ /* opncls.c -- open and close a BFD. - Copyright (C) 1990-2017 Free Software Foundation, Inc. + Copyright (C) 1990-2020 Free Software Foundation, Inc. Written by Cygnus Support. @@ -84,6 +84,7 @@ _bfd_new_bfd (void) if (!bfd_hash_table_init_n (& nbfd->section_htab, bfd_section_hash_newfunc, sizeof (struct section_hash_entry), 13)) { + objalloc_free ((struct objalloc *) nbfd->memory); free (nbfd); return NULL; } @@ -125,9 +126,9 @@ _bfd_delete_bfd (bfd *abfd) bfd_hash_table_free (&abfd->section_htab); objalloc_free ((struct objalloc *) abfd->memory); } + else + free ((char *) bfd_get_filename (abfd)); - if (abfd->filename) - free ((char *) abfd->filename); free (abfd->arelt_data); free (abfd); } @@ -139,6 +140,29 @@ _bfd_free_cached_info (bfd *abfd) { if (abfd->memory) { + const char *filename = bfd_get_filename (abfd); + if (filename) + { + /* We can't afford to lose the bfd filename when freeing + abfd->memory, because that would kill the cache.c scheme + of closing and reopening files in order to limit the + number of open files. To reopen, you need the filename. + And indeed _bfd_compute_and_write_armap calls + _bfd_free_cached_info to free up space used by symbols + and by check_format_matches. Which we want to continue + doing to handle very large archives. Later the archive + elements are copied, which might require reopening files. + We also want to keep using objalloc memory for the + filename since that allows the name to be updated + without either leaking memory or implementing some sort + of reference counted string for copies of the filename. */ + size_t len = strlen (filename) + 1; + char *copy = bfd_malloc (len); + if (copy == NULL) + return FALSE; + memcpy (copy, filename, len); + abfd->filename = copy; + } bfd_hash_table_free (&abfd->section_htab); objalloc_free ((struct objalloc *) abfd->memory); @@ -167,7 +191,7 @@ FUNCTION SYNOPSIS bfd *bfd_fopen (const char *filename, const char *target, - const char *mode, int fd); + const char *mode, int fd); DESCRIPTION Open the file @var{filename} with the target @var{target}. @@ -223,6 +247,8 @@ bfd_fopen (const char *filename, const char *target, const char *mode, int fd) if (nbfd->iostream == NULL) { bfd_set_error (bfd_error_system_call); + if (fd != -1) + close (fd); _bfd_delete_bfd (nbfd); return NULL; } @@ -231,7 +257,12 @@ bfd_fopen (const char *filename, const char *target, const char *mode, int fd) /* PR 11983: Do not cache the original filename, but rather make a copy - the original might go away. */ - nbfd->filename = xstrdup (filename); + if (!bfd_set_filename (nbfd, filename)) + { + fclose (nbfd->iostream); + _bfd_delete_bfd (nbfd); + return NULL; + } /* Figure out whether the user is opening the file for reading, writing, or both, by looking at the MODE argument. */ @@ -243,8 +274,9 @@ bfd_fopen (const char *filename, const char *target, const char *mode, int fd) else nbfd->direction = write_direction; - if (! bfd_cache_init (nbfd)) + if (!bfd_cache_init (nbfd)) { + fclose (nbfd->iostream); _bfd_delete_bfd (nbfd); return NULL; } @@ -367,7 +399,7 @@ FUNCTION SYNOPSIS bfd *bfd_openstreamr (const char * filename, const char * target, - void * stream); + void * stream); DESCRIPTION Open a BFD for read access on an existing stdio stream. When @@ -398,7 +430,11 @@ bfd_openstreamr (const char *filename, const char *target, void *streamarg) nbfd->iostream = stream; /* PR 11983: Do not cache the original filename, but rather make a copy - the original might go away. */ - nbfd->filename = xstrdup (filename); + if (!bfd_set_filename (nbfd, filename)) + { + _bfd_delete_bfd (nbfd); + return NULL; + } nbfd->direction = read_direction; if (! bfd_cache_init (nbfd)) @@ -415,25 +451,25 @@ FUNCTION bfd_openr_iovec SYNOPSIS - bfd *bfd_openr_iovec (const char *filename, const char *target, - void *(*open_func) (struct bfd *nbfd, - void *open_closure), - void *open_closure, - file_ptr (*pread_func) (struct bfd *nbfd, - void *stream, - void *buf, - file_ptr nbytes, - file_ptr offset), - int (*close_func) (struct bfd *nbfd, - void *stream), + bfd *bfd_openr_iovec (const char *filename, const char *target, + void *(*open_func) (struct bfd *nbfd, + void *open_closure), + void *open_closure, + file_ptr (*pread_func) (struct bfd *nbfd, + void *stream, + void *buf, + file_ptr nbytes, + file_ptr offset), + int (*close_func) (struct bfd *nbfd, + void *stream), int (*stat_func) (struct bfd *abfd, - void *stream, - struct stat *sb)); + void *stream, + struct stat *sb)); DESCRIPTION - Create and return a BFD backed by a read-only @var{stream}. - The @var{stream} is created using @var{open_func}, accessed using - @var{pread_func} and destroyed using @var{close_func}. + Create and return a BFD backed by a read-only @var{stream}. + The @var{stream} is created using @var{open_func}, accessed using + @var{pread_func} and destroyed using @var{close_func}. Calls <>, so @var{target} is interpreted as by that function. @@ -555,8 +591,8 @@ opncls_bmmap (struct bfd *abfd ATTRIBUTE_UNUSED, int prot ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED, file_ptr offset ATTRIBUTE_UNUSED, - void **map_addr ATTRIBUTE_UNUSED, - bfd_size_type *map_len ATTRIBUTE_UNUSED) + void **map_addr ATTRIBUTE_UNUSED, + bfd_size_type *map_len ATTRIBUTE_UNUSED) { return (void *) -1; } @@ -594,7 +630,11 @@ bfd_openr_iovec (const char *filename, const char *target, /* PR 11983: Do not cache the original filename, but rather make a copy - the original might go away. */ - nbfd->filename = xstrdup (filename); + if (!bfd_set_filename (nbfd, filename)) + { + _bfd_delete_bfd (nbfd); + return NULL; + } nbfd->direction = read_direction; /* `open_p (...)' would get expanded by an the open(2) syscall macro. */ @@ -661,7 +701,11 @@ bfd_openw (const char *filename, const char *target) /* PR 11983: Do not cache the original filename, but rather make a copy - the original might go away. */ - nbfd->filename = xstrdup (filename); + if (!bfd_set_filename (nbfd, filename)) + { + _bfd_delete_bfd (nbfd); + return NULL; + } nbfd->direction = write_direction; if (bfd_open_file (nbfd) == NULL) @@ -685,7 +729,7 @@ _maybe_make_executable (bfd * abfd) { struct stat buf; - if (stat (abfd->filename, &buf) == 0 + if (stat (bfd_get_filename (abfd), &buf) == 0 /* Do not attempt to change non-regular files. This is here especially for configure scripts and kernel builds which run tests with "ld [...] -o /dev/null". */ @@ -694,7 +738,7 @@ _maybe_make_executable (bfd * abfd) unsigned int mask = umask (0); umask (mask); - chmod (abfd->filename, + chmod (bfd_get_filename (abfd), (0777 & (buf.st_mode | ((S_IXUSR | S_IXGRP | S_IXOTH) &~ mask)))); } @@ -801,7 +845,11 @@ bfd_create (const char *filename, bfd *templ) return NULL; /* PR 11983: Do not cache the original filename, but rather make a copy - the original might go away. */ - nbfd->filename = xstrdup (filename); + if (!bfd_set_filename (nbfd, filename)) + { + _bfd_delete_bfd (nbfd); + return NULL; + } if (templ) nbfd->xvec = templ->xvec; nbfd->direction = no_direction; @@ -952,32 +1000,6 @@ bfd_alloc (bfd *abfd, bfd_size_type size) return ret; } -/* -INTERNAL_FUNCTION - bfd_alloc2 - -SYNOPSIS - void *bfd_alloc2 (bfd *abfd, bfd_size_type nmemb, bfd_size_type size); - -DESCRIPTION - Allocate a block of @var{nmemb} elements of @var{size} bytes each - of memory attached to <> and return a pointer to it. -*/ - -void * -bfd_alloc2 (bfd *abfd, bfd_size_type nmemb, bfd_size_type size) -{ - if ((nmemb | size) >= HALF_BFD_SIZE_TYPE - && size != 0 - && nmemb > ~(bfd_size_type) 0 / size) - { - bfd_set_error (bfd_error_no_memory); - return NULL; - } - - return bfd_alloc (abfd, size * nmemb); -} - /* FUNCTION bfd_zalloc @@ -1001,39 +1023,6 @@ bfd_zalloc (bfd *abfd, bfd_size_type size) return res; } -/* -INTERNAL_FUNCTION - bfd_zalloc2 - -SYNOPSIS - void *bfd_zalloc2 (bfd *abfd, bfd_size_type nmemb, bfd_size_type size); - -DESCRIPTION - Allocate a block of @var{nmemb} elements of @var{size} bytes each - of zeroed memory attached to <> and return a pointer to it. -*/ - -void * -bfd_zalloc2 (bfd *abfd, bfd_size_type nmemb, bfd_size_type size) -{ - void *res; - - if ((nmemb | size) >= HALF_BFD_SIZE_TYPE - && size != 0 - && nmemb > ~(bfd_size_type) 0 / size) - { - bfd_set_error (bfd_error_no_memory); - return NULL; - } - - size *= nmemb; - - res = bfd_alloc (abfd, size); - if (res) - memset (res, 0, (size_t) size); - return res; -} - /* Free a block allocated for a BFD. Note: Also frees all more recently allocated blocks! */ @@ -1179,6 +1168,8 @@ bfd_get_debug_link_info_1 (bfd *abfd, void *crc32_out) bfd_byte *contents; unsigned int crc_offset; char *name; + bfd_size_type size; + ufile_ptr file_size; BFD_ASSERT (abfd); BFD_ASSERT (crc32_out); @@ -1188,19 +1179,25 @@ bfd_get_debug_link_info_1 (bfd *abfd, void *crc32_out) if (sect == NULL) return NULL; + size = bfd_section_size (sect); + file_size = bfd_get_size (abfd); + + /* PR 22794: Make sure that the section has a reasonable size. */ + if (size < 8 || (file_size != 0 && size >= file_size)) + return NULL; + if (!bfd_malloc_and_get_section (abfd, sect, &contents)) { - if (contents != NULL) - free (contents); + free (contents); return NULL; } /* CRC value is stored after the filename, aligned up to 4 bytes. */ name = (char *) contents; - /* PR 17597: avoid reading off the end of the buffer. */ - crc_offset = strnlen (name, bfd_get_section_size (sect)) + 1; + /* PR 17597: Avoid reading off the end of the buffer. */ + crc_offset = strnlen (name, size) + 1; crc_offset = (crc_offset + 3) & ~3; - if (crc_offset + 4 > bfd_get_section_size (sect)) + if (crc_offset + 4 > size) return NULL; *crc32 = bfd_get_32 (abfd, contents + crc_offset); @@ -1242,7 +1239,7 @@ FUNCTION SYNOPSIS char *bfd_get_alt_debug_link_info (bfd * abfd, bfd_size_type *buildid_len, - bfd_byte **buildid_out); + bfd_byte **buildid_out); DESCRIPTION Fetch the filename and BuildID value for any alternate debuginfo @@ -1261,6 +1258,8 @@ bfd_get_alt_debug_link_info (bfd * abfd, bfd_size_type *buildid_len, bfd_byte *contents; unsigned int buildid_offset; char *name; + bfd_size_type size; + ufile_ptr file_size; BFD_ASSERT (abfd); BFD_ASSERT (buildid_len); @@ -1271,20 +1270,24 @@ bfd_get_alt_debug_link_info (bfd * abfd, bfd_size_type *buildid_len, if (sect == NULL) return NULL; + size = bfd_section_size (sect); + file_size = bfd_get_size (abfd); + if (size < 8 || (file_size != 0 && size >= file_size)) + return NULL; + if (!bfd_malloc_and_get_section (abfd, sect, & contents)) { - if (contents != NULL) - free (contents); + free (contents); return NULL; } /* BuildID value is stored after the filename. */ name = (char *) contents; - buildid_offset = strnlen (name, bfd_get_section_size (sect)) + 1; - if (buildid_offset >= bfd_get_section_size (sect)) + buildid_offset = strnlen (name, size) + 1; + if (buildid_offset >= bfd_section_size (sect)) return NULL; - *buildid_len = bfd_get_section_size (sect) - buildid_offset; + *buildid_len = size - buildid_offset; *buildid_out = bfd_malloc (*buildid_len); memcpy (*buildid_out, contents + buildid_offset, *buildid_len); @@ -1395,12 +1398,12 @@ typedef char * (* get_func_type) (bfd *, void *); typedef bfd_boolean (* check_func_type) (const char *, void *); static char * -find_separate_debug_file (bfd * abfd, - const char * debug_file_directory, - bfd_boolean include_dirs, - get_func_type get_func, +find_separate_debug_file (bfd * abfd, + const char * debug_file_directory, + bfd_boolean include_dirs, + get_func_type get_func, check_func_type check_func, - void * func_data) + void * func_data) { char *base; char *dir; @@ -1414,7 +1417,7 @@ find_separate_debug_file (bfd * abfd, debug_file_directory = "."; /* BFD may have been opened from a stream. */ - if (abfd->filename == NULL) + if (bfd_get_filename (abfd) == NULL) { bfd_set_error (bfd_error_invalid_operation); return NULL; @@ -1434,8 +1437,9 @@ find_separate_debug_file (bfd * abfd, if (include_dirs) { - for (dirlen = strlen (abfd->filename); dirlen > 0; dirlen--) - if (IS_DIR_SEPARATOR (abfd->filename[dirlen - 1])) + const char *fname = bfd_get_filename (abfd); + for (dirlen = strlen (fname); dirlen > 0; dirlen--) + if (IS_DIR_SEPARATOR (fname[dirlen - 1])) break; dir = (char *) bfd_malloc (dirlen + 1); @@ -1444,7 +1448,7 @@ find_separate_debug_file (bfd * abfd, free (base); return NULL; } - memcpy (dir, abfd->filename, dirlen); + memcpy (dir, fname, dirlen); dir[dirlen] = '\0'; } else @@ -1456,7 +1460,7 @@ find_separate_debug_file (bfd * abfd, /* Compute the canonical name of the bfd object with all symbolic links resolved, for use in the global debugfile directory. */ - canon_dir = lrealpath (abfd->filename); + canon_dir = lrealpath (bfd_get_filename (abfd)); for (canon_dirlen = strlen (canon_dir); canon_dirlen > 0; canon_dirlen--) if (IS_DIR_SEPARATOR (canon_dir[canon_dirlen - 1])) break; @@ -1471,16 +1475,16 @@ find_separate_debug_file (bfd * abfd, debugfile = (char *) bfd_malloc (strlen (debug_file_directory) + 1 - + (canon_dirlen > dirlen ? canon_dirlen : dirlen) - + strlen (".debug/") + + (canon_dirlen > dirlen ? canon_dirlen : dirlen) + + strlen (".debug/") #ifdef EXTRA_DEBUG_ROOT1 + strlen (EXTRA_DEBUG_ROOT1) #endif #ifdef EXTRA_DEBUG_ROOT2 + strlen (EXTRA_DEBUG_ROOT2) #endif - + strlen (base) - + 1); + + strlen (base) + + 1); if (debugfile == NULL) goto found; /* Actually this returns NULL. */ @@ -1686,14 +1690,14 @@ bfd_create_gnu_debuglink_section (bfd *abfd, const char *filename) debuglink_size &= ~3; debuglink_size += 4; - if (! bfd_set_section_size (abfd, sect, debuglink_size)) + if (!bfd_set_section_size (sect, debuglink_size)) /* XXX Should we delete the section from the bfd ? */ return NULL; /* PR 21193: Ensure that the section has 4-byte alignment for the CRC. Note - despite the name of the function being called, we are setting an alignment power, not a byte alignment value. */ - bfd_set_section_alignment (abfd, sect, 2); + bfd_set_section_alignment (sect, 2); return sect; } @@ -1831,7 +1835,7 @@ get_build_id (bfd *abfd) return NULL; } - size = bfd_get_section_size (sect); + size = bfd_section_size (sect); /* FIXME: Should we support smaller build-id notes ? */ if (size < 0x24) { @@ -1841,15 +1845,14 @@ get_build_id (bfd *abfd) if (!bfd_malloc_and_get_section (abfd, sect, & contents)) { - if (contents != NULL) - free (contents); + free (contents); return NULL; } /* FIXME: Paranoia - allow for compressed build-id sections. Maybe we should complain if this size is different from the one obtained above... */ - size = bfd_get_section_size (sect); + size = bfd_section_size (sect); if (size < sizeof (Elf_External_Note)) { bfd_set_error (bfd_error_invalid_operation); @@ -1865,10 +1868,11 @@ get_build_id (bfd *abfd) inote.descdata = inote.namedata + BFD_ALIGN (inote.namesz, 4); /* FIXME: Should we check for extra notes in this section ? */ - if (inote.descsz == 0 + if (inote.descsz <= 0 || inote.type != NT_GNU_BUILD_ID || inote.namesz != 4 /* sizeof "GNU" */ || strncmp (inote.namedata, "GNU", 4) != 0 + || inote.descsz > 0x7ffffffe || size < (12 + BFD_ALIGN (inote.namesz, 4) + inote.descsz)) { free (contents); @@ -1922,7 +1926,7 @@ get_build_id_name (bfd *abfd, void *build_id_out_p) bfd_size_type s; bfd_byte *d; - if (abfd == NULL || abfd->filename == NULL || build_id_out == NULL) + if (abfd == NULL || bfd_get_filename (abfd) == NULL || build_id_out == NULL) { bfd_set_error (bfd_error_invalid_operation); return NULL; @@ -2047,3 +2051,29 @@ bfd_follow_build_id_debuglink (bfd *abfd, const char *dir) get_build_id_name, check_build_id_file, &build_id); } + +/* +FUNCTION + bfd_set_filename + +SYNOPSIS + const char *bfd_set_filename (bfd *abfd, const char *filename); + +DESCRIPTION + Set the filename of @var{abfd}, copying the FILENAME parameter to + bfd_alloc'd memory owned by @var{abfd}. Returns a pointer the + newly allocated name, or NULL if the allocation failed. +*/ + +const char * +bfd_set_filename (bfd *abfd, const char *filename) +{ + size_t len = strlen (filename) + 1; + char *n = bfd_alloc (abfd, len); + if (n) + { + memcpy (n, filename, len); + abfd->filename = n; + } + return n; +}