This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: pef.c:bfd_pef_object_p breaks other targets
On Tue, Nov 12, 2002 at 04:03:36AM -0500, Klee Dienes wrote:
> I've modified all three targets (pef, mach-o, and sym) to save and
> restore the bfd state using the functions
> bfd_preserve_save/restore/finish before any modifications to tdata or
> the arch. I chose to cut-and-paste the three functions between the
> files to simplify things; I'd be happy to factor them out into a
> separate file if you prefer (and if you can suggest a good filename).
I think these are generally useful, so I moved them to bfd.c. A few
tweaks here and there to your patch and lots of formatting fixes to
pef.c, mach-o.c, xsym.c. In addition, I've re-enabled the target
vectors and made use of the save/restore functions for ELF.
bfd/ChangeLog
* 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.
mach-o, pef and xsym patch not re-posted due to copious formatting
changes.
Index: bfd/bfd.c
===================================================================
RCS file: /cvs/src/src/bfd/bfd.c,v
retrieving revision 1.40
diff -u -p -r1.40 bfd.c
--- bfd/bfd.c 6 Nov 2002 13:26:27 -0000 1.40
+++ bfd/bfd.c 12 Nov 2002 15:16:31 -0000
@@ -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);
+}
Index: bfd/elfcode.h
===================================================================
RCS file: /cvs/src/src/bfd/elfcode.h,v
retrieving revision 1.36
diff -u -p -r1.36 elfcode.h
--- bfd/elfcode.h 21 Sep 2002 09:59:19 -0000 1.36
+++ bfd/elfcode.h 12 Nov 2002 15:16:32 -0000
@@ -505,16 +505,6 @@ elf_file_p (x_ehdrp)
&& (x_ehdrp->e_ident[EI_MAG3] == ELFMAG3));
}
-struct bfd_preserve
-{
- const struct bfd_arch_info *arch_info;
- struct elf_obj_tdata *tdata;
- struct bfd_hash_table section_htab;
- struct sec *sections;
- struct sec **section_tail;
- unsigned int section_count;
-};
-
/* Check to see if the file associated with ABFD matches the target vector
that ABFD points to.
@@ -536,11 +526,10 @@ elf_object_p (abfd)
char *shstrtab; /* Internal copy of section header stringtab */
struct elf_backend_data *ebd;
struct bfd_preserve preserve;
- struct elf_obj_tdata *new_tdata = NULL;
asection *s;
bfd_size_type amt;
- preserve.arch_info = abfd->arch_info;
+ preserve.marker = NULL;
/* Read in the ELF header in external format. */
@@ -584,24 +573,14 @@ elf_object_p (abfd)
the tdata pointer in the bfd. */
amt = sizeof (struct elf_obj_tdata);
- new_tdata = (struct elf_obj_tdata *) bfd_zalloc (abfd, amt);
- if (new_tdata == NULL)
+ preserve.marker = bfd_zalloc (abfd, amt);
+ if (preserve.marker == NULL)
goto got_no_match;
- preserve.tdata = elf_tdata (abfd);
- elf_tdata (abfd) = new_tdata;
-
- /* Clear section information, since there might be a recognized bfd that
- we now check if we can replace, and we don't want to append to it. */
- preserve.sections = abfd->sections;
- preserve.section_tail = abfd->section_tail;
- preserve.section_count = abfd->section_count;
- preserve.section_htab = abfd->section_htab;
- abfd->sections = NULL;
- abfd->section_tail = &abfd->sections;
- abfd->section_count = 0;
- if (!bfd_hash_table_init (&abfd->section_htab, bfd_section_hash_newfunc))
+ if (!bfd_preserve_save (abfd, &preserve))
goto got_no_match;
+ elf_tdata (abfd) = preserve.marker;
+
/* Now that we know the byte order, swap in the rest of the header */
i_ehdrp = elf_elfheader (abfd);
elf_swap_ehdr_in (abfd, &x_ehdr, i_ehdrp);
@@ -633,8 +612,10 @@ elf_object_p (abfd)
/* Check that the ELF e_machine field matches what this particular
BFD format expects. */
if (ebd->elf_machine_code != i_ehdrp->e_machine
- && (ebd->elf_machine_alt1 == 0 || i_ehdrp->e_machine != ebd->elf_machine_alt1)
- && (ebd->elf_machine_alt2 == 0 || i_ehdrp->e_machine != ebd->elf_machine_alt2))
+ && (ebd->elf_machine_alt1 == 0
+ || i_ehdrp->e_machine != ebd->elf_machine_alt1)
+ && (ebd->elf_machine_alt2 == 0
+ || i_ehdrp->e_machine != ebd->elf_machine_alt2))
{
const bfd_target * const *target_ptr;
@@ -844,11 +825,8 @@ elf_object_p (abfd)
}
}
- /* It would be nice to be able to free more memory here, eg. old
- elf_elfsections, old tdata, but that's not possible since these
- blocks are sitting inside obj_alloc'd memory. */
- bfd_hash_table_free (&preserve.section_htab);
- return (abfd->xvec);
+ bfd_preserve_finish (abfd, &preserve);
+ return abfd->xvec;
got_wrong_format_error:
/* There is way too much undoing of half-known state here. The caller,
@@ -864,17 +842,8 @@ elf_object_p (abfd)
got_no_match:
abfd->arch_info = preserve.arch_info;
- if (new_tdata != NULL)
- {
- /* bfd_release frees all memory more recently bfd_alloc'd than
- its arg, as well as its arg. */
- bfd_release (abfd, new_tdata);
- elf_tdata (abfd) = preserve.tdata;
- abfd->section_htab = preserve.section_htab;
- abfd->sections = preserve.sections;
- abfd->section_tail = preserve.section_tail;
- abfd->section_count = preserve.section_count;
- }
+ if (preserve.marker != NULL)
+ bfd_preserve_restore (abfd, &preserve);
return NULL;
}
Index: bfd/elfcore.h
===================================================================
RCS file: /cvs/src/src/bfd/elfcore.h,v
retrieving revision 1.14
diff -u -p -r1.14 elfcore.h
--- bfd/elfcore.h 25 Jun 2002 06:21:53 -0000 1.14
+++ bfd/elfcore.h 12 Nov 2002 15:16:32 -0000
@@ -85,18 +85,18 @@ elf_core_file_p (abfd)
unsigned int phindex;
struct elf_backend_data *ebd;
struct bfd_preserve preserve;
- struct elf_obj_tdata *new_tdata = NULL;
bfd_size_type amt;
- preserve.arch_info = abfd->arch_info;
+ preserve.marker = NULL;
/* Read in the ELF header in external format. */
if (bfd_bread ((PTR) &x_ehdr, (bfd_size_type) sizeof (x_ehdr), abfd)
!= sizeof (x_ehdr))
{
if (bfd_get_error () != bfd_error_system_call)
- bfd_set_error (bfd_error_wrong_format);
- return NULL;
+ goto wrong;
+ else
+ goto fail;
}
/* Check the magic number. */
@@ -126,24 +126,14 @@ elf_core_file_p (abfd)
/* Give abfd an elf_obj_tdata. */
amt = sizeof (struct elf_obj_tdata);
- new_tdata = (struct elf_obj_tdata *) bfd_zalloc (abfd, amt);
- if (new_tdata == NULL)
- return NULL;
- preserve.tdata = elf_tdata (abfd);
- elf_tdata (abfd) = new_tdata;
-
- /* Clear section information, since there might be a recognized bfd that
- we now check if we can replace, and we don't want to append to it. */
- preserve.sections = abfd->sections;
- preserve.section_tail = abfd->section_tail;
- preserve.section_count = abfd->section_count;
- preserve.section_htab = abfd->section_htab;
- abfd->sections = NULL;
- abfd->section_tail = &abfd->sections;
- abfd->section_count = 0;
- if (!bfd_hash_table_init (&abfd->section_htab, bfd_section_hash_newfunc))
+ preserve.marker = bfd_zalloc (abfd, amt);
+ if (preserve.marker == NULL)
+ goto fail;
+ if (!bfd_preserve_save (abfd, &preserve))
goto fail;
+ elf_tdata (abfd) = preserve.marker;
+
/* Swap in the rest of the header, now that we have the byte order. */
i_ehdrp = elf_elfheader (abfd);
elf_swap_ehdr_in (abfd, &x_ehdr, i_ehdrp);
@@ -248,7 +238,7 @@ elf_core_file_p (abfd)
goto wrong;
}
- bfd_hash_table_free (&preserve.section_htab);
+ bfd_preserve_finish (abfd, &preserve);
return abfd->xvec;
wrong:
@@ -264,17 +254,7 @@ wrong:
bfd_set_error (bfd_error_wrong_format);
fail:
- abfd->arch_info = preserve.arch_info;
- if (new_tdata != NULL)
- {
- /* bfd_release frees all memory more recently bfd_alloc'd than
- its arg, as well as its arg. */
- bfd_release (abfd, new_tdata);
- elf_tdata (abfd) = preserve.tdata;
- abfd->section_htab = preserve.section_htab;
- abfd->sections = preserve.sections;
- abfd->section_tail = preserve.section_tail;
- abfd->section_count = preserve.section_count;
- }
+ if (preserve.marker != NULL)
+ bfd_preserve_restore (abfd, &preserve);
return NULL;
}
--
Alan Modra
IBM OzLabs - Linux Technology Centre