summaryrefslogtreecommitdiff
path: root/bfd/bfd.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@bigpond.net.au>2002-11-12 15:44:24 +0000
committerAlan Modra <amodra@bigpond.net.au>2002-11-12 15:44:24 +0000
commit95698efb8534eb1355e6c5850d0d0c5c1e37ce35 (patch)
tree575a0fe3819e8f446702bbb91ea64e7d38139b45 /bfd/bfd.c
parent9af57b5da3611613f96617ae6113ee804b0aea6b (diff)
downloadbinutils-redhat-95698efb8534eb1355e6c5850d0d0c5c1e37ce35.tar.gz
* bfd.c (struct bfd_preserve): New.
(bfd_preserve_save): New function. (bfd_preserve_restore): Ditto. (bfd_preserve_finish): Ditto. * bfd-in2.h: Regenerate. * mach-o.c: Formatting. (bfd_mach_o_scan_read_symtab_symbol): Make "value" unsigned. (bfd_mach_o_object_p): Use bfd_preserve_save/restore/finish. (bfd_mach_o_core_p): Ditto. (bfd_mach_o_scan): Pass in mdata. * mach-o.h (bfd_mach_o_scan): Update prototype. * pef.c: Formatting. (bfd_pef_object_p): Use bfd_preserve_save/restore/finish. (bfd_pef_xlib_object_p): Ditto. (bfd_pef_scan): Pass in mdata. Move version check to bfd_pef_object_p. * pef.h (bfd_pef_scan): Update prototype. * xsym.c: Formatting, K&R fixes. (bfd_sym_object_p): Use bfd_preserve_save/restore/finish. (bfd_sym_scan): New function split out from bfd_sym_object_p. * xsym.h (bfd_sym_scan): Declare. * elfcode.h (elf_object_p): Use bfd_preserve_save/restore/finish. (elf_core_file_p): Likewise. * targets.c (_bfd_target_vector): Revert 2002-11-08 change.
Diffstat (limited to 'bfd/bfd.c')
-rw-r--r--bfd/bfd.c130
1 files changed, 130 insertions, 0 deletions
diff --git a/bfd/bfd.c b/bfd/bfd.c
index cff7119ee2..5412ac8bfc 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -1392,3 +1392,133 @@ bfd_alt_mach_code (abfd, alternative)
return false;
}
+
+/*
+CODE_FRAGMENT
+
+.struct bfd_preserve
+.{
+. PTR marker;
+. PTR tdata;
+. flagword flags;
+. const struct bfd_arch_info *arch_info;
+. struct sec *sections;
+. struct sec **section_tail;
+. unsigned int section_count;
+. struct bfd_hash_table section_htab;
+.};
+.
+*/
+
+/*
+FUNCTION
+ bfd_preserve_save
+
+SYNOPSIS
+ boolean bfd_preserve_save (bfd *, struct bfd_preserve *);
+
+DESCRIPTION
+ When testing an object for compatibility with a particular
+ target back-end, the back-end object_p function needs to set
+ up certain fields in the bfd on successfully recognizing the
+ object. This typically happens in a piecemeal fashion, with
+ failures possible at many points. On failure, the bfd is
+ supposed to be restored to its initial state, which is
+ virtually impossible. However, restoring a subset of the bfd
+ state works in practice. This function stores the subset and
+ reinitializes the bfd.
+
+*/
+
+boolean
+bfd_preserve_save (abfd, preserve)
+ bfd *abfd;
+ struct bfd_preserve *preserve;
+{
+ preserve->tdata = abfd->tdata.any;
+ preserve->arch_info = abfd->arch_info;
+ preserve->flags = abfd->flags;
+
+ preserve->sections = abfd->sections;
+ preserve->section_tail = abfd->section_tail;
+ preserve->section_count = abfd->section_count;
+ preserve->section_htab = abfd->section_htab;
+
+ if (! bfd_hash_table_init (&abfd->section_htab, bfd_section_hash_newfunc))
+ return false;
+
+ abfd->tdata.any = NULL;
+ abfd->arch_info = &bfd_default_arch_struct;
+ abfd->flags = 0;
+
+ abfd->sections = NULL;
+ abfd->section_tail = &abfd->sections;
+ abfd->section_count = 0;
+
+ return true;
+}
+
+/*
+FUNCTION
+ bfd_preserve_restore
+
+SYNOPSIS
+ void bfd_preserve_restore (bfd *, struct bfd_preserve *);
+
+DESCRIPTION
+ This function restores bfd state saved by bfd_preserve_save.
+ If MARKER is non-NULL in struct bfd_preserve then that block
+ and all subsequently bfd_alloc'd memory is freed.
+
+*/
+
+void
+bfd_preserve_restore (abfd, preserve)
+ bfd *abfd;
+ struct bfd_preserve *preserve;
+{
+ bfd_hash_table_free (&abfd->section_htab);
+
+ abfd->tdata.any = preserve->tdata;
+ abfd->arch_info = preserve->arch_info;
+ abfd->flags = preserve->flags;
+
+ abfd->section_htab = preserve->section_htab;
+ abfd->sections = preserve->sections;
+ abfd->section_tail = preserve->section_tail;
+ abfd->section_count = preserve->section_count;
+
+ /* bfd_release frees all memory more recently bfd_alloc'd than
+ its arg, as well as its arg. */
+ if (preserve->marker != NULL)
+ {
+ bfd_release (abfd, preserve->marker);
+ preserve->marker = NULL;
+ }
+}
+
+/*
+FUNCTION
+ bfd_preserve_finish
+
+SYNOPSIS
+ void bfd_preserve_finish (bfd *, struct bfd_preserve *);
+
+DESCRIPTION
+ This function should be called when the bfd state saved by
+ bfd_preserve_save is no longer needed. ie. when the back-end
+ object_p function returns with success.
+
+*/
+
+void
+bfd_preserve_finish (abfd, preserve)
+ bfd *abfd ATTRIBUTE_UNUSED;
+ struct bfd_preserve *preserve;
+{
+ /* It would be nice to be able to free more memory here, eg. old
+ tdata, but that's not possible since these blocks are sitting
+ inside bfd_alloc'd memory. The section hash is on a separate
+ objalloc. */
+ bfd_hash_table_free (&preserve->section_htab);
+}