1999-04-16 01:33:56 +00:00
/* GDB routines for manipulating objfiles.
Copyright 1992 , 1993 , 1994 , 1995 Free Software Foundation , Inc .
Contributed by Cygnus Support , using pieces from other GDB modules .
This file is part of GDB .
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA . */
/* This file contains support routines for creating, manipulating, and
destroying objfile structures . */
# include "defs.h"
# include "bfd.h" /* Binary File Description */
# include "symtab.h"
# include "symfile.h"
# include "objfiles.h"
# include "gdb-stabs.h"
# include "target.h"
# include <sys/types.h>
# include "gdb_stat.h"
# include <fcntl.h>
# include "obstack.h"
# include "gdb_string.h"
1999-04-26 18:23:13 +00:00
# include "breakpoint.h"
1999-04-16 01:33:56 +00:00
/* Prototypes for local functions */
# if defined(USE_MMALLOC) && defined(HAVE_MMAP)
static int
open_existing_mapped_file PARAMS ( ( char * , long , int ) ) ;
static int
open_mapped_file PARAMS ( ( char * filename , long mtime , int mapped ) ) ;
static PTR
map_to_file PARAMS ( ( int ) ) ;
# endif /* defined(USE_MMALLOC) && defined(HAVE_MMAP) */
static void
add_to_objfile_sections PARAMS ( ( bfd * , sec_ptr , PTR ) ) ;
/* Externally visible variables that are owned by this module.
See declarations in objfile . h for more info . */
struct objfile * object_files ; /* Linked list of all objfiles */
struct objfile * current_objfile ; /* For symbol file being read in */
struct objfile * symfile_objfile ; /* Main symbol table loaded from */
struct objfile * rt_common_objfile ; /* For runtime common symbols */
int mapped_symbol_files ; /* Try to use mapped symbol files */
/* Locate all mappable sections of a BFD file.
objfile_p_char is a char * to get it through
bfd_map_over_sections ; we cast it back to its proper type . */
# ifndef TARGET_KEEP_SECTION
# define TARGET_KEEP_SECTION(ASECT) 0
# endif
static void
add_to_objfile_sections ( abfd , asect , objfile_p_char )
bfd * abfd ;
sec_ptr asect ;
PTR 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 - > psymbol_obstack , ( char * ) & section , sizeof ( section ) ) ;
objfile - > sections_end = ( struct obj_section * ) ( ( ( unsigned long ) objfile - > sections_end ) + 1 ) ;
}
/* Builds a section table for OBJFILE.
Returns 0 if OK , 1 on error ( in which case bfd_error contains the
error ) . */
int
build_objfile_section_table ( objfile )
struct objfile * objfile ;
{
/* objfile->sections can be already set when reading a mapped symbol
file . I believe that we do need to rebuild the section table in
this case ( we rebuild other things derived from the bfd ) , but we
can ' t free the old one ( it ' s in the psymbol_obstack ) . So we just
waste some memory . */
objfile - > sections_end = 0 ;
bfd_map_over_sections ( objfile - > obfd , add_to_objfile_sections , ( char * ) objfile ) ;
objfile - > sections = ( struct obj_section * )
obstack_finish ( & objfile - > psymbol_obstack ) ;
objfile - > sections_end = objfile - > sections + ( unsigned long ) objfile - > sections_end ;
return ( 0 ) ;
}
/* Given a pointer to an initialized bfd (ABFD) and a flag that indicates
whether or not an objfile is to be mapped ( MAPPED ) , allocate a new objfile
struct , fill it in as best we can , link it into the list of all known
objfiles , and return a pointer to the new objfile struct .
USER_LOADED is simply recorded in the objfile . This record offers a way for
run_command to remove old objfile entries which are no longer valid ( i . e . ,
are associated with an old inferior ) , but to preserve ones that the user
explicitly loaded via the add - symbol - file command .
IS_SOLIB is also simply recorded in the objfile . */
struct objfile *
allocate_objfile ( abfd , mapped , user_loaded , is_solib )
bfd * abfd ;
int mapped ;
int user_loaded ;
int is_solib ;
{
struct objfile * objfile = NULL ;
struct objfile * last_one = NULL ;
mapped | = mapped_symbol_files ;
# if defined(USE_MMALLOC) && defined(HAVE_MMAP)
if ( abfd ! = NULL )
{
/* If we can support mapped symbol files, try to open/reopen the
mapped file that corresponds to the file from which we wish to
read symbols . If the objfile is to be mapped , we must malloc
the structure itself using the mmap version , and arrange that
all memory allocation for the objfile uses the mmap routines .
If we are reusing an existing mapped file , from which we get
our objfile pointer , we have to make sure that we update the
pointers to the alloc / free functions in the obstack , in case
these functions have moved within the current gdb . */
int fd ;
fd = open_mapped_file ( bfd_get_filename ( abfd ) , bfd_get_mtime ( abfd ) ,
mapped ) ;
if ( fd > = 0 )
{
PTR md ;
if ( ( md = map_to_file ( fd ) ) = = NULL )
{
close ( fd ) ;
}
else if ( ( objfile = ( struct objfile * ) mmalloc_getkey ( md , 0 ) ) ! = NULL )
{
/* Update memory corruption handler function addresses. */
init_malloc ( md ) ;
objfile - > md = md ;
objfile - > mmfd = fd ;
/* Update pointers to functions to *our* copies */
obstack_chunkfun ( & objfile - > psymbol_cache . cache , xmmalloc ) ;
obstack_freefun ( & objfile - > psymbol_cache . cache , mfree ) ;
obstack_chunkfun ( & objfile - > psymbol_obstack , xmmalloc ) ;
obstack_freefun ( & objfile - > psymbol_obstack , mfree ) ;
obstack_chunkfun ( & objfile - > symbol_obstack , xmmalloc ) ;
obstack_freefun ( & objfile - > symbol_obstack , mfree ) ;
obstack_chunkfun ( & objfile - > type_obstack , xmmalloc ) ;
obstack_freefun ( & objfile - > type_obstack , mfree ) ;
/* If already in objfile list, unlink it. */
unlink_objfile ( objfile ) ;
/* Forget things specific to a particular gdb, may have changed. */
objfile - > sf = NULL ;
}
else
{
/* Set up to detect internal memory corruption. MUST be
done before the first malloc . See comments in
init_malloc ( ) and mmcheck ( ) . */
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 , mfree ,
objfile - > md ) ;
obstack_specify_allocation_with_arg ( & objfile - > psymbol_obstack ,
0 , 0 , xmmalloc , mfree ,
objfile - > md ) ;
obstack_specify_allocation_with_arg ( & objfile - > symbol_obstack ,
0 , 0 , xmmalloc , mfree ,
objfile - > md ) ;
obstack_specify_allocation_with_arg ( & objfile - > type_obstack ,
0 , 0 , xmmalloc , mfree ,
objfile - > md ) ;
}
}
if ( mapped & & ( objfile = = NULL ) )
{
warning ( " symbol table for '%s' will not be mapped " ,
bfd_get_filename ( abfd ) ) ;
}
}
# else /* !defined(USE_MMALLOC) || !defined(HAVE_MMAP) */
if ( mapped )
{
warning ( " mapped symbol tables are not supported on this machine; missing or broken mmap(). " ) ;
/* Turn off the global flag so we don't try to do mapped symbol tables
any more , which shuts up gdb unless the user specifically gives the
" mapped " keyword again . */
mapped_symbol_files = 0 ;
}
# endif /* defined(USE_MMALLOC) && defined(HAVE_MMAP) */
/* If we don't support mapped symbol files, didn't ask for the file to be
mapped , or failed to open the mapped file for some reason , then revert
back to an unmapped objfile . */
if ( objfile = = NULL )
{
objfile = ( struct objfile * ) xmalloc ( sizeof ( struct objfile ) ) ;
memset ( objfile , 0 , sizeof ( struct objfile ) ) ;
objfile - > md = NULL ;
obstack_specify_allocation ( & objfile - > psymbol_cache . cache , 0 , 0 ,
xmalloc , free ) ;
obstack_specify_allocation ( & objfile - > psymbol_obstack , 0 , 0 , xmalloc ,
free ) ;
obstack_specify_allocation ( & objfile - > symbol_obstack , 0 , 0 , xmalloc ,
free ) ;
obstack_specify_allocation ( & objfile - > type_obstack , 0 , 0 , xmalloc ,
free ) ;
}
/* Update the per-objfile information that comes from the bfd, ensuring
that any data that is reference is saved in the per - objfile data
region . */
objfile - > obfd = abfd ;
if ( objfile - > name ! = NULL )
{
mfree ( objfile - > md , objfile - > name ) ;
}
if ( abfd ! = NULL )
{
objfile - > name = mstrsave ( objfile - > md , bfd_get_filename ( abfd ) ) ;
objfile - > mtime = bfd_get_mtime ( abfd ) ;
/* Build section table. */
if ( build_objfile_section_table ( objfile ) )
{
error ( " Can't find the file sections in `%s': %s " ,
objfile - > name , bfd_errmsg ( bfd_get_error ( ) ) ) ;
}
}
/* Add this file onto the tail of the linked list of other such files. */
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 ;
}
/* Record whether this objfile was created because the user explicitly
caused it ( e . g . , used the add - symbol - file command ) .
*/
objfile - > user_loaded = user_loaded ;
/* Record whether this objfile definitely represents a solib. */
objfile - > is_solib = is_solib ;
return ( objfile ) ;
}
/* Put OBJFILE at the front of the list. */
void
objfile_to_front ( objfile )
struct objfile * objfile ;
{
struct objfile * * objp ;
for ( objp = & object_files ; * objp ! = NULL ; objp = & ( ( * objp ) - > next ) )
{
if ( * objp = = objfile )
{
/* Unhook it from where it is. */
* objp = objfile - > next ;
/* Put it in the front. */
objfile - > next = object_files ;
object_files = objfile ;
break ;
}
}
}
/* Unlink OBJFILE from the list of known objfiles, if it is found in the
list .
It is not a bug , or error , to call this function if OBJFILE is not known
to be in the current list . This is done in the case of mapped objfiles ,
for example , just to ensure that the mapped objfile doesn ' t appear twice
in the list . Since the list is threaded , linking in a mapped objfile
twice would create a circular list .
If OBJFILE turns out to be in the list , we zap it ' s NEXT pointer after
unlinking it , just to ensure that we have completely severed any linkages
between the OBJFILE and the list . */
void
unlink_objfile ( 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 ;
break ;
}
}
}
/* Destroy an objfile and all the symtabs and psymtabs under it. Note
that as much as possible is allocated on the symbol_obstack and
psymbol_obstack , so that the memory can be efficiently freed .
Things which we do NOT free because they are not in malloc ' d memory
or not in memory specific to the objfile include :
objfile - > sf
FIXME : If the objfile is using reusable symbol information ( via mmalloc ) ,
then we need to take into account the fact that more than one process
may be using the symbol information at the same time ( when mmalloc is
extended to support cooperative locking ) . When more than one process
is using the mapped symbol info , we need to be more careful about when
we free objects in the reusable area . */
void
free_objfile ( objfile )
struct objfile * objfile ;
{
/* First do any symbol file specific actions required when we are
finished with a particular symbol file . Note that if the objfile
is using reusable symbol information ( via mmalloc ) then each of
these routines is responsible for doing the correct thing , either
freeing things which are valid only during this particular gdb
execution , or leaving them to be reused during the next one . */
if ( objfile - > sf ! = NULL )
{
( * objfile - > sf - > sym_finish ) ( objfile ) ;
}
/* We always close the bfd. */
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 ( ) ) ) ;
free ( name ) ;
}
/* Remove it from the chain of all objfiles. */
unlink_objfile ( objfile ) ;
/* If we are going to free the runtime common objfile, mark it
as unallocated . */
if ( objfile = = rt_common_objfile )
rt_common_objfile = NULL ;
/* Before the symbol table code was redone to make it easier to
selectively load and remove information particular to a specific
linkage unit , gdb used to do these things whenever the monolithic
symbol table was blown away . How much still needs to be done
is unknown , but we play it safe for now and keep each action until
it is shown to be no longer needed . */
# if defined (CLEAR_SOLIB)
CLEAR_SOLIB ( ) ;
/* CLEAR_SOLIB closes the bfd's for any shared libraries. But
the to_sections for a core file might refer to those bfd ' s . So
detach any core file . */
{
struct target_ops * t = find_core_target ( ) ;
if ( t ! = NULL )
( t - > to_detach ) ( NULL , 0 ) ;
}
# endif
/* I *think* all our callers call clear_symtab_users. If so, no need
to call this here . */
clear_pc_function_cache ( ) ;
/* The last thing we do is free the objfile struct itself for the
non - reusable case , or detach from the mapped file for the reusable
case . Note that the mmalloc_detach or the mfree is the last thing
we can do with this objfile . */
# if defined(USE_MMALLOC) && defined(HAVE_MMAP)
if ( objfile - > flags & OBJF_MAPPED )
{
/* Remember the fd so we can close it. We can't close it before
doing the detach , and after the detach the objfile is gone . */
int mmfd ;
mmfd = objfile - > mmfd ;
mmalloc_detach ( objfile - > md ) ;
objfile = NULL ;
close ( mmfd ) ;
}
# endif /* defined(USE_MMALLOC) && defined(HAVE_MMAP) */
/* If we still have an objfile, then either we don't support reusable
objfiles or this one was not reusable . So free it normally . */
if ( objfile ! = NULL )
{
if ( objfile - > name ! = NULL )
{
mfree ( objfile - > md , objfile - > name ) ;
}
if ( objfile - > global_psymbols . list )
mfree ( objfile - > md , objfile - > global_psymbols . list ) ;
if ( objfile - > static_psymbols . list )
mfree ( objfile - > md , objfile - > static_psymbols . list ) ;
/* Free the obstacks for non-reusable objfiles */
obstack_free ( & objfile - > psymbol_cache . cache , 0 ) ;
obstack_free ( & objfile - > psymbol_obstack , 0 ) ;
obstack_free ( & objfile - > symbol_obstack , 0 ) ;
obstack_free ( & objfile - > type_obstack , 0 ) ;
mfree ( objfile - > md , objfile ) ;
objfile = NULL ;
}
}
/* Free all the object files at once and clean up their users. */
void
free_all_objfiles ( )
{
struct objfile * objfile , * temp ;
ALL_OBJFILES_SAFE ( objfile , temp )
{
free_objfile ( objfile ) ;
}
clear_symtab_users ( ) ;
}
/* Relocate OBJFILE to NEW_OFFSETS. There should be OBJFILE->NUM_SECTIONS
entries in new_offsets . */
void
objfile_relocate ( objfile , new_offsets )
struct objfile * objfile ;
struct section_offsets * new_offsets ;
{
struct section_offsets * delta = ( struct section_offsets * )
alloca ( sizeof ( struct section_offsets )
+ objfile - > num_sections * sizeof ( delta - > offsets ) ) ;
{
int i ;
int something_changed = 0 ;
for ( i = 0 ; i < objfile - > num_sections ; + + i )
{
ANOFFSET ( delta , i ) =
ANOFFSET ( new_offsets , i ) - ANOFFSET ( objfile - > section_offsets , i ) ;
if ( ANOFFSET ( delta , i ) ! = 0 )
something_changed = 1 ;
}
if ( ! something_changed )
return ;
}
/* OK, get all the symtabs. */
{
struct symtab * s ;
ALL_OBJFILE_SYMTABS ( objfile , s )
{
struct linetable * l ;
struct blockvector * bv ;
int i ;
/* First the line table. */
l = LINETABLE ( s ) ;
if ( l )
{
for ( i = 0 ; i < l - > nitems ; + + i )
l - > item [ i ] . pc + = ANOFFSET ( delta , s - > block_line_section ) ;
}
/* Don't relocate a shared blockvector more than once. */
if ( ! s - > primary )
continue ;
bv = BLOCKVECTOR ( s ) ;
for ( i = 0 ; i < BLOCKVECTOR_NBLOCKS ( bv ) ; + + i )
{
struct block * b ;
int j ;
b = BLOCKVECTOR_BLOCK ( bv , i ) ;
BLOCK_START ( b ) + = ANOFFSET ( delta , s - > block_line_section ) ;
BLOCK_END ( b ) + = ANOFFSET ( delta , s - > block_line_section ) ;
for ( j = 0 ; j < BLOCK_NSYMS ( b ) ; + + j )
{
struct symbol * sym = BLOCK_SYM ( b , j ) ;
/* The RS6000 code from which this was taken skipped
any symbols in STRUCT_NAMESPACE or UNDEF_NAMESPACE .
But I ' m leaving out that test , on the theory that
they can ' t possibly pass the tests below . */
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
/* Relocate Extra Function Info for ecoff. */
else
if ( SYMBOL_CLASS ( sym ) = = LOC_CONST
& & SYMBOL_NAMESPACE ( sym ) = = LABEL_NAMESPACE
& & STRCMP ( SYMBOL_NAME ( sym ) , MIPS_EFI_SYMBOL_NAME ) = = 0 )
ecoff_relocate_efi ( sym , ANOFFSET ( delta ,
s - > block_line_section ) ) ;
# endif
}
}
}
}
{
struct partial_symtab * p ;
ALL_OBJFILE_PSYMTABS ( objfile , p )
{
p - > textlow + = ANOFFSET ( delta , SECT_OFF_TEXT ) ;
p - > texthigh + = ANOFFSET ( delta , SECT_OFF_TEXT ) ;
}
}
{
struct partial_symbol * * psym ;
for ( psym = objfile - > global_psymbols . list ;
psym < objfile - > global_psymbols . next ;
psym + + )
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 + + )
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 ) ) ;
}
/* Relocating different sections by different amounts may cause the symbols
to be out of order . */
msymbols_sort ( objfile ) ;
{
int i ;
for ( i = 0 ; i < objfile - > num_sections ; + + i )
ANOFFSET ( objfile - > section_offsets , i ) = ANOFFSET ( new_offsets , i ) ;
}
{
struct obj_section * s ;
bfd * abfd ;
abfd = objfile - > obfd ;
for ( s = objfile - > sections ;
s < objfile - > sections_end ; + + s )
{
flagword flags ;
flags = bfd_get_section_flags ( abfd , s - > the_bfd_section ) ;
if ( flags & SEC_CODE )
{
s - > addr + = ANOFFSET ( delta , SECT_OFF_TEXT ) ;
s - > endaddr + = ANOFFSET ( delta , SECT_OFF_TEXT ) ;
}
else if ( flags & ( SEC_DATA | SEC_LOAD ) )
{
s - > addr + = ANOFFSET ( delta , SECT_OFF_DATA ) ;
s - > endaddr + = ANOFFSET ( delta , SECT_OFF_DATA ) ;
}
else if ( flags & SEC_ALLOC )
{
s - > addr + = ANOFFSET ( delta , SECT_OFF_BSS ) ;
s - > endaddr + = ANOFFSET ( delta , SECT_OFF_BSS ) ;
}
}
}
if ( objfile - > ei . entry_point ! = ~ ( CORE_ADDR ) 0 )
objfile - > ei . entry_point + = ANOFFSET ( delta , SECT_OFF_TEXT ) ;
if ( objfile - > ei . entry_func_lowpc ! = INVALID_ENTRY_LOWPC )
{
objfile - > ei . entry_func_lowpc + = ANOFFSET ( delta , SECT_OFF_TEXT ) ;
objfile - > ei . entry_func_highpc + = ANOFFSET ( delta , SECT_OFF_TEXT ) ;
}
if ( objfile - > ei . entry_file_lowpc ! = INVALID_ENTRY_LOWPC )
{
objfile - > ei . entry_file_lowpc + = ANOFFSET ( delta , SECT_OFF_TEXT ) ;
objfile - > ei . entry_file_highpc + = ANOFFSET ( delta , SECT_OFF_TEXT ) ;
}
if ( objfile - > ei . main_func_lowpc ! = INVALID_ENTRY_LOWPC )
{
objfile - > ei . main_func_lowpc + = ANOFFSET ( delta , SECT_OFF_TEXT ) ;
objfile - > ei . main_func_highpc + = ANOFFSET ( delta , SECT_OFF_TEXT ) ;
}
/* Relocate breakpoints as necessary, after things are relocated. */
breakpoint_re_set ( ) ;
}
/* Many places in gdb want to test just to see if we have any partial
symbols available . This function returns zero if none are currently
available , nonzero otherwise . */
int
have_partial_symbols ( )
{
struct objfile * ofp ;
ALL_OBJFILES ( ofp )
{
if ( ofp - > psymtabs ! = NULL )
{
return 1 ;
}
}
return 0 ;
}
/* Many places in gdb want to test just to see if we have any full
symbols available . This function returns zero if none are currently
available , nonzero otherwise . */
int
have_full_symbols ( )
{
struct objfile * ofp ;
ALL_OBJFILES ( ofp )
{
if ( ofp - > symtabs ! = NULL )
{
return 1 ;
}
}
return 0 ;
}
/* This operations deletes all objfile entries that represent solibs that
weren ' t explicitly loaded by the user , via e . g . , the add - symbol - file
command .
*/
void
objfile_purge_solibs ( )
{
struct objfile * objf ;
struct objfile * temp ;
ALL_OBJFILES_SAFE ( objf , temp )
{
/* We assume that the solib package has been purged already, or will
be soon .
*/
if ( ! objf - > user_loaded & & objf - > is_solib )
free_objfile ( objf ) ;
}
}
/* Many places in gdb want to test just to see if we have any minimal
symbols available . This function returns zero if none are currently
available , nonzero otherwise . */
int
have_minimal_symbols ( )
{
struct objfile * ofp ;
ALL_OBJFILES ( ofp )
{
if ( ofp - > msymbols ! = NULL )
{
return 1 ;
}
}
return 0 ;
}
# if defined(USE_MMALLOC) && defined(HAVE_MMAP)
/* Given the name of a mapped symbol file in SYMSFILENAME, and the timestamp
of the corresponding symbol file in MTIME , try to open an existing file
with the name SYMSFILENAME and verify it is more recent than the base
file by checking it ' s timestamp against MTIME .
If SYMSFILENAME does not exist ( or can ' t be stat ' d ) , simply returns - 1.
If SYMSFILENAME does exist , but is out of date , we check to see if the
user has specified creation of a mapped file . If so , we don ' t issue
any warning message because we will be creating a new mapped file anyway ,
overwriting the old one . If not , then we issue a warning message so that
the user will know why we aren ' t using this existing mapped symbol file .
In either case , we return - 1.
If SYMSFILENAME does exist and is not out of date , but can ' t be opened for
some reason , then prints an appropriate system error message and returns - 1.
Otherwise , returns the open file descriptor . */
static int
open_existing_mapped_file ( symsfilename , mtime , mapped )
char * symsfilename ;
long mtime ;
int mapped ;
{
int fd = - 1 ;
struct stat sbuf ;
if ( stat ( symsfilename , & sbuf ) = = 0 )
{
if ( sbuf . st_mtime < mtime )
{
if ( ! 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 ) ;
}
/* Look for a mapped symbol file that corresponds to FILENAME and is more
recent than MTIME . If MAPPED is nonzero , the user has asked that gdb
use a mapped symbol file for this file , so create a new one if one does
not currently exist .
If found , then return an open file descriptor for the file , otherwise
return - 1.
This routine is responsible for implementing the policy that generates
the name of the mapped symbol file from the name of a file containing
symbols that gdb would like to read . Currently this policy is to append
" .syms " to the name of the file .
This routine is also responsible for implementing the policy that
determines where the mapped symbol file is found ( the search path ) .
This policy is that when reading an existing mapped file , a file of
the correct name in the current directory takes precedence over a
file of the correct name in the same directory as the symbol file .
When creating a new mapped file , it is always created in the current
directory . This helps to minimize the chances of a user unknowingly
creating big mapped files in places like / bin and / usr / local / bin , and
allows a local copy to override a manually installed global copy ( in
/ bin for example ) . */
static int
open_mapped_file ( filename , mtime , mapped )
char * filename ;
long mtime ;
int mapped ;
{
int fd ;
char * symsfilename ;
/* First try to open an existing file in the current directory, and
then try the directory where the symbol file is located . */
symsfilename = concat ( " ./ " , basename ( filename ) , " .syms " , ( char * ) NULL ) ;
if ( ( fd = open_existing_mapped_file ( symsfilename , mtime , mapped ) ) < 0 )
{
free ( symsfilename ) ;
symsfilename = concat ( filename , " .syms " , ( char * ) NULL ) ;
fd = open_existing_mapped_file ( symsfilename , mtime , mapped ) ;
}
/* If we don't have an open file by now, then either the file does not
already exist , or the base file has changed since it was created . In
either case , if the user has specified use of a mapped file , then
create a new mapped file , truncating any existing one . If we can ' t
create one , print a system error message saying why we can ' t .
By default the file is rw for everyone , with the user ' s umask taking
care of turning off the permissions the user wants off . */
if ( ( fd < 0 ) & & mapped )
{
free ( symsfilename ) ;
symsfilename = concat ( " ./ " , basename ( 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 ) ;
}
}
free ( symsfilename ) ;
return ( fd ) ;
}
static PTR
map_to_file ( fd )
int fd ;
{
PTR md ;
CORE_ADDR mapto ;
md = mmalloc_attach ( fd , ( PTR ) 0 ) ;
if ( md ! = NULL )
{
mapto = ( CORE_ADDR ) mmalloc_getkey ( md , 1 ) ;
md = mmalloc_detach ( md ) ;
if ( md ! = NULL )
{
/* FIXME: should figure out why detach failed */
md = NULL ;
}
else if ( mapto ! = ( CORE_ADDR ) NULL )
{
/* This mapping file needs to be remapped at "mapto" */
md = mmalloc_attach ( fd , ( PTR ) mapto ) ;
}
else
{
/* This is a freshly created mapping file. */
mapto = ( CORE_ADDR ) mmalloc_findbase ( 20 * 1024 * 1024 ) ;
if ( mapto ! = 0 )
{
/* To avoid reusing the freshly created mapping file, at the
address selected by mmap , we must truncate it before trying
to do an attach at the address we want . */
ftruncate ( fd , 0 ) ;
md = mmalloc_attach ( fd , ( PTR ) mapto ) ;
if ( md ! = NULL )
{
mmalloc_setkey ( md , 1 , ( PTR ) mapto ) ;
}
}
}
}
return ( md ) ;
}
# endif /* defined(USE_MMALLOC) && defined(HAVE_MMAP) */
/* Returns a section whose range includes PC and SECTION,
or NULL if none found . Note the distinction between the return type ,
struct obj_section ( which is defined in gdb ) , and the input type
struct sec ( which is a bfd - defined data type ) . The obj_section
contains a pointer to the bfd struct sec section . */
struct obj_section *
find_pc_sect_section ( pc , section )
CORE_ADDR pc ;
struct sec * section ;
{
struct obj_section * s ;
struct objfile * objfile ;
ALL_OBJFILES ( objfile )
for ( s = objfile - > sections ; s < objfile - > sections_end ; + + s )
# if defined(HPUXHPPA)
if ( ( section = = 0 | | section = = s - > the_bfd_section ) & &
s - > addr < = pc & & pc < = s - > endaddr )
# else
if ( ( section = = 0 | | section = = s - > the_bfd_section ) & &
s - > addr < = pc & & pc < s - > endaddr )
# endif
return ( s ) ;
return ( NULL ) ;
}
/* Returns a section whose range includes PC or NULL if none found.
Backward compatibility , no section . */
struct obj_section *
find_pc_section ( pc )
CORE_ADDR pc ;
{
return find_pc_sect_section ( pc , find_pc_mapped_section ( pc ) ) ;
}
/* In SVR4, we recognize a trampoline by it's section name.
That is , if the pc is in a section named " .plt " then we are in
a trampoline . */
int
in_plt_section ( pc , name )
CORE_ADDR pc ;
char * name ;
{
struct obj_section * s ;
int retval = 0 ;
s = find_pc_section ( pc ) ;
retval = ( s ! = NULL
& & s - > the_bfd_section - > name ! = NULL
& & STREQ ( s - > the_bfd_section - > name , " .plt " ) ) ;
return ( retval ) ;
}