[PATCH] Add OSE operating system support [3/5] remote relocation support
Hui Zhu
hui_zhu@mentor.com
Tue Mar 5 10:01:00 GMT 2013
Hi,
This patch add relocation support to remote target.
If target support qXfer:load-map:read, it use this packet to request a list of segment or section load addresses of the main executable.
If target doesn't support it, use qOffsets that support in before request section offsets.
Thanks,
Hui
2013-03-05 Luis Machado <lgustavo@codesourcery.com>
* corelow.c (Makefile.in): Add load-map.dtd.
* features/load-map.dtd: New.
* remote.c (get_offsets): Removed.
(PACKET_qXfer_load_map, load_map_start_segment,
load_map_start_section, load_map_start, load_map_end,
free_load_map, free_current_contents_load_map,
segment_attributes, section_attributes, load_map_children,
load_map_attributes, load_map_elements, parse_load_map,
remote_relocate_using_qXfer_load_map,
remote_relocate_using_qOffsets, remote_relocate): New.
(remote_start_remote): Call remote_relocate.
(remote_pr): Add qXfer:load-map:read.
(extended_remote_attach_1): Call remote_relocate.
(remote_xfer_partial): Handle TARGET_OBJECT_LOAD_MAP.
(_initialize_remote): Add load-map command.
-------------- next part --------------
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -496,8 +496,9 @@ RUNTESTFLAGS=
# XML files to build in to GDB.
XMLFILES = $(srcdir)/features/gdb-target.dtd $(srcdir)/features/xinclude.dtd \
$(srcdir)/features/library-list.dtd \
- $(srcdir)/features/library-list-svr4.dtd $(srcdir)/features/osdata.dtd \
- $(srcdir)/features/threads.dtd $(srcdir)/features/traceframe-info.dtd
+ $(srcdir)/features/library-list-svr4.dtd $(srcdir)/features/load-map.dtd \
+ $(srcdir)/features/osdata.dtd $(srcdir)/features/threads.dtd \
+ $(srcdir)/features/traceframe-info.dtd
# This is ser-unix.o for any system which supports a v7/BSD/SYSV/POSIX
# interface to the serial port. Hopefully if get ported to OS/2, VMS,
--- /dev/null
+++ b/gdb/features/load-map.dtd
@@ -0,0 +1,15 @@
+<!-- Copyright (C) 2010 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!-- load-map: Root element with versioning -->
+<!ELEMENT load-map (segment*, section*)>
+<!ATTLIST load-map version CDATA #FIXED "1.0">
+
+<!ELEMENT segment EMPTY>
+<!ATTLIST segment address CDATA #REQUIRED>
+
+<!ELEMENT section EMPTY>
+<!ATTLIST section address CDATA #REQUIRED>
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -143,8 +143,6 @@ static void interrupt_query (void);
static void set_general_thread (struct ptid ptid);
static void set_continue_thread (struct ptid ptid);
-static void get_offsets (void);
-
static void skip_frame (void);
static long read_frame (char **buf_p, long *sizeof_buf);
@@ -1258,6 +1256,7 @@ enum {
PACKET_qXfer_statictrace_read,
PACKET_qXfer_traceframe_info,
PACKET_qXfer_uib,
+ PACKET_qXfer_load_map,
PACKET_qGetTIBAddr,
PACKET_qGetTLSAddr,
PACKET_qSupported,
@@ -3031,10 +3030,203 @@ remote_close (int quitting)
remote_notif_unregister_async_event_handler ();
}
-/* Query the remote side for the text, data and bss offsets. */
+#if defined(HAVE_LIBEXPAT)
+
+/* Handle the start of a <segment> element. */
static void
-get_offsets (void)
+load_map_start_segment (struct gdb_xml_parser *parser,
+ const struct gdb_xml_element *element,
+ void *user_data, VEC(gdb_xml_value_s) *attributes)
+{
+ struct load_map_info *info = user_data;
+ ULONGEST *address_p = xml_find_attribute (attributes, "address")->value;
+ CORE_ADDR address = (CORE_ADDR) *address_p;
+
+ if (info->section_bases != NULL)
+ gdb_xml_error (parser,
+ _("Library list with both segments and sections"));
+
+ VEC_safe_push (CORE_ADDR, info->section_bases, address);
+}
+
+/* Handle the start of a <section> element. */
+
+static void
+load_map_start_section (struct gdb_xml_parser *parser,
+ const struct gdb_xml_element *element,
+ void *user_data, VEC(gdb_xml_value_s) *attributes)
+{
+ struct load_map_info *info = user_data;
+ ULONGEST *address_p = xml_find_attribute (attributes, "address")->value;
+ CORE_ADDR address = (CORE_ADDR) *address_p;
+
+ if (info->segment_bases != NULL)
+ gdb_xml_error (parser,
+ _("Offsets with both segments and sections"));
+
+ VEC_safe_push (CORE_ADDR, info->segment_bases, address);
+}
+
+/* Handle the start of a <load-map> element. */
+
+static void
+load_map_start (struct gdb_xml_parser *parser,
+ const struct gdb_xml_element *element,
+ void *user_data, VEC(gdb_xml_value_s) *attributes)
+{
+ char *version = xml_find_attribute (attributes, "version")->value;
+
+ if (strcmp (version, "1.0") != 0)
+ gdb_xml_error (parser,
+ _("Offsets list has unsupported version \"%s\""),
+ version);
+}
+
+/* Handle the end of a <load-map> element. */
+
+static void
+load_map_end (struct gdb_xml_parser *parser,
+ const struct gdb_xml_element *element,
+ void *user_data, const char *body_text)
+{
+ struct load_map_info *load_map_info = user_data;
+
+ if (load_map_info->segment_bases == NULL
+ && load_map_info->section_bases == NULL)
+ gdb_xml_error (parser,
+ _("No segment or section bases defined"));
+}
+
+/* Discard the constructed load map. */
+
+static void
+free_load_map (void *p)
+{
+ struct load_map_info *info = p;
+
+ VEC_free (CORE_ADDR, info->segment_bases);
+ VEC_free (CORE_ADDR, info->section_bases);
+ xfree (info);
+}
+
+static void
+free_current_contents_load_map (void *p)
+{
+ struct load_map_info **info = p;
+
+ free_load_map (*info);
+ *info = NULL;
+}
+
+/* The allowed elements and attributes for an XML load map. The root
+ element is a <load-map>. */
+
+static const struct gdb_xml_attribute segment_attributes[] = {
+ { "address", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+ { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+static 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 }
+};
+
+static const struct gdb_xml_element load_map_children[] = {
+ { "segment", segment_attributes, NULL,
+ GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
+ load_map_start_segment, NULL },
+ { "section", section_attributes, NULL,
+ GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
+ load_map_start_section, NULL },
+ { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_attribute load_map_attributes[] = {
+ { "version", GDB_XML_AF_NONE, NULL, NULL },
+ { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_element load_map_elements[] = {
+ { "load-map", load_map_attributes, load_map_children,
+ GDB_XML_EF_NONE, load_map_start, load_map_end },
+ { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+static struct load_map_info *
+parse_load_map (const char *load_map)
+{
+ struct load_map_info *result = XCNEW (struct load_map_info);
+ struct cleanup *back_to = make_cleanup (free_current_contents_load_map,
+ &result);
+
+ if (gdb_xml_parse_quick (_("load map"), "load-map.dtd",
+ load_map_elements, load_map, result) == 0)
+ {
+ /* Parsed successfully, keep the result. */
+ discard_cleanups (back_to);
+ return result;
+ }
+
+ do_cleanups (back_to);
+ return NULL;
+}
+
+#endif
+
+/* Relocate the main symbol file and executable using the load
+ addresses as reported by a qXfer:load-map:read query. Returns true
+ if the target supported the query, false otherwise. We'll still
+ try qOffsets in the latter case. */
+
+static int
+remote_relocate_using_qXfer_load_map (void)
+{
+#if defined(HAVE_LIBEXPAT)
+ if (remote_protocol_packets[PACKET_qXfer_load_map].support == PACKET_ENABLE)
+ {
+ struct section_offsets *offs;
+ const char *load_map_document;
+ struct load_map_info *info;
+ struct bfd *abfd;
+ const char *filename;
+ struct cleanup *old_chain;
+
+ /* Fetch the offset list. */
+
+ load_map_document = target_read_stralloc (¤t_target,
+ TARGET_OBJECT_LOAD_MAP,
+ NULL);
+ if (load_map_document == NULL)
+ return 0;
+
+ old_chain = make_cleanup (xfree, (void *) load_map_document);
+
+ /* Parse the list. */
+ info = parse_load_map (load_map_document);
+ if (info == NULL)
+ {
+ do_cleanups (old_chain);
+ return 0;
+ }
+
+ make_cleanup (free_load_map, info);
+
+ relocate_with_load_map (info);
+
+ do_cleanups (old_chain);
+ return 1;
+ }
+#endif
+
+ return 0;
+}
+
+/* Query the remote side for the text, data and bss section offsets,
+ or text and data segment load bases. */
+
+static void
+remote_relocate_using_qOffsets (void)
{
struct remote_state *rs = get_remote_state ();
char *buf;
@@ -3044,9 +3236,6 @@ get_offsets (void)
struct section_offsets *offs;
struct symfile_segment_data *data;
- if (symfile_objfile == NULL)
- return;
-
putpkt ("qOffsets");
getpkt (&rs->buf, &rs->buf_size, 0);
buf = rs->buf;
@@ -3190,6 +3379,17 @@ get_offsets (void)
objfile_relocate (symfile_objfile, offs);
}
+static void
+remote_relocate (void)
+{
+ if (symfile_objfile == NULL)
+ return;
+
+ if (remote_relocate_using_qXfer_load_map ())
+ return;
+ remote_relocate_using_qOffsets ();
+}
+
/* Callback for iterate_over_threads. Set the STOP_REQUESTED flags in
threads we know are stopped already. This is used during the
initial remote connection in non-stop mode --- threads that are
@@ -3468,7 +3668,9 @@ remote_start_remote (int from_tty, struc
manipulation. */
init_wait_for_inferior ();
- get_offsets (); /* Get text, data & bss offsets. */
+ /* Get section/segment load offsets/addresses from the
+ target. */
+ remote_relocate ();
/* If we could not find a description using qXfer, and we know
how to do it some other way, try again. This is not
@@ -3542,7 +3744,9 @@ remote_start_remote (int from_tty, struc
if (ptid_equal (inferior_ptid, minus_one_ptid))
error (_("remote didn't report the current thread in non-stop mode"));
- get_offsets (); /* Get text, data & bss offsets. */
+ /* Get section/segment load offsets/addresses from the
+ target. */
+ remote_relocate ();
/* In non-stop mode, any cached wait status will be stored in
the stop reply queue. */
@@ -3950,6 +4154,8 @@ static struct protocol_feature remote_pr
PACKET_qXfer_threads },
{ "qXfer:traceframe-info:read", PACKET_DISABLE, remote_supported_packet,
PACKET_qXfer_traceframe_info },
+ { "qXfer:load-map:read", PACKET_DISABLE, remote_supported_packet,
+ PACKET_qXfer_load_map },
{ "QPassSignals", PACKET_DISABLE, remote_supported_packet,
PACKET_QPassSignals },
{ "QProgramSignals", PACKET_DISABLE, remote_supported_packet,
@@ -4519,6 +4725,9 @@ extended_remote_attach_1 (struct target_
this before anything involving memory or registers. */
target_find_description ();
+ /* Get updated relocation offsets. */
+ remote_relocate ();
+
if (!non_stop)
{
/* Use the previously fetched status. */
@@ -7950,7 +8159,7 @@ extended_remote_create_inferior_1 (char
{
/* Clean up from the last time we ran, before we mark the target
running again. This will mark breakpoints uninserted, and
- get_offsets may insert breakpoints. */
+ remote_relocate may insert breakpoints. */
init_thread_list ();
init_wait_for_inferior ();
}
@@ -7959,8 +8168,8 @@ extended_remote_create_inferior_1 (char
stop_reply = run_worked ? rs->buf : NULL;
add_current_inferior_and_thread (stop_reply);
- /* Get updated offsets, if the stub uses qOffsets. */
- get_offsets ();
+ /* Get section/segment load offsets/addresses from the target. */
+ remote_relocate ();
}
static void
@@ -8796,6 +9005,10 @@ remote_xfer_partial (struct target_ops *
return remote_read_qxfer (ops, "uib", annex, readbuf, offset, len,
&remote_protocol_packets[PACKET_qXfer_uib]);
+ case TARGET_OBJECT_LOAD_MAP:
+ gdb_assert (annex == NULL);
+ return remote_read_qxfer (ops, "load-map", annex, readbuf, offset, len,
+ &remote_protocol_packets[PACKET_qXfer_load_map]);
default:
return -1;
}
@@ -11663,6 +11876,9 @@ Show the maximum size of the address (in
add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_uib],
"qXfer:uib:read", "unwind-info-block", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_load_map],
+ "qXfer:load-map:read", "load-map", 0);
+
add_packet_config_cmd (&remote_protocol_packets[PACKET_qGetTLSAddr],
"qGetTLSAddr", "get-thread-local-storage-address",
0);
More information about the Gdb-patches
mailing list