#include "defs.h"
#include "gdb_string.h"
#if defined(__CYGNUSCLIB__)
#include <sys/types.h>
#include <fcntl.h>
#endif
static int read_type_psym_p = 1;
static int end_fun_absolute_p = 0;
#include "gdb_obstack.h"
#include "gdb_stat.h"
#include "symtab.h"
#include "breakpoint.h"
#include "command.h"
#include "gdbcmd.h"
#include "target.h"
#include "gdbcore.h"
#include "libaout.h"
#include "objfiles.h"
#include "buildsym.h"
#include "stabsread.h"
#include "gdb-stabs.h"
#include "demangle.h"
#include "complaints.h"
#include "cp-abi.h"
#include "mach-o.h"
#include "block.h"
#include "gdb_assert.h"
#include "gdb_string.h"
#include "aout/aout64.h"
#include "aout/stab_gnu.h"
struct symloc
{
int ldsymoff;
int ldsymlen;
int symbol_size;
int symbol_offset;
int string_offset;
int file_string_offset;
const char *prefix;
};
#define LDSYMOFF(p) (((struct symloc *)((p)->read_symtab_private))->ldsymoff)
#define LDSYMLEN(p) (((struct symloc *)((p)->read_symtab_private))->ldsymlen)
#define SYMLOC(p) ((struct symloc *)((p)->read_symtab_private))
#define SYMBOL_SIZE(p) (SYMLOC(p)->symbol_size)
#define SYMBOL_OFFSET(p) (SYMLOC(p)->symbol_offset)
#define STRING_OFFSET(p) (SYMLOC(p)->string_offset)
#define FILE_STRING_OFFSET(p) (SYMLOC(p)->file_string_offset)
#define SYMBOL_PREFIX(p) (SYMLOC(p)->prefix)
static enum language psymtab_language = language_unknown;
static struct objfile *processing_objfile;
static unsigned symbol_size;
static unsigned symbol_table_offset;
static unsigned string_table_offset;
static unsigned int file_string_table_offset;
static unsigned int next_file_string_table_offset;
static int symfile_relocatable = 0;
static int block_address_function_relative = 0;
static CORE_ADDR lowest_text_address;
static int has_line_numbers;
static void read_ofile_symtab_from_oso (struct partial_symtab *pst,
struct bfd *oso_bfd);
static struct cleanup *
stabsect_read_strtab_from_oso (struct bfd *oso_bfd, int *symcount,
int *symsize, int *strtab_size,
bfd_byte **stab_data_handle, char **strtab_data_handle);
static void
unknown_symtype_complaint (const char *arg1)
{
complaint (&symfile_complaints, _("unknown symbol type %s"), arg1);
}
static void
lbrac_mismatch_complaint (int arg1)
{
complaint (&symfile_complaints,
_("N_LBRAC/N_RBRAC symbol mismatch at symtab pos %d"), arg1);
}
static void
repeated_header_complaint (const char *arg1, int arg2)
{
complaint (&symfile_complaints,
_("\"repeated\" header file %s not previously seen, at symtab pos %d"),
arg1, arg2);
}
static void
find_text_range (bfd * sym_bfd, struct objfile *objfile)
{
asection *sec;
int found_any = 0;
CORE_ADDR start = 0;
CORE_ADDR end = 0;
for (sec = sym_bfd->sections; sec; sec = sec->next)
if (bfd_get_section_flags (sym_bfd, sec) & SEC_CODE)
{
CORE_ADDR sec_start = bfd_section_vma (sym_bfd, sec);
CORE_ADDR sec_end = sec_start + bfd_section_size (sym_bfd, sec);
if (found_any)
{
if (sec_start < start)
start = sec_start;
if (sec_end > end)
end = sec_end;
}
else
{
start = sec_start;
end = sec_end;
}
found_any = 1;
}
if (!found_any)
error (_("Can't find any code sections in symbol file"));
DBX_TEXT_ADDR (objfile) = start;
DBX_TEXT_SIZE (objfile) = end - start;
}
struct header_file_location
{
char *name;
unsigned long hash;
int instance;
struct partial_symtab *pst;
};
static struct header_file_location *bincl_list, *next_bincl;
static int bincls_allocated;
extern void _initialize_dbxread (void);
static void read_ofile_symtab (struct partial_symtab *);
static void dbx_psymtab_to_symtab (struct partial_symtab *);
static void dbx_psymtab_to_symtab_1 (struct partial_symtab *);
static void read_dbx_dynamic_symtab (struct objfile *objfile);
static void read_dbx_symtab (struct objfile *, int);
static void free_bincl_list (struct objfile *);
static struct partial_symtab *find_corresponding_bincl_psymtab (char *, int);
static void add_bincl_to_list (struct partial_symtab *, char *, int);
static void init_bincl_list (int, struct objfile *);
static char *dbx_next_symbol_text (struct objfile *);
static void fill_symbuf (struct objfile *);
static void dbx_symfile_init (struct objfile *);
static void dbx_new_init (struct objfile *);
void dbx_symfile_read (struct objfile *, int);
static void dbx_symfile_finish (struct objfile *);
static void record_minimal_symbol (char *, CORE_ADDR, int, struct objfile *);
static void add_new_header_file (char *, int);
static void add_old_header_file (char *, int);
static void add_this_object_header_file (int);
static struct partial_symtab *start_psymtab (struct objfile *, char *,
CORE_ADDR, int,
struct partial_symbol **,
struct partial_symbol **,
const char *prefix);
static enum language read_so_stab_language_hint (short unsigned n_desc);
static int objfile_contains_objc (struct objfile *objfile);
void
free_header_files (void)
{
if (this_object_header_files)
{
xfree (this_object_header_files);
this_object_header_files = NULL;
}
n_allocated_this_object_header_files = 0;
}
void
init_header_files (void)
{
n_allocated_this_object_header_files = 10;
this_object_header_files = (int *) xmalloc (10 * sizeof (int));
}
static void
add_this_object_header_file (int i)
{
if (n_this_object_header_files == n_allocated_this_object_header_files)
{
n_allocated_this_object_header_files *= 2;
this_object_header_files
= (int *) xrealloc ((char *) this_object_header_files,
n_allocated_this_object_header_files * sizeof (int));
}
this_object_header_files[n_this_object_header_files++] = i;
}
static void
add_old_header_file (char *name, int instance)
{
struct header_file *p = HEADER_FILES (current_objfile);
int i;
for (i = 0; i < N_HEADER_FILES (current_objfile); i++)
if (strcmp (p[i].name, name) == 0 && instance == p[i].instance)
{
add_this_object_header_file (i);
return;
}
repeated_header_complaint (name, symnum);
}
static void
add_new_header_file (char *name, int instance)
{
int i;
struct header_file *hfile;
i = N_ALLOCATED_HEADER_FILES (current_objfile);
if (N_HEADER_FILES (current_objfile) == i)
{
if (i == 0)
{
N_ALLOCATED_HEADER_FILES (current_objfile) = 10;
HEADER_FILES (current_objfile) = (struct header_file *)
xmalloc (10 * sizeof (struct header_file));
}
else
{
i *= 2;
N_ALLOCATED_HEADER_FILES (current_objfile) = i;
HEADER_FILES (current_objfile) = (struct header_file *)
xrealloc ((char *) HEADER_FILES (current_objfile),
(i * sizeof (struct header_file)));
}
}
i = N_HEADER_FILES (current_objfile)++;
hfile = HEADER_FILES (current_objfile) + i;
hfile->name = savestring (name, strlen (name));
hfile->instance = instance;
hfile->length = 10;
hfile->vector
= (struct type **) xmalloc (10 * sizeof (struct type *));
memset (hfile->vector, 0, 10 * sizeof (struct type *));
add_this_object_header_file (i);
}
#if 0
static struct type **
explicit_lookup_type (int real_filenum, int index)
{
struct header_file *f = &HEADER_FILES (current_objfile)[real_filenum];
if (index >= f->length)
{
f->length *= 2;
f->vector = (struct type **)
xrealloc (f->vector, f->length * sizeof (struct type *));
memset (&f->vector[f->length / 2],
'\0', f->length * sizeof (struct type *) / 2);
}
return &f->vector[index];
}
#endif
static void
record_minimal_symbol (char *name, CORE_ADDR address, int type,
struct objfile *objfile)
{
enum minimal_symbol_type ms_type;
int section;
asection *bfd_section;
switch (type)
{
case N_TEXT | N_EXT:
ms_type = mst_text;
section = SECT_OFF_TEXT (objfile);
if (address >= DBX_TEXT_ADDR (objfile) &&
address < DBX_TEXT_ADDR (objfile) + DBX_TEXT_SIZE (objfile))
{
bfd_section = DBX_TEXT_SECTION (objfile)->the_bfd_section;
}
else if (address >= DBX_COALESCED_TEXT_ADDR (objfile) &&
address < DBX_COALESCED_TEXT_ADDR (objfile) + DBX_COALESCED_TEXT_SIZE (objfile))
{
bfd_section = DBX_COALESCED_TEXT_SECTION (objfile)->the_bfd_section;
}
else
bfd_section = DBX_TEXT_SECTION (objfile)->the_bfd_section;
break;
case N_DATA | N_EXT:
ms_type = mst_data;
section = SECT_OFF_DATA (objfile);
bfd_section = DBX_DATA_SECTION (objfile)->the_bfd_section;
break;
case N_BSS | N_EXT:
ms_type = mst_bss;
section = SECT_OFF_BSS (objfile);
bfd_section = DBX_BSS_SECTION (objfile)->the_bfd_section;
break;
case N_ABS | N_EXT:
ms_type = mst_abs;
section = -1;
bfd_section = NULL;
break;
#ifdef N_SETV
case N_SETV | N_EXT:
ms_type = mst_data;
section = SECT_OFF_DATA (objfile);
bfd_section = DBX_DATA_SECTION (objfile)->the_bfd_section;
break;
case N_SETV:
ms_type = mst_file_data;
section = SECT_OFF_DATA (objfile);
bfd_section = DBX_DATA_SECTION (objfile)->the_bfd_section;
break;
#endif
case N_TEXT:
case N_NBTEXT:
case N_FN:
case N_FN_SEQ:
ms_type = mst_file_text;
section = SECT_OFF_TEXT (objfile);
if (address >= DBX_TEXT_ADDR (objfile) &&
address < DBX_TEXT_ADDR (objfile) + DBX_TEXT_SIZE (objfile))
{
bfd_section = DBX_TEXT_SECTION (objfile)->the_bfd_section;
}
else if (address >= DBX_COALESCED_TEXT_ADDR (objfile) &&
address < DBX_COALESCED_TEXT_ADDR (objfile) + DBX_COALESCED_TEXT_SIZE (objfile))
{
bfd_section = DBX_COALESCED_TEXT_SECTION (objfile)->the_bfd_section;
}
else
bfd_section = DBX_TEXT_SECTION (objfile)->the_bfd_section;
break;
case N_DATA:
ms_type = mst_file_data;
if (name[8] == 'C' && strcmp ("__DYNAMIC", name) == 0)
ms_type = mst_data;
{
char *tempstring = name;
if (tempstring[0] == bfd_get_symbol_leading_char (objfile->obfd))
++tempstring;
if (is_vtable_name (tempstring))
ms_type = mst_data;
}
section = SECT_OFF_DATA (objfile);
bfd_section = DBX_DATA_SECTION (objfile)->the_bfd_section;
break;
case N_BSS:
ms_type = mst_file_bss;
section = SECT_OFF_BSS (objfile);
bfd_section = DBX_BSS_SECTION (objfile)->the_bfd_section;
break;
default:
ms_type = mst_unknown;
section = -1;
bfd_section = NULL;
break;
}
if ((ms_type == mst_file_text || ms_type == mst_text)
&& address < lowest_text_address)
lowest_text_address = address;
prim_record_minimal_symbol_and_info
(name, address, ms_type, NULL, section, bfd_section, objfile);
}
void
dbx_symfile_read (struct objfile *objfile, int mainline)
{
bfd *sym_bfd;
int val;
struct cleanup *back_to;
file_ptr dbx_symtab_offset;
int dbx_symtab_count;
sym_bfd = objfile->obfd;
symfile_relocatable = bfd_get_file_flags (sym_bfd) & HAS_RELOC;
block_address_function_relative =
((0 == strncmp (bfd_get_target (sym_bfd), "elf", 3))
|| (0 == strncmp (bfd_get_target (sym_bfd), "som", 3))
|| (0 == strncmp (bfd_get_target (sym_bfd), "coff", 4))
|| (0 == strncmp (bfd_get_target (sym_bfd), "pe", 2))
|| (0 == strncmp (bfd_get_target (sym_bfd), "epoc-pe", 7))
|| (0 == strncmp (bfd_get_target (sym_bfd), "nlm", 3)));
if (objfile->symflags != OBJF_SYM_ALL
&& (objfile->symflags & OBJF_SYM_EXTERN
|| objfile->symflags & OBJF_SYM_CONTAINER)
&& objfile->symflags & ~OBJF_SYM_LOCAL
&& objfile->symflags & ~OBJF_SYM_DEBUG
&& DBX_LOCAL_STAB_COUNT (objfile) != 0
&& DBX_NONLOCAL_STAB_COUNT (objfile) != 0
&& !objfile_contains_objc (objfile))
{
dbx_symtab_offset = DBX_NONLOCAL_STAB_OFFSET (objfile);
dbx_symtab_count = DBX_NONLOCAL_STAB_COUNT (objfile);
}
else
{
dbx_symtab_offset = DBX_SYMTAB_OFFSET (objfile);
dbx_symtab_count = DBX_SYMCOUNT (objfile);
}
val = bfd_seek (sym_bfd, dbx_symtab_offset, SEEK_SET);
if (val < 0)
perror_with_name (objfile->name);
if (mainline
|| (objfile->global_psymbols.size == 0
&& objfile->static_psymbols.size == 0))
init_psymbol_list (objfile, dbx_symtab_count);
symbol_size = DBX_SYMBOL_SIZE (objfile);
symbol_table_offset = dbx_symtab_offset;
free_pending_blocks ();
back_to = make_cleanup (really_free_pendings, 0);
#if 0
init_minimal_symbol_collection ();
make_cleanup_discard_minimal_symbols ();
#endif
read_dbx_symtab (objfile, dbx_symtab_count);
read_dbx_dynamic_symtab (objfile);
#if 0
install_minimal_symbols (objfile);
#endif
do_cleanups (back_to);
}
static void
dbx_new_init (struct objfile *ignore)
{
stabsread_new_init ();
buildsym_new_init ();
init_header_files ();
}
#define DBX_STRINGTAB_SIZE_SIZE sizeof(long)
static void
dbx_symfile_init (struct objfile *objfile)
{
int val;
bfd *sym_bfd = objfile->obfd;
char *name = bfd_get_filename (sym_bfd);
asection *text_sect;
unsigned char size_temp[DBX_STRINGTAB_SIZE_SIZE];
objfile->deprecated_sym_stab_info = (struct dbx_symfile_info *)
xmalloc (sizeof (struct dbx_symfile_info));
memset (objfile->deprecated_sym_stab_info, 0, sizeof (struct dbx_symfile_info));
#if 0
DBX_TEXT_SECTION (objfile) = bfd_get_section_by_name (sym_bfd, ".text");
DBX_DATA_SECTION (objfile) = bfd_get_section_by_name (sym_bfd, ".data");
DBX_BSS_SECTION (objfile) = bfd_get_section_by_name (sym_bfd, ".bss");
#else
DBX_TEXT_SECTION (objfile) = NULL;
DBX_DATA_SECTION (objfile) = NULL;
DBX_BSS_SECTION (objfile) = NULL;
#endif
#define STRING_TABLE_OFFSET (sym_bfd->origin + obj_str_filepos (sym_bfd))
#define SYMBOL_TABLE_OFFSET (sym_bfd->origin + obj_sym_filepos (sym_bfd))
DBX_SYMFILE_INFO (objfile)->stab_section_info = NULL;
text_sect = bfd_get_section_by_name (sym_bfd, ".text");
if (!text_sect)
error (_("Can't find .text section in symbol file"));
DBX_TEXT_ADDR (objfile) = bfd_section_vma (sym_bfd, text_sect);
DBX_TEXT_SIZE (objfile) = bfd_section_size (sym_bfd, text_sect);
DBX_SYMBOL_SIZE (objfile) = obj_symbol_entry_size (sym_bfd);
DBX_SYMCOUNT (objfile) = bfd_get_symcount (sym_bfd);
DBX_SYMTAB_OFFSET (objfile) = SYMBOL_TABLE_OFFSET;
if (STRING_TABLE_OFFSET == 0)
{
DBX_STRINGTAB_SIZE (objfile) = 0;
DBX_STRINGTAB (objfile) = NULL;
}
else
{
val = bfd_seek (sym_bfd, STRING_TABLE_OFFSET, SEEK_SET);
if (val < 0)
perror_with_name (name);
memset (size_temp, 0, sizeof (size_temp));
val = bfd_bread (size_temp, sizeof (size_temp), sym_bfd);
if (val < 0)
{
perror_with_name (name);
}
else if (val == 0)
{
DBX_STRINGTAB_SIZE (objfile) = 0;
DBX_STRINGTAB (objfile) = NULL;
}
else
{
DBX_STRINGTAB_SIZE (objfile) = bfd_h_get_32 (sym_bfd, size_temp);
if (DBX_STRINGTAB_SIZE (objfile) < sizeof (size_temp)
|| DBX_STRINGTAB_SIZE (objfile) > bfd_get_size (sym_bfd))
error (_("ridiculous string table size (%d bytes)."),
DBX_STRINGTAB_SIZE (objfile));
DBX_STRINGTAB (objfile) =
(char *) obstack_alloc (&objfile->objfile_obstack,
DBX_STRINGTAB_SIZE (objfile));
OBJSTAT (objfile, sz_strtab += DBX_STRINGTAB_SIZE (objfile));
val = bfd_seek (sym_bfd, STRING_TABLE_OFFSET, SEEK_SET);
if (val < 0)
perror_with_name (name);
val = bfd_bread (DBX_STRINGTAB (objfile),
DBX_STRINGTAB_SIZE (objfile),
sym_bfd);
if (val != DBX_STRINGTAB_SIZE (objfile))
perror_with_name (name);
}
}
}
static void
dbx_symfile_finish (struct objfile *objfile)
{
if (objfile->deprecated_sym_stab_info != NULL)
{
if (HEADER_FILES (objfile) != NULL)
{
int i = N_HEADER_FILES (objfile);
struct header_file *hfiles = HEADER_FILES (objfile);
while (--i >= 0)
{
xfree (hfiles[i].name);
xfree (hfiles[i].vector);
}
xfree (hfiles);
}
xfree (objfile->deprecated_sym_stab_info);
}
free_header_files ();
}
static unsigned char *symbuf = NULL;
static size_t symbuf_size = 0;
static int symbuf_idx;
static int symbuf_end;
static char *last_function_name;
static char *stringtab_global;
static struct stab_section_list *symbuf_sections;
static unsigned int symbuf_left;
static unsigned int symbuf_read;
static bfd_byte *stabs_data;
static void
fill_symbuf (struct objfile *objfile)
{
bfd *sym_bfd = objfile->obfd;
unsigned int count;
int nbytes;
if (symbuf == NULL)
{
symbuf_size = 4096 * DBX_SYMBOL_SIZE (objfile);
symbuf = xmalloc (symbuf_size);
}
if (stabs_data)
{
return;
#if 0
nbytes = symbuf_size;
if (nbytes > symbuf_left)
nbytes = symbuf_left;
memcpy (symbuf, stabs_data + symbuf_read, nbytes);
#endif
}
else if (symbuf_sections == NULL)
{
count = symbuf_size;
nbytes = bfd_bread (symbuf, count, sym_bfd);
}
else
{
if (symbuf_left <= 0)
{
file_ptr filepos = symbuf_sections->section->filepos;
if (bfd_seek (sym_bfd, filepos, SEEK_SET) != 0)
perror_with_name (bfd_get_filename (sym_bfd));
symbuf_left = bfd_section_size (sym_bfd, symbuf_sections->section);
symbol_table_offset = filepos - symbuf_read;
symbuf_sections = symbuf_sections->next;
}
count = symbuf_left;
if (count > symbuf_size)
count = symbuf_size;
nbytes = bfd_bread (symbuf, count, sym_bfd);
}
if (nbytes < 0)
perror_with_name (bfd_get_filename (sym_bfd));
else if (nbytes == 0)
error (_("Premature end of file reading symbol table"));
symbuf_end = nbytes / symbol_size;
symbuf_idx = 0;
symbuf_left -= nbytes;
symbuf_read += nbytes;
}
static void
stabs_seek (int sym_offset)
{
if (stabs_data)
{
symbuf_idx = symbuf_idx + sym_offset/symbol_size;
#if 0
symbuf_read += sym_offset;
symbuf_left -= sym_offset;
#endif
}
else
bfd_seek (processing_objfile->obfd, sym_offset, SEEK_CUR);
}
#ifndef INTERNALIZE_SYMBOL
#define INTERNALIZE_SYMBOL(intern, sect_p, extern, abfd) \
{ \
(intern).n_type = bfd_h_get_8 (abfd, (extern)->e_type); \
(intern).n_strx = bfd_h_get_32 (abfd, (extern)->e_strx); \
(intern).n_desc = bfd_h_get_16 (abfd, (extern)->e_desc); \
if (bfd_get_sign_extend_vma (abfd)) \
(intern).n_value = bfd_h_get_signed_32 (abfd, (extern)->e_value); \
else \
(intern).n_value = bfd_h_get_32 (abfd, (extern)->e_value); \
}
#endif
#ifndef PEEK_SYMBOL
#define PEEK_SYMBOL(intern, sect_p, abfd) \
{ \
if (symbuf_idx == symbuf_end) \
fill_symbuf (processing_objfile); \
INTERNALIZE_SYMBOL (intern, sect_p, (struct external_nlist *) \
((stabs_data ? stabs_data: symbuf) \
+ (symbol_size * symbuf_idx)), abfd); \
}
#endif
#ifndef NEXT_SYMBOL
#define NEXT_SYMBOL(intern, sect_p, abfd) \
{ \
PEEK_SYMBOL (intern, sect_p, abfd); \
symbuf_idx++; \
}
#endif
static char *
dbx_next_symbol_text (struct objfile *objfile)
{
struct internal_nlist nlist1;
struct internal_nlist nlist2;
int sect_p;
PEEK_SYMBOL (nlist1, sect_p, processing_objfile->obfd);
if (nlist1.n_type & N_STAB)
{
symbuf_idx++;
symnum++;
OBJSTAT (objfile, n_stabs++);
return (nlist1.n_strx + stringtab_global + file_string_table_offset);
}
symbuf_idx++;
PEEK_SYMBOL (nlist2, sect_p, processing_objfile->obfd);
symbuf_idx--;
if (nlist2.n_type & N_STAB)
{
memcpy (symbuf + ((symbuf_idx + 0) * symbol_size),
symbuf + ((symbuf_idx + 1) * symbol_size), symbol_size);
symbuf_idx++;
symnum++;
OBJSTAT (objfile, n_stabs++);
return (nlist2.n_strx + stringtab_global + file_string_table_offset);
}
complaint (&symfile_complaints, "unable to find symbol continuation");
return (nlist1.n_strx + stringtab_global + file_string_table_offset);
}
#define bincl_hash msymbol_hash
static void
init_bincl_list (int number, struct objfile *objfile)
{
bincls_allocated = number;
next_bincl = bincl_list = (struct header_file_location *)
xmalloc (bincls_allocated * sizeof (struct header_file_location));
}
static void
add_bincl_to_list (struct partial_symtab *pst, char *name, int instance)
{
if (next_bincl >= bincl_list + bincls_allocated)
{
int offset = next_bincl - bincl_list;
bincls_allocated *= 2;
bincl_list = (struct header_file_location *)
xrealloc ((char *) bincl_list,
bincls_allocated * sizeof (struct header_file_location));
next_bincl = bincl_list + offset;
}
next_bincl->pst = pst;
next_bincl->hash = bincl_hash (name);
next_bincl->instance = instance;
next_bincl++->name = name;
}
static struct partial_symtab *
find_corresponding_bincl_psymtab (char *name, int instance)
{
struct header_file_location *bincl;
unsigned long hash = bincl_hash (name);
for (bincl = bincl_list; bincl < next_bincl; bincl++)
if ((bincl->hash == hash)
&& (bincl->instance == instance)
&& strcmp (name, bincl->name) == 0)
return bincl->pst;
repeated_header_complaint (name, symnum);
return (struct partial_symtab *) 0;
}
static void
free_bincl_list (struct objfile *objfile)
{
xfree (bincl_list);
bincls_allocated = 0;
}
static void
do_free_bincl_list_cleanup (void *objfile)
{
free_bincl_list (objfile);
}
static struct cleanup *
make_cleanup_free_bincl_list (struct objfile *objfile)
{
return make_cleanup (do_free_bincl_list_cleanup, objfile);
}
static char *
set_namestring_1 (int strtab_size, char *strtab, char leading_char,
struct internal_nlist nlist, const char *prefix)
{
char *namestring;
static char *namebuf = NULL;
static size_t namebuf_len = 0;
if (((unsigned int) nlist.n_strx + file_string_table_offset) >=
strtab_size)
{
complaint (&symfile_complaints, _("bad string table offset in symbol %d"),
symnum);
namestring = "<bad string table offset>";
}
else
{
const char *p = prefix;
char *s = nlist.n_strx + file_string_table_offset + strtab;
if ((p != NULL) && (p[0] != '\0'))
{
size_t req = 1 + strlen (p) + strlen (s) + 1 - 1;
while (namebuf_len < req)
{
if (namebuf_len == 0)
namebuf_len = 1024;
namebuf_len *= 2;
}
namebuf = xrealloc (namebuf, namebuf_len);
sprintf (namebuf, "%c%s%s", leading_char, p, s + 1);
namestring = namebuf;
} else {
namestring = s;
}
}
return namestring;
}
static char *
set_namestring (struct objfile *objfile, struct internal_nlist nlist, const char *prefix)
{
return set_namestring_1 (DBX_STRINGTAB_SIZE (objfile),
DBX_STRINGTAB (objfile),
bfd_get_symbol_leading_char (objfile->obfd),
nlist,
prefix);
}
static void
read_dbx_dynamic_symtab (struct objfile *objfile)
{
bfd *abfd = objfile->obfd;
struct cleanup *back_to;
int counter;
long dynsym_size;
long dynsym_count;
asymbol **dynsyms;
asymbol **symptr;
arelent **relptr;
long dynrel_size;
long dynrel_count;
arelent **dynrels;
CORE_ADDR sym_value;
char *name;
if (bfd_get_flavour (abfd) != bfd_target_aout_flavour
|| (bfd_get_file_flags (abfd) & DYNAMIC) == 0
|| bfd_get_arch (abfd) == bfd_arch_unknown)
return;
dynsym_size = bfd_get_dynamic_symtab_upper_bound (abfd);
if (dynsym_size < 0)
return;
dynsyms = (asymbol **) xmalloc (dynsym_size);
back_to = make_cleanup (xfree, dynsyms);
dynsym_count = bfd_canonicalize_dynamic_symtab (abfd, dynsyms);
if (dynsym_count < 0)
{
do_cleanups (back_to);
return;
}
if (bfd_get_symcount (abfd) <= 0)
{
symptr = dynsyms;
for (counter = 0; counter < dynsym_count; counter++, symptr++)
{
asymbol *sym = *symptr;
asection *sec;
int type;
sec = bfd_get_section (sym);
sym_value = sym->value + sec->vma;
if (bfd_get_section_flags (abfd, sec) & SEC_CODE)
{
sym_value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
type = N_TEXT;
}
else if (bfd_get_section_flags (abfd, sec) & SEC_DATA)
{
sym_value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile));
type = N_DATA;
}
else if (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)
{
sym_value += ANOFFSET (objfile->section_offsets, SECT_OFF_BSS (objfile));
type = N_BSS;
}
else
continue;
if (sym->flags & BSF_GLOBAL)
type |= N_EXT;
record_minimal_symbol ((char *) bfd_asymbol_name (sym), sym_value,
type, objfile);
}
}
dynrel_size = bfd_get_dynamic_reloc_upper_bound (abfd);
if (dynrel_size < 0)
{
do_cleanups (back_to);
return;
}
dynrels = (arelent **) xmalloc (dynrel_size);
make_cleanup (xfree, dynrels);
dynrel_count = bfd_canonicalize_dynamic_reloc (abfd, dynrels, dynsyms);
if (dynrel_count < 0)
{
do_cleanups (back_to);
return;
}
for (counter = 0, relptr = dynrels;
counter < dynrel_count;
counter++, relptr++)
{
arelent *rel = *relptr;
CORE_ADDR address =
rel->address + ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile));
switch (bfd_get_arch (abfd))
{
case bfd_arch_sparc:
if (rel->howto->type != RELOC_JMP_SLOT)
continue;
break;
case bfd_arch_m68k:
if (rel->howto->type != 16)
continue;
address -= 2;
break;
default:
continue;
}
name = (char *) bfd_asymbol_name (*rel->sym_ptr_ptr);
prim_record_minimal_symbol (name, address, mst_solib_trampoline,
objfile);
}
do_cleanups (back_to);
}
#ifdef SOFUN_ADDRESS_MAYBE_MISSING
static CORE_ADDR
find_stab_function_addr (char *namestring, char *filename,
struct objfile *objfile)
{
struct minimal_symbol *msym;
char *p;
int n;
p = strchr (namestring, ':');
if (p == NULL)
p = namestring;
n = p - namestring;
p = alloca (n + 2);
strncpy (p, namestring, n);
p[n] = 0;
msym = lookup_minimal_symbol (p, filename, objfile);
if (msym == NULL)
{
p[n] = '_';
p[n + 1] = 0;
msym = lookup_minimal_symbol (p, filename, objfile);
}
if (msym == NULL && filename != NULL)
{
p[n] = 0;
msym = lookup_minimal_symbol (p, NULL, objfile);
}
if (msym == NULL && filename != NULL)
{
p[n] = '_';
p[n + 1] = 0;
msym = lookup_minimal_symbol (p, NULL, objfile);
}
return msym == NULL ? 0 : SYMBOL_VALUE_ADDRESS (msym);
}
#endif
static void
function_outside_compilation_unit_complaint (const char *arg1)
{
complaint (&symfile_complaints,
_("function `%s' appears to be defined outside of all compilation units"),
arg1);
}
struct oso_pst_list *
init_oso_pst_list (char *oso_name, struct objfile *objfile)
{
struct oso_pst_list *oso_list;
oso_list = (struct oso_pst_list *) obstack_alloc (&objfile->objfile_obstack,
sizeof (struct oso_pst_list));
oso_list->oso_name = oso_name;
oso_list->readin = 0;
oso_list->pst_list = NULL;
return oso_list;
}
static int oso_pst_num_allocated = 0;
static int oso_pst_num_used = 0;
void
add_oso_pst_to_list (struct oso_pst_list *list,
struct partial_symtab *pst,
struct objfile *objfile)
{
if (list->pst_list == NULL)
{
oso_pst_num_allocated = 30;
oso_pst_num_used = 0;
list->pst_list = (struct partial_symtab **)
xmalloc (oso_pst_num_allocated * sizeof (struct partial_symtab *));
}
else if (oso_pst_num_allocated == oso_pst_num_used)
{
oso_pst_num_allocated *= 2;
list->pst_list = (struct partial_symtab **) xrealloc (list->pst_list,
oso_pst_num_allocated * sizeof (struct partial_symtab *));
}
list->pst_list[oso_pst_num_used++] = pst;
if (pst != NULL)
PSYMTAB_OSO_PST_LIST (pst) = list;
}
void
end_oso_pst_list (struct oso_pst_list *list, struct objfile *objfile)
{
struct partial_symtab **old_list;
add_oso_pst_to_list (list, NULL, objfile);
old_list = list->pst_list;
list->pst_list = obstack_alloc (&objfile->objfile_obstack,
oso_pst_num_used * sizeof (struct partial_symtab *));
memcpy (list->pst_list, old_list,
oso_pst_num_used * sizeof (struct partial_symtab *));
oso_pst_num_used = 0;
oso_pst_num_allocated = 0;
xfree (old_list);
}
static void
read_dbx_symtab (struct objfile *objfile, int dbx_symcount)
{
struct internal_nlist nlist;
CORE_ADDR text_addr;
int text_size;
char *namestring;
int nsl;
int past_first_source_file = 0;
CORE_ADDR last_o_file_start = 0;
CORE_ADDR last_function_start = 0;
struct cleanup *back_to;
bfd *abfd;
int textlow_not_set;
const char *prefix = NULL;
int data_sect_index;
struct partial_symtab *pst;
char **psymtab_include_list;
int includes_allocated;
int includes_used;
struct partial_symtab **dependency_list;
int dependencies_used, dependencies_allocated;
struct partial_symtab_list {
struct partial_symtab_list *next;
struct partial_symtab *pst;
};
struct partial_symtab_list *symbol_sep_pst = NULL;
struct oso_fun_list *cur_fun_statics = NULL;
char *cur_fun_name = NULL;
struct partial_symtab *last_oso_pst = NULL;
struct oso_pst_list *cur_oso_list = NULL;
int in_dwarf_debug_map = 0;
text_addr = DBX_TEXT_ADDR (objfile);
text_size = DBX_TEXT_SIZE (objfile);
prefix = objfile->prefix;
file_string_table_offset = 0;
next_file_string_table_offset = 0;
stringtab_global = DBX_STRINGTAB (objfile);
pst = (struct partial_symtab *) 0;
includes_allocated = 30;
includes_used = 0;
psymtab_include_list = (char **) alloca (includes_allocated *
sizeof (char *));
dependencies_allocated = 30;
dependencies_used = 0;
dependency_list =
(struct partial_symtab **) alloca (dependencies_allocated *
sizeof (struct partial_symtab *));
init_bincl_list (20, objfile);
back_to = make_cleanup_free_bincl_list (objfile);
last_source_file = NULL;
lowest_text_address = (CORE_ADDR) -1;
processing_objfile = objfile;
abfd = objfile->obfd;
symbuf_end = symbuf_idx = 0;
next_symbol_text_func = dbx_next_symbol_text;
textlow_not_set = 1;
has_line_numbers = 0;
data_sect_index = objfile->sect_index_data;
if (data_sect_index == -1)
data_sect_index = SECT_OFF_BSS (objfile);
if (data_sect_index == -1)
data_sect_index = SECT_OFF_RODATA (objfile);
for (symnum = 0; symnum < dbx_symcount; symnum++)
{
char leading_char = bfd_get_symbol_leading_char (objfile->obfd);
int sect_p;
QUIT;
namestring = NULL;
NEXT_SYMBOL (nlist, sect_p, abfd);
if (nlist.n_type == N_SLINE)
{
has_line_numbers = 1;
continue;
}
OBJSTAT (objfile, n_stabs++);
if ((nlist.n_type & N_STAB) && ! (objfile->symflags & OBJF_SYM_DEBUG))
continue;
switch (nlist.n_type)
{
case N_TEXT | N_EXT:
case N_NBTEXT | N_EXT:
nlist.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
goto record_it;
case N_DATA | N_EXT:
case N_NBDATA | N_EXT:
nlist.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile));
goto record_it;
case N_BSS:
case N_BSS | N_EXT:
case N_NBBSS | N_EXT:
case N_SETV | N_EXT:
nlist.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_BSS (objfile));
goto record_it;
case N_ABS | N_EXT:
record_it:
#ifdef NM_NEXTSTEP
if (sect_p && !macosx_record_symbols_from_sect_p (objfile->obfd,
nlist.n_type,
nlist.n_other))
continue;
#endif
namestring = set_namestring (objfile, nlist, prefix);
bss_ext_symbol:
if (leading_char == namestring[0])
namestring++;
record_minimal_symbol (namestring, nlist.n_value,
nlist.n_type, objfile);
continue;
}
switch (nlist.n_type)
{
case N_NBTEXT:
case N_FN:
case N_FN_SEQ:
case N_TEXT:
nlist.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
namestring = set_namestring (objfile, nlist, prefix);
if ((! (objfile->symflags & (OBJF_SYM_LOCAL | OBJF_SYM_DEBUG)))
&& ((namestring[0] != '+') && (namestring[0] != '-')))
continue;
if ((namestring[0] == '-' && namestring[1] == 'l')
|| (namestring[(nsl = strlen (namestring)) - 1] == 'o'
&& namestring[nsl - 2] == '.'))
{
if (past_first_source_file && pst
&& nlist.n_value >= pst->textlow)
{
end_psymtab (pst, psymtab_include_list, includes_used,
symnum * symbol_size,
nlist.n_value > pst->texthigh
? nlist.n_value : pst->texthigh,
dependency_list, dependencies_used, textlow_not_set);
pst = (struct partial_symtab *) 0;
includes_used = 0;
dependencies_used = 0;
in_dwarf_debug_map = 0;
}
else
past_first_source_file = 1;
last_o_file_start = nlist.n_value;
}
else
goto record_it;
continue;
}
if (in_dwarf_debug_map && pst)
{
int name_has_dot_in_it;
namestring = set_namestring (objfile, nlist, prefix);
if (nlist.n_type == N_FUN && namestring[0] == '\0')
{
CORE_ADDR valu = nlist.n_value + last_function_start;
if (valu > pst->texthigh)
pst->texthigh = valu;
continue;
}
namestring++;
if (nlist.n_type == N_FUN)
{
nlist.n_value += ANOFFSET (objfile->section_offsets,
SECT_OFF_TEXT (objfile));
if (textlow_not_set)
{
pst->textlow = nlist.n_value;
textlow_not_set = 0;
}
if (pst->textlow > nlist.n_value
&& nlist.n_value != ANOFFSET (objfile->section_offsets,
SECT_OFF_TEXT (objfile)))
{
pst->textlow = nlist.n_value;
}
last_function_start = nlist.n_value;
add_psymbol_to_list (namestring, strlen (namestring),
VAR_DOMAIN, LOC_BLOCK,
&objfile->global_psymbols,
0, nlist.n_value,
psymtab_language, objfile);
continue;
}
if (nlist.n_type == N_GSYM
&& namestring[0] == '_'
&& namestring[1] == 'Z'
&& namestring[2] == 'T'
&& namestring[3] == 'V'
&& namestring[4] >= '0' && namestring[4] <= '9')
{
int i = 4;
while (namestring[i] >= '0' && namestring[i] <= '9')
i++;
if (namestring[i] != '\0')
{
add_psymbol_to_list (&namestring[i], strlen (&namestring[i]),
STRUCT_DOMAIN, LOC_TYPEDEF,
&objfile->static_psymbols,
0, 0,
psymtab_language, objfile);
}
}
name_has_dot_in_it = 0;
if (nlist.n_type == N_GSYM || nlist.n_type == N_STSYM)
if (strchr (namestring, '.') != NULL)
name_has_dot_in_it = 1;
if (nlist.n_type == N_STSYM || name_has_dot_in_it)
{
nlist.n_value += ANOFFSET (objfile->section_offsets,
data_sect_index);
add_psymbol_to_list (namestring, strlen (namestring),
VAR_DOMAIN, LOC_STATIC,
&objfile->static_psymbols,
0, nlist.n_value,
psymtab_language, objfile);
continue;
}
if (nlist.n_type == N_GSYM && !name_has_dot_in_it)
{
nlist.n_value += ANOFFSET (objfile->section_offsets,
data_sect_index);
add_psymbol_to_list (namestring, strlen (namestring),
VAR_DOMAIN, LOC_STATIC,
&objfile->global_psymbols,
0, nlist.n_value,
psymtab_language, objfile);
continue;
}
}
switch (nlist.n_type)
{
char *p;
case N_DATA:
nlist.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile));
goto record_it;
case N_UNDF | N_EXT:
if (nlist.n_value != 0)
{
CORE_ADDR reladdr;
namestring = set_namestring (objfile, nlist, prefix);
if (target_lookup_symbol (namestring, &reladdr))
{
continue;
}
nlist.n_type ^= (N_BSS ^ N_UNDF);
nlist.n_value = reladdr;
goto bss_ext_symbol;
}
continue;
case N_UNDF:
if (processing_acc_compilation && nlist.n_strx == 1)
{
past_first_source_file = 1;
file_string_table_offset = next_file_string_table_offset;
next_file_string_table_offset =
file_string_table_offset + nlist.n_value;
if (next_file_string_table_offset < file_string_table_offset)
error (_("string table offset backs up at %d"), symnum);
continue;
}
continue;
case N_ABS:
case N_NBDATA:
case N_NBBSS:
continue;
case N_INDR:
case N_INDR | N_EXT:
case N_SETA:
case N_SETA | N_EXT:
case N_SETT:
case N_SETT | N_EXT:
case N_SETD:
case N_SETD | N_EXT:
case N_SETB:
case N_SETB | N_EXT:
case N_SETV:
continue;
case N_SO:
{
CORE_ADDR valu;
static int prev_so_symnum = -10;
static int first_so_symnum;
char *p;
static char *dirname_nso;
int prev_textlow_not_set;
valu = nlist.n_value + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
prev_textlow_not_set = textlow_not_set;
#ifdef SOFUN_ADDRESS_MAYBE_MISSING
if (nlist.n_value == 0)
{
textlow_not_set = 1;
valu = 0;
}
else
textlow_not_set = 0;
#else
textlow_not_set = 0;
#endif
past_first_source_file = 1;
if (prev_so_symnum != symnum - 1)
{
first_so_symnum = symnum;
if (pst)
{
end_psymtab (pst, psymtab_include_list, includes_used,
symnum * symbol_size,
valu > pst->texthigh ? valu : pst->texthigh,
dependency_list, dependencies_used,
prev_textlow_not_set);
pst = (struct partial_symtab *) 0;
includes_used = 0;
dependencies_used = 0;
in_dwarf_debug_map = 0;
}
}
prev_so_symnum = symnum;
namestring = set_namestring (objfile, nlist, NULL);
if (*namestring == '\000')
{
psymtab_language = language_unknown;
continue;
}
p = strrchr (namestring, '/');
if (p && *(p + 1) == '\000')
{
dirname_nso = namestring;
continue;
}
psymtab_language = read_so_stab_language_hint (nlist.n_desc);
if (!pst)
pst = start_psymtab (objfile,
namestring, valu,
first_so_symnum * symbol_size,
objfile->global_psymbols.next,
objfile->static_psymbols.next, prefix);
{
struct partial_symtab_list *listptr;
for (listptr = symbol_sep_pst;
listptr != NULL;
listptr = listptr->next)
dependency_list[dependencies_used++] = listptr->pst;
}
continue;
}
case N_OSO:
{
namestring = set_namestring (objfile, nlist, NULL);
if (namestring[0] == '\0')
continue;
if (pst == NULL)
{
complaint (&symfile_complaints,
"N_OSO %s not in entries for any file, at symtab pos %d",
namestring, symnum);
continue;
}
PSYMTAB_OSO_NAME (pst) = obsavestring (namestring,
strlen (namestring),
&objfile->objfile_obstack);
PSYMTAB_OSO_MTIME (pst) = (long) nlist.n_value;
if (strstr (namestring, ".gch.o") != NULL)
{
struct partial_symtab_list *listptr =
xmalloc (sizeof (struct partial_symtab_list));
make_cleanup (xfree, listptr);
listptr->next = symbol_sep_pst;
symbol_sep_pst = listptr;
symbol_sep_pst->pst = pst;
}
LDSYMOFF (pst) = 0;
if (last_oso_pst != NULL)
{
if (strcmp (PSYMTAB_OSO_NAME (last_oso_pst),
PSYMTAB_OSO_NAME (pst)) == 0)
{
if (cur_oso_list == NULL)
{
cur_oso_list = init_oso_pst_list (PSYMTAB_OSO_NAME (pst),
objfile);
add_oso_pst_to_list (cur_oso_list, last_oso_pst,
objfile);
}
add_oso_pst_to_list (cur_oso_list, pst, objfile);
}
else
{
if (cur_oso_list != NULL)
end_oso_pst_list (cur_oso_list, objfile);
cur_oso_list = NULL;
}
}
last_oso_pst = pst;
if (nlist.n_desc == 1)
{
in_dwarf_debug_map = 1;
pst->read_symtab = dwarf2_debug_map_psymtab_to_symtab;
PSYMTAB_OSO_STATICS (pst) = NULL;
}
continue;
}
case N_BINCL:
{
enum language tmp_language;
namestring = set_namestring (objfile, nlist, NULL);
if (psymtab_language == language_unknown)
{
tmp_language = deduce_language_from_filename (namestring);
if (tmp_language != language_unknown
&& (tmp_language != language_c
|| (psymtab_language != language_cplus
&& psymtab_language != language_objcplus)))
psymtab_language = tmp_language;
}
if (pst == NULL)
{
complaint (&symfile_complaints,
_("N_BINCL %s not in entries for any file, at symtab pos %d"),
namestring, symnum);
continue;
}
add_bincl_to_list (pst, namestring, nlist.n_value);
goto record_include_file;
}
case N_SOL:
{
enum language tmp_language;
namestring = set_namestring (objfile, nlist, NULL);
if (psymtab_language == language_unknown)
{
tmp_language = deduce_language_from_filename (namestring);
if (tmp_language != language_unknown
&& (tmp_language != language_c
|| (psymtab_language != language_cplus
&& psymtab_language != language_objcplus)))
psymtab_language = tmp_language;
}
if (pst && strcmp (namestring, pst->filename) == 0)
continue;
{
int i;
for (i = 0; i < includes_used; i++)
if (strcmp (namestring, psymtab_include_list[i]) == 0)
{
i = -1;
break;
}
if (i == -1)
continue;
}
record_include_file:
psymtab_include_list[includes_used++] = namestring;
if (includes_used >= includes_allocated)
{
char **orig = psymtab_include_list;
psymtab_include_list = (char **)
alloca ((includes_allocated *= 2) *
sizeof (char *));
memcpy (psymtab_include_list, orig,
includes_used * sizeof (char *));
}
continue;
}
case N_LSYM:
case N_STSYM:
case N_LCSYM:
case N_ROSYM:
case N_NBSTS:
case N_NBLCS:
if (!read_type_psym_p)
break;
case N_FUN:
case N_GSYM:
case N_PC:
case N_M2C:
case N_SCOPE:
namestring = set_namestring (objfile, nlist, NULL);
if (pst && nlist.n_type == N_FUN && *namestring == '\000')
{
CORE_ADDR valu;
if (processing_gcc_compilation || !end_fun_absolute_p)
valu = nlist.n_value + last_function_start;
else
valu = nlist.n_value;
if (valu > pst->texthigh)
pst->texthigh = valu;
if (cur_fun_name != NULL)
{
xfree (cur_fun_name);
cur_fun_name = NULL;
}
cur_fun_statics = NULL;
break;
}
p = (char *) find_name_end (namestring);
if (!p)
continue;
switch (p[1])
{
int is_global_fun;
case 'V':
if (PSYMTAB_OSO_NAME (pst))
{
struct oso_fun_static *new_static;
int sym_name_len;
if (cur_fun_statics == NULL)
{
struct oso_fun_list *pst_statics;
struct oso_fun_list *tmp_ptr;
cur_fun_statics = (struct oso_fun_list *)
xmalloc (sizeof (struct oso_fun_list));
pst_statics = PSYMTAB_OSO_STATICS (pst);
if (pst_statics == NULL)
PSYMTAB_OSO_STATICS (pst) = cur_fun_statics;
else
{
for (tmp_ptr = pst_statics; tmp_ptr->next != NULL;
tmp_ptr = tmp_ptr->next) { ; }
tmp_ptr->next = cur_fun_statics;
}
cur_fun_statics->next = NULL;
if (cur_fun_name != NULL)
cur_fun_statics->name = xstrdup (cur_fun_name);
else
{
warning ("Building statics list with no function name");
cur_fun_statics->name = NULL;
}
cur_fun_statics->statics = NULL;
cur_fun_statics->tail = NULL;
}
new_static = (struct oso_fun_static *) xmalloc (sizeof (struct oso_fun_static));
new_static->address = nlist.n_value
+ ANOFFSET (objfile->section_offsets, data_sect_index);
sym_name_len = p - namestring;
new_static->name = xmalloc (sym_name_len + 1);
strncpy (new_static->name, namestring, sym_name_len);
new_static->name[sym_name_len] = '\0';
new_static->next = NULL;
if (cur_fun_statics->statics == NULL)
{
cur_fun_statics->statics = new_static;
cur_fun_statics->tail = new_static;
}
else
{
cur_fun_statics->tail->next = new_static;
cur_fun_statics->tail = new_static;
}
}
continue;
case 'S':
nlist.n_value += ANOFFSET (objfile->section_offsets, data_sect_index);
#ifdef STATIC_TRANSFORM_NAME
namestring = STATIC_TRANSFORM_NAME (namestring);
#endif
add_psymbol_to_list (namestring, p - namestring,
VAR_DOMAIN, LOC_STATIC,
&objfile->static_psymbols,
0, nlist.n_value,
psymtab_language, objfile);
continue;
case 'G':
nlist.n_value += ANOFFSET (objfile->section_offsets, data_sect_index);
add_psymbol_to_list (namestring, p - namestring,
VAR_DOMAIN, LOC_STATIC,
&objfile->global_psymbols,
0, nlist.n_value,
psymtab_language, objfile);
continue;
case 'T':
if (p >= namestring + 2
|| (p == namestring + 1
&& namestring[0] != ' '))
{
add_psymbol_to_list (namestring, p - namestring,
STRUCT_DOMAIN, LOC_TYPEDEF,
&objfile->static_psymbols,
nlist.n_value, 0,
psymtab_language, objfile);
if (p[2] == 't')
{
add_psymbol_to_list (namestring, p - namestring,
VAR_DOMAIN, LOC_TYPEDEF,
&objfile->static_psymbols,
nlist.n_value, 0,
psymtab_language, objfile);
p += 1;
}
}
goto check_enum;
case 't':
if (p != namestring)
{
add_psymbol_to_list (namestring, p - namestring,
VAR_DOMAIN, LOC_TYPEDEF,
&objfile->static_psymbols,
nlist.n_value, 0,
psymtab_language, objfile);
}
check_enum:
p += 2;
while ((*p >= '0' && *p <= '9')
|| *p == '(' || *p == ',' || *p == ')'
|| *p == '=')
p++;
if (*p++ == 'e')
{
if (*p == '-')
{
while (*p != ':')
p++;
p++;
}
while (*p && *p != ';' && *p != ',')
{
char *q;
if (*p == '\\' || (*p == '?' && p[1] == '\0'))
p = next_symbol_text (objfile);
for (q = p; *q && *q != ':'; q++)
;
add_psymbol_to_list (p, q - p,
VAR_DOMAIN, LOC_CONST,
&objfile->static_psymbols, 0,
0, psymtab_language, objfile);
p = q;
while (*p && *p != ',')
p++;
if (*p)
p++;
}
}
continue;
case 'c':
add_psymbol_to_list (namestring, p - namestring,
VAR_DOMAIN, LOC_CONST,
&objfile->static_psymbols, nlist.n_value,
0, psymtab_language, objfile);
continue;
case 'F':
is_global_fun = 1;
goto global_or_local;
case 'f':
is_global_fun = 0;
global_or_local:
if (! pst)
{
int name_len = p - namestring;
char *name = xmalloc (name_len + 1);
memcpy (name, namestring, name_len);
name[name_len] = '\0';
function_outside_compilation_unit_complaint (name);
xfree (name);
}
nlist.n_value += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
last_function_name = namestring;
#ifdef SOFUN_ADDRESS_MAYBE_MISSING
if (nlist.n_value == ANOFFSET (objfile->section_offsets,
SECT_OFF_TEXT (objfile)))
{
CORE_ADDR minsym_valu =
find_stab_function_addr (namestring, pst->filename, objfile);
if (minsym_valu != 0)
nlist.n_value = minsym_valu;
}
if (pst && textlow_not_set)
{
pst->textlow = nlist.n_value;
textlow_not_set = 0;
}
#endif
last_function_start = nlist.n_value;
if (pst
&& (textlow_not_set
|| (nlist.n_value < pst->textlow
&& (nlist.n_value
!= ANOFFSET (objfile->section_offsets,
SECT_OFF_TEXT (objfile))))))
{
pst->textlow = nlist.n_value;
textlow_not_set = 0;
}
if (pst && PSYMTAB_OSO_NAME (pst) != NULL)
{
if (cur_fun_name != NULL)
xfree (cur_fun_name);
cur_fun_name = xmalloc (p - namestring + 1);
strncpy (cur_fun_name, namestring, p - namestring);
cur_fun_name[p - namestring] = '\0';
}
add_psymbol_to_list (namestring, p - namestring,
VAR_DOMAIN, LOC_BLOCK,
is_global_fun ? &objfile->global_psymbols : &objfile->static_psymbols,
0, nlist.n_value,
psymtab_language, objfile);
continue;
case '(':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '-':
case '#':
continue;
case ':':
continue;
default:
complaint (&symfile_complaints, _("unknown symbol descriptor `%c'"),
p[1]);
continue;
}
case N_EXCL:
namestring = set_namestring (objfile, nlist, NULL);
{
struct partial_symtab *needed_pst =
find_corresponding_bincl_psymtab (namestring, nlist.n_value);
if (needed_pst == pst)
continue;
if (needed_pst)
{
int i;
int found = 0;
for (i = 0; i < dependencies_used; i++)
if (dependency_list[i] == needed_pst)
{
found = 1;
break;
}
if (found)
continue;
dependency_list[dependencies_used++] = needed_pst;
if (dependencies_used >= dependencies_allocated)
{
struct partial_symtab **orig = dependency_list;
dependency_list =
(struct partial_symtab **)
alloca ((dependencies_allocated *= 2)
* sizeof (struct partial_symtab *));
memcpy (dependency_list, orig,
(dependencies_used
* sizeof (struct partial_symtab *)));
#ifdef DEBUG_INFO
fprintf_unfiltered (gdb_stderr, "Had to reallocate dependency list.\n");
fprintf_unfiltered (gdb_stderr, "New dependencies allocated: %d\n",
dependencies_allocated);
#endif
}
}
}
continue;
case N_ENDM:
#ifdef SOFUN_ADDRESS_MAYBE_MISSING
if (pst)
{
end_psymtab (pst, psymtab_include_list, includes_used,
symnum * symbol_size,
(CORE_ADDR) 0,
dependency_list, dependencies_used, textlow_not_set);
pst = (struct partial_symtab *) 0;
includes_used = 0;
dependencies_used = 0;
in_dwarf_debug_map = 0;
}
#endif
continue;
case N_RBRAC:
#ifdef HANDLE_RBRAC
HANDLE_RBRAC (nlist.n_value);
continue;
#endif
case N_EINCL:
case N_DSLINE:
case N_BSLINE:
case N_SSYM:
case N_ENTRY:
case N_MAIN:
case N_CATCH:
case N_EHDECL:
case N_LENG:
case N_BCOMM:
case N_ECOMM:
case N_ECOML:
case N_FNAME:
case N_SLINE:
case N_RSYM:
case N_PSYM:
case N_LBRAC:
case N_NSYMS:
case N_DEFD:
case N_ALIAS:
case N_OBJ:
continue;
case N_OPT:
{
const char *tempstring;
namestring = set_namestring (objfile, nlist, NULL);
tempstring = namestring;
if (DEPRECATED_STREQ (namestring, GCC_COMPILED_FLAG_SYMBOL))
processing_gcc_compilation = 1;
else if (DEPRECATED_STREQ (namestring, GCC2_COMPILED_FLAG_SYMBOL))
processing_gcc_compilation = 2;
if (tempstring[0] == bfd_get_symbol_leading_char (objfile->obfd))
++tempstring;
if (DEPRECATED_STREQN (tempstring, "__gnu_compiled", 14))
processing_gcc_compilation = 2;
}
continue;
case N_PATCH:
case N_BNSYM:
case N_ENSYM:
continue;
default:
unknown_symtype_complaint (hex_string (nlist.n_type));
continue;
}
while ((namestring != NULL) && (namestring[strlen (namestring) - 1] == '\\'))
{
namestring = next_symbol_text (objfile);
}
}
if (cur_oso_list != NULL)
{
end_oso_pst_list (cur_oso_list, objfile);
cur_oso_list = NULL;
}
if (pst)
{
CORE_ADDR text_end =
(lowest_text_address == (CORE_ADDR) -1
? (text_addr + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)))
: lowest_text_address)
+ text_size;
end_psymtab (pst, psymtab_include_list, includes_used,
symnum * symbol_size,
text_end > pst->texthigh ? text_end : pst->texthigh,
dependency_list, dependencies_used, textlow_not_set);
in_dwarf_debug_map = 0;
}
do_cleanups (back_to);
}
static struct partial_symtab *
start_psymtab (struct objfile *objfile, char *filename, CORE_ADDR textlow,
int ldsymoff, struct partial_symbol **global_syms,
struct partial_symbol **static_syms, const char *prefix)
{
struct partial_symtab *result =
start_psymtab_common (objfile, objfile->section_offsets,
filename, textlow, global_syms, static_syms);
result->read_symtab_private = (char *)
obstack_alloc (&objfile->objfile_obstack, sizeof (struct symloc));
LDSYMOFF (result) = ldsymoff;
result->read_symtab = dbx_psymtab_to_symtab;
SYMBOL_SIZE (result) = symbol_size;
SYMBOL_OFFSET (result) = symbol_table_offset;
STRING_OFFSET (result) = string_table_offset;
FILE_STRING_OFFSET (result) = file_string_table_offset;
SYMBOL_PREFIX (result) = prefix;
elfstab_offset_sections (objfile, result);
if (psymtab_language == language_unknown)
{
psymtab_language = deduce_language_from_filename (filename);
}
result->language = psymtab_language;
return result;
}
struct partial_symtab *
end_psymtab (struct partial_symtab *pst, char **include_list, int num_includes,
int capping_symbol_offset, CORE_ADDR capping_text,
struct partial_symtab **dependency_list, int number_dependencies,
int textlow_not_set)
{
int i;
struct objfile *objfile = pst->objfile;
if (capping_symbol_offset != -1)
LDSYMLEN (pst) = capping_symbol_offset - LDSYMOFF (pst);
pst->texthigh = capping_text;
#ifdef SOFUN_ADDRESS_MAYBE_MISSING
if (pst->texthigh == 0 && last_function_name)
{
char *p;
int n;
struct minimal_symbol *minsym;
p = find_name_end (last_function_name);
if (p == NULL)
p = last_function_name;
n = p - last_function_name;
p = alloca (n + 2);
strncpy (p, last_function_name, n);
p[n] = 0;
minsym = lookup_minimal_symbol (p, pst->filename, objfile);
if (minsym == NULL)
{
p[n] = '_';
p[n + 1] = 0;
minsym = lookup_minimal_symbol (p, pst->filename, objfile);
}
if (minsym)
pst->texthigh = SYMBOL_VALUE_ADDRESS (minsym) + MSYMBOL_SIZE (minsym);
last_function_name = NULL;
}
if (textlow_not_set)
pst->textlow = pst->texthigh;
else
{
struct partial_symtab *p1;
ALL_OBJFILE_PSYMTABS (objfile, p1)
{
if (p1->texthigh == 0 && p1->textlow != 0 && p1 != pst)
{
p1->texthigh = pst->textlow;
if (p1->textlow == 0)
p1->textlow = p1->texthigh;
}
}
}
#endif
pst->n_global_syms =
objfile->global_psymbols.next - (objfile->global_psymbols.list + pst->globals_offset);
pst->n_static_syms =
objfile->static_psymbols.next - (objfile->static_psymbols.list + pst->statics_offset);
pst->number_of_dependencies = number_dependencies;
if (number_dependencies)
{
pst->dependencies = (struct partial_symtab **)
obstack_alloc (&objfile->objfile_obstack,
number_dependencies * sizeof (struct partial_symtab *));
memcpy (pst->dependencies, dependency_list,
number_dependencies * sizeof (struct partial_symtab *));
}
else
pst->dependencies = 0;
for (i = 0; i < num_includes; i++)
{
struct partial_symtab *subpst =
allocate_psymtab (include_list[i], objfile);
subpst->section_offsets = pst->section_offsets;
subpst->read_symtab_private =
(char *) obstack_alloc (&objfile->objfile_obstack,
sizeof (struct symloc));
LDSYMOFF (subpst) =
LDSYMLEN (subpst) =
subpst->textlow =
subpst->texthigh = 0;
PSYMTAB_OSO_NAME (subpst) = NULL;
PSYMTAB_OSO_PST_LIST (subpst) = NULL;
PSYMTAB_OSO_STATICS (subpst) = NULL;
subpst->dependencies = (struct partial_symtab **)
obstack_alloc (&objfile->objfile_obstack,
sizeof (struct partial_symtab *));
subpst->dependencies[0] = pst;
subpst->number_of_dependencies = 1;
subpst->globals_offset =
subpst->n_global_syms =
subpst->statics_offset =
subpst->n_static_syms = 0;
subpst->readin = 0;
subpst->symtab = 0;
subpst->read_symtab = pst->read_symtab;
}
sort_pst_symbols (pst);
free_named_symtabs (pst->filename);
PSYMTAB_OBSOLETED (pst) = 50;
if (num_includes == 0
&& number_dependencies == 0
&& pst->n_global_syms == 0
&& pst->n_static_syms == 0
&& has_line_numbers == 0
&& PSYMTAB_OSO_NAME (pst) == NULL)
{
discard_psymtab (pst);
pst = (struct partial_symtab *) NULL;
}
return pst;
}
struct bfd *
open_bfd_from_oso (struct partial_symtab *pst, bfd **containing_archive)
{
struct bfd *oso_bfd, *retval;
char *paren_begin;
long mtime;
char *oso_name;
long oso_mtime;
if (containing_archive != NULL)
*containing_archive = NULL;
oso_name = PSYMTAB_OSO_NAME (pst);
oso_mtime = PSYMTAB_OSO_MTIME (pst);
paren_begin = strrchr (oso_name, '(');
if (paren_begin != NULL)
{
char *paren_end;
paren_end = strrchr (oso_name, ')');
if (!paren_end || paren_end[1] != '\0')
paren_begin = NULL;
}
if (paren_begin == NULL
|| paren_begin == oso_name
|| paren_begin[-1] == '\\')
{
oso_bfd = bfd_openr (oso_name, gnutarget);
if (!oso_bfd)
{
if (pst->objfile && pst->objfile->separate_debug_objfile != NULL)
{
return NULL;
}
else
{
if (strncmp ("/private/var/tmp", oso_name, 16) == 0)
error ("Could not find object file \"%s\".\n"
"Did you remember to compile with "
"--save-temps on the gcc compile line?", oso_name);
else
error ("Could not find object file: \"%s\"", oso_name);
}
}
if (bfd_check_format (oso_bfd, bfd_archive))
{
oso_bfd = open_bfd_matching_arch (oso_bfd, bfd_object);
if (oso_bfd == NULL)
error ("Could not open OSO file matching current "
"architecture for \"%s\".",
oso_name);
}
retval = oso_bfd;
mtime = bfd_get_mtime (retval);
}
else
{
char *archive_name, *member_name, *member_begin, *member_end;
int archive_len, member_len;
struct bfd *archive_bfd, *member_bfd;
struct stat member_statbuf;
int status;
archive_len = paren_begin - oso_name;
archive_name = alloca (archive_len + 1);
archive_name = strncpy (archive_name, oso_name, archive_len);
archive_name[archive_len] = '\0';
archive_bfd = bfd_openr (archive_name, gnutarget);
if (archive_bfd == NULL)
{
warning ("Could not open OSO archive file \"%s\"", archive_name);
return NULL;
}
if (!bfd_check_format (archive_bfd, bfd_archive))
{
warning ("OSO archive file \"%s\" not an archive.",archive_name);
return NULL;
}
if (strcmp(archive_bfd->xvec->name, "mach-o-fat") == 0)
{
archive_bfd = open_bfd_matching_arch (archive_bfd, bfd_archive);
if (archive_bfd == NULL)
{
warning ("Could not open fork matching current "
"architecture for OSO archive \"%s\"",
archive_name);
return NULL;
}
if (!bfd_check_format (archive_bfd, bfd_archive))
{
warning ("Current architecture fork of OSO archive "
"file \"%s\" not an archive", archive_name);
return NULL;
}
}
if (containing_archive != NULL)
*containing_archive = archive_bfd;
member_begin = paren_begin + 1;
member_end = strrchr (member_begin, ')');
if (member_end == NULL)
warning ("Mal-formed OSO archive string: \"%s\"", oso_name);
member_len = member_end - member_begin;
member_name = alloca (member_len + 1);
strncpy (member_name, member_begin, member_len);
member_name[member_len] = '\0';
member_bfd = bfd_openr_next_archived_file (archive_bfd, NULL);
if (member_bfd == NULL)
{
warning ("Could not read archive members out of OSO archive \"%s\"",
archive_name);
return NULL;
}
while (member_bfd != NULL)
{
bfd *prev_bfd;
if (strcmp (member_bfd->filename, member_name) == 0)
break;
prev_bfd = member_bfd;
member_bfd = bfd_openr_next_archived_file (archive_bfd, prev_bfd);
bfd_close (prev_bfd);
}
if (member_bfd == NULL)
warning ("Could not find specified archive member for OSO name \"%s\"",
oso_name);
retval = member_bfd;
status = bfd_stat_arch_elt (member_bfd, &member_statbuf);
if (status == -1)
mtime = 0;
else
mtime = member_statbuf.st_mtime;
}
if (mtime && oso_mtime && mtime != oso_mtime)
warning (".o file \"%s\" more recent than executable timestamp", oso_name);
return retval;
}
void
oso_scan_partial_symtab (struct partial_symtab *pst)
{
struct internal_nlist nlist;
struct oso_pst_list *list;
struct bfd *oso_bfd, *containing_archive;
struct cleanup *oso_data_cleanup;
int num_syms, sym_size, strtab_size, sym_offset;
char *strtab_data;
int sect_p;
unsigned char type;
const char *prefix;
int current_list_element = -1;
struct partial_symtab *current_pst;
struct objfile *objfile;
char leading_char;
struct partial_symtab **dependency_list;
int dependencies_used, dependencies_allocated;
dependencies_allocated = 30;
dependencies_used = 0;
dependency_list =
(struct partial_symtab **) alloca (dependencies_allocated *
sizeof (struct partial_symtab *));
list = PSYMTAB_OSO_PST_LIST (pst);
if (list == NULL || list->readin)
return;
list->readin = 1;
prefix = SYMBOL_PREFIX (pst);
objfile = pst->objfile;
oso_bfd = open_bfd_from_oso (pst, &containing_archive);
if (oso_bfd == NULL)
error ("Couldn't open bfd for .o file: %s\n", PSYMTAB_OSO_NAME (pst));
if (!bfd_check_format (oso_bfd, bfd_object))
warning ("Not in bfd_object form");
leading_char = bfd_get_symbol_leading_char (oso_bfd);
oso_data_cleanup = stabsect_read_strtab_from_oso (oso_bfd, &num_syms, &sym_size, &strtab_size,
&stabs_data, &strtab_data);
sym_offset = 0;
symbuf_end = symbuf_idx = 0;
symbuf_read = 0;
symbuf_left = sym_offset + num_syms * sym_size;
stabs_seek (sym_offset);
init_bincl_list (20, objfile);
make_cleanup_free_bincl_list (objfile);
for (symnum = 0;
symnum < num_syms;
symnum++)
{
NEXT_SYMBOL (nlist, sect_p, oso_bfd);
type = nlist.n_type;
switch (type)
{
case N_SO:
{
char *p;
static int prev_so_symnum = -10;
static int first_so_symnum;
char *namestring;
namestring = set_namestring_1 (strtab_size, strtab_data,
leading_char, nlist, prefix);
if (prev_so_symnum != symnum - 1)
first_so_symnum = symnum;
prev_so_symnum = symnum;
if (*namestring == '\0')
{
LDSYMLEN (current_pst) = symnum * symbol_size - LDSYMOFF (current_pst);
current_pst->number_of_dependencies = dependencies_used;
if (dependencies_used)
{
current_pst->dependencies = (struct partial_symtab **)
obstack_alloc (&objfile->objfile_obstack,
dependencies_used * sizeof (struct partial_symtab *));
memcpy (current_pst->dependencies, dependency_list,
dependencies_used * sizeof (struct partial_symtab *));
}
else
current_pst->dependencies = 0;
dependencies_used = 0;
current_pst = NULL;
continue;
}
p = strrchr (namestring, '/');
if (p && *(p + 1) == '\000')
continue;
current_list_element++;
current_pst = list->pst_list[current_list_element];
if (strcmp(current_pst->filename, namestring) != 0)
error ("SO in .o file \"%s\" out of order\n", PSYMTAB_OSO_NAME (pst));
LDSYMOFF (current_pst) = first_so_symnum * symbol_size;
break;
}
case N_BINCL:
{
char *namestring;
namestring = set_namestring_1 (strtab_size, strtab_data,
leading_char, nlist, prefix);
add_bincl_to_list (current_pst, namestring, nlist.n_value);
break;
}
case N_EXCL:
{
struct partial_symtab *needed_pst;
char *namestring;
namestring = set_namestring_1 (strtab_size, strtab_data,
leading_char, nlist, prefix);
needed_pst = find_corresponding_bincl_psymtab (namestring, nlist.n_value);
if (needed_pst == current_pst)
continue;
if (needed_pst)
{
int i;
int found = 0;
for (i = 0; i < dependencies_used; i++)
if (dependency_list[i] == needed_pst)
{
found = 1;
break;
}
if (found)
continue;
dependency_list[dependencies_used++] = needed_pst;
if (dependencies_used >= dependencies_allocated)
{
struct partial_symtab **orig = dependency_list;
dependency_list =
(struct partial_symtab **)
alloca ((dependencies_allocated *= 2)
* sizeof (struct partial_symtab *));
memcpy (dependency_list, orig,
(dependencies_used
* sizeof (struct partial_symtab *)));
}
}
break;
}
default:
continue;
}
}
do_cleanups (oso_data_cleanup);
if (containing_archive != NULL)
bfd_close (containing_archive);
bfd_close(oso_bfd);
}
void
read_oso_nlists (bfd *oso_bfd, struct partial_symtab *pst,
struct nlist_rec **nlists, int *nlists_count,
char ***common_symnames, int *common_symnames_count)
{
struct internal_nlist nlist;
const char *prefix;
struct objfile *objfile;
char leading_char;
int num_syms, sym_size, strtab_size, sym_offset;
char *strtab_data;
int sect_p;
int nlists_arr_size = 256;
int common_symnames_arr_size = 32;
char *namestring;
struct cleanup *oso_data_cleanup;
*nlists = (struct nlist_rec *) xmalloc
(sizeof (struct nlist_rec) * nlists_arr_size);
*nlists_count = 0;
*common_symnames = (char **) xmalloc
(sizeof (char *) * common_symnames_arr_size);
*common_symnames_count = 0;
prefix = SYMBOL_PREFIX (pst);
objfile = pst->objfile;
leading_char = bfd_get_symbol_leading_char (oso_bfd);
oso_data_cleanup = stabsect_read_strtab_from_oso (oso_bfd,
&num_syms, &sym_size,
&strtab_size, &stabs_data,
&strtab_data);
sym_offset = 0;
symbuf_end = symbuf_idx = 0;
symbuf_read = 0;
symbuf_left = sym_offset + num_syms * sym_size;
stabs_seek (sym_offset);
for (symnum = 0;
symnum < num_syms;
symnum++)
{
int record_standard = 0;
int record_common = 0;
NEXT_SYMBOL (nlist, sect_p, oso_bfd);
if (nlist.n_type & N_STAB)
continue;
switch (nlist.n_type)
{
case N_TEXT:
case N_TEXT | N_EXT:
case N_NBTEXT | N_EXT:
case N_DATA:
case N_DATA | N_EXT:
case N_NBDATA | N_EXT:
case N_BSS:
case N_BSS | N_EXT:
case N_NBBSS | N_EXT:
case N_SETV | N_EXT:
case N_ABS | N_EXT:
case N_NBTEXT:
case N_FN:
case N_FN_SEQ:
record_standard = 1;
break;
case N_UNDF | N_EXT:
record_common = 1;
break;
}
if (sect_p && !macosx_record_symbols_from_sect_p (oso_bfd,
nlist.n_type,
nlist.n_other))
continue;
if (record_standard)
{
namestring = set_namestring_1 (strtab_size, strtab_data,
leading_char, nlist, prefix);
if (leading_char == namestring[0])
namestring++;
(*nlists)[*nlists_count].addr = nlist.n_value;
(*nlists)[*nlists_count].name = xstrdup (namestring);
if (++(*nlists_count) == nlists_arr_size)
{
nlists_arr_size *= 2;
*nlists = (struct nlist_rec *)
xrealloc (*nlists,
sizeof (struct nlist_rec) * nlists_arr_size);
}
}
if (record_common)
{
namestring = set_namestring_1 (strtab_size, strtab_data,
leading_char, nlist, prefix);
if (leading_char == namestring[0])
namestring++;
(*common_symnames)[*common_symnames_count] = xstrdup (namestring);
if (++(*common_symnames_count) == common_symnames_arr_size)
{
common_symnames_arr_size *= 2;
*common_symnames = (char **)
xrealloc (*common_symnames,
sizeof (char *) * common_symnames_arr_size);
}
}
}
do_cleanups (oso_data_cleanup);
}
static void
dbx_psymtab_to_symtab_1 (struct partial_symtab *pst)
{
struct cleanup *old_chain;
int i;
if (!pst)
return;
if (pst->readin)
{
fprintf_unfiltered (gdb_stderr, "Psymtab for %s already read in. Shouldn't happen.\n",
pst->filename);
return;
}
if (SYMLOC (pst) != NULL
&& PSYMTAB_OSO_PST_LIST (pst) != NULL
&& !((PSYMTAB_OSO_PST_LIST (pst))->readin))
oso_scan_partial_symtab (pst);
for (i = 0; i < pst->number_of_dependencies; i++)
if (!pst->dependencies[i]->readin)
{
if (info_verbose)
{
fputs_filtered (" ", gdb_stdout);
wrap_here ("");
fputs_filtered ("and ", gdb_stdout);
wrap_here ("");
printf_filtered ("%s...", pst->dependencies[i]->filename);
wrap_here ("");
gdb_flush (gdb_stdout);
}
dbx_psymtab_to_symtab_1 (pst->dependencies[i]);
}
if (LDSYMLEN (pst))
{
stabsread_init ();
buildsym_init ();
old_chain = make_cleanup (really_free_pendings, 0);
if (!PSYMTAB_OSO_NAME (pst))
{
file_string_table_offset = FILE_STRING_OFFSET (pst);
symbol_size = SYMBOL_SIZE (pst);
bfd_seek (pst->objfile->obfd, SYMBOL_OFFSET (pst), SEEK_SET);
read_ofile_symtab (pst);
}
else
{
struct bfd *oso_bfd, *containing_archive;
oso_bfd = open_bfd_from_oso (pst, &containing_archive);
if (oso_bfd == NULL)
error ("Couldn't open bfd for .o file: %s\n", PSYMTAB_OSO_NAME (pst));
if (!bfd_check_format (oso_bfd, bfd_object))
warning ("Not in bfd_object form");
read_ofile_symtab_from_oso (pst, oso_bfd);
if (containing_archive != NULL)
bfd_close (containing_archive);
bfd_close(oso_bfd);
}
do_cleanups (old_chain);
}
pst->readin = 1;
}
struct oso_data_cleanup
{
#ifdef HAVE_MMAP
bfd_window stab_window;
bfd_window strtab_window;
#endif
bfd_byte **stab_data_handle;
char **strtab_data_handle;
};
static void
cleanup_oso_data (void *data)
{
struct oso_data_cleanup *args = (struct oso_data_cleanup *) data;
#ifdef HAVE_MMAP
bfd_free_window (&(args->stab_window));
bfd_free_window (&(args->strtab_window));
#else
xfree (*args->stab_data_handle);
xfree (*args->strtab_window);
#endif
*args->stab_data_handle = NULL;
*args->strtab_data_handle = NULL;
xfree (args);
}
static struct cleanup *
stabsect_read_strtab_from_oso (struct bfd *oso_bfd, int *symcount,
int *symsize, int *strtab_size,
bfd_byte **stab_data_handle,
char **strtab_data_handle)
{
asection *stabsect = bfd_get_section_by_name (oso_bfd, "LC_SYMTAB.stabs");
asection *stabstrsect = bfd_get_section_by_name (oso_bfd, "LC_SYMTAB.stabstr");
int val;
char *name = bfd_get_filename (oso_bfd);
int stabs_size;
struct oso_data_cleanup *oso_cleanup
= (struct oso_data_cleanup *) malloc (sizeof (struct oso_data_cleanup));
if (!stabsect || ! stabstrsect)
error ("Couldn't find stabs in .o file %s\n", oso_bfd->filename);
oso_cleanup->stab_data_handle = stab_data_handle;
oso_cleanup->strtab_data_handle = strtab_data_handle;
*symsize =
(bfd_mach_o_version (oso_bfd) > 1) ? 16 : 12;
stabs_size = bfd_section_size (oso_bfd, stabsect);
*symcount = stabs_size / (*symsize);
*strtab_size = bfd_section_size (oso_bfd, stabstrsect);
#if HAVE_MMAP
bfd_init_window (&(oso_cleanup->stab_window));
val = bfd_get_section_contents_in_window_with_mode
(oso_bfd, stabstrsect, &(oso_cleanup->stab_window), 0, *strtab_size, 0);
if (!val)
perror_with_name (name);
*strtab_data_handle = oso_cleanup->stab_window.data;
bfd_init_window (&(oso_cleanup->strtab_window));
val = bfd_get_section_contents_in_window_with_mode
(oso_bfd, stabsect, &(oso_cleanup->strtab_window), 0, stabs_size, 0);
if (!val)
perror_with_name (name);
*stab_data_handle = oso_cleanup->strtab_window.data;
#else
if (strtab_size > bfd_get_size (oso_bfd))
error
("error parsing symbol file: invalid string table size (%d bytes)",
strtab_size);
*strtab_data_handle =
(char *) malloc (strtab_size + 1);
val = bfd_get_section_contents
(oso_bfd, stabstrsect, *strtab_data_handle, 0,
strtab_size);
if (!val)
perror_with_name (name);
*stabs_data_handle =
(char *) malloc (stabs_size + 1);
val = bfd_get_section_contents
(oso_bfd, stabsect, *stabs_data_handle, 0,
stabs_size);
if (!val)
perror_with_name (name);
#endif
return make_cleanup (cleanup_oso_data, oso_cleanup);
}
static void
dbx_psymtab_to_symtab (struct partial_symtab *pst)
{
bfd *sym_bfd;
struct cleanup *back_to = NULL;
if (!pst)
return;
if (pst->readin)
{
fprintf_unfiltered (gdb_stderr, "Psymtab for %s already read in. Shouldn't happen.\n",
pst->filename);
return;
}
if (LDSYMLEN (pst) || pst->number_of_dependencies)
{
if (info_verbose)
{
printf_filtered ("Reading in symbols for %s...", pst->filename);
gdb_flush (gdb_stdout);
}
sym_bfd = pst->objfile->obfd;
next_symbol_text_func = dbx_next_symbol_text;
if (DBX_STAB_SECTION (pst->objfile))
{
stabs_data
= symfile_relocate_debug_section (pst->objfile->obfd,
DBX_STAB_SECTION (pst->objfile),
NULL);
if (stabs_data)
back_to = make_cleanup (free_current_contents, (void *) &stabs_data);
}
dbx_psymtab_to_symtab_1 (pst);
if (back_to)
do_cleanups (back_to);
scan_file_globals (pst->objfile);
if (info_verbose)
printf_filtered ("done.\n");
}
}
static void
read_ofile_symtab (struct partial_symtab *pst)
{
char *namestring = NULL;
struct internal_nlist nlist;
int sect_p;
unsigned char type;
unsigned max_symnum;
bfd *abfd;
struct objfile *objfile;
int sym_offset;
int sym_size;
CORE_ADDR text_offset;
int text_size;
struct section_offsets *section_offsets;
const char *prefix;
objfile = pst->objfile;
sym_offset = LDSYMOFF (pst);
sym_size = LDSYMLEN (pst);
text_offset = pst->textlow;
text_size = pst->texthigh - pst->textlow;
section_offsets = pst->section_offsets;
prefix = SYMBOL_PREFIX (pst);
current_objfile = objfile;
subfile_stack = NULL;
stringtab_global = DBX_STRINGTAB (objfile);
last_source_file = NULL;
abfd = objfile->obfd;
processing_objfile = objfile;
symbuf_end = symbuf_idx = 0;
symbuf_read = 0;
symbuf_left = sym_offset + sym_size;
if (!processing_acc_compilation && sym_offset >= (int) symbol_size)
{
stabs_seek (sym_offset - symbol_size);
NEXT_SYMBOL (nlist, sect_p, abfd);
OBJSTAT (objfile, n_stabs++);
namestring = set_namestring (objfile, nlist, prefix);
processing_gcc_compilation = 0;
if (nlist.n_type == N_TEXT)
{
const char *tempstring = namestring;
if (strcmp (namestring, GCC_COMPILED_FLAG_SYMBOL) == 0)
processing_gcc_compilation = 1;
else if (strcmp (namestring, GCC2_COMPILED_FLAG_SYMBOL) == 0)
processing_gcc_compilation = 2;
if (tempstring[0] == bfd_get_symbol_leading_char (processing_objfile->obfd))
++tempstring;
if (strncmp (tempstring, "__gnu_compiled", 14) == 0)
processing_gcc_compilation = 2;
}
#if 0
if (processing_gcc_compilation)
{
if (AUTO_DEMANGLING)
{
set_demangling_style (GNU_DEMANGLING_STYLE_STRING);
}
}
#endif
}
else
{
stabs_seek (sym_offset);
processing_gcc_compilation = 0;
}
PEEK_SYMBOL (nlist, sect_p, abfd);
if (nlist.n_type != N_SO)
error (_("First symbol in segment of executable not a source symbol"));
max_symnum = sym_size / symbol_size;
for (symnum = 0;
symnum < max_symnum;
symnum++)
{
QUIT;
NEXT_SYMBOL (nlist, sect_p, abfd);
OBJSTAT (objfile, n_stabs++);
type = nlist.n_type;
namestring = set_namestring (objfile, nlist, prefix);
if (type & N_STAB)
{
process_one_symbol (type, nlist.n_desc, nlist.n_value,
namestring, prefix, section_offsets, objfile);
}
else if (type == N_TEXT)
{
if (strcmp (namestring, GCC_COMPILED_FLAG_SYMBOL) == 0)
processing_gcc_compilation = 1;
else if (strcmp (namestring, GCC2_COMPILED_FLAG_SYMBOL) == 0)
processing_gcc_compilation = 2;
#if 0
if (AUTO_DEMANGLING)
{
set_demangling_style (GNU_DEMANGLING_STYLE_STRING);
}
#endif
}
else if (type & N_EXT || type == (unsigned char) N_TEXT
|| type == (unsigned char) N_NBTEXT
)
{
;
}
}
current_objfile = NULL;
if (last_source_start_addr == 0)
last_source_start_addr = text_offset;
if (last_source_start_addr > text_offset)
last_source_start_addr = text_offset;
pst->symtab = end_symtab (text_offset + text_size, objfile, SECT_OFF_TEXT (objfile));
end_stabs ();
}
static struct partial_symbol *
lookup_psymbol_from_namestring (struct partial_symtab *pst,
char *namestring,
enum domain_enum_tag domain)
{
struct partial_symbol *psym;
char *name;
int name_len;
char *demangled;
int free_demangled;
int global;
name = find_name_end (namestring);
switch (name[1])
{
case 'F':
global = 1;
break;
case 'S':
case 'f':
case 'V':
global = 0;
break;
default:
warning ("Unknown type passed to lookup_psymbol_from_namestring");
return NULL;
break;
}
name_len = name - namestring;
name = alloca (name_len + 1);
strncpy (name, namestring, name_len);
name[name_len] = '\0';
demangled = NULL;
if (pst->language == language_cplus
|| pst->language == language_objcplus)
{
demangled =
cplus_demangle (name, DMGL_PARAMS | DMGL_ANSI);
}
if (demangled == NULL)
{
demangled = name;
free_demangled = 0;
}
else
free_demangled = 1;
psym = lookup_partial_symbol (pst, demangled, name, global, domain);
if (!psym)
complaint (&symfile_complaints,
"Couldn't find psymbol from namestring for: demangled: %s mangled: %s.\n",
demangled, name);
if (free_demangled)
xfree (demangled);
return psym;
}
static struct oso_fun_list *
oso_statics_pop (struct oso_fun_list *list_ptr)
{
struct oso_fun_static *static_ptr;
struct oso_fun_list *ret_ptr;
static_ptr = list_ptr->statics;
while (static_ptr != NULL)
{
struct oso_fun_static *tmp_ptr;
tmp_ptr = static_ptr->next;
xfree (static_ptr->name);
xfree (static_ptr);
static_ptr = tmp_ptr;
}
ret_ptr = list_ptr->next;
xfree (list_ptr->name);
xfree (list_ptr);
return ret_ptr;
}
static void
read_ofile_symtab_from_oso (struct partial_symtab *pst, struct bfd *oso_bfd)
{
char *namestring = NULL;
struct internal_nlist nlist;
int sect_p;
unsigned char type;
bfd *abfd;
struct objfile *objfile;
int sym_offset;
int sym_size;
int num_syms;
int strtab_size;
char *strtab_data;
CORE_ADDR text_offset;
int text_size;
struct section_offsets *section_offsets;
const char *prefix;
char leading_char;
struct cleanup *oso_data_cleanup;
char *cur_fun_name = NULL;
objfile = pst->objfile;
leading_char = bfd_get_symbol_leading_char (oso_bfd);
oso_data_cleanup = stabsect_read_strtab_from_oso (oso_bfd, &num_syms, &sym_size, &strtab_size,
&stabs_data, &strtab_data);
text_offset = pst->textlow;
text_size = pst->texthigh - pst->textlow;
section_offsets = pst->section_offsets;
prefix = SYMBOL_PREFIX (pst);
current_objfile = objfile;
subfile_stack = NULL;
stringtab_global = (char *) stabs_data;
last_source_file = NULL;
abfd = oso_bfd;
processing_objfile = objfile;
sym_offset = LDSYMOFF (pst);
symbuf_end = symbuf_idx = 0;
symbuf_read = 0;
symbuf_left = sym_offset + num_syms * sym_size;
stabs_seek (sym_offset);
symnum = symbuf_idx;
processing_gcc_compilation = 0;
PEEK_SYMBOL (nlist, sect_p, oso_bfd);
if (nlist.n_type != N_SO)
error ("First symbol in segment of executable not a source symbol");
for (;
symnum < num_syms;
symnum++)
{
CORE_ADDR offset;
QUIT;
NEXT_SYMBOL (nlist, sect_p, oso_bfd);
type = nlist.n_type;
namestring = set_namestring_1 (strtab_size, strtab_data,
leading_char, nlist, prefix);
if (type == N_BNSYM)
{
struct internal_nlist tmp_nlist;
struct partial_symbol *fun_psym;
char *fun_namestring;
int scan_ptr = symnum;
int old_symbuf_idx = symbuf_idx;
int found_it = 0;
while (scan_ptr < num_syms)
{
NEXT_SYMBOL (tmp_nlist, sect_p, oso_bfd);
if (tmp_nlist.n_type == N_FUN)
{
found_it = 1;
break;
}
if (tmp_nlist.n_type == N_ENSYM)
{
found_it = 0;
break;
}
scan_ptr++;
}
if (!found_it)
{
complaint (&symfile_complaints, "Scan to end from BNSYM without finding FUN");
}
else
{
fun_namestring = set_namestring_1 (strtab_size, strtab_data,
leading_char, tmp_nlist, prefix);
if (fun_namestring[0] == '\0')
{
complaint (&symfile_complaints, "Found NULL FUN stab scanning for function.");
fun_psym = NULL;
}
else
{
fun_psym = lookup_psymbol_from_namestring (pst, fun_namestring,
VAR_DOMAIN);
}
}
if (fun_psym == NULL)
{
found_it = 0;
symbuf_idx = old_symbuf_idx;
while (symnum < num_syms)
{
char *tmp_namestring;
NEXT_SYMBOL (tmp_nlist, sect_p, oso_bfd);
if (tmp_nlist.n_type == N_ENSYM)
{
found_it = 1;
break;
}
switch (tmp_nlist.n_type)
{
case N_FUN:
case N_LSYM:
case N_STSYM:
case N_LCSYM:
case N_GSYM:
case N_PSYM:
case N_RSYM:
tmp_namestring = set_namestring_1 (strtab_size, strtab_data,
leading_char, tmp_nlist, prefix);
process_symbol_types_only (tmp_namestring, prefix, tmp_nlist.n_desc,
tmp_nlist.n_type, objfile);
break;
default:
break;
}
symnum++;
}
if (!found_it)
complaint (&symfile_complaints, "Missing ENSYM in scanning OSO file");
}
else
{
offset = SYMBOL_VALUE_ADDRESS (fun_psym) - nlist.n_value
- ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
symbuf_idx = old_symbuf_idx;
}
continue;
}
if (type & N_STAB)
{
switch (type)
{
case N_FUN:
if (*namestring == '\0')
{
struct oso_fun_list *list_ptr;
list_ptr = PSYMTAB_OSO_STATICS(pst);
if (list_ptr)
{
if (list_ptr->name == NULL)
warning ("OSO fun missing name for pst: %s", pst->filename);
else if (!cur_fun_name)
warning ("Current function name not found for pst: \"%s\" and fun: \"%s\"", pst->filename, list_ptr->name);
else if (strcmp (list_ptr->name, cur_fun_name) == 0)
PSYMTAB_OSO_STATICS(pst) = oso_statics_pop (list_ptr);
}
if (cur_fun_name)
xfree (cur_fun_name);
cur_fun_name = NULL;
break;
}
else
{
char *p = find_name_end (namestring);
int namelen = p - namestring;
if (cur_fun_name != NULL)
xfree (cur_fun_name);
cur_fun_name = xmalloc (namelen + 1);
strncpy (cur_fun_name, namestring, namelen);
cur_fun_name[namelen] = '\0';
}
case N_SO:
case N_RBRAC:
case N_LBRAC:
case N_SLINE:
nlist.n_value += offset;
break;
case N_LCSYM:
case N_ROSYM:
case N_STSYM:
{
char *p;
p = find_name_end (namestring);
if (p[1] == 'V')
{
struct oso_fun_list *statics_list;
struct oso_fun_static *static_ptr, *prev_static_ptr;
int namelen = p - namestring;
if (cur_fun_name == NULL)
{
warning ("NULL current function name"
" while processing: \"%s\"", namestring);
}
else
{
for (statics_list = PSYMTAB_OSO_STATICS (pst);
statics_list != NULL; statics_list = statics_list->next)
{
if (statics_list->name == NULL)
continue;
if (strcmp (statics_list->name, cur_fun_name) == 0)
break;
}
if (statics_list == NULL)
{
warning ("Could not find statics info for function: %s",
cur_fun_name);
}
else
{
for (static_ptr = statics_list->statics, prev_static_ptr = static_ptr;
static_ptr != NULL;
prev_static_ptr = static_ptr, static_ptr = static_ptr->next)
{
if (strncmp(static_ptr->name, namestring, namelen) == 0)
break;
}
if (static_ptr == NULL)
{
char *symname;
symname = xmalloc (namelen + 1);
strncpy (symname, namestring, namelen);
symname[namelen] = '\0';
warning ("Could not find statics info for symbol: %s in function: %s",
symname, cur_fun_name);
xfree (symname);
}
else
{
nlist.n_value = static_ptr->address;
if (statics_list->statics == prev_static_ptr)
statics_list->statics = prev_static_ptr->next;
else
prev_static_ptr->next = static_ptr->next;
xfree (static_ptr->name);
xfree (static_ptr);
}
}
}
}
else
{
struct partial_symbol *static_psym;
static_psym = lookup_psymbol_from_namestring (pst, namestring,
VAR_DOMAIN);
if (static_psym)
nlist.n_value = SYMBOL_VALUE_ADDRESS (static_psym)
- ANOFFSET (objfile->section_offsets, SECT_OFF_DATA (objfile));
}
break;
}
default:
break;
}
if (type == N_SO
&& last_source_file != NULL
&& previous_stab_code != (unsigned char) N_SO
&& *namestring == '\0')
break;
process_one_symbol (type, nlist.n_desc, nlist.n_value,
namestring, prefix, section_offsets, objfile);
}
}
current_objfile = NULL;
if (last_source_start_addr == 0)
last_source_start_addr = text_offset;
if (last_source_start_addr > text_offset)
last_source_start_addr = text_offset;
pst->symtab = end_symtab (text_offset + text_size, objfile, SECT_OFF_TEXT (objfile));
end_stabs ();
if (cur_fun_name != NULL)
xfree (cur_fun_name);
do_cleanups (oso_data_cleanup);
}
void
process_one_symbol (int type, int desc, CORE_ADDR valu, char *name,
const char *prefix,
struct section_offsets *section_offsets,
struct objfile *objfile)
{
struct context_stack *new = NULL;
static CORE_ADDR function_start_offset;
static CORE_ADDR last_function_start;
static int sline_found_in_function = 1;
static int n_opt_found;
static int function_stab_type = 0;
static int saw_fun_start = 0;
if (!block_address_function_relative)
{
function_start_offset =
ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile));
}
if (last_source_file == NULL && type != (unsigned char) N_SO)
{
return;
}
switch (type)
{
case N_FUN:
case N_FNAME:
if (*name == '\000')
{
CORE_ADDR valu_abs;
if (context_stack_depth <= 0)
{
lbrac_mismatch_complaint (symnum);
break;
}
if (!saw_fun_start)
{
complaint (&symfile_complaints,
"Found an end function stab with no corresponding begin");
break;
}
else
saw_fun_start = 0;
if (sline_found_in_function)
{
if (processing_gcc_compilation || !end_fun_absolute_p)
record_line (current_subfile, 0, last_function_start + valu);
else
record_line (current_subfile, 0, valu);
}
within_function = 0;
new = pop_context ();
if (processing_gcc_compilation || !end_fun_absolute_p)
valu_abs = new->start_addr + valu;
else
{
valu_abs = valu;
valu_abs += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile));
valu_abs = SMASH_TEXT_ADDRESS (valu_abs);
}
finish_block (new->name, &local_symbols, new->old_blocks,
new->start_addr, valu_abs,
objfile);
if (block_address_function_relative)
function_start_offset = 0;
break;
}
sline_found_in_function = 0;
valu += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile));
valu = SMASH_TEXT_ADDRESS (valu);
last_function_start = valu;
goto define_a_symbol;
case N_LBRAC:
if (n_opt_found && desc == 1)
break;
#if defined(BLOCK_ADDRESS_ABSOLUTE)
valu += function_start_offset;
#else
if (block_address_function_relative)
valu += function_start_offset;
else
valu += last_source_start_addr;
#endif
new = push_context (desc, valu);
break;
case N_RBRAC:
if (n_opt_found && desc == 1)
break;
#if defined(BLOCK_ADDRESS_ABSOLUTE)
valu += function_start_offset;
#else
if (block_address_function_relative)
valu += function_start_offset;
else
valu += last_source_start_addr;
#endif
if (context_stack_depth <= 0)
{
lbrac_mismatch_complaint (symnum);
break;
}
new = pop_context ();
if (desc != new->depth)
lbrac_mismatch_complaint (symnum);
#if !defined (VARIABLES_INSIDE_BLOCK)
#define VARIABLES_INSIDE_BLOCK(desc, gcc_p) 0
#endif
if (!VARIABLES_INSIDE_BLOCK (desc, processing_gcc_compilation))
{
if (local_symbols != NULL)
{
complaint (&symfile_complaints, _("\
misplaced N_LBRAC entry; discarding local symbols which have \
no enclosing block"));
}
local_symbols = new->locals;
}
if (context_stack_depth
> !VARIABLES_INSIDE_BLOCK (desc, processing_gcc_compilation))
{
if (local_symbols != NULL)
{
if (new->start_addr > valu)
{
complaint (&symfile_complaints,
_("block start larger than block end"));
new->start_addr = valu;
}
finish_block (0, &local_symbols, new->old_blocks,
new->start_addr, valu, objfile);
}
}
else
{
within_function = 0;
}
if (VARIABLES_INSIDE_BLOCK (desc, processing_gcc_compilation))
local_symbols = new->locals;
break;
case N_FN:
case N_FN_SEQ:
valu += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile));
break;
case N_SO:
valu += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile));
n_opt_found = 0;
if (last_source_file)
{
if (previous_stab_code == (unsigned char) N_SO)
{
patch_subfile_names (current_subfile, name);
if (read_so_stab_language_hint (desc) != language_unknown)
current_subfile->language = read_so_stab_language_hint (desc);
break;
}
end_symtab (valu, objfile, SECT_OFF_TEXT (objfile));
end_stabs ();
}
if (*name == '\000')
break;
if (block_address_function_relative)
function_start_offset = 0;
start_stabs ();
start_symtab (name, NULL, valu);
record_debugformat ("stabs");
break;
case N_OSO:
break;
case N_SOL:
valu += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile));
start_subfile (name, current_subfile->dirname);
break;
case N_BINCL:
push_subfile ();
add_new_header_file (name, valu);
start_subfile (name, current_subfile->dirname);
break;
case N_EINCL:
start_subfile (pop_subfile (), current_subfile->dirname);
break;
case N_EXCL:
add_old_header_file (name, valu);
break;
case N_SLINE:
valu += function_start_offset;
if (within_function && sline_found_in_function == 0)
{
if (processing_gcc_compilation == 2)
record_line (current_subfile, desc, last_function_start);
else
record_line (current_subfile, desc, valu);
sline_found_in_function = 1;
}
else
record_line (current_subfile, desc, valu);
break;
case N_BCOMM:
common_block_start (name, objfile);
break;
case N_ECOMM:
common_block_end (objfile);
break;
case N_STSYM:
case N_LCSYM:
case N_ROSYM:
{
char *p;
if (!symfile_relocatable)
{
p = find_name_end (name);
if (p != 0 && p[1] == 'S')
{
valu += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile));
goto define_a_symbol;
}
}
switch (type)
{
case N_STSYM:
goto case_N_STSYM;
case N_LCSYM:
goto case_N_LCSYM;
case N_ROSYM:
goto case_N_ROSYM;
default:
internal_error (__FILE__, __LINE__,
_("failed internal consistency check"));
}
}
case_N_STSYM:
case N_DSLINE:
valu += ANOFFSET (section_offsets, SECT_OFF_DATA (objfile));
goto define_a_symbol;
case_N_LCSYM:
case N_BSLINE:
valu += ANOFFSET (section_offsets, SECT_OFF_BSS (objfile));
goto define_a_symbol;
case_N_ROSYM:
valu += ANOFFSET (section_offsets, SECT_OFF_RODATA (objfile));
goto define_a_symbol;
case N_ENTRY:
valu += ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile));
goto define_a_symbol;
case N_ENSYM:
case N_BNSYM:
break;
default:
case N_CATCH:
case N_EHDECL:
case N_PC:
case N_M2C:
case N_SCOPE:
case N_ECOML:
case N_NBTEXT:
case N_NBDATA:
case N_NBBSS:
case N_NBSTS:
case N_NBLCS:
unknown_symtype_complaint (hex_string (type));
define_a_symbol:
case N_GSYM:
case N_NSYMS:
case N_NOMAP:
case N_RSYM:
case N_DEFD:
case N_SSYM:
case N_LSYM:
case N_PSYM:
case N_LENG:
if (name)
{
int deftype;
char *colon_pos = find_name_end (name);
if (colon_pos == NULL)
deftype = '\0';
else
deftype = colon_pos[1];
switch (deftype)
{
case 'f':
case 'F':
function_stab_type = type;
#ifdef SOFUN_ADDRESS_MAYBE_MISSING
if (type == N_FUN
&& valu == ANOFFSET (section_offsets,
SECT_OFF_TEXT (objfile)))
{
CORE_ADDR minsym_valu =
find_stab_function_addr (name, last_source_file, objfile);
if (minsym_valu != 0)
valu = minsym_valu;
}
#endif
if (block_address_function_relative)
function_start_offset = valu;
within_function = 1;
saw_fun_start = 1;
if (context_stack_depth > 1)
{
complaint (&symfile_complaints,
_("unmatched N_LBRAC before symtab pos %d"), symnum);
break;
}
if (context_stack_depth > 0)
{
new = pop_context ();
finish_block (new->name, &local_symbols, new->old_blocks,
new->start_addr, valu, objfile);
}
new = push_context (0, valu);
new->name = define_symbol (valu, name, prefix, desc, type, objfile);
break;
default:
define_symbol (valu, name, prefix, desc, type, objfile);
break;
}
}
break;
case N_OPT:
if (name)
{
if (strcmp (name, GCC2_COMPILED_FLAG_SYMBOL) == 0)
{
processing_gcc_compilation = 2;
#if 0
if (AUTO_DEMANGLING)
{
set_demangling_style (GNU_DEMANGLING_STYLE_STRING);
}
#endif
}
else
n_opt_found = 1;
}
break;
case N_MAIN:
if (name != NULL)
set_main_name (name);
break;
case N_OBJ:
case N_PATCH:
case N_ENDM:
case N_ALIAS:
break;
}
if (name[0] == '#')
{
char *s = name;
int refnum;
refnum = symbol_reference_defined (&s);
if (refnum >= 0)
if (!ref_search (refnum))
ref_add (refnum, 0, name, valu);
name = s;
}
previous_stab_code = type;
}
void
coffstab_build_psymtabs (struct objfile *objfile, int mainline,
CORE_ADDR textaddr, unsigned int textsize,
struct stab_section_list *stabsects,
file_ptr stabstroffset, unsigned int stabstrsize)
{
int val;
bfd *sym_bfd = objfile->obfd;
char *name = bfd_get_filename (sym_bfd);
struct dbx_symfile_info *info;
unsigned int stabsize;
info = objfile->deprecated_sym_stab_info;
DBX_TEXT_ADDR (objfile) = textaddr;
DBX_TEXT_SIZE (objfile) = textsize;
#define COFF_STABS_SYMBOL_SIZE 12
DBX_SYMBOL_SIZE (objfile) = COFF_STABS_SYMBOL_SIZE;
DBX_STRINGTAB_SIZE (objfile) = stabstrsize;
if (stabstrsize > bfd_get_size (sym_bfd))
error ("error parsing symbol file: invalid string table size (%d bytes).", stabstrsize);
DBX_STRINGTAB (objfile) = (char *)
obstack_alloc (&objfile->objfile_obstack, stabstrsize + 1);
OBJSTAT (objfile, sz_strtab += stabstrsize + 1);
val = bfd_seek (sym_bfd, stabstroffset, SEEK_SET);
if (val < 0)
perror_with_name (name);
val = bfd_bread (DBX_STRINGTAB (objfile), stabstrsize, sym_bfd);
if (val != stabstrsize)
perror_with_name (name);
stabsread_new_init ();
buildsym_new_init ();
free_header_files ();
init_header_files ();
processing_acc_compilation = 1;
if (stabsects->next == NULL)
{
stabsize = bfd_section_size (sym_bfd, stabsects->section);
DBX_SYMCOUNT (objfile) = stabsize / DBX_SYMBOL_SIZE (objfile);
DBX_SYMTAB_OFFSET (objfile) = stabsects->section->filepos;
}
else
{
struct stab_section_list *stabsect;
DBX_SYMCOUNT (objfile) = 0;
for (stabsect = stabsects; stabsect != NULL; stabsect = stabsect->next)
{
stabsize = bfd_section_size (sym_bfd, stabsect->section);
DBX_SYMCOUNT (objfile) += stabsize / DBX_SYMBOL_SIZE (objfile);
}
DBX_SYMTAB_OFFSET (objfile) = stabsects->section->filepos;
symbuf_sections = stabsects->next;
symbuf_left = bfd_section_size (sym_bfd, stabsects->section);
symbuf_read = 0;
}
dbx_symfile_read (objfile, 0);
}
void
elfstab_build_psymtabs (struct objfile *objfile, int mainline,
asection *stabsect,
file_ptr stabstroffset, unsigned int stabstrsize)
{
int val;
bfd *sym_bfd = objfile->obfd;
char *name = bfd_get_filename (sym_bfd);
struct dbx_symfile_info *info;
struct cleanup *back_to = NULL;
info = objfile->deprecated_sym_stab_info;
find_text_range (sym_bfd, objfile);
#define ELF_STABS_SYMBOL_SIZE 12
DBX_SYMBOL_SIZE (objfile) = ELF_STABS_SYMBOL_SIZE;
DBX_SYMCOUNT (objfile)
= bfd_section_size (objfile->obfd, stabsect) / DBX_SYMBOL_SIZE (objfile);
DBX_STRINGTAB_SIZE (objfile) = stabstrsize;
DBX_SYMTAB_OFFSET (objfile) = stabsect->filepos;
DBX_STAB_SECTION (objfile) = stabsect;
if (stabstrsize > bfd_get_size (sym_bfd))
error ("error parsing symbol file: invalid string table size (%d bytes).", stabstrsize);
DBX_STRINGTAB (objfile) = (char *)
obstack_alloc (&objfile->objfile_obstack, stabstrsize + 1);
OBJSTAT (objfile, sz_strtab += stabstrsize + 1);
val = bfd_seek (sym_bfd, stabstroffset, SEEK_SET);
if (val < 0)
perror_with_name (name);
val = bfd_bread (DBX_STRINGTAB (objfile), stabstrsize, sym_bfd);
if (val != stabstrsize)
perror_with_name (name);
stabsread_new_init ();
buildsym_new_init ();
free_header_files ();
init_header_files ();
processing_acc_compilation = 1;
symbuf_read = 0;
symbuf_left = bfd_section_size (objfile->obfd, stabsect);
stabs_data = symfile_relocate_debug_section (objfile->obfd, stabsect, NULL);
if (stabs_data)
back_to = make_cleanup (free_current_contents, (void *) &stabs_data);
dbx_symfile_read (objfile, 0);
if (back_to)
do_cleanups (back_to);
}
void
stabsect_build_psymtabs (struct objfile *objfile, int mainline, char *stab_name,
char *stabstr_name, char *text_name)
{
int val;
bfd *sym_bfd = objfile->obfd;
char *name = bfd_get_filename (sym_bfd);
asection *stabsect;
asection *stabstrsect;
asection *text_sect;
stabsect = bfd_get_section_by_name (sym_bfd, stab_name);
stabstrsect = bfd_get_section_by_name (sym_bfd, stabstr_name);
if (!stabsect)
return;
if (!stabstrsect)
error (_("stabsect_build_psymtabs: Found stabs (%s), but not string section (%s)"),
stab_name, stabstr_name);
objfile->deprecated_sym_stab_info = (struct dbx_symfile_info *)
xmalloc (sizeof (struct dbx_symfile_info));
memset (objfile->deprecated_sym_stab_info, 0, sizeof (struct dbx_symfile_info));
text_sect = bfd_get_section_by_name (sym_bfd, text_name);
if (!text_sect)
error (_("Can't find %s section in symbol file"), text_name);
DBX_TEXT_ADDR (objfile) = bfd_section_vma (sym_bfd, text_sect);
DBX_TEXT_SIZE (objfile) = bfd_section_size (sym_bfd, text_sect);
DBX_SYMBOL_SIZE (objfile) = sizeof (struct external_nlist);
DBX_SYMCOUNT (objfile) = bfd_section_size (sym_bfd, stabsect)
/ DBX_SYMBOL_SIZE (objfile);
DBX_STRINGTAB_SIZE (objfile) = bfd_section_size (sym_bfd, stabstrsect);
DBX_SYMTAB_OFFSET (objfile) = stabsect->filepos;
if (DBX_STRINGTAB_SIZE (objfile) > bfd_get_size (sym_bfd))
error (_("ridiculous string table size: %d bytes"), DBX_STRINGTAB_SIZE (objfile));
DBX_STRINGTAB (objfile) = (char *)
obstack_alloc (&objfile->objfile_obstack, DBX_STRINGTAB_SIZE (objfile) + 1);
OBJSTAT (objfile, sz_strtab += DBX_STRINGTAB_SIZE (objfile) + 1);
val = bfd_get_section_contents (sym_bfd,
stabstrsect,
DBX_STRINGTAB (objfile),
0,
DBX_STRINGTAB_SIZE (objfile));
if (!val)
perror_with_name (name);
stabsread_new_init ();
buildsym_new_init ();
free_header_files ();
init_header_files ();
}
static enum language
read_so_stab_language_hint (short unsigned n_desc)
{
switch (n_desc) {
case N_SO_AS:
return language_asm;
case N_SO_C:
return language_c;
case N_SO_ANSI_C:
return language_c;
case N_SO_CC:
return language_cplus;
case N_SO_FORTRAN:
return language_fortran;
case N_SO_PASCAL:
return language_pascal;
case N_SO_FORTRAN90:
return language_fortran;
case N_SO_OBJC:
return language_objc;
case N_SO_OBJCPLUS:
return language_objcplus;
default:
return language_unknown;
}
}
static int
objfile_contains_objc (struct objfile *objfile)
{
if (bfd_get_section_by_name (objfile->obfd, "LC_SEGMENT.__OBJC"))
return 1;
return 0;
}
static struct sym_fns aout_sym_fns =
{
bfd_target_aout_flavour,
dbx_new_init,
dbx_symfile_init,
dbx_symfile_read,
dbx_symfile_finish,
default_symfile_offsets,
NULL
};
void
_initialize_dbxread (void)
{
add_setshow_boolean_cmd ("read-type-psyms", class_obscure,
&read_type_psym_p, _("\
Set if we should create partial symbols for types."), _("\
Show if we should create partial symbols for types."), NULL,
NULL,
NULL,
&setlist, &showlist);
add_setshow_boolean_cmd ("function-end-absolute", class_obscure,
&end_fun_absolute_p, _("\
Set if N_FUN end-of-function symbols use absolute addresses on non-GCC files."), _("\
Show if N_FUN end-of-function symbols use absolute addresses on non-GCC files."), NULL,
NULL,
NULL,
&setlist, &showlist);
add_symtab_fns (&aout_sym_fns);
}