#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 "bcache.h"
#include "gdb_assert.h"
#include <sys/types.h>
#include "gdb_stat.h"
#include <fcntl.h>
#include "gdb_obstack.h"
#include "gdb_string.h"
#include "buildsym.h"
#include "hashtab.h"
#include "breakpoint.h"
#include "block.h"
#include "dictionary.h"
#if defined(USE_MMALLOC) && defined(HAVE_MMAP)
#include "mmalloc.h"
#ifdef FSF_OBJFILES
static int open_existing_mapped_file (char *, long, int);
static int open_mapped_file (char *filename, long mtime, int flags);
static void *map_to_file (int);
#endif
#endif
#ifdef FSF_OBJFILES
static void add_to_objfile_sections (bfd *, sec_ptr, void *);
#endif
static void objfile_remove_from_restrict_list (struct objfile *);
void objfile_alloc_data (struct objfile *objfile);
static void objfile_free_data (struct objfile *objfile);
#ifndef TEXT_SECTION_NAME
#define TEXT_SECTION_NAME ".text"
#endif
#ifndef DATA_SECTION_NAME
#define DATA_SECTION_NAME ".data"
#endif
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 = 0;
struct ordered_obj_section
{
struct obj_section *obj_section;
struct bfd_section *the_bfd_section;
CORE_ADDR addr;
CORE_ADDR endaddr;
};
static struct ordered_obj_section *ordered_sections;
static int num_ordered_sections = 0;
#define ORDERED_SECTIONS_CHUNK_SIZE 3000
static int max_num_ordered_sections = ORDERED_SECTIONS_CHUNK_SIZE;
static int find_in_ordered_sections_index (CORE_ADDR addr, struct bfd_section *bfd_section);
static int get_insert_index_in_ordered_sections (struct obj_section *section);
struct obj_section_with_index
{
int index;
struct obj_section *section;
};
static int
backward_section_compare (const void *left_ptr,
const void *right_ptr)
{
struct obj_section_with_index *left
= (struct obj_section_with_index *) left_ptr;
struct obj_section_with_index * right
= (struct obj_section_with_index *) right_ptr;
if (left->section->addr > right->section->addr)
return -1;
else if (left->section->addr < right->section->addr)
return 1;
else
return 0;
}
static int
forward_int_compare (const void *left_ptr,
const void *right_ptr)
{
int *left = (int *) left_ptr;
int *right = (int *) right_ptr;
if (*left < *right)
return -1;
else if (*left > *right)
return 1;
else
return 0;
}
#define STATIC_DELETE_LIST_SIZE 256
static int
number_of_dots (const char *s)
{
int numdots = 0;
while (*s != '\0')
{
if (*s == '.')
numdots++;
s++;
}
return numdots;
}
void
objfile_delete_from_ordered_sections (struct objfile *objfile)
{
int i;
int ndeleted;
int delete_list_size;
int static_delete_list[STATIC_DELETE_LIST_SIZE];
int *delete_list = static_delete_list;
struct obj_section *s;
delete_list_size = objfile->sections_end - objfile->sections;
if (delete_list_size > STATIC_DELETE_LIST_SIZE)
delete_list = (int *) xmalloc (delete_list_size * sizeof (int));
ndeleted = 0;
ALL_OBJFILE_OSECTIONS (objfile, s)
{
int index;
if (s->the_bfd_section && s->the_bfd_section->name &&
number_of_dots (s->the_bfd_section->name) == 1)
continue;
index = find_in_ordered_sections_index (s->addr, s->the_bfd_section);
if (index == -1)
warning ("Trying to remove a section from"
" the ordered section list that did not exist"
" at 0x%s.", paddr_nz (s->addr));
else
{
delete_list[ndeleted] = index;
ndeleted++;
}
}
qsort (delete_list, ndeleted, sizeof (int),
forward_int_compare);
delete_list[ndeleted] = num_ordered_sections;
for (i = 0; i < ndeleted; i++)
{
struct ordered_obj_section *src, *dest;
size_t len;
src = &(ordered_sections[delete_list[i] + 1]);
dest = &(ordered_sections[delete_list[i] - i]);
len = (delete_list[i+1] - delete_list[i] - 1)
* sizeof (struct ordered_obj_section);
bcopy (src, dest, len);
}
num_ordered_sections -= ndeleted;
if (delete_list != static_delete_list)
xfree (delete_list);
}
static int
get_insert_index_in_ordered_sections (struct obj_section *section)
{
int insert = -1;
if (num_ordered_sections > 0)
{
int bot = 0;
int top = num_ordered_sections - 1;
do
{
int mid = (top + bot) / 2;
if (ordered_sections[mid].addr < section->addr)
{
if ((mid == num_ordered_sections - 1)
|| (ordered_sections[mid + 1].addr >= section->addr))
{
insert = mid;
break;
}
else if (mid + 1 == num_ordered_sections - 1)
{
insert = mid + 1;
break;
}
bot = mid + 1;
}
else
{
if (mid == 0 || ordered_sections[mid - 1].addr <= section->addr)
{
insert = mid - 1;
break;
}
top = mid - 1;
}
} while (top > bot);
}
return insert + 1;
}
#define STATIC_INSERT_LIST_SIZE 256
void
objfile_add_to_ordered_sections (struct objfile *objfile)
{
struct obj_section *s;
int i, num_left, total;
struct obj_section_with_index static_insert_list[STATIC_INSERT_LIST_SIZE];
struct obj_section_with_index *insert_list = static_insert_list;
int insert_list_size;
CHECK_FATAL (objfile != NULL);
insert_list_size = objfile->sections_end - objfile->sections;
if (insert_list_size > STATIC_INSERT_LIST_SIZE)
insert_list = (struct obj_section_with_index *) xmalloc (insert_list_size * sizeof (struct obj_section_with_index));
total = 0;
ALL_OBJFILE_OSECTIONS (objfile, s)
{
if (s->the_bfd_section && s->the_bfd_section->name &&
number_of_dots (s->the_bfd_section->name) == 1)
continue;
insert_list[total].index = get_insert_index_in_ordered_sections (s);
insert_list[total].section = s;
total++;
}
qsort (insert_list, total, sizeof (struct obj_section_with_index),
backward_section_compare);
if (ordered_sections == NULL)
{
max_num_ordered_sections = ORDERED_SECTIONS_CHUNK_SIZE;
ordered_sections = (struct ordered_obj_section *)
xmalloc (max_num_ordered_sections
* sizeof (struct ordered_obj_section));
}
else if (num_ordered_sections + total >= max_num_ordered_sections)
{
max_num_ordered_sections += ORDERED_SECTIONS_CHUNK_SIZE + total;
ordered_sections = (struct ordered_obj_section *)
xrealloc (ordered_sections,
max_num_ordered_sections
* sizeof (struct ordered_obj_section));
}
num_left = total;
for (i = 0; i < total; i++)
{
struct ordered_obj_section *src;
struct ordered_obj_section *dest;
struct obj_section *s;
size_t len;
int pos;
src = &(ordered_sections[insert_list[i].index]);
dest = &(ordered_sections[insert_list[i].index + num_left]);
if (i == 0)
len = num_ordered_sections - insert_list[i].index;
else
len = insert_list[i - 1].index - insert_list[i].index;
len *= sizeof (struct ordered_obj_section);
bcopy (src, dest, len);
s = insert_list[i].section;
pos = insert_list[i].index + num_left - 1;
ordered_sections[pos].addr = s->addr;
ordered_sections[pos].endaddr = s->endaddr;
ordered_sections[pos].obj_section = s;
ordered_sections[pos].the_bfd_section = s->the_bfd_section;
num_left--;
if (num_left == 0)
break;
}
num_ordered_sections += total;
if (insert_list != static_insert_list)
xfree (insert_list);
}
static int
find_in_ordered_sections_index (CORE_ADDR addr, struct bfd_section *bfd_section)
{
int bot = 0;
int top = num_ordered_sections;
struct ordered_obj_section *obj_sect_ptr;
if (num_ordered_sections == 0)
return -1;
do
{
int mid = (top + bot) / 2;
obj_sect_ptr = &ordered_sections[mid];
if (obj_sect_ptr->addr <= addr)
{
if (addr < obj_sect_ptr->endaddr)
{
if ((bfd_section == NULL )
|| (bfd_section == obj_sect_ptr->the_bfd_section))
return mid;
else
{
int pos;
for (pos = mid + 1; pos < num_ordered_sections; pos++)
{
if (ordered_sections[pos].addr > addr)
break;
else if ((ordered_sections[pos].endaddr > addr)
&& (ordered_sections[pos].the_bfd_section == bfd_section))
return pos;
}
for (pos = mid - 1; pos >= 0; pos--)
{
if ((ordered_sections[pos].endaddr > addr)
&& (ordered_sections[pos].the_bfd_section == bfd_section))
return pos;
}
return -1;
}
}
bot = mid + 1;
}
else
{
top = mid - 1;
}
} while (bot <= top);
return -1;
}
struct obj_section *
find_pc_sect_in_ordered_sections (CORE_ADDR addr, struct bfd_section *bfd_section)
{
int index = find_in_ordered_sections_index (addr, bfd_section);
if (index == -1)
return NULL;
else
return ordered_sections[index].obj_section;
}
#ifdef FSF_OBJFILES
#ifndef TARGET_KEEP_SECTION
#define TARGET_KEEP_SECTION(ASECT) 0
#endif
static void
add_to_objfile_sections (struct bfd *abfd, struct bfd_section *asect,
void *objfile_p_char)
{
struct objfile *objfile = (struct objfile *) objfile_p_char;
struct obj_section section;
flagword aflag;
aflag = bfd_get_section_flags (abfd, asect);
if (!(aflag & SEC_ALLOC) && !(TARGET_KEEP_SECTION (asect)))
return;
if (0 == bfd_section_size (abfd, asect))
return;
section.offset = 0;
section.objfile = objfile;
section.the_bfd_section = asect;
section.ovly_mapped = 0;
section.addr = bfd_section_vma (abfd, asect);
section.endaddr = section.addr + bfd_section_size (abfd, asect);
obstack_grow (&objfile->objfile_obstack, (char *) §ion, sizeof (section));
objfile->sections_end = (struct obj_section *) (((unsigned long) objfile->sections_end) + 1);
}
int
build_objfile_section_table (struct objfile *objfile)
{
objfile->sections_end = 0;
bfd_map_over_sections (objfile->obfd, add_to_objfile_sections, (char *) objfile);
objfile->sections = (struct obj_section *)
obstack_finish (&objfile->objfile_obstack);
objfile->sections_end = objfile->sections + (unsigned long) objfile->sections_end;
objfile_add_to_ordered_sections (objfile);
return (0);
}
struct objfile *
allocate_objfile (bfd *abfd, int flags)
{
struct objfile *objfile = NULL;
if (mapped_symbol_files)
flags |= OBJF_MAPPED;
#if defined(USE_MMALLOC) && defined(HAVE_MMAP)
if (abfd != NULL)
{
int fd;
fd = open_mapped_file (bfd_get_filename (abfd), bfd_get_mtime (abfd),
flags);
if (fd >= 0)
{
void *md;
if ((md = map_to_file (fd)) == NULL)
{
close (fd);
}
else if ((objfile = (struct objfile *) mmalloc_getkey (md, 0)) != NULL)
{
init_malloc (md);
objfile->md = md;
objfile->mmfd = fd;
if (objfile->demangled_names_hash)
htab_set_functions_ex
(objfile->demangled_names_hash, htab_hash_string,
(int (*) (const void *, const void *)) streq, NULL,
objfile->md, xmcalloc, xmfree);
obstack_chunkfun (&objfile->psymbol_cache.cache, xmmalloc);
obstack_freefun (&objfile->psymbol_cache.cache, xmfree);
obstack_chunkfun (&objfile->macro_cache.cache, xmmalloc);
obstack_freefun (&objfile->macro_cache.cache, xmfree);
obstack_chunkfun (&objfile->psymbol_obstack, xmmalloc);
obstack_freefun (&objfile->psymbol_obstack, xmfree);
obstack_chunkfun (&objfile->symbol_obstack, xmmalloc);
obstack_freefun (&objfile->symbol_obstack, xmfree);
obstack_chunkfun (&objfile->type_obstack, xmmalloc);
obstack_freefun (&objfile->type_obstack, xmfree);
unlink_objfile (objfile);
objfile->sf = NULL;
}
else
{
init_malloc (md);
objfile = (struct objfile *)
xmmalloc (md, sizeof (struct objfile));
memset (objfile, 0, sizeof (struct objfile));
objfile->md = md;
objfile->mmfd = fd;
objfile->flags |= OBJF_MAPPED;
mmalloc_setkey (objfile->md, 0, objfile);
obstack_specify_allocation_with_arg (&objfile->psymbol_cache.cache,
0, 0, xmmalloc, xmfree,
objfile->md);
obstack_specify_allocation_with_arg (&objfile->macro_cache.cache,
0, 0, xmmalloc, xmfree,
objfile->md);
obstack_specify_allocation_with_arg (&objfile->psymbol_obstack,
0, 0, xmmalloc, xmfree,
objfile->md);
obstack_specify_allocation_with_arg (&objfile->symbol_obstack,
0, 0, xmmalloc, xmfree,
objfile->md);
obstack_specify_allocation_with_arg (&objfile->type_obstack,
0, 0, xmmalloc, xmfree,
objfile->md);
}
}
if ((flags & OBJF_MAPPED) && (objfile == NULL))
{
warning ("symbol table for '%s' will not be mapped",
bfd_get_filename (abfd));
flags &= ~OBJF_MAPPED;
}
}
#else
if (flags & OBJF_MAPPED)
{
warning ("mapped symbol tables are not supported on this machine; missing or broken mmap().");
mapped_symbol_files = 0;
flags &= ~OBJF_MAPPED;
}
#endif
if (objfile == NULL)
{
objfile = (struct objfile *) xmalloc (sizeof (struct objfile));
memset (objfile, 0, sizeof (struct objfile));
objfile->md = NULL;
objfile->psymbol_cache = bcache_xmalloc (NULL);
objfile->macro_cache = bcache_xmalloc (NULL);
obstack_init (&objfile->objfile_obstack);
terminate_minimal_symbol_table (objfile);
flags &= ~OBJF_MAPPED;
}
objfile_alloc_data (objfile);
objfile->obfd = abfd;
if (objfile->name != NULL)
{
xmfree (objfile->md, objfile->name);
}
if (abfd != NULL)
{
objfile->name = mstrsave (objfile->md, bfd_get_filename (abfd));
objfile->mtime = bfd_get_mtime (abfd);
if (build_objfile_section_table (objfile))
{
error ("Can't find the file sections in `%s': %s",
objfile->name, bfd_errmsg (bfd_get_error ()));
}
}
else
{
objfile->name = mstrsave (objfile->md, "<<anonymous objfile>>");
}
objfile->sect_index_text = -1;
objfile->sect_index_data = -1;
objfile->sect_index_bss = -1;
objfile->sect_index_rodata = -1;
objfile->cp_namespace_symtab = NULL;
objfile->flags |= flags;
objfile->symflags = -1;
link_objfile (objfile);
return (objfile);
}
#endif
void
init_entry_point_info (struct objfile *objfile)
{
if (bfd_get_file_flags (objfile->obfd) & EXEC_P)
{
objfile->ei.entry_point = bfd_get_start_address (objfile->obfd);
}
else
{
objfile->ei.entry_point = INVALID_ENTRY_POINT;
}
objfile->ei.deprecated_entry_file_lowpc = INVALID_ENTRY_LOWPC;
objfile->ei.deprecated_entry_file_highpc = INVALID_ENTRY_HIGHPC;
objfile->ei.entry_func_lowpc = INVALID_ENTRY_LOWPC;
objfile->ei.entry_func_highpc = INVALID_ENTRY_HIGHPC;
objfile->ei.main_func_lowpc = INVALID_ENTRY_LOWPC;
objfile->ei.main_func_highpc = INVALID_ENTRY_HIGHPC;
}
CORE_ADDR
entry_point_address (void)
{
return symfile_objfile ? symfile_objfile->ei.entry_point : 0;
}
void
terminate_minimal_symbol_table (struct objfile *objfile)
{
if (! objfile->msymbols)
objfile->msymbols = ((struct minimal_symbol *)
obstack_alloc (&objfile->objfile_obstack,
sizeof (objfile->msymbols[0])));
{
struct minimal_symbol *m
= &objfile->msymbols[objfile->minimal_symbol_count];
memset (m, 0, sizeof (*m));
MSYMBOL_TYPE (m) = mst_unknown;
SYMBOL_INIT_LANGUAGE_SPECIFIC (m, language_unknown);
}
}
void
put_objfile_before (struct objfile *objfile, struct objfile *before_this)
{
struct objfile **objp;
unlink_objfile (objfile);
for (objp = &object_files; *objp != NULL; objp = &((*objp)->next))
{
if (*objp == before_this)
{
objfile->next = *objp;
*objp = objfile;
return;
}
}
internal_error (__FILE__, __LINE__,
"put_objfile_before: before objfile not in list");
}
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
link_objfile (struct objfile *objfile)
{
struct objfile *last_one = NULL;
struct objfile *o, *temp;
ALL_OBJFILES_SAFE (o, temp)
if (objfile == o)
internal_error (__FILE__, __LINE__,
"link_objfile: objfile already linked");
if (objfile->next != NULL)
internal_error (__FILE__, __LINE__,
"link_objfile: objfile already linked");
objfile->next = NULL;
if (object_files == NULL)
object_files = objfile;
else
{
for (last_one = object_files;
last_one->next;
last_one = last_one->next);
last_one->next = objfile;
}
}
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->separate_debug_objfile)
{
free_objfile (objfile->separate_debug_objfile);
}
if (objfile->separate_debug_objfile_backlink)
{
objfile->separate_debug_objfile_backlink->separate_debug_objfile = NULL;
}
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);
objfile_remove_from_restrict_list (objfile);
objfile_delete_from_ordered_sections (objfile);
if (objfile == rt_common_objfile)
rt_common_objfile = NULL;
clear_pc_function_cache ();
objfile_free_data (objfile);
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);
bcache_xfree (objfile->psymbol_cache);
bcache_xfree (objfile->macro_cache);
if (objfile->demangled_names_hash)
htab_delete (objfile->demangled_names_hash);
obstack_free (&objfile->objfile_obstack, 0);
xmfree (objfile->md, objfile);
objfile = NULL;
}
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_N_SECTION_OFFSETS (objfile->num_sections)));
{
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)
{
unsigned int num_discontinuities = 0;
int discontinuity_index = -1;
for (i = 0; i < l->nitems; ++i)
l->item[i].pc += ANOFFSET (delta, s->block_line_section);
for (i = 0; i < (l->nitems - 1); ++i)
if (l->item[i].pc > l->item[i + 1].pc)
{
num_discontinuities++;
discontinuity_index = i + 1;
}
if (num_discontinuities == 1)
{
struct linetable *new_linetable = NULL;
size_t size = ((l->nitems - 1) * sizeof (struct linetable_entry))
+ sizeof (struct linetable);
new_linetable = (struct linetable *) xmalloc (size);
memcpy (new_linetable, l, sizeof (struct linetable));
memcpy (new_linetable->item,
l->item + discontinuity_index,
(l->nitems - discontinuity_index) * sizeof (struct linetable_entry));
memcpy (new_linetable->item + (l->nitems - discontinuity_index),
l->item,
discontinuity_index * sizeof (struct linetable_entry));
memcpy (l->item, new_linetable->item, l->nitems * sizeof (struct linetable_entry));
xfree (new_linetable);
}
else if (num_discontinuities > 0)
{
warning ("line table was not properly sorted; re-sorting");
qsort (l->item, l->nitems, sizeof (struct linetable_entry), compare_line_numbers);
}
}
if (!s->primary)
continue;
bv = BLOCKVECTOR (s);
for (i = 0; i < BLOCKVECTOR_NBLOCKS (bv); ++i)
{
struct block *b;
struct symbol *sym;
struct dict_iterator iter;
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, iter, 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_DOMAIN (sym) == LABEL_DOMAIN
&& strcmp (DEPRECATED_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;
objfile_delete_from_ordered_sections (objfile);
ALL_OBJFILE_OSECTIONS (objfile, s)
{
int idx = s->the_bfd_section->index;
s->addr += ANOFFSET (delta, idx);
s->endaddr += ANOFFSET (delta, idx);
}
objfile_add_to_ordered_sections (objfile);
}
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.deprecated_entry_file_lowpc != INVALID_ENTRY_LOWPC)
{
objfile->ei.deprecated_entry_file_lowpc += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
objfile->ei.deprecated_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 (objfile);
}
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)
{
#ifdef NM_MACOSX
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->minimal_symbol_count > 0)
{
return 1;
}
}
return 0;
}
#ifdef FSF_OBJFILES
#if defined(USE_MMALLOC) && defined(HAVE_MMAP)
static int
open_existing_mapped_file (char *symsfilename, long mtime, int flags)
{
int fd = -1;
struct stat sbuf;
if (stat (symsfilename, &sbuf) == 0)
{
if (sbuf.st_mtime < mtime)
{
if (!(flags & OBJF_MAPPED))
{
warning ("mapped symbol file `%s' is out of date, ignored it",
symsfilename);
}
}
else if ((fd = open (symsfilename, O_RDWR)) < 0)
{
if (error_pre_print)
{
printf_unfiltered (error_pre_print);
}
print_sys_errmsg (symsfilename, errno);
}
}
return (fd);
}
static int
open_mapped_file (char *filename, long mtime, int flags)
{
int fd;
char *symsfilename;
symsfilename = concat ("./", lbasename (filename), ".syms", (char *) NULL);
if ((fd = open_existing_mapped_file (symsfilename, mtime, flags)) < 0)
{
xfree (symsfilename);
symsfilename = concat (filename, ".syms", (char *) NULL);
fd = open_existing_mapped_file (symsfilename, mtime, flags);
}
if ((fd < 0) && (flags & OBJF_MAPPED))
{
xfree (symsfilename);
symsfilename = concat ("./", lbasename (filename), ".syms",
(char *) NULL);
if ((fd = open (symsfilename, O_RDWR | O_CREAT | O_TRUNC, 0666)) < 0)
{
if (error_pre_print)
{
printf_unfiltered (error_pre_print);
}
print_sys_errmsg (symsfilename, errno);
}
}
xfree (symsfilename);
return (fd);
}
static void *
map_to_file (int fd)
{
void *md;
CORE_ADDR mapto;
md = mmalloc_attach (fd, 0);
if (md != NULL)
{
mapto = (CORE_ADDR) mmalloc_getkey (md, 1);
md = mmalloc_detach (md);
if (md != NULL)
{
md = NULL;
}
else if (mapto != (CORE_ADDR) NULL)
{
md = mmalloc_attach (fd, mapto);
}
else
{
mapto = (CORE_ADDR) mmalloc_findbase (20 * 1024 * 1024);
if (mapto != 0)
{
ftruncate (fd, 0);
md = mmalloc_attach (fd, mapto);
if (md != NULL)
{
mmalloc_setkey (md, 1, mapto);
}
}
}
}
return (md);
}
#endif
#endif
struct obj_section *
find_pc_sect_section (CORE_ADDR pc, struct bfd_section *section)
{
struct obj_section *s;
struct objfile *objfile;
s = find_pc_sect_in_ordered_sections (pc, section);
if (s != NULL)
return (s);
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
&& strcmp (s->the_bfd_section->name, ".plt") == 0);
return (retval);
}
int
is_in_import_list (char *name, struct objfile *objfile)
{
int i;
if (!objfile || !name || !*name)
return 0;
for (i = 0; i < objfile->import_list_size; i++)
if (objfile->import_list[i] && DEPRECATED_STREQ (name, objfile->import_list[i]))
return 1;
return 0;
}
static struct objfile_list *objfile_list_ptr;
static int restrict_search = 0;
struct objfile_list *objfile_list;
int
objfile_restrict_search (int on)
{
int old = restrict_search;
restrict_search = on;
return old;
}
void
objfile_add_to_restrict_list (struct objfile *objfile)
{
struct objfile_list *new_objfile = (struct objfile_list *)
xmalloc (sizeof (struct objfile_list));
new_objfile->next = objfile_list;
new_objfile->objfile = objfile;
objfile_list = new_objfile;
}
static void
objfile_remove_from_restrict_list (struct objfile *objfile)
{
struct objfile_list **objpp;
struct objfile_list *i;
for (objpp = &objfile_list; *objpp != NULL; objpp = &((*objpp)->next))
{
if ((*objpp)->objfile == objfile)
{
i = *objpp;
*objpp = (*objpp)->next;
xfree (i);
return;
}
}
}
void
objfile_clear_restrict_list ()
{
while (objfile_list != NULL)
{
struct objfile_list *list_ptr;
list_ptr = objfile_list;
objfile_list = list_ptr->next;
xfree (list_ptr);
}
}
struct swap_objfile_list_cleanup
{
struct objfile_list *old_list;
int restrict_state;
};
void
do_cleanup_restrict_to_objfile (void *arg)
{
struct swap_objfile_list_cleanup *data =
(struct swap_objfile_list_cleanup *) arg;
objfile_clear_restrict_list ();
objfile_list = data->old_list;
objfile_restrict_search (data->restrict_state);
}
struct cleanup *
make_cleanup_restrict_to_objfile (struct objfile *objfile)
{
struct swap_objfile_list_cleanup *data
= (struct swap_objfile_list_cleanup *) xmalloc (sizeof (struct swap_objfile_list_cleanup));
data->old_list = objfile_list;
objfile_list = NULL;
objfile_add_to_restrict_list (objfile);
data->restrict_state = objfile_restrict_search (1);
return make_cleanup (do_cleanup_restrict_to_objfile, (void *) data);
}
#define CACHED_SYM_SUFFIX ".syms"
int
objfile_matches_name (struct objfile *objfile, char *name)
{
const char *filename;
int len;
static int suffixlen = strlen (CACHED_SYM_SUFFIX);
const char *real_name;
if (objfile->name == NULL)
return 0;
len = strlen (objfile->name);
if (len > suffixlen
&& strcmp (objfile->name + len - suffixlen, CACHED_SYM_SUFFIX) == 0
&& objfile->obfd != NULL && objfile->obfd->filename != NULL)
{
real_name = objfile->obfd->filename;
}
else
real_name = objfile->name;
if (strcmp (real_name, name) == 0)
return 1;
filename = lbasename (real_name);
if (filename == NULL)
return 0;
if (strcmp (filename, name) == 0)
return 1;
return 0;
}
struct cleanup *
make_cleanup_restrict_to_shlib (char *requested_shlib)
{
struct objfile *requested_objfile = NULL;
struct objfile *tmp_obj;
if (requested_shlib == NULL)
return NULL;
ALL_OBJFILES (tmp_obj)
{
if (objfile_matches_name (tmp_obj, requested_shlib))
{
requested_objfile = tmp_obj;
break;
}
}
if (requested_objfile == NULL)
return (void *) -1;
else
return make_cleanup_restrict_to_objfile (requested_objfile);
}
struct objfile *
objfile_get_first ()
{
if (!restrict_search || objfile_list == NULL)
return object_files;
else
{
objfile_list_ptr = objfile_list->next;
return objfile_list->objfile;
}
}
struct objfile *
objfile_get_next (struct objfile *in_objfile)
{
struct objfile *objfile;
if (!restrict_search || objfile_list == NULL)
{
if (in_objfile)
return in_objfile->next;
else
return NULL;
}
if (objfile_list_ptr == NULL)
{
return NULL;
}
objfile = objfile_list_ptr->objfile;
objfile_list_ptr = objfile_list_ptr->next;
return objfile;
}
int
objfile_set_load_state (struct objfile *o, int load_state)
{
if (o->symflags >= load_state)
return 1;
#ifdef NM_NEXTSTEP
extern int dyld_objfile_set_load_state (struct objfile *, int);
return dyld_objfile_set_load_state (o, load_state);
#else
return 1;
#endif
}
int
pc_set_load_state (CORE_ADDR pc, int load_state)
{
struct obj_section *s;
s = find_pc_section (pc);
if (s == NULL)
return 0;
if (s->objfile == NULL)
return 0;
return objfile_set_load_state (s->objfile, load_state);
}
static void
sanity_check_symtab_obsoleted_flag (struct symtab *s)
{
if (s != NULL &&
SYMTAB_OBSOLETED (s) != 51 &&
SYMTAB_OBSOLETED (s) != 50)
{
struct objfile *objfile;
struct symtab *symtab;
const char *objfile_name = "(not found)";
const char *symtab_name = "(null)";
ALL_SYMTABS_INCL_OBSOLETED (objfile, symtab)
if (symtab == s)
{
objfile_name = objfile->name;
break;
}
if (s->filename)
symtab_name = s->filename;
error ("Symtab with invalid OBSOLETED flag setting. "
"Value is %d, symtab name is %s objfile name is %s",
SYMTAB_OBSOLETED (s), symtab_name, objfile_name);
}
}
static void sanity_check_psymtab_obsoleted_flag (struct partial_symtab *ps)
{
if (ps != NULL &&
PSYMTAB_OBSOLETED (ps) != 51 &&
PSYMTAB_OBSOLETED (ps) != 50)
{
struct objfile *objfile;
struct partial_symtab *psymtab;
const char *objfile_name = "(not found)";
const char *psymtab_name = "(null)";
ALL_PSYMTABS_INCL_OBSOLETED (objfile, psymtab)
if (psymtab == ps)
{
objfile_name = objfile->name;
break;
}
if (ps->filename)
psymtab_name = ps->filename;
error ("Psymtab with invalid OBSOLETED flag setting. "
"Value is %d, psymtab name is %s, objfile name is %s",
PSYMTAB_OBSOLETED (ps), psymtab_name, objfile_name);
}
}
struct symtab *
symtab_get_first (struct objfile *objfile, int skip_obsolete)
{
struct symtab *s;
s = objfile->symtabs;
if (skip_obsolete)
sanity_check_symtab_obsoleted_flag (s);
while (s != NULL && skip_obsolete && SYMTAB_OBSOLETED (s) == 51)
{
s = s->next;
if (skip_obsolete)
sanity_check_symtab_obsoleted_flag (s);
}
return (s);
}
struct symtab *
symtab_get_next (struct symtab *s, int skip_obsolete)
{
if (s == NULL)
return NULL;
s = s->next;
if (skip_obsolete)
sanity_check_symtab_obsoleted_flag (s);
while (s != NULL && skip_obsolete && SYMTAB_OBSOLETED (s) == 51)
{
s = s->next;
if (skip_obsolete)
sanity_check_symtab_obsoleted_flag (s);
}
return s;
}
struct partial_symtab *
psymtab_get_first (struct objfile *objfile, int skip_obsolete)
{
struct partial_symtab *ps;
ps = objfile->psymtabs;
if (skip_obsolete)
sanity_check_psymtab_obsoleted_flag (ps);
while (ps != NULL && skip_obsolete && PSYMTAB_OBSOLETED (ps) == 51)
{
if (skip_obsolete)
sanity_check_psymtab_obsoleted_flag (ps);
ps = ps->next;
}
return (ps);
}
struct partial_symtab *
psymtab_get_next (struct partial_symtab *ps, int skip_obsolete)
{
if (ps == NULL)
return NULL;
ps = ps->next;
if (skip_obsolete)
sanity_check_psymtab_obsoleted_flag (ps);
while (ps != NULL && skip_obsolete && PSYMTAB_OBSOLETED (ps) == 51)
{
ps = ps->next;
if (skip_obsolete)
sanity_check_psymtab_obsoleted_flag (ps);
}
return ps;
}
struct objfile_data
{
unsigned index;
};
struct objfile_data_registration
{
struct objfile_data *data;
struct objfile_data_registration *next;
};
struct objfile_data_registry
{
struct objfile_data_registration *registrations;
unsigned num_registrations;
};
static struct objfile_data_registry objfile_data_registry = { NULL, 0 };
const struct objfile_data *
register_objfile_data (void)
{
struct objfile_data_registration **curr;
for (curr = &objfile_data_registry.registrations;
*curr != NULL; curr = &(*curr)->next);
*curr = XMALLOC (struct objfile_data_registration);
(*curr)->next = NULL;
(*curr)->data = XMALLOC (struct objfile_data);
(*curr)->data->index = objfile_data_registry.num_registrations++;
return (*curr)->data;
}
void
objfile_alloc_data (struct objfile *objfile)
{
gdb_assert (objfile->data == NULL);
objfile->num_data = objfile_data_registry.num_registrations;
objfile->data = XCALLOC (objfile->num_data, void *);
}
static void
objfile_free_data (struct objfile *objfile)
{
gdb_assert (objfile->data != NULL);
xfree (objfile->data);
objfile->data = NULL;
}
void
clear_objfile_data (struct objfile *objfile)
{
gdb_assert (objfile->data != NULL);
memset (objfile->data, 0, objfile->num_data * sizeof (void *));
}
void
set_objfile_data (struct objfile *objfile, const struct objfile_data *data,
void *value)
{
gdb_assert (data->index < objfile->num_data);
objfile->data[data->index] = value;
}
void *
objfile_data (struct objfile *objfile, const struct objfile_data *data)
{
gdb_assert (data->index < objfile->num_data);
return objfile->data[data->index];
}
void
_initialize_objfiles (void)
{
struct cmd_list_element *c;
#if HAVE_MMAP
c = add_set_cmd ("generate-cached-symfiles", 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-cached-symfiles", 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);
c = add_set_cmd ("generate-precompiled-symfiles", 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-precompiled-symfiles", 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
}