* features/library-list.dtd: Allow "section" elements as children

of "library".  Add "section" element and describe its attributes.

	* solib-target.c (struct lm_info): Add section_bases member.
	(library_list_start_segment): Error out if seen a section element.
	(library_list_start_section): New.
	(library_list_end_library): New.
	(solib_target_free_library_list): Free section_bases.
	(section_attributes): New.
	(library_children): Make "segment" optional.  Add "section" child.
	(library_list_children): Register library_list_end_library.
	(solib_target_relocate_section_addresses): Handle section bases.

	* NEWS: Mention new qXfer:libraries:read section offsets support.

doc/
	* gdb.texinfo (Library List Format): Update to mention the
	possibility to pass section addresses instead of segment
	addresses.
This commit is contained in:
Pedro Alves 2008-03-14 22:30:07 +00:00
parent 29035cbe96
commit 1fddbabb01
6 changed files with 215 additions and 48 deletions

View file

@ -1,3 +1,20 @@
2008-03-14 Pedro Alves <pedro@codesourcery.com>
* features/library-list.dtd: Allow "section" elements as children
of "library". Add "section" element and describe its attributes.
* solib-target.c (struct lm_info): Add section_bases member.
(library_list_start_segment): Error out if seen a section element.
(library_list_start_section): New.
(library_list_end_library): New.
(solib_target_free_library_list): Free section_bases.
(section_attributes): New.
(library_children): Make "segment" optional. Add "section" child.
(library_list_children): Register library_list_end_library.
(solib_target_relocate_section_addresses): Handle section bases.
* NEWS: Mention new qXfer:libraries:read section offsets support.
2008-03-14 Vladimir Prus <vladimir@codesourcery.com>
* defs.h (do_exec_error_cleanups, discard_exec_error_cleanups)

View file

@ -6,6 +6,9 @@
* Watchpoints can now be set on unreadable memory locations, e.g. addresses
which will be allocated using malloc later in program execution.
* The qXfer:libraries:read remote procotol packet now allows passing a
list of section offsets.
* New features in the GDB remote stub, gdbserver
- The "--wrapper" command-line argument tells gdbserver to use a

View file

@ -1,3 +1,10 @@
2008-03-14 Pedro Alves <pedro@codesourcery.com>
Sandra Loosemore <sandra@codesourcery.com>
* gdb.texinfo (Library List Format): Update to mention the
possibility to pass section addresses instead of segment
addresses.
2008-03-10 Daniel Jacobowitz <dan@codesourcery.com>
* gdb.texinfo (Starting): Document "set exec-wrapper".

View file

@ -23776,8 +23776,8 @@ up to the first @samp{;} or @samp{?} (or the end of the packet).
@item vAttach;@var{pid}
@cindex @samp{vAttach} packet
Attach to a new process with the specified process ID. @var{pid} is a
hexadecimal integer identifying the process. The attached process is
stopped.
hexadecimal integer identifying the process. If the stub is currently
controlling a process, it is killed. The attached process is stopped.
This packet is only available in extended mode (@pxref{extended mode}).
@ -23891,7 +23891,7 @@ Run the program @var{filename}, passing it each @var{argument} on its
command line. The file and arguments are hex-encoded strings. If
@var{filename} is an empty string, the stub may use a default program
(e.g.@: the last program run). The program is created in the stopped
state.
state. If the stub is currently controlling a process, it is killed.
This packet is only available in extended mode (@pxref{extended mode}).
@ -26334,10 +26334,15 @@ are loaded.
The @samp{qXfer:libraries:read} packet returns an XML document which
lists loaded libraries and their offsets. Each library has an
associated name and one or more segment base addresses, which report
where the library was loaded in memory. The segment bases are start
addresses, not relocation offsets; they do not depend on the library's
link-time base addresses.
associated name and one or more segment or section base addresses,
which report where the library was loaded in memory.
For the common case of libraries that are fully linked binaries, the
library should have a list of segments. If the target supports
dynamic linking of a relocatable object file, its library XML element
should instead include a list of allocated sections. The segment or
section bases are start addresses, not relocation offsets; they do not
depend on the library's link-time base addresses.
@value{GDBN} must be linked with the Expat library to support XML
library lists. @xref{Expat}.
@ -26353,18 +26358,37 @@ offset, looks like this:
</library-list>
@end smallexample
Another simple memory map, with one loaded library with three
allocated sections (.text, .data, .bss), looks like this:
@smallexample
<library-list>
<library name="sharedlib.o">
<section address="0x10000000"/>
<section address="0x20000000"/>
<section address="0x30000000"/>
</library>
</library-list>
@end smallexample
The format of a library list is described by this DTD:
@smallexample
<!-- library-list: Root element with versioning -->
<!ELEMENT library-list (library)*>
<!ATTLIST library-list version CDATA #FIXED "1.0">
<!ELEMENT library (segment)*>
<!ELEMENT library (segment*, section*)>
<!ATTLIST library name CDATA #REQUIRED>
<!ELEMENT segment EMPTY>
<!ATTLIST segment address CDATA #REQUIRED>
<!ELEMENT section EMPTY>
<!ATTLIST section address CDATA #REQUIRED>
@end smallexample
In addition, segments and section descriptors cannot be mixed within a
single library element, and you must supply at least one segment or
section for each library.
@node Memory Map Format
@section Memory Map Format
@cindex memory map format

View file

@ -8,8 +8,11 @@
<!ELEMENT library-list (library)*>
<!ATTLIST library-list version CDATA #FIXED "1.0">
<!ELEMENT library (segment)*>
<!ELEMENT library (segment*, section*)>
<!ATTLIST library name CDATA #REQUIRED>
<!ELEMENT segment EMPTY>
<!ATTLIST segment address CDATA #REQUIRED>
<!ELEMENT section EMPTY>
<!ATTLIST section address CDATA #REQUIRED>

View file

@ -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);
asection *sect;
int num_section_bases
= VEC_length (CORE_ADDR, so->lm_info->section_bases);
int num_alloc_sections = 0;
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"),
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;
int bases_index = 0;
int found_range = 0;
CORE_ADDR *section_bases;
section_bases = VEC_address (CORE_ADDR,
so->lm_info->section_bases);
/* 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 = ~(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;
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);
num_bases = VEC_length (CORE_ADDR, so->lm_info->segment_bases);
segment_bases = VEC_address (CORE_ADDR,
so->lm_info->segment_bases);
free_symfile_segment_data (data);
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);
}
}
}