* symfile.h (struct symfile_segment_data): Doc fixes.

* symfile.c (symfile_map_offsets_to_segments): Doc fixes.
Assert that we were passed some loaded segment addresses,
and that sections' segment numbers are valid.
Simplify offset calculation.
* remote.c (get_offsets): Clarify selection of relocate-by-segment
strategy, and set num_segments correctly.  Delete redundant
assignments to do_sections.
This commit is contained in:
Jim Blandy 2007-09-24 21:48:29 +00:00
parent 3227663267
commit 28c32713ac
4 changed files with 65 additions and 33 deletions

View file

@ -1,3 +1,14 @@
2007-09-24 Jim Blandy <jimb@codesourcery.com>
* symfile.h (struct symfile_segment_data): Doc fixes.
* symfile.c (symfile_map_offsets_to_segments): Doc fixes.
Assert that we were passed some loaded segment addresses,
and that sections' segment numbers are valid.
Simplify offset calculation.
* remote.c (get_offsets): Clarify selection of relocate-by-segment
strategy, and set num_segments correctly. Delete redundant
assignments to do_sections.
2007-09-24 Daniel Jacobowitz <dan@codesourcery.com>
* frame.c (get_prev_frame_1): Also check for PC in the same register.

View file

@ -2103,28 +2103,24 @@ get_offsets (void)
do_segments = (data != NULL);
do_sections = num_segments == 0;
/* Text= and Data= specify offsets for the text and data sections,
but symfile_map_offsets_to_segments expects base addresses
instead of offsets. If we have two segments, we can still
try to relocate the whole segments instead of just ".text"
and ".data". */
if (num_segments == 0)
if (num_segments > 0)
{
do_sections = 1;
if (data == NULL || data->num_segments != 2)
do_segments = 0;
else
{
segments[0] = data->segment_bases[0] + text_addr;
segments[1] = data->segment_bases[1] + data_addr;
}
}
else
{
do_sections = 0;
segments[0] = text_addr;
segments[1] = data_addr;
}
/* If we have two segments, we can still try to relocate everything
by assuming that the .text and .data offsets apply to the whole
text and data segments. Convert the offsets given in the packet
to base addresses for symfile_map_offsets_to_segments. */
else if (data && data->num_segments == 2)
{
segments[0] = data->segment_bases[0] + text_addr;
segments[1] = data->segment_bases[1] + data_addr;
num_segments = 2;
}
/* There's no way to relocate by segment. */
else
do_segments = 0;
if (do_segments)
{

View file

@ -3987,6 +3987,22 @@ free_symfile_segment_data (struct symfile_segment_data *data)
xfree (data);
}
/* Given:
- DATA, containing segment addresses from the object file ABFD, and
the mapping from ABFD's sections onto the segments that own them,
and
- SEGMENT_BASES[0 .. NUM_SEGMENT_BASES - 1], holding the actual
segment addresses reported by the target,
store the appropriate offsets for each section in OFFSETS.
If there are fewer entries in SEGMENT_BASES than there are segments
in DATA, then apply SEGMENT_BASES' last entry to all the segments.
If there are more, then verify that all the excess addresses are
the same as the last legitimate one, and then ignore them. This
allows "TextSeg=X;DataSeg=X" qOffset replies for files which have
only a single segment. */
int
symfile_map_offsets_to_segments (bfd *abfd, struct symfile_segment_data *data,
struct section_offsets *offsets,
@ -3996,15 +4012,16 @@ symfile_map_offsets_to_segments (bfd *abfd, struct symfile_segment_data *data,
int i;
asection *sect;
/* It doesn't make sense to call this function unless you have some
segment base addresses. */
gdb_assert (segment_bases > 0);
/* If we do not have segment mappings for the object file, we
can not relocate it by segments. */
gdb_assert (data != NULL);
gdb_assert (data->num_segments > 0);
/* If more offsets are provided than we have segments, make sure the
excess offsets are all the same as the last segment's offset.
This allows "Text=X;Data=X" for files which have only a single
segment. */
/* Check any extra SEGMENT_BASES entries. */
if (num_segment_bases > data->num_segments)
for (i = data->num_segments; i < num_segment_bases; i++)
if (segment_bases[i] != segment_bases[data->num_segments - 1])
@ -4012,17 +4029,22 @@ symfile_map_offsets_to_segments (bfd *abfd, struct symfile_segment_data *data,
for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next)
{
CORE_ADDR vma;
int which = data->segment_info[i];
if (which > num_segment_bases)
offsets->offsets[i] = segment_bases[num_segment_bases - 1];
else if (which > 0)
offsets->offsets[i] = segment_bases[which - 1];
else
continue;
gdb_assert (0 <= which && which <= data->num_segments);
offsets->offsets[i] -= data->segment_bases[which - 1];
/* Don't bother computing offsets for sections that aren't
loaded as part of any segment. */
if (! which)
continue;
/* Use the last SEGMENT_BASES entry as the address of any extra
segments mentioned in DATA->segment_info. */
if (which > num_segment_bases)
which = num_segment_bases;
offsets->offsets[i] = (segment_bases[which - 1]
- data->segment_bases[which - 1]);
}
return 1;

View file

@ -83,6 +83,9 @@ struct section_addr_info
} other[1];
};
/* A table listing the load segments in a symfile, and which segment
each BFD section belongs to. */
struct symfile_segment_data
{
/* How many segments are present in this file. If there are
@ -99,9 +102,9 @@ struct symfile_segment_data
CORE_ADDR *segment_sizes;
/* If NUM_SEGMENTS is greater than zero, this is an array of entries
recording which segment contains each BFD section. It is
ordered by section index. A zero means that the section is not
in any segment. */
recording which segment contains each BFD section.
SEGMENT_INFO[I] is S+1 if the I'th BFD section belongs to segment
S, or zero if it is not in any segment. */
int *segment_info;
};