This patch adds a new API entrypoint to libbfd: bfd_uninit, which resets global state within the library.
The patch (and subsequent ones) follow a pattern I used in gcc for cleaning up global state: for each source file e.g. foo.c to have a function: extern void foo_c_finalize (void); to explicitly reset all statically-allocated global data back to its initial value. Two warts: where should prototypes for internal functions be declared? I need to put an: extern void section_c_finalize (void); into an internal header, but I don't want to expose that as API. Similarly, is there a way to use a linker script to hide the function? bfd/ChangeLog: * bfd-in2.h: Regenerate. * elflink.c (elf_flags_to_names): Make const. * init.c (bfd_uninit): New function. * section.c (reinit_BFD_FAKE_SECTION): New function. (reinit_STD_SECTION): New function. (section_c_finalize): New function. --- bfd/bfd-in2.h | 2 ++ bfd/elflink.c | 2 +- bfd/init.c | 20 ++++++++++++++++++++ bfd/section.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 1 deletion(-) diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index ade49ff..cba57b3 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -1016,6 +1016,8 @@ extern bfd_boolean v850_elf_set_note /* Extracted from init.c. */ void bfd_init (void); +void bfd_uninit (void); + /* Extracted from opncls.c. */ /* Set to N to open the next N BFDs using an alternate id space. */ extern unsigned int bfd_use_reserved_id; diff --git a/bfd/elflink.c b/bfd/elflink.c index 6efe1e4..d8c1171 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -12639,7 +12639,7 @@ typedef struct flagword flag_value; } elf_flags_to_name_table; -static elf_flags_to_name_table elf_flags_to_names [] = +static const elf_flags_to_name_table elf_flags_to_names [] = { { "SHF_WRITE", SHF_WRITE }, { "SHF_ALLOC", SHF_ALLOC }, diff --git a/bfd/init.c b/bfd/init.c index 323f0ac..e4fae11 100644 --- a/bfd/init.c +++ b/bfd/init.c @@ -52,3 +52,23 @@ void bfd_init (void) { } + +/* +FUNCTION + bfd_uninit + +SYNOPSIS + void bfd_uninit (void); + +DESCRIPTION + Purge internal state within the library. +*/ + +/* FIXME: where should prototypes for internal functions be declared? */ +extern void section_c_finalize (void); + +void +bfd_uninit (void) +{ + section_c_finalize (); +} diff --git a/bfd/section.c b/bfd/section.c index 24422bf..f1d445f 100644 --- a/bfd/section.c +++ b/bfd/section.c @@ -1666,3 +1666,56 @@ bfd_generic_discard_group (bfd *abfd ATTRIBUTE_UNUSED, { return TRUE; } + +/* Helper function for reinit_STD_SECTION + Reset the given section back to its initial state. + Based on macro BFD_FAKE_SECTION. */ + +static void +reinit_BFD_FAKE_SECTION (asection *sec, + int flags, + const struct bfd_symbol *sym, + const char *name, + int idx) +{ + /* Zero it. */ + memset (sec, 0, sizeof (*sec)); + + /* Now fixup the things that BFD_FAKE_SECTION makes nonzero. */ + sec->name = name; + sec->id = idx; + sec->flags = flags; + sec->gc_mark = 1; + sec->output_section = sec; + sec->symbol = (struct bfd_symbol *) sym; /* (cast away constness) */ + sec->symbol_ptr_ptr = &sec->symbol; +} + +/* Helper function for section_c_finalize. + Reset one of the global sections within _bfd_std_section back to its + initial state. + Based on macros STD_SECTION and BFD_FAKE_SECTION. */ + +static void +reinit_STD_SECTION (const char *name, + int idx, + int flags) +{ + asection *sec = &_bfd_std_section[idx]; + reinit_BFD_FAKE_SECTION (sec, flags, &global_syms[idx], name, idx); +} + +/* FIXME: where should prototypes for internal functions be declared? */ +extern void +section_c_finalize (void); + +/* Reset global state within section.c back to its original state. */ + +void +section_c_finalize (void) +{ + reinit_STD_SECTION (BFD_COM_SECTION_NAME, 0, SEC_IS_COMMON); + reinit_STD_SECTION (BFD_UND_SECTION_NAME, 1, 0); + reinit_STD_SECTION (BFD_ABS_SECTION_NAME, 2, 0); + reinit_STD_SECTION (BFD_IND_SECTION_NAME, 3, 0); +} -- 1.8.5.3