/* opncls.c -- open and close a BFD.
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000,
- 2001, 2002, 2003, 2004, 2005
+ 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
Written by Cygnus Support.
nbfd->iostream = NULL;
nbfd->where = 0;
if (!bfd_hash_table_init_n (& nbfd->section_htab, bfd_section_hash_newfunc,
- 251))
+ sizeof (struct section_hash_entry), 251))
{
free (nbfd);
return NULL;
void
_bfd_delete_bfd (bfd *abfd)
{
- bfd_hash_table_free (&abfd->section_htab);
- objalloc_free ((struct objalloc *) abfd->memory);
+ if (abfd->memory)
+ {
+ bfd_hash_table_free (&abfd->section_htab);
+ objalloc_free ((struct objalloc *) abfd->memory);
+ }
free (abfd);
}
+/* Free objalloc memory. */
+
+bfd_boolean
+_bfd_free_cached_info (bfd *abfd)
+{
+ if (abfd->memory)
+ {
+ bfd_hash_table_free (&abfd->section_htab);
+ objalloc_free ((struct objalloc *) abfd->memory);
+
+ abfd->sections = NULL;
+ abfd->section_last = NULL;
+ abfd->outsymbols = NULL;
+ abfd->tdata.any = NULL;
+ abfd->usrdata = NULL;
+ abfd->memory = NULL;
+ }
+
+ return TRUE;
+}
+
/*
SECTION
Opening and closing BFDs
+SUBSECTION
+ Functions for opening and closing
*/
/*
nbfd->iostream = fdopen (fd, mode);
else
#endif
- nbfd->iostream = fopen (filename, mode);
+ nbfd->iostream = real_fopen (filename, mode);
if (nbfd->iostream == NULL)
{
bfd_set_error (bfd_error_system_call);
file_ptr nbytes,
file_ptr offset),
int (*close) (struct bfd *nbfd,
- void *stream));
+ void *stream),
+ int (*stat) (struct bfd *abfd,
+ void *stream,
+ struct stat *sb));
DESCRIPTION
<<bfd_close>>. @var{close} either succeeds returning 0, or
fails returning -1 (setting <<bfd_error>>).
+ Calls @var{stat} to fill in a stat structure for bfd_stat,
+ bfd_get_size, and bfd_get_mtime calls. @var{stat} returns 0
+ on success, or returns -1 on failure (setting <<bfd_error>>).
+
If <<bfd_openr_iovec>> returns <<NULL>> then an error has
occurred. Possible errors are <<bfd_error_no_memory>>,
<<bfd_error_invalid_target>> and <<bfd_error_system_call>>.
file_ptr (*pread) (struct bfd *abfd, void *stream, void *buf,
file_ptr nbytes, file_ptr offset);
int (*close) (struct bfd *abfd, void *stream);
+ int (*stat) (struct bfd *abfd, void *stream, struct stat *sb);
file_ptr where;
};
}
static int
-opncls_bstat (struct bfd *abfd ATTRIBUTE_UNUSED, struct stat *sb)
+opncls_bstat (struct bfd *abfd, struct stat *sb)
{
+ struct opncls *vec = abfd->iostream;
+
memset (sb, 0, sizeof (*sb));
- return 0;
+ if (vec->stat == NULL)
+ return 0;
+
+ return (vec->stat) (abfd, vec->stream, sb);
}
static const struct bfd_iovec opncls_iovec = {
file_ptr nbytes,
file_ptr offset),
int (*close) (struct bfd *nbfd,
- void *stream))
+ void *stream),
+ int (*stat) (struct bfd *abfd,
+ void *stream,
+ struct stat *sb))
{
bfd *nbfd;
const bfd_target *target_vec;
vec->stream = stream;
vec->pread = pread;
vec->close = close;
+ vec->stat = stat;
nbfd->iovec = &opncls_iovec;
nbfd->iostream = vec;
return ret;
}
+/*
+INTERNAL_FUNCTION
+ bfd_alloc2
+
+SYNOPSIS
+ void *bfd_alloc2 (bfd *abfd, bfd_size_type nmemb, bfd_size_type size);
+
+DESCRIPTION
+ Allocate a block of @var{nmemb} elements of @var{size} bytes each
+ of memory attached to <<abfd>> and return a pointer to it.
+*/
+
+void *
+bfd_alloc2 (bfd *abfd, bfd_size_type nmemb, bfd_size_type size)
+{
+ void *ret;
+
+ if ((nmemb | size) >= HALF_BFD_SIZE_TYPE
+ && size != 0
+ && nmemb > ~(bfd_size_type) 0 / size)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return NULL;
+ }
+
+ size *= nmemb;
+
+ if (size != (unsigned long) size)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return NULL;
+ }
+
+ ret = objalloc_alloc (abfd->memory, (unsigned long) size);
+ if (ret == NULL)
+ bfd_set_error (bfd_error_no_memory);
+ return ret;
+}
+
/*
INTERNAL_FUNCTION
bfd_zalloc
return res;
}
+/*
+INTERNAL_FUNCTION
+ bfd_zalloc2
+
+SYNOPSIS
+ void *bfd_zalloc2 (bfd *abfd, bfd_size_type nmemb, bfd_size_type size);
+
+DESCRIPTION
+ Allocate a block of @var{nmemb} elements of @var{size} bytes each
+ of zeroed memory attached to <<abfd>> and return a pointer to it.
+*/
+
+void *
+bfd_zalloc2 (bfd *abfd, bfd_size_type nmemb, bfd_size_type size)
+{
+ void *res;
+
+ if ((nmemb | size) >= HALF_BFD_SIZE_TYPE
+ && size != 0
+ && nmemb > ~(bfd_size_type) 0 / size)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return NULL;
+ }
+
+ size *= nmemb;
+
+ res = bfd_alloc (abfd, size);
+ if (res)
+ memset (res, 0, (size_t) size);
+ return res;
+}
+
/* Free a block allocated for a BFD.
Note: Also frees all more recently allocated blocks! */
{
asection *sect;
bfd_size_type debuglink_size;
+ flagword flags;
if (abfd == NULL || filename == NULL)
{
return NULL;
}
- sect = bfd_make_section (abfd, GNU_DEBUGLINK);
+ flags = SEC_HAS_CONTENTS | SEC_READONLY | SEC_DEBUGGING;
+ sect = bfd_make_section_with_flags (abfd, GNU_DEBUGLINK, flags);
if (sect == NULL)
return NULL;
- if (! bfd_set_section_flags (abfd, sect,
- SEC_HAS_CONTENTS | SEC_READONLY | SEC_DEBUGGING))
- /* XXX Should we delete the section from the bfd ? */
- return NULL;
-
-
debuglink_size = strlen (filename) + 1;
debuglink_size += 3;
debuglink_size &= ~3;
.gnu_debuglink section, we insist upon the user providing us with a
correct-for-section-creation-time path, but this need not conform to
the gdb location algorithm. */
- handle = fopen (filename, FOPEN_RB);
+ handle = real_fopen (filename, FOPEN_RB);
if (handle == NULL)
{
bfd_set_error (bfd_error_system_call);