From 28c32713ac37a0123d8397527e5fe9cc2d108f1a Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Mon, 24 Sep 2007 21:48:29 +0000 Subject: [PATCH] * 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. --- gdb/ChangeLog | 11 +++++++++++ gdb/remote.c | 32 ++++++++++++++------------------ gdb/symfile.c | 44 +++++++++++++++++++++++++++++++++----------- gdb/symfile.h | 9 ++++++--- 4 files changed, 64 insertions(+), 32 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 5f34782573d..326694b8bea 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,14 @@ +2007-09-24 Jim Blandy + + * 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 * frame.c (get_prev_frame_1): Also check for PC in the same register. diff --git a/gdb/remote.c b/gdb/remote.c index 4d376434a33..b46fb1308e8 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -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) - { - 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 + if (num_segments > 0) { - 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) { diff --git a/gdb/symfile.c b/gdb/symfile.c index a73f936feb9..10617a13d2f 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -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]; + gdb_assert (0 <= which && which <= data->num_segments); + + /* 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) - offsets->offsets[i] = segment_bases[num_segment_bases - 1]; - else if (which > 0) - offsets->offsets[i] = segment_bases[which - 1]; - else - continue; + which = num_segment_bases; - offsets->offsets[i] -= data->segment_bases[which - 1]; + offsets->offsets[i] = (segment_bases[which - 1] + - data->segment_bases[which - 1]); } return 1; diff --git a/gdb/symfile.h b/gdb/symfile.h index 15f60cc988f..fd14215c7be 100644 --- a/gdb/symfile.h +++ b/gdb/symfile.h @@ -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; }; -- 2.30.2