mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-11-16 12:34:43 +00:00
ecoff find_nearest_line and final link leaks
Freeing ecoff_debug_info "pointers to the unswapped symbolic info" isn't a simple matter, due to differing allocation strategies. In _bfd_ecoff_slurp_symbolic_info the pointers are to objalloc memory. In the ecoff linker they are to separately malloc'd memory. In gas we have most (obj-elf) or all (obj-ecoff) into a single malloc'd buffer. This patch fixes the leaks for binutils and ld, leaving the gas leaks for another day. The mips elf backend already had this covered, and the ecoff backend had a pointer, raw_syments used as a flag, so most of the patch is moving these around a little so they are accessible for both ecoff and elf. include/ * coff/ecoff.h (struct ecoff_debug_info): Add alloc_syments. bfd/ * libecoff.h (struct ecoff_tdata): Delete raw_syments. * elfxx-mips.c (free_ecoff_debug): Delete. Replace uses with _bfd_ecoff_free_ecoff_debug_info. (_bfd_mips_elf_final_link): Init debug.alloc_syments. * ecofflink.c (_bfd_ecoff_free_ecoff_debug_info): New function. * ecoff.c (_bfd_ecoff_bfd_free_cached_info): Call _bfd_ecoff_free_ecoff_debug_info. (_bfd_ecoff_slurp_symbolic_info): Replace uses of raw_syments with alloc_syments. (ecoff_final_link_debug_accumulate): Likewise. Use _bfd_ecoff_free_ecoff_debug_info. (_bfd_ecoff_bfd_copy_private_bfd_data): Set alloc_syments for copied output. * elf64-alpha.c (elf64_alpha_read_ecoff_info): Use _bfd_ecoff_free_ecoff_debug_info. * libbfd-in.h (_bfd_ecoff_free_ecoff_debug_info): Declare. * libbfd.h: Regenerate. gas/ * config/obj-ecoff.c (ecoff_frob_file): Set alloc_syments. * config/obj-elf.c (elf_frob_file_after_relocs): Likewise.
This commit is contained in:
52
bfd/ecoff.c
52
bfd/ecoff.c
@@ -117,12 +117,15 @@ _bfd_ecoff_bfd_free_cached_info (bfd *abfd)
|
||||
if ((bfd_get_format (abfd) == bfd_object
|
||||
|| bfd_get_format (abfd) == bfd_core)
|
||||
&& (tdata = ecoff_data (abfd)) != NULL)
|
||||
while (tdata->mips_refhi_list != NULL)
|
||||
{
|
||||
struct mips_hi *ref = tdata->mips_refhi_list;
|
||||
tdata->mips_refhi_list = ref->next;
|
||||
free (ref);
|
||||
}
|
||||
{
|
||||
while (tdata->mips_refhi_list != NULL)
|
||||
{
|
||||
struct mips_hi *ref = tdata->mips_refhi_list;
|
||||
tdata->mips_refhi_list = ref->next;
|
||||
free (ref);
|
||||
}
|
||||
_bfd_ecoff_free_ecoff_debug_info (&tdata->debug_info);
|
||||
}
|
||||
return _bfd_generic_bfd_free_cached_info (abfd);
|
||||
}
|
||||
|
||||
@@ -524,7 +527,7 @@ _bfd_ecoff_slurp_symbolic_info (bfd *abfd,
|
||||
|
||||
/* Check whether we've already gotten it, and whether there's any to
|
||||
get. */
|
||||
if (ecoff_data (abfd)->raw_syments != NULL)
|
||||
if (debug->alloc_syments)
|
||||
return true;
|
||||
if (ecoff_data (abfd)->sym_filepos == 0)
|
||||
{
|
||||
@@ -595,7 +598,7 @@ _bfd_ecoff_slurp_symbolic_info (bfd *abfd,
|
||||
if (raw == NULL)
|
||||
return false;
|
||||
|
||||
ecoff_data (abfd)->raw_syments = raw;
|
||||
debug->alloc_syments = true;
|
||||
|
||||
/* Get pointers for the numeric offsets in the HDRR structure. */
|
||||
#define FIX(start, count, ptr, type) \
|
||||
@@ -1918,6 +1921,9 @@ _bfd_ecoff_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
|
||||
|
||||
oinfo->symbolic_header.crfd = iinfo->symbolic_header.crfd;
|
||||
oinfo->external_rfd = iinfo->external_rfd;
|
||||
|
||||
/* Flag that oinfo entries should not be freed. */
|
||||
oinfo->alloc_syments = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3809,9 +3815,9 @@ ecoff_final_link_debug_accumulate (bfd *output_bfd,
|
||||
((char *) debug->ptr)[amt] = 0; \
|
||||
} while (0)
|
||||
|
||||
/* If raw_syments is not NULL, then the data was already by read by
|
||||
/* If alloc_syments is true, then the data was already by read by
|
||||
_bfd_ecoff_slurp_symbolic_info. */
|
||||
if (ecoff_data (input_bfd)->raw_syments == NULL)
|
||||
if (!debug->alloc_syments)
|
||||
{
|
||||
READ (line, cbLineOffset, cbLine, sizeof (unsigned char));
|
||||
READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size);
|
||||
@@ -3833,31 +3839,7 @@ ecoff_final_link_debug_accumulate (bfd *output_bfd,
|
||||
input_bfd, debug, swap, info));
|
||||
|
||||
return_something:
|
||||
if (ecoff_data (input_bfd)->raw_syments == NULL)
|
||||
{
|
||||
free (debug->line);
|
||||
free (debug->external_dnr);
|
||||
free (debug->external_pdr);
|
||||
free (debug->external_sym);
|
||||
free (debug->external_opt);
|
||||
free (debug->external_aux);
|
||||
free (debug->ss);
|
||||
free (debug->external_fdr);
|
||||
free (debug->external_rfd);
|
||||
|
||||
/* Make sure we don't accidentally follow one of these pointers
|
||||
into freed memory. */
|
||||
debug->line = NULL;
|
||||
debug->external_dnr = NULL;
|
||||
debug->external_pdr = NULL;
|
||||
debug->external_sym = NULL;
|
||||
debug->external_opt = NULL;
|
||||
debug->external_aux = NULL;
|
||||
debug->ss = NULL;
|
||||
debug->external_fdr = NULL;
|
||||
debug->external_rfd = NULL;
|
||||
}
|
||||
|
||||
_bfd_ecoff_free_ecoff_debug_info (debug);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -1696,6 +1696,38 @@ bfd_ecoff_write_accumulated_debug (void * handle,
|
||||
/* Handle the find_nearest_line function for both ECOFF and MIPS ELF
|
||||
files. */
|
||||
|
||||
/* Free ECOFF debugging info used by find_nearest_line. */
|
||||
|
||||
void
|
||||
_bfd_ecoff_free_ecoff_debug_info (struct ecoff_debug_info *debug)
|
||||
{
|
||||
if (!debug->alloc_syments)
|
||||
{
|
||||
free (debug->line);
|
||||
free (debug->external_dnr);
|
||||
free (debug->external_pdr);
|
||||
free (debug->external_sym);
|
||||
free (debug->external_opt);
|
||||
free (debug->external_aux);
|
||||
free (debug->ss);
|
||||
free (debug->ssext);
|
||||
free (debug->external_fdr);
|
||||
free (debug->external_rfd);
|
||||
free (debug->external_ext);
|
||||
}
|
||||
debug->line= NULL;
|
||||
debug->external_dnr= NULL;
|
||||
debug->external_pdr= NULL;
|
||||
debug->external_sym= NULL;
|
||||
debug->external_opt= NULL;
|
||||
debug->external_aux= NULL;
|
||||
debug->ss= NULL;
|
||||
debug->ssext= NULL;
|
||||
debug->external_fdr= NULL;
|
||||
debug->external_rfd= NULL;
|
||||
debug->external_ext= NULL;
|
||||
}
|
||||
|
||||
/* Compare FDR entries. This is called via qsort. */
|
||||
|
||||
static int
|
||||
|
||||
@@ -1425,17 +1425,7 @@ elf64_alpha_read_ecoff_info (bfd *abfd, asection *section,
|
||||
|
||||
error_return:
|
||||
free (ext_hdr);
|
||||
free (debug->line);
|
||||
free (debug->external_dnr);
|
||||
free (debug->external_pdr);
|
||||
free (debug->external_sym);
|
||||
free (debug->external_opt);
|
||||
free (debug->external_aux);
|
||||
free (debug->ss);
|
||||
free (debug->ssext);
|
||||
free (debug->external_fdr);
|
||||
free (debug->external_rfd);
|
||||
free (debug->external_ext);
|
||||
_bfd_ecoff_free_ecoff_debug_info (debug);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1389,35 +1389,6 @@ struct mips_elf_find_line
|
||||
struct ecoff_find_line i;
|
||||
};
|
||||
|
||||
/* Free ECOFF debugging info used by find_nearest_line. */
|
||||
|
||||
static void
|
||||
free_ecoff_debug (struct ecoff_debug_info *debug)
|
||||
{
|
||||
free (debug->line);
|
||||
free (debug->external_dnr);
|
||||
free (debug->external_pdr);
|
||||
free (debug->external_sym);
|
||||
free (debug->external_opt);
|
||||
free (debug->external_aux);
|
||||
free (debug->ss);
|
||||
free (debug->ssext);
|
||||
free (debug->external_fdr);
|
||||
free (debug->external_rfd);
|
||||
free (debug->external_ext);
|
||||
debug->line = NULL;
|
||||
debug->external_dnr = NULL;
|
||||
debug->external_pdr = NULL;
|
||||
debug->external_sym = NULL;
|
||||
debug->external_opt = NULL;
|
||||
debug->external_aux = NULL;
|
||||
debug->ss = NULL;
|
||||
debug->ssext = NULL;
|
||||
debug->external_fdr = NULL;
|
||||
debug->external_rfd = NULL;
|
||||
debug->external_ext = NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
_bfd_mips_elf_free_cached_info (bfd *abfd)
|
||||
{
|
||||
@@ -1435,7 +1406,7 @@ _bfd_mips_elf_free_cached_info (bfd *abfd)
|
||||
free (hi);
|
||||
}
|
||||
if (tdata->find_line_info != NULL)
|
||||
free_ecoff_debug (&tdata->find_line_info->d);
|
||||
_bfd_ecoff_free_ecoff_debug_info (&tdata->find_line_info->d);
|
||||
}
|
||||
return _bfd_elf_free_cached_info (abfd);
|
||||
}
|
||||
@@ -1523,7 +1494,7 @@ _bfd_mips_elf_read_ecoff_info (bfd *abfd, asection *section,
|
||||
|
||||
error_return:
|
||||
free (ext_hdr);
|
||||
free_ecoff_debug (debug);
|
||||
_bfd_ecoff_free_ecoff_debug_info (debug);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -13225,7 +13196,7 @@ _bfd_mips_elf_find_nearest_line (bfd *abfd, asymbol **symbols,
|
||||
fi->d.fdr = bfd_alloc (abfd, amt);
|
||||
if (fi->d.fdr == NULL)
|
||||
{
|
||||
free_ecoff_debug (&fi->d);
|
||||
_bfd_ecoff_free_ecoff_debug_info (&fi->d);
|
||||
msec->flags = origflags;
|
||||
return false;
|
||||
}
|
||||
@@ -15043,6 +15014,7 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
|
||||
|
||||
/* We accumulate the debugging information itself in the
|
||||
debug_info structure. */
|
||||
debug.alloc_syments = false;
|
||||
debug.line = NULL;
|
||||
debug.external_dnr = NULL;
|
||||
debug.external_pdr = NULL;
|
||||
@@ -15128,7 +15100,7 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
|
||||
(mdebug_handle, abfd, &debug, swap, input_bfd,
|
||||
&input_debug, input_swap, info)))
|
||||
{
|
||||
free_ecoff_debug (&input_debug);
|
||||
_bfd_ecoff_free_ecoff_debug_info (&input_debug);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -15171,7 +15143,7 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
|
||||
}
|
||||
|
||||
/* Free up the information we just read. */
|
||||
free_ecoff_debug (&input_debug);
|
||||
_bfd_ecoff_free_ecoff_debug_info (&input_debug);
|
||||
|
||||
/* Hack: reset the SEC_HAS_CONTENTS flag so that
|
||||
elf_link_input_bfd ignores this section. */
|
||||
|
||||
@@ -787,6 +787,8 @@ struct ecoff_debug_swap;
|
||||
struct ecoff_extr;
|
||||
struct ecoff_find_line;
|
||||
|
||||
extern void _bfd_ecoff_free_ecoff_debug_info
|
||||
(struct ecoff_debug_info *debug);
|
||||
extern bool _bfd_ecoff_locate_line
|
||||
(bfd *, asection *, bfd_vma, struct ecoff_debug_info * const,
|
||||
const struct ecoff_debug_swap * const, struct ecoff_find_line *,
|
||||
|
||||
@@ -793,6 +793,8 @@ struct ecoff_debug_swap;
|
||||
struct ecoff_extr;
|
||||
struct ecoff_find_line;
|
||||
|
||||
extern void _bfd_ecoff_free_ecoff_debug_info
|
||||
(struct ecoff_debug_info *debug);
|
||||
extern bool _bfd_ecoff_locate_line
|
||||
(bfd *, asection *, bfd_vma, struct ecoff_debug_info * const,
|
||||
const struct ecoff_debug_swap * const, struct ecoff_find_line *,
|
||||
|
||||
@@ -124,9 +124,6 @@ typedef struct ecoff_tdata
|
||||
/* The ECOFF symbolic debugging information. */
|
||||
struct ecoff_debug_info debug_info;
|
||||
|
||||
/* The unswapped ECOFF symbolic information. */
|
||||
void * raw_syments;
|
||||
|
||||
/* The canonical BFD symbols. */
|
||||
struct ecoff_symbol_struct *canonical_symbols;
|
||||
|
||||
|
||||
@@ -151,6 +151,7 @@ ecoff_frob_file (void)
|
||||
ecoff_build_debug (hdr, &buf, debug_swap);
|
||||
|
||||
/* Finish up the ecoff_tdata structure. */
|
||||
ecoff_data (stdoutput)->debug_info.alloc_syments = true;
|
||||
set = buf;
|
||||
#define SET(ptr, count, type, size) \
|
||||
if (hdr->count == 0) \
|
||||
|
||||
@@ -3008,6 +3008,7 @@ elf_frob_file_after_relocs (void)
|
||||
ecoff_build_debug (&debug.symbolic_header, &buf, debug_swap);
|
||||
|
||||
/* Set up the pointers in debug. */
|
||||
debug.alloc_syments = true;
|
||||
#define SET(ptr, offset, type) \
|
||||
debug.ptr = (type) (buf + debug.symbolic_header.offset)
|
||||
|
||||
|
||||
@@ -299,7 +299,10 @@ struct ecoff_debug_info
|
||||
all pointers to arrays, not single structures. They will be NULL
|
||||
if there are no instances of the relevant structure. These
|
||||
fields are also used by the assembler to output ECOFF debugging
|
||||
information. */
|
||||
information. If alloc_syments is true then the pointers are to
|
||||
objalloc memory, or into a single malloc'd buffer, or otherwise
|
||||
should not be freed. */
|
||||
bool alloc_syments;
|
||||
unsigned char *line;
|
||||
void *external_dnr; /* struct dnr_ext */
|
||||
void *external_pdr; /* struct pdr_ext */
|
||||
|
||||
Reference in New Issue
Block a user