gdb/gdb_bfd.c - gdb
Global variables defined
Data types defined
Functions defined
Macros defined
Source code
- #include "defs.h"
- #include "gdb_bfd.h"
- #include "ui-out.h"
- #include "gdbcmd.h"
- #include "hashtab.h"
- #include "filestuff.h"
- #include "vec.h"
- #ifdef HAVE_ZLIB_H
- #include <zlib.h>
- #endif
- #ifdef HAVE_MMAP
- #include <sys/mman.h>
- #ifndef MAP_FAILED
- #define MAP_FAILED ((void *) -1)
- #endif
- #endif
- typedef bfd *bfdp;
- DEF_VEC_P (bfdp);
- struct gdb_bfd_section_data
- {
-
- bfd_size_type size;
-
- bfd_size_type map_len;
-
- void *data;
-
- void *map_addr;
- };
- static htab_t all_bfds;
- struct gdb_bfd_data
- {
-
- int refc;
-
- time_t mtime;
-
- unsigned int relocation_computed : 1;
-
- unsigned int needs_relocations : 1;
-
- unsigned int crc_computed : 1;
-
- unsigned long crc;
-
- bfd *archive_bfd;
-
- VEC (bfdp) *included_bfds;
-
- REGISTRY_FIELDS;
- };
- #define GDB_BFD_DATA_ACCESSOR(ABFD) \
- ((struct gdb_bfd_data *) bfd_usrdata (ABFD))
- DEFINE_REGISTRY (bfd, GDB_BFD_DATA_ACCESSOR)
- static htab_t gdb_bfd_cache;
- struct gdb_bfd_cache_search
- {
-
- const char *filename;
-
- time_t mtime;
- };
- static hashval_t
- hash_bfd (const void *b)
- {
- const bfd *abfd = b;
-
- return htab_hash_string (bfd_get_filename (abfd));
- }
- static int
- eq_bfd (const void *a, const void *b)
- {
- const bfd *abfd = a;
- const struct gdb_bfd_cache_search *s = b;
- struct gdb_bfd_data *gdata = bfd_usrdata (abfd);
- return (gdata->mtime == s->mtime
- && strcmp (bfd_get_filename (abfd), s->filename) == 0);
- }
- struct bfd *
- gdb_bfd_open (const char *name, const char *target, int fd)
- {
- hashval_t hash;
- void **slot;
- bfd *abfd;
- struct gdb_bfd_cache_search search;
- struct stat st;
- if (gdb_bfd_cache == NULL)
- gdb_bfd_cache = htab_create_alloc (1, hash_bfd, eq_bfd, NULL,
- xcalloc, xfree);
- if (fd == -1)
- {
- fd = gdb_open_cloexec (name, O_RDONLY | O_BINARY, 0);
- if (fd == -1)
- {
- bfd_set_error (bfd_error_system_call);
- return NULL;
- }
- }
- search.filename = name;
- if (fstat (fd, &st) < 0)
- {
-
- search.mtime = 0;
- }
- else
- search.mtime = st.st_mtime;
-
- hash = htab_hash_string (name);
-
- abfd = htab_find_with_hash (gdb_bfd_cache, &search, hash);
- if (abfd != NULL)
- {
- close (fd);
- gdb_bfd_ref (abfd);
- return abfd;
- }
- abfd = bfd_fopen (name, target, FOPEN_RB, fd);
- if (abfd == NULL)
- return NULL;
- slot = htab_find_slot_with_hash (gdb_bfd_cache, &search, hash, INSERT);
- gdb_assert (!*slot);
- *slot = abfd;
- gdb_bfd_ref (abfd);
- return abfd;
- }
- static void
- free_one_bfd_section (bfd *abfd, asection *sectp, void *ignore)
- {
- struct gdb_bfd_section_data *sect = bfd_get_section_userdata (abfd, sectp);
- if (sect != NULL && sect->data != NULL)
- {
- #ifdef HAVE_MMAP
- if (sect->map_addr != NULL)
- {
- int res;
- res = munmap (sect->map_addr, sect->map_len);
- gdb_assert (res == 0);
- }
- else
- #endif
- xfree (sect->data);
- }
- }
- static int
- gdb_bfd_close_or_warn (struct bfd *abfd)
- {
- int ret;
- char *name = bfd_get_filename (abfd);
- bfd_map_over_sections (abfd, free_one_bfd_section, NULL);
- ret = bfd_close (abfd);
- if (!ret)
- warning (_("cannot close \"%s\": %s"),
- name, bfd_errmsg (bfd_get_error ()));
- return ret;
- }
- void
- gdb_bfd_ref (struct bfd *abfd)
- {
- struct gdb_bfd_data *gdata;
- void **slot;
- if (abfd == NULL)
- return;
- gdata = bfd_usrdata (abfd);
- if (gdata != NULL)
- {
- gdata->refc += 1;
- return;
- }
-
- abfd->flags |= BFD_DECOMPRESS;
- gdata = bfd_zalloc (abfd, sizeof (struct gdb_bfd_data));
- gdata->refc = 1;
- gdata->mtime = bfd_get_mtime (abfd);
- gdata->archive_bfd = NULL;
- bfd_usrdata (abfd) = gdata;
- bfd_alloc_data (abfd);
-
- slot = htab_find_slot (all_bfds, abfd, INSERT);
- gdb_assert (slot && !*slot);
- *slot = abfd;
- }
- void
- gdb_bfd_unref (struct bfd *abfd)
- {
- int ix;
- struct gdb_bfd_data *gdata;
- struct gdb_bfd_cache_search search;
- bfd *archive_bfd, *included_bfd;
- if (abfd == NULL)
- return;
- gdata = bfd_usrdata (abfd);
- gdb_assert (gdata->refc >= 1);
- gdata->refc -= 1;
- if (gdata->refc > 0)
- return;
- archive_bfd = gdata->archive_bfd;
- search.filename = bfd_get_filename (abfd);
- if (gdb_bfd_cache && search.filename)
- {
- hashval_t hash = htab_hash_string (search.filename);
- void **slot;
- search.mtime = gdata->mtime;
- slot = htab_find_slot_with_hash (gdb_bfd_cache, &search, hash,
- NO_INSERT);
- if (slot && *slot)
- htab_clear_slot (gdb_bfd_cache, slot);
- }
- for (ix = 0;
- VEC_iterate (bfdp, gdata->included_bfds, ix, included_bfd);
- ++ix)
- gdb_bfd_unref (included_bfd);
- VEC_free (bfdp, gdata->included_bfds);
- bfd_free_data (abfd);
- bfd_usrdata (abfd) = NULL;
- htab_remove_elt (all_bfds, abfd);
- gdb_bfd_close_or_warn (abfd);
- gdb_bfd_unref (archive_bfd);
- }
- static struct gdb_bfd_section_data *
- get_section_descriptor (asection *section)
- {
- struct gdb_bfd_section_data *result;
- result = bfd_get_section_userdata (section->owner, section);
- if (result == NULL)
- {
- result = bfd_zalloc (section->owner, sizeof (*result));
- bfd_set_section_userdata (section->owner, section, result);
- }
- return result;
- }
- const gdb_byte *
- gdb_bfd_map_section (asection *sectp, bfd_size_type *size)
- {
- bfd *abfd;
- struct gdb_bfd_section_data *descriptor;
- bfd_byte *data;
- gdb_assert ((sectp->flags & SEC_RELOC) == 0);
- gdb_assert (size != NULL);
- abfd = sectp->owner;
- descriptor = get_section_descriptor (sectp);
-
- if (descriptor->data != NULL)
- goto done;
- #ifdef HAVE_MMAP
- if (!bfd_is_section_compressed (abfd, sectp))
- {
-
- static int pagesize;
- if (pagesize == 0)
- pagesize = getpagesize ();
-
- if (bfd_get_section_size (sectp) > 4 * pagesize)
- {
- descriptor->size = bfd_get_section_size (sectp);
- descriptor->data = bfd_mmap (abfd, 0, descriptor->size, PROT_READ,
- MAP_PRIVATE, sectp->filepos,
- &descriptor->map_addr,
- &descriptor->map_len);
- if ((caddr_t)descriptor->data != MAP_FAILED)
- {
- #if HAVE_POSIX_MADVISE
- posix_madvise (descriptor->map_addr, descriptor->map_len,
- POSIX_MADV_WILLNEED);
- #endif
- goto done;
- }
-
- memset (descriptor, 0, sizeof (*descriptor));
- }
- }
- #endif
-
- descriptor->size = bfd_get_section_size (sectp);
- descriptor->data = NULL;
- data = NULL;
- if (!bfd_get_full_section_contents (abfd, sectp, &data))
- error (_("Can't read data for section '%s' in file '%s'"),
- bfd_get_section_name (abfd, sectp),
- bfd_get_filename (abfd));
- descriptor->data = data;
- done:
- gdb_assert (descriptor->data != NULL);
- *size = descriptor->size;
- return descriptor->data;
- }
- static int
- get_file_crc (bfd *abfd, unsigned long *file_crc_return)
- {
- unsigned long file_crc = 0;
- if (bfd_seek (abfd, 0, SEEK_SET) != 0)
- {
- warning (_("Problem reading \"%s\" for CRC: %s"),
- bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
- return 0;
- }
- for (;;)
- {
- gdb_byte buffer[8 * 1024];
- bfd_size_type count;
- count = bfd_bread (buffer, sizeof (buffer), abfd);
- if (count == (bfd_size_type) -1)
- {
- warning (_("Problem reading \"%s\" for CRC: %s"),
- bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
- return 0;
- }
- if (count == 0)
- break;
- file_crc = bfd_calc_gnu_debuglink_crc32 (file_crc, buffer, count);
- }
- *file_crc_return = file_crc;
- return 1;
- }
- int
- gdb_bfd_crc (struct bfd *abfd, unsigned long *crc_out)
- {
- struct gdb_bfd_data *gdata = bfd_usrdata (abfd);
- if (!gdata->crc_computed)
- gdata->crc_computed = get_file_crc (abfd, &gdata->crc);
- if (gdata->crc_computed)
- *crc_out = gdata->crc;
- return gdata->crc_computed;
- }
- bfd *
- gdb_bfd_fopen (const char *filename, const char *target, const char *mode,
- int fd)
- {
- bfd *result = bfd_fopen (filename, target, mode, fd);
- if (result)
- gdb_bfd_ref (result);
- return result;
- }
- bfd *
- gdb_bfd_openr (const char *filename, const char *target)
- {
- bfd *result = bfd_openr (filename, target);
- if (result)
- gdb_bfd_ref (result);
- return result;
- }
- bfd *
- gdb_bfd_openw (const char *filename, const char *target)
- {
- bfd *result = bfd_openw (filename, target);
- if (result)
- gdb_bfd_ref (result);
- return result;
- }
- bfd *
- gdb_bfd_openr_iovec (const char *filename, const char *target,
- void *(*open_func) (struct bfd *nbfd,
- void *open_closure),
- void *open_closure,
- file_ptr (*pread_func) (struct bfd *nbfd,
- void *stream,
- void *buf,
- file_ptr nbytes,
- file_ptr offset),
- int (*close_func) (struct bfd *nbfd,
- void *stream),
- int (*stat_func) (struct bfd *abfd,
- void *stream,
- struct stat *sb))
- {
- bfd *result = bfd_openr_iovec (filename, target,
- open_func, open_closure,
- pread_func, close_func, stat_func);
- if (result)
- gdb_bfd_ref (result);
- return result;
- }
- void
- gdb_bfd_mark_parent (bfd *child, bfd *parent)
- {
- struct gdb_bfd_data *gdata;
- gdb_bfd_ref (child);
-
- gdata = bfd_usrdata (child);
- if (gdata->archive_bfd == NULL)
- {
- gdata->archive_bfd = parent;
- gdb_bfd_ref (parent);
- }
- else
- gdb_assert (gdata->archive_bfd == parent);
- }
- bfd *
- gdb_bfd_openr_next_archived_file (bfd *archive, bfd *previous)
- {
- bfd *result = bfd_openr_next_archived_file (archive, previous);
- if (result)
- gdb_bfd_mark_parent (result, archive);
- return result;
- }
- void
- gdb_bfd_record_inclusion (bfd *includer, bfd *includee)
- {
- struct gdb_bfd_data *gdata;
- gdb_bfd_ref (includee);
- gdata = bfd_usrdata (includer);
- VEC_safe_push (bfdp, gdata->included_bfds, includee);
- }
- bfd *
- gdb_bfd_fdopenr (const char *filename, const char *target, int fd)
- {
- bfd *result = bfd_fdopenr (filename, target, fd);
- if (result)
- gdb_bfd_ref (result);
- return result;
- }
- gdb_static_assert (ARRAY_SIZE (_bfd_std_section) == 4);
- int
- gdb_bfd_section_index (bfd *abfd, asection *section)
- {
- if (section == NULL)
- return -1;
- else if (section == bfd_com_section_ptr)
- return bfd_count_sections (abfd) + 1;
- else if (section == bfd_und_section_ptr)
- return bfd_count_sections (abfd) + 2;
- else if (section == bfd_abs_section_ptr)
- return bfd_count_sections (abfd) + 3;
- else if (section == bfd_ind_section_ptr)
- return bfd_count_sections (abfd) + 4;
- return section->index;
- }
- int
- gdb_bfd_count_sections (bfd *abfd)
- {
- return bfd_count_sections (abfd) + 4;
- }
- int
- gdb_bfd_requires_relocations (bfd *abfd)
- {
- struct gdb_bfd_data *gdata = bfd_usrdata (abfd);
- if (gdata->relocation_computed == 0)
- {
- asection *sect;
- for (sect = abfd->sections; sect != NULL; sect = sect->next)
- if ((sect->flags & SEC_RELOC) != 0)
- {
- gdata->needs_relocations = 1;
- break;
- }
- gdata->relocation_computed = 1;
- }
- return gdata->needs_relocations;
- }
- static int
- print_one_bfd (void **slot, void *data)
- {
- bfd *abfd = *slot;
- struct gdb_bfd_data *gdata = bfd_usrdata (abfd);
- struct ui_out *uiout = data;
- struct cleanup *inner;
- inner = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
- ui_out_field_int (uiout, "refcount", gdata->refc);
- ui_out_field_string (uiout, "addr", host_address_to_string (abfd));
- ui_out_field_string (uiout, "filename", bfd_get_filename (abfd));
- ui_out_text (uiout, "\n");
- do_cleanups (inner);
- return 1;
- }
- static void
- maintenance_info_bfds (char *arg, int from_tty)
- {
- struct cleanup *cleanup;
- struct ui_out *uiout = current_uiout;
- cleanup = make_cleanup_ui_out_table_begin_end (uiout, 3, -1, "bfds");
- ui_out_table_header (uiout, 10, ui_left, "refcount", "Refcount");
- ui_out_table_header (uiout, 18, ui_left, "addr", "Address");
- ui_out_table_header (uiout, 40, ui_left, "filename", "Filename");
- ui_out_table_body (uiout);
- htab_traverse (all_bfds, print_one_bfd, uiout);
- do_cleanups (cleanup);
- }
- extern initialize_file_ftype _initialize_gdb_bfd;
- void
- _initialize_gdb_bfd (void)
- {
- all_bfds = htab_create_alloc (10, htab_hash_pointer, htab_eq_pointer,
- NULL, xcalloc, xfree);
- add_cmd ("bfds", class_maintenance, maintenance_info_bfds, _("\
- List the BFDs that are currently open."),
- &maintenanceinfolist);
- }