#include "defs.h"
#include "bfd.h"
#include "symtab.h"
#include "symfile.h"
#include "objfiles.h"
#include "gdb-stabs.h"
#include "target.h"
#include "gdbcmd.h"
#include <sys/types.h>
#include "gdb_stat.h"
#include <fcntl.h>
#include "obstack.h"
#include "gdb_string.h"
#include "breakpoint.h"
#include <assert.h>
#ifndef TEXT_SECTION_NAME
#define TEXT_SECTION_NAME ".text"
#endif
#ifndef DATA_SECTION_NAME
#define DATA_SECTION_NAME ".data"
#endif
#define MAPPED_SYMFILES (USE_MMALLOC && HAVE_MMAP)
struct objfile *object_files;
struct objfile *current_objfile;
struct objfile *symfile_objfile;
struct objfile *rt_common_objfile;
int mapped_symbol_files = 0;
int use_mapped_symbol_files = 1;
void
objfile_to_front (struct objfile *objfile)
{
struct objfile **objp;
for (objp = &object_files; *objp != NULL; objp = &((*objp)->next))
{
if (*objp == objfile)
{
*objp = objfile->next;
objfile->next = object_files;
object_files = objfile;
break;
}
}
}
void
unlink_objfile (struct objfile *objfile)
{
struct objfile **objpp;
for (objpp = &object_files; *objpp != NULL; objpp = &((*objpp)->next))
{
if (*objpp == objfile)
{
*objpp = (*objpp)->next;
objfile->next = NULL;
return;
}
}
internal_error (__FILE__, __LINE__,
"unlink_objfile: objfile already unlinked");
}
void
free_objfile (struct objfile *objfile)
{
if (objfile->sf != NULL)
{
(*objfile->sf->sym_finish) (objfile);
}
if (objfile->obfd != NULL)
{
char *name = bfd_get_filename (objfile->obfd);
if (!bfd_close (objfile->obfd))
warning ("cannot close \"%s\": %s",
name, bfd_errmsg (bfd_get_error ()));
xfree (name);
}
unlink_objfile (objfile);
if (objfile == rt_common_objfile)
rt_common_objfile = NULL;
#if defined (CLEAR_SOLIB)
CLEAR_SOLIB ();
{
struct target_ops *t = find_core_target ();
if (t != NULL)
(t->to_detach) (NULL, 0);
}
#endif
clear_pc_function_cache ();
#if MAPPED_SYMFILES
if (objfile->flags & OBJF_MAPPED)
{
int mmfd;
mmfd = objfile->mmfd;
mmalloc_detach (objfile->md);
objfile = NULL;
close (mmfd);
}
#endif
if (objfile != NULL)
{
if (objfile->name != NULL)
{
xmfree (objfile->md, objfile->name);
}
if (objfile->global_psymbols.list)
xmfree (objfile->md, objfile->global_psymbols.list);
if (objfile->static_psymbols.list)
xmfree (objfile->md, objfile->static_psymbols.list);
free_bcache (&objfile->psymbol_cache);
obstack_free (&objfile->psymbol_obstack, 0);
obstack_free (&objfile->symbol_obstack, 0);
obstack_free (&objfile->type_obstack, 0);
xmfree (objfile->md, objfile);
objfile = NULL;
}
{
extern struct target_ops exec_ops;
update_section_tables (¤t_target);
update_section_tables (&exec_ops);
}
}
void
update_section_tables (struct target_ops *target)
{
struct objfile *objfile;
struct obj_section *osection;
unsigned int nsections = 0;
struct section_table *sections, *tsection;
if (target->to_sections != NULL) {
assert (target->to_sections_end >= target->to_sections);
target->to_sections = NULL;
target->to_sections_end = NULL;
}
nsections = 0;
ALL_OBJSECTIONS (objfile, osection) {
nsections++;
}
sections = (struct section_table *) xmalloc (nsections * sizeof (struct section_table));
tsection = sections;
ALL_OBJSECTIONS (objfile, osection) {
assert (objfile != NULL);
assert (osection != NULL);
assert (osection->objfile != NULL);
tsection->addr = osection->addr;
tsection->endaddr = osection->endaddr;
tsection->the_bfd_section =osection->the_bfd_section;
tsection->bfd = osection->objfile->obfd;
tsection++;
}
target->to_sections = sections;
target->to_sections_end = sections + nsections;
}
static void
do_free_objfile_cleanup (void *obj)
{
free_objfile (obj);
}
struct cleanup *
make_cleanup_free_objfile (struct objfile *obj)
{
return make_cleanup (do_free_objfile_cleanup, obj);
}
void
free_all_objfiles (void)
{
struct objfile *objfile, *temp;
ALL_OBJFILES_SAFE (objfile, temp)
{
free_objfile (objfile);
}
clear_symtab_users ();
}
void
objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets)
{
struct section_offsets *delta =
(struct section_offsets *) alloca (SIZEOF_SECTION_OFFSETS);
{
int i;
int something_changed = 0;
for (i = 0; i < objfile->num_sections; ++i)
{
delta->offsets[i] =
ANOFFSET (new_offsets, i) - ANOFFSET (objfile->section_offsets, i);
if (ANOFFSET (delta, i) != 0)
something_changed = 1;
}
if (!something_changed)
return;
}
{
struct symtab *s;
ALL_OBJFILE_SYMTABS (objfile, s)
{
struct linetable *l;
struct blockvector *bv;
int i;
l = LINETABLE (s);
if (l)
{
for (i = 0; i < l->nitems; ++i)
l->item[i].pc += ANOFFSET (delta, s->block_line_section);
}
if (!s->primary)
continue;
bv = BLOCKVECTOR (s);
for (i = 0; i < BLOCKVECTOR_NBLOCKS (bv); ++i)
{
struct block *b;
struct symbol *sym;
int j;
b = BLOCKVECTOR_BLOCK (bv, i);
BLOCK_START (b) += ANOFFSET (delta, s->block_line_section);
BLOCK_END (b) += ANOFFSET (delta, s->block_line_section);
ALL_BLOCK_SYMBOLS (b, j, sym)
{
fixup_symbol_section (sym, objfile);
if ((SYMBOL_CLASS (sym) == LOC_LABEL
|| SYMBOL_CLASS (sym) == LOC_STATIC
|| SYMBOL_CLASS (sym) == LOC_INDIRECT)
&& SYMBOL_SECTION (sym) >= 0)
{
SYMBOL_VALUE_ADDRESS (sym) +=
ANOFFSET (delta, SYMBOL_SECTION (sym));
}
#ifdef MIPS_EFI_SYMBOL_NAME
else if (SYMBOL_CLASS (sym) == LOC_CONST
&& SYMBOL_NAMESPACE (sym) == LABEL_NAMESPACE
&& strcmp (SYMBOL_NAME (sym), MIPS_EFI_SYMBOL_NAME) == 0)
ecoff_relocate_efi (sym, ANOFFSET (delta,
s->block_line_section));
#endif
}
}
}
}
{
struct partial_symtab *p;
ALL_OBJFILE_PSYMTABS (objfile, p)
{
p->textlow += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
p->texthigh += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
}
}
{
struct partial_symbol **psym;
for (psym = objfile->global_psymbols.list;
psym < objfile->global_psymbols.next;
psym++)
{
fixup_psymbol_section (*psym, objfile);
if (SYMBOL_SECTION (*psym) >= 0)
SYMBOL_VALUE_ADDRESS (*psym) += ANOFFSET (delta,
SYMBOL_SECTION (*psym));
}
for (psym = objfile->static_psymbols.list;
psym < objfile->static_psymbols.next;
psym++)
{
fixup_psymbol_section (*psym, objfile);
if (SYMBOL_SECTION (*psym) >= 0)
SYMBOL_VALUE_ADDRESS (*psym) += ANOFFSET (delta,
SYMBOL_SECTION (*psym));
}
}
{
struct minimal_symbol *msym;
ALL_OBJFILE_MSYMBOLS (objfile, msym)
if (SYMBOL_SECTION (msym) >= 0)
SYMBOL_VALUE_ADDRESS (msym) += ANOFFSET (delta, SYMBOL_SECTION (msym));
}
msymbols_sort (objfile);
{
int i;
for (i = 0; i < objfile->num_sections; ++i)
(objfile->section_offsets)->offsets[i] = ANOFFSET (new_offsets, i);
}
if (objfile->ei.entry_point != ~(CORE_ADDR) 0)
{
struct obj_section *s;
s = find_pc_section (objfile->ei.entry_point);
if (s)
objfile->ei.entry_point += ANOFFSET (delta, s->the_bfd_section->index);
else
objfile->ei.entry_point += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
}
{
struct obj_section *s;
bfd *abfd;
abfd = objfile->obfd;
ALL_OBJFILE_OSECTIONS (objfile, s)
{
int idx = s->the_bfd_section->index;
s->addr += ANOFFSET (delta, idx);
s->endaddr += ANOFFSET (delta, idx);
}
}
if (objfile->ei.entry_func_lowpc != INVALID_ENTRY_LOWPC)
{
objfile->ei.entry_func_lowpc += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
objfile->ei.entry_func_highpc += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
}
if (objfile->ei.entry_file_lowpc != INVALID_ENTRY_LOWPC)
{
objfile->ei.entry_file_lowpc += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
objfile->ei.entry_file_highpc += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
}
if (objfile->ei.main_func_lowpc != INVALID_ENTRY_LOWPC)
{
objfile->ei.main_func_lowpc += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
objfile->ei.main_func_highpc += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
}
breakpoint_re_set ();
}
int
have_partial_symbols (void)
{
struct objfile *ofp;
ALL_OBJFILES (ofp)
{
if (ofp->psymtabs != NULL)
{
return 1;
}
}
return 0;
}
int
have_full_symbols (void)
{
struct objfile *ofp;
ALL_OBJFILES (ofp)
{
if (ofp->symtabs != NULL)
{
return 1;
}
}
return 0;
}
void
objfile_purge_solibs (void)
{
struct objfile *objf;
struct objfile *temp;
ALL_OBJFILES_SAFE (objf, temp)
{
#if 0
if (!(objf->flags & OBJF_USERLOADED) && (objf->flags & OBJF_SHARED))
free_objfile (objf);
#endif
}
}
int
have_minimal_symbols (void)
{
struct objfile *ofp;
ALL_OBJFILES (ofp)
{
if (ofp->msymbols != NULL)
{
return 1;
}
}
return 0;
}
struct obj_section *
find_pc_sect_section (CORE_ADDR pc, struct sec *section)
{
struct obj_section *s;
struct objfile *objfile;
ALL_OBJSECTIONS (objfile, s)
if ((section == 0 || section == s->the_bfd_section) &&
s->addr <= pc && pc < s->endaddr)
return (s);
return (NULL);
}
struct obj_section *
find_pc_section (CORE_ADDR pc)
{
return find_pc_sect_section (pc, find_pc_mapped_section (pc));
}
int
in_plt_section (CORE_ADDR pc, char *name)
{
struct obj_section *s;
int retval = 0;
s = find_pc_section (pc);
retval = (s != NULL
&& s->the_bfd_section->name != NULL
&& STREQ (s->the_bfd_section->name, ".plt"));
return (retval);
}
int
is_in_import_list (char *name, struct objfile *objfile)
{
register int i;
if (!objfile || !name || !*name)
return 0;
for (i = 0; i < objfile->import_list_size; i++)
if (objfile->import_list[i] && STREQ (name, objfile->import_list[i]))
return 1;
return 0;
}
void
_initialize_objfiles (void)
{
struct cmd_list_element *c;
#if HAVE_MMAP
c = add_set_cmd ("generate-persistent-symbol-tables", class_obscure, var_boolean,
(char *) &mapped_symbol_files,
"Set if GDB should generate persistent symbol tables by default.",
&setlist);
add_show_from_set (c, &showlist);
c = add_set_cmd ("use-persistent-symbol-tables", class_obscure, var_boolean,
(char *) &use_mapped_symbol_files,
"Set if GDB should use persistent symbol tables by default.",
&setlist);
add_show_from_set (c, &showlist);
#endif
}