static SCM gdbscm_memory_port_range (SCM port) { ioscm_memory_port *iomem; SCM_ASSERT_TYPE (gdbscm_is_memory_port (port), port, SCM_ARG1, FUNC_NAME, memory_port_desc_name); iomem = (ioscm_memory_port *) SCM_STREAM (port); return scm_list_2 (gdbscm_scm_from_ulongest (iomem->start), gdbscm_scm_from_ulongest (iomem->end)); }
static SCM gdbscm_open_memory (SCM rest) { const SCM keywords[] = { mode_keyword, start_keyword, size_keyword, SCM_BOOL_F }; char *mode = NULL; CORE_ADDR start = 0; CORE_ADDR end; int mode_arg_pos = -1, start_arg_pos = -1, size_arg_pos = -1; ULONGEST size; SCM port; long mode_bits; gdbscm_parse_function_args (FUNC_NAME, SCM_ARG1, keywords, "#sUU", rest, &mode_arg_pos, &mode, &start_arg_pos, &start, &size_arg_pos, &size); scm_dynwind_begin ((scm_t_dynwind_flags) 0); if (mode == NULL) mode = xstrdup ("r"); scm_dynwind_free (mode); if (size_arg_pos > 0) { /* For now be strict about start+size overflowing. If it becomes a nuisance we can relax things later. */ if (start + size < start) { gdbscm_out_of_range_error (FUNC_NAME, 0, scm_list_2 (gdbscm_scm_from_ulongest (start), gdbscm_scm_from_ulongest (size)), _("start+size overflows")); } end = start + size; } else end = ~(CORE_ADDR) 0; mode_bits = ioscm_parse_mode_bits (FUNC_NAME, mode); port = ioscm_open_port (memory_port_desc, mode_bits); ioscm_init_memory_port (port, start, end); scm_dynwind_end (); /* TODO: Set the file name as "memory-start-end"? */ return port; }
static void gdbscm_memory_port_flush (SCM port) { scm_t_port *pt = SCM_PTAB_ENTRY (port); ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port); size_t to_write = pt->write_pos - pt->write_buf; if (to_write == 0) return; /* There's no way to indicate a short write, so if the request goes past the end of the port's memory range, flag an error. */ if (to_write > iomem->size - iomem->current) { gdbscm_out_of_range_error (FUNC_NAME, 0, gdbscm_scm_from_ulongest (to_write), _("writing beyond end of memory range")); } if (target_write_memory (iomem->start + iomem->current, pt->write_buf, to_write) != 0) gdbscm_memory_error (FUNC_NAME, _("error writing memory"), SCM_EOL); iomem->current += to_write; pt->write_pos = pt->write_buf; pt->rw_active = SCM_PORT_NEITHER; }
static SCM gdbscm_lazy_string_address (SCM self) { SCM ls_scm = lsscm_get_lazy_string_arg_unsafe (self, SCM_ARG1, FUNC_NAME); lazy_string_smob *ls_smob = (lazy_string_smob *) SCM_SMOB_DATA (ls_scm); return gdbscm_scm_from_ulongest (ls_smob->address); }
static SCM gdbscm_sal_pc (SCM self) { sal_smob *s_smob = stscm_get_valid_sal_smob_arg (self, SCM_ARG1, FUNC_NAME); const struct symtab_and_line *sal = &s_smob->sal; return gdbscm_scm_from_ulongest (sal->pc); }
static SCM gdbscm_sal_last (SCM self) { sal_smob *s_smob = stscm_get_valid_sal_smob_arg (self, SCM_ARG1, FUNC_NAME); const struct symtab_and_line *sal = &s_smob->sal; if (sal->end > 0) return gdbscm_scm_from_ulongest (sal->end - 1); return SCM_BOOL_F; }
static SCM dascm_make_insn (CORE_ADDR pc, const char *assembly, int insn_len) { return scm_list_3 (scm_cons (address_symbol, gdbscm_scm_from_ulongest (pc)), scm_cons (asm_symbol, gdbscm_scm_from_c_string (assembly)), scm_cons (length_symbol, scm_from_int (insn_len))); }
static const char * gdbscm_disasm_read_memory_worker (void *datap) { struct gdbscm_disasm_read_data *data = (struct gdbscm_disasm_read_data *) datap; struct disassemble_info *dinfo = data->dinfo; struct gdbscm_disasm_data *disasm_data = (struct gdbscm_disasm_data *) dinfo->application_data; SCM seekto, newpos, port = disasm_data->port; size_t bytes_read; seekto = gdbscm_scm_from_ulongest (data->memaddr - disasm_data->offset); newpos = scm_seek (port, seekto, scm_from_int (SEEK_SET)); if (!scm_is_eq (seekto, newpos)) return "seek error"; bytes_read = scm_c_read (port, data->myaddr, data->length); if (bytes_read != data->length) return "short read"; /* If we get here the read succeeded. */ return NULL; }
static SCM gdbscm_arch_disassemble (SCM self, SCM start_scm, SCM rest) { arch_smob *a_smob = arscm_get_arch_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME); struct gdbarch *gdbarch = arscm_get_gdbarch (a_smob); const SCM keywords[] = { port_keyword, offset_keyword, size_keyword, count_keyword, SCM_BOOL_F }; int port_arg_pos = -1, offset_arg_pos = -1; int size_arg_pos = -1, count_arg_pos = -1; SCM port = SCM_BOOL_F; ULONGEST offset = 0; unsigned int count = 1; unsigned int size; ULONGEST start_arg; CORE_ADDR start, end; CORE_ADDR pc; unsigned int i; int using_port; SCM result; gdbscm_parse_function_args (FUNC_NAME, SCM_ARG2, keywords, "U#OUuu", start_scm, &start_arg, rest, &port_arg_pos, &port, &offset_arg_pos, &offset, &size_arg_pos, &size, &count_arg_pos, &count); /* START is first stored in a ULONGEST because we don't have a format char for CORE_ADDR, and it's not really worth it to have one yet. */ start = start_arg; if (port_arg_pos > 0) { SCM_ASSERT_TYPE (gdbscm_is_false (port) || gdbscm_is_true (scm_input_port_p (port)), port, port_arg_pos, FUNC_NAME, _("input port")); } using_port = gdbscm_is_true (port); if (offset_arg_pos > 0 && (port_arg_pos < 0 || gdbscm_is_false (port))) { gdbscm_out_of_range_error (FUNC_NAME, offset_arg_pos, gdbscm_scm_from_ulongest (offset), _("offset provided but port is missing")); } if (size_arg_pos > 0) { if (size == 0) return SCM_EOL; /* For now be strict about start+size overflowing. If it becomes a nuisance we can relax things later. */ if (start + size < start) { gdbscm_out_of_range_error (FUNC_NAME, 0, scm_list_2 (gdbscm_scm_from_ulongest (start), gdbscm_scm_from_ulongest (size)), _("start+size overflows")); } end = start + size - 1; } else end = ~(CORE_ADDR) 0; if (count == 0) return SCM_EOL; result = SCM_EOL; for (pc = start, i = 0; pc <= end && i < count; ) { int insn_len = 0; struct ui_file *memfile = mem_fileopen (); struct cleanup *cleanups = make_cleanup_ui_file_delete (memfile); TRY { if (using_port) { insn_len = gdbscm_print_insn_from_port (gdbarch, port, offset, pc, memfile, NULL); } else insn_len = gdb_print_insn (gdbarch, pc, memfile, NULL); } CATCH (except, RETURN_MASK_ALL) { GDBSCM_HANDLE_GDB_EXCEPTION_WITH_CLEANUPS (except, cleanups); } END_CATCH std::string as = ui_file_as_string (memfile); result = scm_cons (dascm_make_insn (pc, as.c_str (), insn_len), result); pc += insn_len; i++; do_cleanups (cleanups); }
static void gdbscm_memory_port_write (SCM port, const void *void_data, size_t size) { scm_t_port *pt = SCM_PTAB_ENTRY (port); ioscm_memory_port *iomem = (ioscm_memory_port *) SCM_STREAM (port); const gdb_byte *data = (const gdb_byte *) void_data; /* There's no way to indicate a short write, so if the request goes past the end of the port's memory range, flag an error. */ if (size > iomem->size - iomem->current) { gdbscm_out_of_range_error (FUNC_NAME, 0, gdbscm_scm_from_ulongest (size), _("writing beyond end of memory range")); } if (pt->write_buf == &pt->shortbuf) { /* Unbuffered port. */ if (target_write_memory (iomem->start + iomem->current, data, size) != 0) gdbscm_memory_error (FUNC_NAME, _("error writing memory"), SCM_EOL); iomem->current += size; return; } /* Note: The edge case of what to do when the buffer exactly fills is debatable. Guile flushes when the buffer exactly fills up, so we do too. It's counter-intuitive to my mind, but in case there's a subtlety somewhere that depends on this, we do the same. */ { size_t space = pt->write_end - pt->write_pos; if (size < space) { /* Data fits in buffer, and does not fill it. */ memcpy (pt->write_pos, data, size); pt->write_pos += size; } else { memcpy (pt->write_pos, data, space); pt->write_pos = pt->write_end; gdbscm_memory_port_flush (port); { const gdb_byte *ptr = data + space; size_t remaining = size - space; if (remaining >= pt->write_buf_size) { if (target_write_memory (iomem->start + iomem->current, ptr, remaining) != 0) gdbscm_memory_error (FUNC_NAME, _("error writing memory"), SCM_EOL); iomem->current += remaining; } else { memcpy (pt->write_pos, ptr, remaining); pt->write_pos += remaining; } } } } }