X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fremote.c;h=9021d5a777e7a48aafdfd6fb4a376d664ecb5818;hb=f9780d5b2309f1fed7773b38a7eda5144ed181d3;hp=acb30abf485f8ed395ca73ed5a8f73664c4eb4e2;hpb=632110b170821f06baf4eec34716b9ad7b1284f7;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/remote.c b/gdb/remote.c index acb30abf48..9021d5a777 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -85,8 +85,6 @@ static void handle_remote_sigint_twice (int); static void async_remote_interrupt (gdb_client_data); void async_remote_interrupt_twice (gdb_client_data); -static void build_remote_gdbarch_data (void); - static void remote_files_info (struct target_ops *ignore); static void remote_prepare_to_store (struct regcache *regcache); @@ -260,7 +258,8 @@ struct packet_reg int in_g_packet; /* Always part of G packet. */ /* long size in bytes; == register_size (current_gdbarch, regnum); at present. */ - /* char *name; == REGISTER_NAME (regnum); at present. */ + /* char *name; == gdbarch_register_name (current_gdbarch, regnum); + at present. */ }; struct remote_arch_state @@ -906,7 +905,10 @@ enum { PACKET_Z4, PACKET_qXfer_auxv, PACKET_qXfer_features, + PACKET_qXfer_libraries, PACKET_qXfer_memory_map, + PACKET_qXfer_spu_read, + PACKET_qXfer_spu_write, PACKET_qGetTLSAddr, PACKET_qSupported, PACKET_QPassSignals, @@ -2013,9 +2015,13 @@ get_offsets (void) struct remote_state *rs = get_remote_state (); char *buf; char *ptr; - int lose; - CORE_ADDR text_addr, data_addr, bss_addr; + int lose, num_segments = 0, do_sections, do_segments; + CORE_ADDR text_addr, data_addr, bss_addr, segments[2]; struct section_offsets *offs; + struct symfile_segment_data *data; + + if (symfile_objfile == NULL) + return; putpkt ("qOffsets"); getpkt (&rs->buf, &rs->buf_size, 0); @@ -2044,47 +2050,109 @@ get_offsets (void) /* Don't use strtol, could lose on big values. */ while (*ptr && *ptr != ';') text_addr = (text_addr << 4) + fromhex (*ptr++); - } - else - lose = 1; - if (!lose && strncmp (ptr, ";Data=", 6) == 0) - { - ptr += 6; - while (*ptr && *ptr != ';') - data_addr = (data_addr << 4) + fromhex (*ptr++); - } - else - lose = 1; + if (strncmp (ptr, ";Data=", 6) == 0) + { + ptr += 6; + while (*ptr && *ptr != ';') + data_addr = (data_addr << 4) + fromhex (*ptr++); + } + else + lose = 1; - if (!lose && strncmp (ptr, ";Bss=", 5) == 0) + if (!lose && strncmp (ptr, ";Bss=", 5) == 0) + { + ptr += 5; + while (*ptr && *ptr != ';') + bss_addr = (bss_addr << 4) + fromhex (*ptr++); + + if (bss_addr != data_addr) + warning (_("Target reported unsupported offsets: %s"), buf); + } + else + lose = 1; + } + else if (strncmp (ptr, "TextSeg=", 8) == 0) { - ptr += 5; + ptr += 8; + /* Don't use strtol, could lose on big values. */ while (*ptr && *ptr != ';') - bss_addr = (bss_addr << 4) + fromhex (*ptr++); + text_addr = (text_addr << 4) + fromhex (*ptr++); + num_segments = 1; + + if (strncmp (ptr, ";DataSeg=", 9) == 0) + { + ptr += 9; + while (*ptr && *ptr != ';') + data_addr = (data_addr << 4) + fromhex (*ptr++); + num_segments++; + } } else lose = 1; if (lose) error (_("Malformed response to offset query, %s"), buf); - - if (symfile_objfile == NULL) - return; + else if (*ptr != '\0') + warning (_("Target reported unsupported offsets: %s"), buf); offs = ((struct section_offsets *) alloca (SIZEOF_N_SECTION_OFFSETS (symfile_objfile->num_sections))); memcpy (offs, symfile_objfile->section_offsets, SIZEOF_N_SECTION_OFFSETS (symfile_objfile->num_sections)); - offs->offsets[SECT_OFF_TEXT (symfile_objfile)] = text_addr; + data = get_symfile_segment_data (symfile_objfile->obfd); + do_segments = (data != NULL); + do_sections = num_segments == 0; - /* This is a temporary kludge to force data and bss to use the same offsets - because that's what nlmconv does now. The real solution requires changes - to the stub and remote.c that I don't have time to do right now. */ + /* 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 + { + do_sections = 0; + segments[0] = text_addr; + segments[1] = data_addr; + } - offs->offsets[SECT_OFF_DATA (symfile_objfile)] = data_addr; - offs->offsets[SECT_OFF_BSS (symfile_objfile)] = data_addr; + if (do_segments) + { + int ret = symfile_map_offsets_to_segments (symfile_objfile->obfd, data, + offs, num_segments, segments); + + if (ret == 0 && !do_sections) + error (_("Can not handle qOffsets TextSeg response with this symbol file")); + + if (ret > 0) + do_sections = 0; + } + + free_symfile_segment_data (data); + + if (do_sections) + { + offs->offsets[SECT_OFF_TEXT (symfile_objfile)] = text_addr; + + /* This is a temporary kludge to force data and bss to use the same offsets + because that's what nlmconv does now. The real solution requires changes + to the stub and remote.c that I don't have time to do right now. */ + + offs->offsets[SECT_OFF_DATA (symfile_objfile)] = data_addr; + offs->offsets[SECT_OFF_BSS (symfile_objfile)] = data_addr; + } objfile_relocate (symfile_objfile, offs); } @@ -2191,9 +2259,19 @@ remote_check_symbols (struct objfile *objfile) if (sym == NULL) xsnprintf (msg, get_remote_packet_size (), "qSymbol::%s", &reply[8]); else - xsnprintf (msg, get_remote_packet_size (), "qSymbol:%s:%s", - paddr_nz (SYMBOL_VALUE_ADDRESS (sym)), - &reply[8]); + { + CORE_ADDR sym_addr = SYMBOL_VALUE_ADDRESS (sym); + + /* If this is a function address, return the start of code + instead of any data function descriptor. */ + sym_addr = gdbarch_convert_from_func_ptr_addr (current_gdbarch, + sym_addr, + ¤t_target); + + xsnprintf (msg, get_remote_packet_size (), "qSymbol:%s:%s", + paddr_nz (sym_addr), &reply[8]); + } + putpkt (msg); getpkt (&rs->buf, &rs->buf_size, 0); reply = rs->buf; @@ -2309,8 +2387,14 @@ static struct protocol_feature remote_protocol_features[] = { PACKET_qXfer_auxv }, { "qXfer:features:read", PACKET_DISABLE, remote_supported_packet, PACKET_qXfer_features }, + { "qXfer:libraries:read", PACKET_DISABLE, remote_supported_packet, + PACKET_qXfer_libraries }, { "qXfer:memory-map:read", PACKET_DISABLE, remote_supported_packet, PACKET_qXfer_memory_map }, + { "qXfer:spu:read", PACKET_DISABLE, remote_supported_packet, + PACKET_qXfer_spu_read }, + { "qXfer:spu:write", PACKET_DISABLE, remote_supported_packet, + PACKET_qXfer_spu_write }, { "QPassSignals", PACKET_DISABLE, remote_supported_packet, PACKET_QPassSignals }, }; @@ -3110,6 +3194,7 @@ remote_wait (ptid_t ptid, struct target_waitstatus *status) struct remote_arch_state *rsa = get_remote_arch_state (); ULONGEST thread_num = -1; ULONGEST addr; + int solibs_changed = 0; status->kind = TARGET_WAITKIND_EXITED; status->value.integer = 0; @@ -3195,6 +3280,16 @@ Packet: '%s'\n"), p = unpack_varlen_hex (++p1, &addr); remote_watch_data_address = (CORE_ADDR)addr; } + else if (strncmp (p, "library", p1 - p) == 0) + { + p1++; + p_temp = p1; + while (*p_temp && *p_temp != ';') + p_temp++; + + solibs_changed = 1; + p = p_temp; + } else { /* Silently skip unknown optional info. */ @@ -3225,7 +3320,7 @@ Packet: '%s'\n"), if (fieldsize < register_size (current_gdbarch, reg->regnum)) warning (_("Remote reply is too short: %s"), buf); - regcache_raw_supply (current_regcache, + regcache_raw_supply (get_current_regcache (), reg->regnum, regs); } @@ -3236,9 +3331,14 @@ Packet: '%s'\n"), } /* fall through */ case 'S': /* Old style status, just signal only. */ - status->kind = TARGET_WAITKIND_STOPPED; - status->value.sig = (enum target_signal) - (((fromhex (buf[1])) << 4) + (fromhex (buf[2]))); + if (solibs_changed) + status->kind = TARGET_WAITKIND_LOADED; + else + { + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = (enum target_signal) + (((fromhex (buf[1])) << 4) + (fromhex (buf[2]))); + } if (buf[3] == 'p') { @@ -3301,6 +3401,7 @@ remote_async_wait (ptid_t ptid, struct target_waitstatus *status) struct remote_arch_state *rsa = get_remote_arch_state (); ULONGEST thread_num = -1; ULONGEST addr; + int solibs_changed = 0; status->kind = TARGET_WAITKIND_EXITED; status->value.integer = 0; @@ -3362,7 +3463,7 @@ remote_async_wait (ptid_t ptid, struct target_waitstatus *status) /* If this packet is an awatch packet, don't parse the 'a' as a register number. */ - if (!strncmp (p, "awatch", strlen ("awatch")) != 0) + if (strncmp (p, "awatch", strlen("awatch")) != 0) { /* Read the register number. */ pnum = strtol (p, &p_temp, 16); @@ -3392,6 +3493,16 @@ Packet: '%s'\n"), p = unpack_varlen_hex (++p1, &addr); remote_watch_data_address = (CORE_ADDR)addr; } + else if (strncmp (p, "library", p1 - p) == 0) + { + p1++; + p_temp = p1; + while (*p_temp && *p_temp != ';') + p_temp++; + + solibs_changed = 1; + p = p_temp; + } else { /* Silently skip unknown optional info. */ @@ -3422,7 +3533,8 @@ Packet: '%s'\n"), if (fieldsize < register_size (current_gdbarch, reg->regnum)) warning (_("Remote reply is too short: %s"), buf); - regcache_raw_supply (current_regcache, reg->regnum, regs); + regcache_raw_supply (get_current_regcache (), + reg->regnum, regs); } if (*p++ != ';') @@ -3432,9 +3544,14 @@ Packet: '%s'\n"), } /* fall through */ case 'S': /* Old style status, just signal only. */ - status->kind = TARGET_WAITKIND_STOPPED; - status->value.sig = (enum target_signal) - (((fromhex (buf[1])) << 4) + (fromhex (buf[2]))); + if (solibs_changed) + status->kind = TARGET_WAITKIND_LOADED; + else + { + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = (enum target_signal) + (((fromhex (buf[1])) << 4) + (fromhex (buf[2]))); + } if (buf[3] == 'p') { @@ -3919,13 +4036,18 @@ hexnumnstr (char *buf, ULONGEST num, int width) static CORE_ADDR remote_address_masked (CORE_ADDR addr) { - if (remote_address_size > 0 - && remote_address_size < (sizeof (ULONGEST) * 8)) + int address_size = remote_address_size; + /* If "remoteaddresssize" was not set, default to target address size. */ + if (!address_size) + address_size = gdbarch_addr_bit (current_gdbarch); + + if (address_size > 0 + && address_size < (sizeof (ULONGEST) * 8)) { /* Only create a mask when that mask can safely be constructed in a ULONGEST variable. */ ULONGEST mask = 1; - mask = (mask << remote_address_size) - 1; + mask = (mask << address_size) - 1; addr &= mask; } return addr; @@ -5121,7 +5243,8 @@ remote_insert_breakpoint (struct bp_target_info *bp_tgt) *(p++) = 'Z'; *(p++) = '0'; *(p++) = ','; - BREAKPOINT_FROM_PC (&bp_tgt->placed_address, &bp_tgt->placed_size); + gdbarch_breakpoint_from_pc + (current_gdbarch, &bp_tgt->placed_address, &bp_tgt->placed_size); addr = (ULONGEST) remote_address_masked (bp_tgt->placed_address); p += hexnumstr (p, addr); sprintf (p, ",%d", bp_tgt->placed_size); @@ -5316,7 +5439,8 @@ remote_insert_hw_breakpoint (struct bp_target_info *bp_tgt) /* The length field should be set to the size of a breakpoint instruction, even though we aren't inserting one ourselves. */ - BREAKPOINT_FROM_PC (&bp_tgt->placed_address, &bp_tgt->placed_size); + gdbarch_breakpoint_from_pc + (current_gdbarch, &bp_tgt->placed_address, &bp_tgt->placed_size); if (remote_protocol_packets[PACKET_Z1].support == PACKET_DISABLE) return -1; @@ -5515,6 +5639,45 @@ the loaded file\n")); printf_filtered (_("No loaded section named '%s'.\n"), args); } +/* Write LEN bytes from WRITEBUF into OBJECT_NAME/ANNEX at OFFSET + into remote target. The number of bytes written to the remote + target is returned, or -1 for error. */ + +static LONGEST +remote_write_qxfer (struct target_ops *ops, const char *object_name, + const char *annex, const gdb_byte *writebuf, + ULONGEST offset, LONGEST len, + struct packet_config *packet) +{ + int i, buf_len; + ULONGEST n; + gdb_byte *wbuf; + struct remote_state *rs = get_remote_state (); + int max_size = get_memory_write_packet_size (); + + if (packet->support == PACKET_DISABLE) + return -1; + + /* Insert header. */ + i = snprintf (rs->buf, max_size, + "qXfer:%s:write:%s:%s:", + object_name, annex ? annex : "", + phex_nz (offset, sizeof offset)); + max_size -= (i + 1); + + /* Escape as much data as fits into rs->buf. */ + buf_len = remote_escape_output + (writebuf, len, (rs->buf + i), &max_size, max_size); + + if (putpkt_binary (rs->buf, i + buf_len) < 0 + || getpkt_sane (&rs->buf, &rs->buf_size, 0) < 0 + || packet_ok (rs->buf, packet) != PACKET_OK) + return -1; + + unpack_varlen_hex (rs->buf, &n); + return n; +} + /* Read OBJECT_NAME/ANNEX from the remote target using a qXfer packet. Data at OFFSET, of up to LEN bytes, is read into READBUF; the number of bytes read is returned, or 0 for EOF, or -1 for error. @@ -5587,9 +5750,9 @@ remote_read_qxfer (struct target_ops *ops, const char *object_name, i = remote_unescape_input (rs->buf + 1, packet_len - 1, readbuf, n); /* 'l' is an EOF marker, possibly including a final block of data, - or possibly empty. Record it to bypass the next read, if one is - issued. */ - if (rs->buf[0] == 'l') + or possibly empty. If we have the final block of a non-empty + object, record this fact to bypass a subsequent partial read. */ + if (rs->buf[0] == 'l' && offset + i > 0) { finished_object = xstrdup (object_name); finished_annex = xstrdup (annex ? annex : ""); @@ -5628,6 +5791,19 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object, return -1; } + /* Handle SPU memory using qxfer packets. */ + if (object == TARGET_OBJECT_SPU) + { + if (readbuf) + return remote_read_qxfer (ops, "spu", annex, readbuf, offset, len, + &remote_protocol_packets + [PACKET_qXfer_spu_read]); + else + return remote_write_qxfer (ops, "spu", annex, writebuf, offset, len, + &remote_protocol_packets + [PACKET_qXfer_spu_write]); + } + /* Only handle flash writes. */ if (writebuf != NULL) { @@ -5668,6 +5844,11 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object, (ops, "features", annex, readbuf, offset, len, &remote_protocol_packets[PACKET_qXfer_features]); + case TARGET_OBJECT_LIBRARIES: + return remote_read_qxfer + (ops, "libraries", annex, readbuf, offset, len, + &remote_protocol_packets[PACKET_qXfer_libraries]); + case TARGET_OBJECT_MEMORY_MAP: gdb_assert (annex == NULL); return remote_read_qxfer (ops, "memory-map", annex, readbuf, offset, len, @@ -6285,7 +6466,7 @@ Specify the serial device it is connected to (e.g. /dev/ttya)."; remote_async_ops.to_memory_map = remote_memory_map; remote_async_ops.to_flash_erase = remote_flash_erase; remote_async_ops.to_flash_done = remote_flash_done; - remote_ops.to_read_description = remote_read_description; + remote_async_ops.to_read_description = remote_read_description; } /* Set up the async extended remote vector by making a copy of the standard @@ -6347,11 +6528,6 @@ show_remote_cmd (char *args, int from_tty) do_cleanups (showlist_chain); } -static void -build_remote_gdbarch_data (void) -{ - remote_address_size = TARGET_ADDR_BIT; -} /* Function to be called whenever a new objfile (shlib) is detected. */ static void @@ -6372,11 +6548,6 @@ _initialize_remote (void) remote_g_packet_data_handle = gdbarch_data_register_pre_init (remote_g_packet_data_init); - /* Old tacky stuff. NOTE: This comes after the remote protocol so - that the remote protocol has been initialized. */ - DEPRECATED_REGISTER_GDBARCH_SWAP (remote_address_size); - deprecated_register_gdbarch_swap (NULL, 0, build_remote_gdbarch_data); - /* Initialize the per-target state. At the moment there is only one of these, not one per target. Only one target is active at a time. The default buffer size is unimportant; it will be expanded @@ -6535,9 +6706,18 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL, add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_features], "qXfer:features:read", "target-features", 0); + add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_libraries], + "qXfer:libraries:read", "library-info", 0); + add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_memory_map], "qXfer:memory-map:read", "memory-map", 0); + add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_spu_read], + "qXfer:spu:read", "read-spu-object", 0); + + add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_spu_write], + "qXfer:spu:write", "write-spu-object", 0); + add_packet_config_cmd (&remote_protocol_packets[PACKET_qGetTLSAddr], "qGetTLSAddr", "get-thread-local-storage-address", 0);