@ -37,12 +37,19 @@ struct lm_info
so_list ; it is only here during XML parsing . */
char * name ;
/* The target can either specify segment bases or section bases, not
both . */
/* The base addresses for each independently relocatable segment of
this shared library . */
VEC ( CORE_ADDR ) * segment_bases ;
/* The base addresses for each independently allocatable,
relocatable section of this shared library . */
VEC ( CORE_ADDR ) * section_bases ;
/* The cached offsets for each section of this shared library,
determined from SEGMENT_BASES . */
determined from SEGMENT_BASES , or SECTION_BASES . */
struct section_offsets * offsets ;
} ;
@ -82,9 +89,30 @@ library_list_start_segment (struct gdb_xml_parser *parser,
ULONGEST * address_p = VEC_index ( gdb_xml_value_s , attributes , 0 ) - > value ;
CORE_ADDR address = ( CORE_ADDR ) * address_p ;
if ( last - > section_bases ! = NULL )
gdb_xml_error ( parser ,
_ ( " Library list with both segments and sections " ) ) ;
VEC_safe_push ( CORE_ADDR , last - > segment_bases , & address ) ;
}
static void
library_list_start_section ( struct gdb_xml_parser * parser ,
const struct gdb_xml_element * element ,
void * user_data , VEC ( gdb_xml_value_s ) * attributes )
{
VEC ( lm_info_p ) * * list = user_data ;
struct lm_info * last = VEC_last ( lm_info_p , * list ) ;
ULONGEST * address_p = VEC_index ( gdb_xml_value_s , attributes , 0 ) - > value ;
CORE_ADDR address = ( CORE_ADDR ) * address_p ;
if ( last - > segment_bases ! = NULL )
gdb_xml_error ( parser ,
_ ( " Library list with both segments and sections " ) ) ;
VEC_safe_push ( CORE_ADDR , last - > section_bases , & address ) ;
}
/* Handle the start of a <library> element. */
static void
@ -100,6 +128,20 @@ library_list_start_library (struct gdb_xml_parser *parser,
VEC_safe_push ( lm_info_p , * list , item ) ;
}
static void
library_list_end_library ( struct gdb_xml_parser * parser ,
const struct gdb_xml_element * element ,
void * user_data , const char * body_text )
{
VEC ( lm_info_p ) * * list = user_data ;
struct lm_info * lm_info = VEC_last ( lm_info_p , * list ) ;
if ( lm_info - > segment_bases = = NULL
& & lm_info - > section_bases = = NULL )
gdb_xml_error ( parser ,
_ ( " No segment or section bases defined " ) ) ;
}
/* Handle the start of a <library-list> element. */
static void
@ -128,6 +170,7 @@ solib_target_free_library_list (void *p)
{
xfree ( info - > name ) ;
VEC_free ( CORE_ADDR , info - > segment_bases ) ;
VEC_free ( CORE_ADDR , info - > section_bases ) ;
xfree ( info ) ;
}
VEC_free ( lm_info_p , * result ) ;
@ -142,9 +185,18 @@ const struct gdb_xml_attribute segment_attributes[] = {
{ NULL , GDB_XML_AF_NONE , NULL , NULL }
} ;
const struct gdb_xml_attribute section_attributes [ ] = {
{ " address " , GDB_XML_AF_NONE , gdb_xml_parse_attr_ulongest , NULL } ,
{ NULL , GDB_XML_AF_NONE , NULL , NULL }
} ;
const struct gdb_xml_element library_children [ ] = {
{ " segment " , segment_attributes , NULL , GDB_XML_EF_REPEATABLE ,
{ " segment " , segment_attributes , NULL ,
GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL ,
library_list_start_segment , NULL } ,
{ " section " , section_attributes , NULL ,
GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL ,
library_list_start_section , NULL } ,
{ NULL , NULL , NULL , GDB_XML_EF_NONE , NULL , NULL }
} ;
@ -156,7 +208,7 @@ const struct gdb_xml_attribute library_attributes[] = {
const struct gdb_xml_element library_list_children [ ] = {
{ " library " , library_attributes , library_children ,
GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL ,
library_list_start_library , NULL } ,
library_list_start_library , library_list_end_library } ,
{ NULL , NULL , NULL , GDB_XML_EF_NONE , NULL , NULL }
} ;
@ -285,55 +337,116 @@ solib_target_relocate_section_addresses (struct so_list *so,
it any earlier , since we need to open the file first . */
if ( so - > lm_info - > offsets = = NULL )
{
struct symfile_segment_data * data ;
int num_sections = bfd_count_sections ( so - > abfd ) ;
so - > lm_info - > offsets = xzalloc ( SIZEOF_N_SECTION_OFFSETS ( num_sections ) ) ;
data = get_symfile_segment_data ( so - > abfd ) ;
if ( data = = NULL )
warning ( _ ( " Could not relocate shared library \" %s \" : no segments " ) ,
so - > so_name ) ;
else
if ( so - > lm_info - > section_bases )
{
ULONGEST orig_delta ;
int i ;
int num_bases = VEC_length ( CORE_ADDR , so - > lm_info - > segment_bases ) ;
CORE_ADDR * segment_bases = VEC_address ( CORE_ADDR ,
so - > lm_info - > segment_bases ) ;
if ( ! symfile_map_offsets_to_segments ( so - > abfd , data ,
so - > lm_info - > offsets ,
num_bases , segment_bases ) )
warning ( _ ( " Could not relocate shared library \" %s \" : bad offsets " ) ,
asection * sect ;
int num_section_bases
= VEC_length ( CORE_ADDR , so - > lm_info - > section_bases ) ;
int num_alloc_sections = 0 ;
for ( i = 0 , sect = so - > abfd - > sections ;
sect ! = NULL ;
i + + , sect = sect - > next )
if ( ( bfd_get_section_flags ( so - > abfd , sect ) & SEC_ALLOC ) )
num_alloc_sections + + ;
if ( num_alloc_sections ! = num_section_bases )
warning ( _ ( " \
Could not relocate shared library \ " %s \" : wrong number of ALLOC sections " ) ,
so - > so_name ) ;
/* Find the range of addresses to report for this library in
" info sharedlibrary " . Report any consecutive segments
which were relocated as a single unit . */
gdb_assert ( num_bases > 0 ) ;
orig_delta = segment_bases [ 0 ] - data - > segment_bases [ 0 ] ;
for ( i = 1 ; i < data - > num_segments ; i + + )
else
{
/* If we have run out of offsets, assume all remaining segments
have the same offset . */
if ( i > = num_bases )
continue ;
/* If this segment does not have the same offset, do not include
it in the library ' s range . */
if ( segment_bases [ i ] - data - > segment_bases [ i ] ! = orig_delta )
break ;
int bases_index = 0 ;
int found_range = 0 ;
CORE_ADDR * section_bases ;
section_bases = VEC_address ( CORE_ADDR ,
so - > lm_info - > section_bases ) ;
so - > addr_low = ~ ( CORE_ADDR ) 0 ;
so - > addr_high = 0 ;
for ( i = 0 , sect = so - > abfd - > sections ;
sect ! = NULL ;
i + + , sect = sect - > next )
{
if ( ! ( bfd_get_section_flags ( so - > abfd , sect ) & SEC_ALLOC ) )
continue ;
if ( bfd_section_size ( so - > abfd , sect ) > 0 )
{
CORE_ADDR low , high ;
low = section_bases [ i ] ;
high = low + bfd_section_size ( so - > abfd , sect ) - 1 ;
if ( low < so - > addr_low )
so - > addr_low = low ;
if ( high > so - > addr_high )
so - > addr_high = high ;
gdb_assert ( so - > addr_low < = so - > addr_high ) ;
found_range = 1 ;
}
so - > lm_info - > offsets - > offsets [ i ] = section_bases [ bases_index ] ;
bases_index + + ;
}
if ( ! found_range )
so - > addr_low = so - > addr_high = 0 ;
gdb_assert ( so - > addr_low < = so - > addr_high ) ;
}
}
else if ( so - > lm_info - > segment_bases )
{
struct symfile_segment_data * data ;
data = get_symfile_segment_data ( so - > abfd ) ;
if ( data = = NULL )
warning ( _ ( " \
Could not relocate shared library \ " %s \" : no segments " ) , so - > so_name ) ;
else
{
ULONGEST orig_delta ;
int i ;
int num_bases ;
CORE_ADDR * segment_bases ;
num_bases = VEC_length ( CORE_ADDR , so - > lm_info - > segment_bases ) ;
segment_bases = VEC_address ( CORE_ADDR ,
so - > lm_info - > segment_bases ) ;
if ( ! symfile_map_offsets_to_segments ( so - > abfd , data ,
so - > lm_info - > offsets ,
num_bases , segment_bases ) )
warning ( _ ( " \
Could not relocate shared library \ " %s \" : bad offsets " ) , so - > so_name ) ;
/* Find the range of addresses to report for this library in
" info sharedlibrary " . Report any consecutive segments
which were relocated as a single unit . */
gdb_assert ( num_bases > 0 ) ;
orig_delta = segment_bases [ 0 ] - data - > segment_bases [ 0 ] ;
for ( i = 1 ; i < data - > num_segments ; i + + )
{
/* If we have run out of offsets, assume all
remaining segments have the same offset . */
if ( i > = num_bases )
continue ;
/* If this segment does not have the same offset, do
not include it in the library ' s range . */
if ( segment_bases [ i ] - data - > segment_bases [ i ] ! = orig_delta )
break ;
}
so - > addr_low = segment_bases [ 0 ] ;
so - > addr_high = ( data - > segment_bases [ i - 1 ]
+ data - > segment_sizes [ i - 1 ]
+ orig_delta ) ;
gdb_assert ( so - > addr_low < = so - > addr_high ) ;
free_symfile_segment_data ( data ) ;
}
so - > addr_low = segment_bases [ 0 ] ;
so - > addr_high = ( data - > segment_bases [ i - 1 ]
+ data - > segment_sizes [ i - 1 ]
+ orig_delta ) ;
gdb_assert ( so - > addr_low < = so - > addr_high ) ;
free_symfile_segment_data ( data ) ;
}
}