alloc gas seginfo on notes obstack

Lots of memory used in gas should go on this obstack.  The patch also
frees all the gas obstacks on exit, which isn't a completely trivial
task.

	* subsegs.c (alloc_seginfo): New function.
	(subseg_change, subseg_get): Use it.
	(subsegs_end): New function.
	* as.h (subsegs_end): Declare.
	* output-file.c: Include subsegs.h
	(stash_frchain_obs): New function.
	(output_file_close): Save obstacks attached to output bfd before
	closing.  Call subsegs_end with the array of obstacks.
This commit is contained in:
Alan Modra
2022-07-04 12:45:47 +09:30
parent 0772daccb3
commit eeeaf705fe
3 changed files with 64 additions and 20 deletions

View File

@ -476,6 +476,7 @@ void input_scrub_end (void);
void new_logical_line (const char *, int);
void new_logical_line_flags (const char *, int, int);
void subsegs_begin (void);
void subsegs_end (struct obstack **);
void subseg_change (segT, int);
segT subseg_new (const char *, subsegT);
segT subseg_force_new (const char *, subsegT);

View File

@ -19,6 +19,7 @@
02110-1301, USA. */
#include "as.h"
#include "subsegs.h"
#include "output-file.h"
#ifndef TARGET_MACH
@ -49,24 +50,55 @@ output_file_create (const char *name)
stdoutput->flags |= BFD_TRADITIONAL_FORMAT;
}
static void
stash_frchain_obs (asection *sec)
{
segment_info_type *info = seg_info (sec);
if (info)
{
struct frchain *frchp;
for (frchp = info->frchainP; frchp; frchp = frchp->frch_next)
obstack_ptr_grow (&notes, &frchp->frch_obstack);
info->frchainP = NULL;
}
}
void
output_file_close (const char *filename)
{
bool res;
bfd *obfd = stdoutput;
struct obstack **obs;
asection *sec;
if (stdoutput == NULL)
if (obfd == NULL)
return;
/* Close the bfd. */
if (!flag_always_generate_output && had_errors ())
res = bfd_cache_close_all ();
else
res = bfd_close (stdoutput);
/* Prevent an infinite loop - if the close failed we will call as_fatal
which will call xexit() which may call this function again... */
stdoutput = NULL;
/* We can't free obstacks attached to the output bfd sections before
closing the output bfd since data in those obstacks may need to
be accessed, but we can't access anything in the output bfd after
it is closed.. */
for (sec = obfd->sections; sec; sec = sec->next)
stash_frchain_obs (sec);
stash_frchain_obs (reg_section);
stash_frchain_obs (expr_section);
stash_frchain_obs (bfd_abs_section_ptr);
stash_frchain_obs (bfd_und_section_ptr);
obstack_ptr_grow (&notes, NULL);
obs = obstack_finish (&notes);
/* Close the bfd. */
if (!flag_always_generate_output && had_errors ())
res = bfd_cache_close_all ();
else
res = bfd_close (obfd);
subsegs_end (obs);
if (! res)
as_fatal ("%s: %s", filename, bfd_errmsg (bfd_get_error ()));
}

View File

@ -43,7 +43,27 @@ subsegs_begin (void)
frchain_now = NULL; /* Warn new_subseg() that we are booting. */
frag_now = &dummy_frag;
}
void
subsegs_end (struct obstack **obs)
{
for (; *obs; obs++)
_obstack_free (*obs, NULL);
_obstack_free (&frchains, NULL);
_obstack_free (&cond_obstack, NULL);
_obstack_free (&notes, NULL);
}
static void
alloc_seginfo (segT seg)
{
segment_info_type *seginfo;
seginfo = obstack_alloc (&notes, sizeof (*seginfo));
memset (seginfo, 0, sizeof (*seginfo));
seginfo->bfd_section = seg;
bfd_set_section_userdata (seg, seginfo);
}
/*
* subseg_change()
*
@ -57,16 +77,11 @@ subsegs_begin (void)
void
subseg_change (segT seg, int subseg)
{
segment_info_type *seginfo = seg_info (seg);
now_seg = seg;
now_subseg = subseg;
if (! seginfo)
{
seginfo = XCNEW (segment_info_type);
seginfo->bfd_section = seg;
bfd_set_section_userdata (seg, seginfo);
}
if (!seg_info (seg))
alloc_seginfo (seg);
}
static void
@ -149,7 +164,6 @@ segT
subseg_get (const char *segname, int force_new)
{
segT secptr;
segment_info_type *seginfo;
const char *now_seg_name = now_seg ? bfd_section_name (now_seg) : 0;
if (!force_new
@ -163,13 +177,10 @@ subseg_get (const char *segname, int force_new)
else
secptr = bfd_make_section_anyway (stdoutput, segname);
seginfo = seg_info (secptr);
if (! seginfo)
if (!seg_info (secptr))
{
secptr->output_section = secptr;
seginfo = XCNEW (segment_info_type);
seginfo->bfd_section = secptr;
bfd_set_section_userdata (secptr, seginfo);
alloc_seginfo (secptr);
}
return secptr;
}