Exemplo n.º 1
0
static int str9x_write(struct flash_bank *bank,
		uint8_t *buffer, uint32_t offset, uint32_t count)
{
	struct target *target = bank->target;
	uint32_t words_remaining = (count / 2);
	uint32_t bytes_remaining = (count & 0x00000001);
	uint32_t address = bank->base + offset;
	uint32_t bytes_written = 0;
	uint8_t status;
	int retval;
	uint32_t check_address = offset;
	uint32_t bank_adr;
	int i;

	if (bank->target->state != TARGET_HALTED) {
		LOG_ERROR("Target not halted");
		return ERROR_TARGET_NOT_HALTED;
	}

	if (offset & 0x1) {
		LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
		return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
	}

	for (i = 0; i < bank->num_sectors; i++) {
		uint32_t sec_start = bank->sectors[i].offset;
		uint32_t sec_end = sec_start + bank->sectors[i].size;

		/* check if destination falls within the current sector */
		if ((check_address >= sec_start) && (check_address < sec_end)) {
			/* check if destination ends in the current sector */
			if (offset + count < sec_end)
				check_address = offset + count;
			else
				check_address = sec_end;
		}
	}

	if (check_address != offset + count)
		return ERROR_FLASH_DST_OUT_OF_BANK;

	/* multiple half words (2-byte) to be programmed? */
	if (words_remaining > 0) {
		/* try using a block write */
		retval = str9x_write_block(bank, buffer, offset, words_remaining);
		if (retval != ERROR_OK) {
			if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
				/* if block write failed (no sufficient working area),
				 * we use normal (slow) single dword accesses */
				LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
			} else if (retval == ERROR_FLASH_OPERATION_FAILED) {
				LOG_ERROR("flash writing failed");
				return ERROR_FLASH_OPERATION_FAILED;
			}
		} else {
			buffer += words_remaining * 2;
			address += words_remaining * 2;
			words_remaining = 0;
		}
	}

	while (words_remaining > 0) {
		bank_adr = address & ~0x03;

		/* write data command */
		target_write_u16(target, bank_adr, 0x40);
		target_write_memory(target, address, 2, 1, buffer + bytes_written);

		/* get status command */
		target_write_u16(target, bank_adr, 0x70);

		int timeout;
		for (timeout = 0; timeout < 1000; timeout++) {
			target_read_u8(target, bank_adr, &status);
			if (status & 0x80)
				break;
			alive_sleep(1);
		}
		if (timeout == 1000) {
			LOG_ERROR("write timed out");
			return ERROR_FAIL;
		}

		/* clear status reg and read array */
		target_write_u16(target, bank_adr, 0x50);
		target_write_u16(target, bank_adr, 0xFF);

		if (status & 0x10)
			return ERROR_FLASH_OPERATION_FAILED;
		else if (status & 0x02)
			return ERROR_FLASH_OPERATION_FAILED;

		bytes_written += 2;
		words_remaining--;
		address += 2;
	}

	if (bytes_remaining) {
		uint8_t last_halfword[2] = {0xff, 0xff};

		/* copy the last remaining bytes into the write buffer */
		memcpy(last_halfword, buffer+bytes_written, bytes_remaining);

		bank_adr = address & ~0x03;

		/* write data command */
		target_write_u16(target, bank_adr, 0x40);
		target_write_memory(target, address, 2, 1, last_halfword);

		/* query status command */
		target_write_u16(target, bank_adr, 0x70);

		int timeout;
		for (timeout = 0; timeout < 1000; timeout++) {
			target_read_u8(target, bank_adr, &status);
			if (status & 0x80)
				break;
			alive_sleep(1);
		}
		if (timeout == 1000) {
			LOG_ERROR("write timed out");
			return ERROR_FAIL;
		}

		/* clear status reg and read array */
		target_write_u16(target, bank_adr, 0x50);
		target_write_u16(target, bank_adr, 0xFF);

		if (status & 0x10)
			return ERROR_FLASH_OPERATION_FAILED;
		else if (status & 0x02)
			return ERROR_FLASH_OPERATION_FAILED;
	}

	return ERROR_OK;
}
Exemplo n.º 2
0
int
agent_run_command (int pid, const char *cmd, int len)
{
  int fd;
  int tid = agent_get_helper_thread_id ();
  ptid_t ptid = ptid_build (pid, tid, 0);

  int ret = target_write_memory (ipa_sym_addrs.addr_cmd_buf,
				 (gdb_byte *) cmd, len);

  if (ret != 0)
    {
      warning (_("unable to write"));
      return -1;
    }

  DEBUG_AGENT ("agent: resumed helper thread\n");

  /* Resume helper thread.  */
  target_continue_no_signal (ptid);

  fd = gdb_connect_sync_socket (pid);
  if (fd >= 0)
    {
      char buf[1] = "";
      int ret;

      DEBUG_AGENT ("agent: signalling helper thread\n");

      do
	{
	  ret = write (fd, buf, 1);
	} while (ret == -1 && errno == EINTR);

	DEBUG_AGENT ("agent: waiting for helper thread's response\n");

      do
	{
	  ret = read (fd, buf, 1);
	} while (ret == -1 && errno == EINTR);

      close (fd);

      DEBUG_AGENT ("agent: helper thread's response received\n");
    }
  else
    return -1;

  /* Need to read response with the inferior stopped.  */
  if (!ptid_equal (ptid, null_ptid))
    {
      /* Stop thread PTID.  */
      DEBUG_AGENT ("agent: stop helper thread\n");
      target_stop_and_wait (ptid);
    }

  if (fd >= 0)
    {
      if (target_read_memory (ipa_sym_addrs.addr_cmd_buf, (gdb_byte *) cmd,
			      IPA_CMD_BUF_SIZE))
	{
	  warning (_("Error reading command response"));
	  return -1;
	}
    }

  return 0;
}
Exemplo n.º 3
0
static void
copy_sections (bfd *abfd, asection *sect, void *data)
{
  asymbol **symbol_table = data;
  bfd_byte *sect_data, *sect_data_got;
  struct cleanup *cleanups;
  struct bfd_link_info link_info;
  struct bfd_link_order link_order;
  CORE_ADDR inferior_addr;
  struct link_hash_table_cleanup_data cleanup_data;

  if ((bfd_get_section_flags (abfd, sect) & (SEC_ALLOC | SEC_LOAD))
      != (SEC_ALLOC | SEC_LOAD))
    return;

  if (bfd_get_section_size (sect) == 0)
    return;

  /* Mostly a copy of bfd_simple_get_relocated_section_contents which GDB
     cannot use as it does not report relocations to undefined symbols.  */
  memset (&link_info, 0, sizeof (link_info));
  link_info.output_bfd = abfd;
  link_info.input_bfds = abfd;
  link_info.input_bfds_tail = &abfd->link.next;

  cleanup_data.abfd = abfd;
  cleanup_data.link_next = abfd->link.next;

  abfd->link.next = NULL;
  link_info.hash = bfd_link_hash_table_create (abfd);

  cleanups = make_cleanup (link_hash_table_free, &cleanup_data);
  link_info.callbacks = &link_callbacks;

  memset (&link_order, 0, sizeof (link_order));
  link_order.next = NULL;
  link_order.type = bfd_indirect_link_order;
  link_order.offset = 0;
  link_order.size = bfd_get_section_size (sect);
  link_order.u.indirect.section = sect;

  sect_data = xmalloc (bfd_get_section_size (sect));
  make_cleanup (xfree, sect_data);

  sect_data_got = bfd_get_relocated_section_contents (abfd, &link_info,
						      &link_order, sect_data,
						      FALSE, symbol_table);

  if (sect_data_got == NULL)
    error (_("Cannot map compiled module \"%s\" section \"%s\": %s"),
	   bfd_get_filename (abfd), bfd_get_section_name (abfd, sect),
	   bfd_errmsg (bfd_get_error ()));
  gdb_assert (sect_data_got == sect_data);

  inferior_addr = bfd_get_section_vma (abfd, sect);
  if (0 != target_write_memory (inferior_addr, sect_data,
				bfd_get_section_size (sect)))
    error (_("Cannot write compiled module \"%s\" section \"%s\" "
	     "to inferior memory range %s-%s."),
	   bfd_get_filename (abfd), bfd_get_section_name (abfd, sect),
	   paddress (target_gdbarch (), inferior_addr),
	   paddress (target_gdbarch (),
		     inferior_addr + bfd_get_section_size (sect)));

  do_cleanups (cleanups);
}
Exemplo n.º 4
0
static LONGEST
ld_so_xfer_auxv (gdb_byte *readbuf,
		 const gdb_byte *writebuf,
		 ULONGEST offset,
		 LONGEST len)
{
  struct minimal_symbol *msym;
  CORE_ADDR data_address, pointer_address;
  struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
  size_t ptr_size = TYPE_LENGTH (ptr_type);
  size_t auxv_pair_size = 2 * ptr_size;
  gdb_byte *ptr_buf = alloca (ptr_size);
  LONGEST retval;
  size_t block;

  msym = lookup_minimal_symbol ("_dl_auxv", NULL, NULL);
  if (msym == NULL)
    return -1;

  if (MSYMBOL_SIZE (msym) != ptr_size)
    return -1;

  /* POINTER_ADDRESS is a location where the `_dl_auxv' variable
     resides.  DATA_ADDRESS is the inferior value present in
     `_dl_auxv', therefore the real inferior AUXV address.  */

  pointer_address = SYMBOL_VALUE_ADDRESS (msym);

  /* The location of the _dl_auxv symbol may no longer be correct if
     ld.so runs at a different address than the one present in the
     file.  This is very common case - for unprelinked ld.so or with a
     PIE executable.  PIE executable forces random address even for
     libraries already being prelinked to some address.  PIE
     executables themselves are never prelinked even on prelinked
     systems.  Prelinking of a PIE executable would block their
     purpose of randomizing load of everything including the
     executable.

     If the memory read fails, return -1 to fallback on another
     mechanism for retrieving the AUXV.

     In most cases of a PIE running under valgrind there is no way to
     find out the base addresses of any of ld.so, executable or AUXV
     as everything is randomized and /proc information is not relevant
     for the virtual executable running under valgrind.  We think that
     we might need a valgrind extension to make it work.  This is PR
     11440.  */

  if (target_read_memory (pointer_address, ptr_buf, ptr_size) != 0)
    return -1;

  data_address = extract_typed_address (ptr_buf, ptr_type);

  /* Possibly still not initialized such as during an inferior
     startup.  */
  if (data_address == 0)
    return -1;

  data_address += offset;

  if (writebuf != NULL)
    {
      if (target_write_memory (data_address, writebuf, len) == 0)
	return len;
      else
	return -1;
    }

  /* Stop if trying to read past the existing AUXV block.  The final
     AT_NULL was already returned before.  */

  if (offset >= auxv_pair_size)
    {
      if (target_read_memory (data_address - auxv_pair_size, ptr_buf,
			      ptr_size) != 0)
	return -1;

      if (extract_typed_address (ptr_buf, ptr_type) == AT_NULL)
	return 0;
    }

  retval = 0;
  block = 0x400;
  gdb_assert (block % auxv_pair_size == 0);

  while (len > 0)
    {
      if (block > len)
	block = len;

      /* Reading sizes smaller than AUXV_PAIR_SIZE is not supported.
	 Tails unaligned to AUXV_PAIR_SIZE will not be read during a
	 call (they should be completed during next read with
	 new/extended buffer).  */

      block &= -auxv_pair_size;
      if (block == 0)
	return retval;

      if (target_read_memory (data_address, readbuf, block) != 0)
	{
	  if (block <= auxv_pair_size)
	    return retval;

	  block = auxv_pair_size;
	  continue;
	}

      data_address += block;
      len -= block;

      /* Check terminal AT_NULL.  This function is being called
         indefinitely being extended its READBUF until it returns EOF
         (0).  */

      while (block >= auxv_pair_size)
	{
	  retval += auxv_pair_size;

	  if (extract_typed_address (readbuf, ptr_type) == AT_NULL)
	    return retval;

	  readbuf += auxv_pair_size;
	  block -= auxv_pair_size;
	}
    }

  return retval;
}
Exemplo n.º 5
0
static int str7x_write(struct flash_bank *bank, const uint8_t *buffer,
		uint32_t offset, uint32_t count)
{
	struct target *target = bank->target;
	uint32_t dwords_remaining = (count / 8);
	uint32_t bytes_remaining = (count & 0x00000007);
	uint32_t address = bank->base + offset;
	uint32_t bytes_written = 0;
	uint32_t cmd;
	int retval;
	uint32_t check_address = offset;
	int i;

	if (bank->target->state != TARGET_HALTED) {
		LOG_ERROR("Target not halted");
		return ERROR_TARGET_NOT_HALTED;
	}

	if (offset & 0x7) {
		LOG_WARNING("offset 0x%" PRIx32 " breaks required 8-byte alignment", offset);
		return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
	}

	for (i = 0; i < bank->num_sectors; i++) {
		uint32_t sec_start = bank->sectors[i].offset;
		uint32_t sec_end = sec_start + bank->sectors[i].size;

		/* check if destination falls within the current sector */
		if ((check_address >= sec_start) && (check_address < sec_end)) {
			/* check if destination ends in the current sector */
			if (offset + count < sec_end)
				check_address = offset + count;
			else
				check_address = sec_end;
		}
	}

	if (check_address != offset + count)
		return ERROR_FLASH_DST_OUT_OF_BANK;

	/* clear FLASH_ER register */
	target_write_u32(target, str7x_get_flash_adr(bank, FLASH_ER), 0x0);

	/* multiple dwords (8-byte) to be programmed? */
	if (dwords_remaining > 0) {
		/* try using a block write */
		retval = str7x_write_block(bank, buffer, offset, dwords_remaining);
		if (retval != ERROR_OK) {
			if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
				/* if block write failed (no sufficient working area),
				 * we use normal (slow) single dword accesses */
				LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
			} else {
				return retval;
			}
		} else {
			buffer += dwords_remaining * 8;
			address += dwords_remaining * 8;
			dwords_remaining = 0;
		}
	}

	while (dwords_remaining > 0) {
		/* command */
		cmd = FLASH_DWPG;
		target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);

		/* address */
		target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), address);

		/* data word 1 */
		target_write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0),
				4, 1, buffer + bytes_written);
		bytes_written += 4;

		/* data word 2 */
		target_write_memory(target, str7x_get_flash_adr(bank, FLASH_DR1),
				4, 1, buffer + bytes_written);
		bytes_written += 4;

		/* start programming cycle */
		cmd = FLASH_DWPG | FLASH_WMS;
		target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);

		int err;
		err = str7x_waitbusy(bank);
		if (err != ERROR_OK)
			return err;

		err = str7x_result(bank);
		if (err != ERROR_OK)
			return err;

		dwords_remaining--;
		address += 8;
	}

	if (bytes_remaining) {
		uint8_t last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};

		/* copy the last remaining bytes into the write buffer */
		memcpy(last_dword, buffer+bytes_written, bytes_remaining);

		/* command */
		cmd = FLASH_DWPG;
		target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);

		/* address */
		target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), address);

		/* data word 1 */
		target_write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0),
				4, 1, last_dword);

		/* data word 2 */
		target_write_memory(target, str7x_get_flash_adr(bank, FLASH_DR1),
				4, 1, last_dword + 4);

		/* start programming cycle */
		cmd = FLASH_DWPG | FLASH_WMS;
		target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);

		int err;
		err = str7x_waitbusy(bank);
		if (err != ERROR_OK)
			return err;

		err = str7x_result(bank);
		if (err != ERROR_OK)
			return err;
	}

	return ERROR_OK;
}
Exemplo n.º 6
0
static int do_semihosting(struct target *target)
{
	struct arm *arm = target_to_arm(target);
	struct gdb_fileio_info *fileio_info = target->fileio_info;
	uint32_t r0 = buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32);
	uint32_t r1 = buf_get_u32(arm->core_cache->reg_list[1].value, 0, 32);
	uint8_t params[16];
	int retval;

	/*
	 * TODO: lots of security issues are not considered yet, such as:
	 * - no validation on target provided file descriptors
	 * - no safety checks on opened/deleted/renamed file paths
	 * Beware the target app you use this support with.
	 *
	 * TODO: unsupported semihosting fileio operations could be
	 * implemented if we had a small working area at our disposal.
	 */
	switch ((arm->semihosting_op = r0)) {
	case 0x01:	/* SYS_OPEN */
		retval = target_read_memory(target, r1, 4, 3, params);
		if (retval != ERROR_OK)
			return retval;
		else {
			uint32_t a = target_buffer_get_u32(target, params+0);
			uint32_t m = target_buffer_get_u32(target, params+4);
			uint32_t l = target_buffer_get_u32(target, params+8);
			uint8_t fn[256];
			retval = target_read_memory(target, a, 1, l, fn);
			if (retval != ERROR_OK)
				return retval;
			fn[l] = 0;
			if (arm->is_semihosting_fileio) {
				if (strcmp((char *)fn, ":tt") == 0)
					arm->semihosting_result = 0;
				else {
					arm->semihosting_hit_fileio = true;
					fileio_info->identifier = "open";
					fileio_info->param_1 = a;
					fileio_info->param_2 = l;
					fileio_info->param_3 = open_modeflags[m];
					fileio_info->param_4 = 0644;
				}
			} else {
				if (l <= 255 && m <= 11) {
					if (strcmp((char *)fn, ":tt") == 0) {
						if (m < 4)
							arm->semihosting_result = dup(STDIN_FILENO);
						else
							arm->semihosting_result = dup(STDOUT_FILENO);
					} else {
						/* cygwin requires the permission setting
						 * otherwise it will fail to reopen a previously
						 * written file */
						arm->semihosting_result = open((char *)fn, open_modeflags[m], 0644);
					}
					arm->semihosting_errno =  errno;
				} else {
					arm->semihosting_result = -1;
					arm->semihosting_errno = EINVAL;
				}
			}
		}
		break;

	case 0x02:	/* SYS_CLOSE */
		retval = target_read_memory(target, r1, 4, 1, params);
		if (retval != ERROR_OK)
			return retval;
		else {
			int fd = target_buffer_get_u32(target, params+0);
			if (arm->is_semihosting_fileio) {
				arm->semihosting_hit_fileio = true;
				fileio_info->identifier = "close";
				fileio_info->param_1 = fd;
			} else {
				arm->semihosting_result = close(fd);
				arm->semihosting_errno = errno;
			}
		}
		break;

	case 0x03:	/* SYS_WRITEC */
		if (arm->is_semihosting_fileio) {
			arm->semihosting_hit_fileio = true;
			fileio_info->identifier = "write";
			fileio_info->param_1 = 1;
			fileio_info->param_2 = r1;
			fileio_info->param_3 = 1;
		} else {
			unsigned char c;
			retval = target_read_memory(target, r1, 1, 1, &c);
			if (retval != ERROR_OK)
				return retval;
			putchar(c);
			arm->semihosting_result = 0;
		}
		break;

	case 0x04:	/* SYS_WRITE0 */
		if (arm->is_semihosting_fileio) {
			size_t count = 0;
			for (uint32_t a = r1;; a++) {
				unsigned char c;
				retval = target_read_memory(target, a, 1, 1, &c);
				if (retval != ERROR_OK)
					return retval;
				if (c == '\0')
					break;
				count++;
			}
			arm->semihosting_hit_fileio = true;
			fileio_info->identifier = "write";
			fileio_info->param_1 = 1;
			fileio_info->param_2 = r1;
			fileio_info->param_3 = count;
		} else {
			do {
				unsigned char c;
				retval = target_read_memory(target, r1++, 1, 1, &c);
				if (retval != ERROR_OK)
					return retval;
				if (!c)
					break;
				putchar(c);
			} while (1);
			arm->semihosting_result = 0;
		}
		break;

	case 0x05:	/* SYS_WRITE */
		retval = target_read_memory(target, r1, 4, 3, params);
		if (retval != ERROR_OK)
			return retval;
		else {
			int fd = target_buffer_get_u32(target, params+0);
			uint32_t a = target_buffer_get_u32(target, params+4);
			size_t l = target_buffer_get_u32(target, params+8);
			if (arm->is_semihosting_fileio) {
				arm->semihosting_hit_fileio = true;
				fileio_info->identifier = "write";
				fileio_info->param_1 = fd;
				fileio_info->param_2 = a;
				fileio_info->param_3 = l;
			} else {
				uint8_t *buf = malloc(l);
				if (!buf) {
					arm->semihosting_result = -1;
					arm->semihosting_errno = ENOMEM;
				} else {
					retval = target_read_buffer(target, a, l, buf);
					if (retval != ERROR_OK) {
						free(buf);
						return retval;
					}
					arm->semihosting_result = write(fd, buf, l);
					arm->semihosting_errno = errno;
					if (arm->semihosting_result >= 0)
						arm->semihosting_result = l - arm->semihosting_result;
					free(buf);
				}
			}
		}
		break;

	case 0x06:	/* SYS_READ */
		retval = target_read_memory(target, r1, 4, 3, params);
		if (retval != ERROR_OK)
			return retval;
		else {
			int fd = target_buffer_get_u32(target, params+0);
			uint32_t a = target_buffer_get_u32(target, params+4);
			ssize_t l = target_buffer_get_u32(target, params+8);
			if (arm->is_semihosting_fileio) {
				arm->semihosting_hit_fileio = true;
				fileio_info->identifier = "read";
				fileio_info->param_1 = fd;
				fileio_info->param_2 = a;
				fileio_info->param_3 = l;
			} else {
				uint8_t *buf = malloc(l);
				if (!buf) {
					arm->semihosting_result = -1;
					arm->semihosting_errno = ENOMEM;
				} else {
					arm->semihosting_result = read(fd, buf, l);
					arm->semihosting_errno = errno;
					if (arm->semihosting_result >= 0) {
						retval = target_write_buffer(target, a, arm->semihosting_result, buf);
						if (retval != ERROR_OK) {
							free(buf);
							return retval;
						}
						arm->semihosting_result = l - arm->semihosting_result;
					}
					free(buf);
				}
			}
		}
		break;

	case 0x07:	/* SYS_READC */
		if (arm->is_semihosting_fileio) {
			LOG_ERROR("SYS_READC not supported by semihosting fileio");
			return ERROR_FAIL;
		}
		arm->semihosting_result = getchar();
		break;

	case 0x08:	/* SYS_ISERROR */
		retval = target_read_memory(target, r1, 4, 1, params);
		if (retval != ERROR_OK)
			return retval;
		arm->semihosting_result = (target_buffer_get_u32(target, params+0) != 0);
		break;

	case 0x09:	/* SYS_ISTTY */
		if (arm->is_semihosting_fileio) {
			arm->semihosting_hit_fileio = true;
			fileio_info->identifier = "isatty";
			fileio_info->param_1 = r1;
		} else {
			retval = target_read_memory(target, r1, 4, 1, params);
			if (retval != ERROR_OK)
				return retval;
			arm->semihosting_result = isatty(target_buffer_get_u32(target, params+0));
		}
		break;

	case 0x0a:	/* SYS_SEEK */
		retval = target_read_memory(target, r1, 4, 2, params);
		if (retval != ERROR_OK)
			return retval;
		else {
			int fd = target_buffer_get_u32(target, params+0);
			off_t pos = target_buffer_get_u32(target, params+4);
			if (arm->is_semihosting_fileio) {
				arm->semihosting_hit_fileio = true;
				fileio_info->identifier = "lseek";
				fileio_info->param_1 = fd;
				fileio_info->param_2 = pos;
				fileio_info->param_3 = SEEK_SET;
			} else {
				arm->semihosting_result = lseek(fd, pos, SEEK_SET);
				arm->semihosting_errno = errno;
				if (arm->semihosting_result == pos)
					arm->semihosting_result = 0;
			}
		}
		break;

	case 0x0c:	/* SYS_FLEN */
		if (arm->is_semihosting_fileio) {
			LOG_ERROR("SYS_FLEN not supported by semihosting fileio");
			return ERROR_FAIL;
		}
		retval = target_read_memory(target, r1, 4, 1, params);
		if (retval != ERROR_OK)
			return retval;
		else {
			int fd = target_buffer_get_u32(target, params+0);
			struct stat buf;
			arm->semihosting_result = fstat(fd, &buf);
			if (arm->semihosting_result == -1) {
				arm->semihosting_errno = errno;
				arm->semihosting_result = -1;
				break;
			}
			arm->semihosting_result = buf.st_size;
		}
		break;

	case 0x0e:	/* SYS_REMOVE */
		retval = target_read_memory(target, r1, 4, 2, params);
		if (retval != ERROR_OK)
			return retval;
		else {
			uint32_t a = target_buffer_get_u32(target, params+0);
			uint32_t l = target_buffer_get_u32(target, params+4);
			if (arm->is_semihosting_fileio) {
				arm->semihosting_hit_fileio = true;
				fileio_info->identifier = "unlink";
				fileio_info->param_1 = a;
				fileio_info->param_2 = l;
			} else {
				if (l <= 255) {
					uint8_t fn[256];
					retval = target_read_memory(target, a, 1, l, fn);
					if (retval != ERROR_OK)
						return retval;
					fn[l] = 0;
					arm->semihosting_result = remove((char *)fn);
					arm->semihosting_errno =  errno;
				} else {
					arm->semihosting_result = -1;
					arm->semihosting_errno = EINVAL;
				}
			}
		}
		break;

	case 0x0f:	/* SYS_RENAME */
		retval = target_read_memory(target, r1, 4, 4, params);
		if (retval != ERROR_OK)
			return retval;
		else {
			uint32_t a1 = target_buffer_get_u32(target, params+0);
			uint32_t l1 = target_buffer_get_u32(target, params+4);
			uint32_t a2 = target_buffer_get_u32(target, params+8);
			uint32_t l2 = target_buffer_get_u32(target, params+12);
			if (arm->is_semihosting_fileio) {
				arm->semihosting_hit_fileio = true;
				fileio_info->identifier = "rename";
				fileio_info->param_1 = a1;
				fileio_info->param_2 = l1;
				fileio_info->param_3 = a2;
				fileio_info->param_4 = l2;
			} else {
				if (l1 <= 255 && l2 <= 255) {
					uint8_t fn1[256], fn2[256];
					retval = target_read_memory(target, a1, 1, l1, fn1);
					if (retval != ERROR_OK)
						return retval;
					retval = target_read_memory(target, a2, 1, l2, fn2);
					if (retval != ERROR_OK)
						return retval;
					fn1[l1] = 0;
					fn2[l2] = 0;
					arm->semihosting_result = rename((char *)fn1, (char *)fn2);
					arm->semihosting_errno =  errno;
				} else {
					arm->semihosting_result = -1;
					arm->semihosting_errno = EINVAL;
				}
			}
		}
		break;

	case 0x11:	/* SYS_TIME */
		arm->semihosting_result = time(NULL);
		break;

	case 0x13:	/* SYS_ERRNO */
		arm->semihosting_result = arm->semihosting_errno;
		break;

	case 0x15:	/* SYS_GET_CMDLINE */
		retval = target_read_memory(target, r1, 4, 2, params);
		if (retval != ERROR_OK)
			return retval;
		else {
			uint32_t a = target_buffer_get_u32(target, params+0);
			uint32_t l = target_buffer_get_u32(target, params+4);
			char *arg = arm->semihosting_cmdline != NULL ? arm->semihosting_cmdline : "";
			uint32_t s = strlen(arg) + 1;
			if (l < s)
				arm->semihosting_result = -1;
			else {
				retval = target_write_buffer(target, a, s, (uint8_t *)arg);
				if (retval != ERROR_OK)
					return retval;
				arm->semihosting_result = 0;
			}
		}
		break;

	case 0x16:	/* SYS_HEAPINFO */
		retval = target_read_memory(target, r1, 4, 1, params);
		if (retval != ERROR_OK)
			return retval;
		else {
			uint32_t a = target_buffer_get_u32(target, params+0);
			/* tell the remote we have no idea */
			memset(params, 0, 4*4);
			retval = target_write_memory(target, a, 4, 4, params);
			if (retval != ERROR_OK)
				return retval;
			arm->semihosting_result = 0;
		}
		break;

	case 0x18:	/* angel_SWIreason_ReportException */
		switch (r1) {
		case 0x20026:	/* ADP_Stopped_ApplicationExit */
			fprintf(stderr, "semihosting: *** application exited ***\n");
			break;
		case 0x20000:	/* ADP_Stopped_BranchThroughZero */
		case 0x20001:	/* ADP_Stopped_UndefinedInstr */
		case 0x20002:	/* ADP_Stopped_SoftwareInterrupt */
		case 0x20003:	/* ADP_Stopped_PrefetchAbort */
		case 0x20004:	/* ADP_Stopped_DataAbort */
		case 0x20005:	/* ADP_Stopped_AddressException */
		case 0x20006:	/* ADP_Stopped_IRQ */
		case 0x20007:	/* ADP_Stopped_FIQ */
		case 0x20020:	/* ADP_Stopped_BreakPoint */
		case 0x20021:	/* ADP_Stopped_WatchPoint */
		case 0x20022:	/* ADP_Stopped_StepComplete */
		case 0x20023:	/* ADP_Stopped_RunTimeErrorUnknown */
		case 0x20024:	/* ADP_Stopped_InternalError */
		case 0x20025:	/* ADP_Stopped_UserInterruption */
		case 0x20027:	/* ADP_Stopped_StackOverflow */
		case 0x20028:	/* ADP_Stopped_DivisionByZero */
		case 0x20029:	/* ADP_Stopped_OSSpecific */
		default:
			fprintf(stderr, "semihosting: exception %#x\n",
					(unsigned) r1);
		}
		return target_call_event_callbacks(target, TARGET_EVENT_HALTED);

	case 0x12:	/* SYS_SYSTEM */
		/* Provide SYS_SYSTEM functionality.  Uses the
		 * libc system command, there may be a reason *NOT*
		 * to use this, but as I can't think of one, I
		 * implemented it this way.
		 */
		retval = target_read_memory(target, r1, 4, 2, params);
		if (retval != ERROR_OK)
			return retval;
		else {
			uint32_t len = target_buffer_get_u32(target, params+4);
			uint32_t c_ptr = target_buffer_get_u32(target, params);
			if (arm->is_semihosting_fileio) {
				arm->semihosting_hit_fileio = true;
				fileio_info->identifier = "system";
				fileio_info->param_1 = c_ptr;
				fileio_info->param_2 = len;
			} else {
				uint8_t cmd[256];
				if (len > 255) {
					arm->semihosting_result = -1;
					arm->semihosting_errno = EINVAL;
				} else {
					memset(cmd, 0x0, 256);
					retval = target_read_memory(target, c_ptr, 1, len, cmd);
					if (retval != ERROR_OK)
						return retval;
					else
						arm->semihosting_result = system((const char *)cmd);
				}
			}
		}
		break;
	case 0x0d:	/* SYS_TMPNAM */
	case 0x10:	/* SYS_CLOCK */
	case 0x17:	/* angel_SWIreason_EnterSVC */
	case 0x30:	/* SYS_ELAPSED */
	case 0x31:	/* SYS_TICKFREQ */
	default:
		fprintf(stderr, "semihosting: unsupported call %#x\n",
				(unsigned) r0);
		arm->semihosting_result = -1;
		arm->semihosting_errno = ENOTSUP;
	}

	return ERROR_OK;
}
Exemplo n.º 7
0
int
default_memory_remove_breakpoint (struct bp_target_info *bp_tgt)
{
  return target_write_memory (bp_tgt->placed_address, bp_tgt->shadow_contents,
			      bp_tgt->placed_size);
}
Exemplo n.º 8
0
static void
remote_fileio_func_fstat (char *buf)
{
  CORE_ADDR ptrval;
  int fd, ret;
  long target_fd;
  LONGEST lnum;
  struct stat st;
  struct fio_stat fst;
  struct timeval tv;

  /* 1. Parameter: file descriptor */
  if (remote_fileio_extract_int (&buf, &target_fd))
    {
      remote_fileio_ioerror ();
      return;
    }
  fd = remote_fileio_map_fd ((int) target_fd);
  if (fd == FIO_FD_INVALID)
    {
      remote_fileio_badfd ();
      return;
    }
  /* 2. Parameter: Ptr to struct stat */
  if (remote_fileio_extract_long (&buf, &lnum))
    {
      remote_fileio_ioerror ();
      return;
    }
  ptrval = (CORE_ADDR) lnum;

  remote_fio_no_longjmp = 1;
  if (fd == FIO_FD_CONSOLE_IN || fd == FIO_FD_CONSOLE_OUT)
    {
      host_to_fileio_uint (1, fst.fst_dev);
      memset (&st, 0, sizeof (st));
      st.st_mode = S_IFCHR | (fd == FIO_FD_CONSOLE_IN ? S_IRUSR : S_IWUSR);
      st.st_nlink = 1;
#ifdef HAVE_GETUID
      st.st_uid = getuid ();
#endif
#ifdef HAVE_GETGID
      st.st_gid = getgid ();
#endif
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
      st.st_blksize = 512;
#endif
#if HAVE_STRUCT_STAT_ST_BLOCKS
      st.st_blocks = 0;
#endif
      if (!gettimeofday (&tv, NULL))
	st.st_atime = st.st_mtime = st.st_ctime = tv.tv_sec;
      else
        st.st_atime = st.st_mtime = st.st_ctime = (time_t) 0;
      ret = 0;
    }
  else
    ret = fstat (fd, &st);

  if (ret == -1)
    {
      remote_fileio_return_errno (-1);
      return;
    }
  if (ptrval)
    {
      host_to_fileio_stat (&st, &fst);

      errno = target_write_memory (ptrval, (gdb_byte *) &fst, sizeof fst);
      if (errno != 0)
	{
	  remote_fileio_return_errno (-1);
	  return;
	}
    }
  remote_fileio_return_success (ret);
}
Exemplo n.º 9
0
static void
restore_section_callback(bfd *ibfd, asection *isec, void *args)
{
  struct callback_data *data = (struct callback_data *)args;
  bfd_vma sec_start = bfd_section_vma(ibfd, isec);
  bfd_size_type size = bfd_section_size(ibfd, isec);
  bfd_vma sec_end = (sec_start + size);
  bfd_size_type sec_offset = 0UL;
  bfd_size_type sec_load_count = size;
  struct cleanup *old_chain;
  gdb_byte *buf;
  int ret;

  /* Ignore non-loadable sections, eg. from elf files: */
  if (!(bfd_get_section_flags(ibfd, isec) & SEC_LOAD))
    return;

  /* Does the section overlap with the desired restore range? */
  if ((sec_end <= data->load_start)
      || ((data->load_end > 0) && (sec_start >= data->load_end)))
    {
      /* No, no useable data in this section. */
      printf_filtered(_("skipping section %s...\n"),
		      bfd_section_name(ibfd, isec));
      return;
    }

  /* Compare section address range with user-requested
     address range (if any).  Compute where the actual
     transfer should start and end.  */
  if (sec_start < data->load_start)
    sec_offset = (data->load_start - sec_start);
  /* Size of a partial transfer: */
  sec_load_count -= sec_offset;
  if ((data->load_end > 0) && (sec_end > data->load_end))
    sec_load_count -= (sec_end - data->load_end);

  /* Get the data.  */
  buf = (gdb_byte *)xmalloc((size_t)size);
  old_chain = make_cleanup(xfree, buf);
  if (!bfd_get_section_contents(ibfd, isec, buf, 0, size))
    error(_("Failed to read bfd file %s: '%s'."), bfd_get_filename(ibfd),
	  bfd_errmsg(bfd_get_error()));

  printf_filtered("Restoring section %s (0x%lx to 0x%lx)",
		  bfd_section_name(ibfd, isec),
		  (unsigned long)sec_start, (unsigned long)sec_end);

  if ((data->load_offset != 0) || (data->load_start != 0) || (data->load_end != 0))
    printf_filtered(" into memory (0x%s to 0x%s)\n",
		    paddr_nz((unsigned long)sec_start
                             + sec_offset + data->load_offset),
		    paddr_nz((unsigned long)sec_start + sec_offset
                             + data->load_offset + sec_load_count));
  else
    puts_filtered("\n");

  /* Write the data: */
  ret = target_write_memory((sec_start + sec_offset + data->load_offset),
			    (buf + sec_offset), (int)sec_load_count);
  if (ret != 0)
    warning(_("restore: memory write failed (%s)."), safe_strerror(ret));
  do_cleanups(old_chain);
  return;
}
Exemplo n.º 10
0
/* APPLE LOCAL BEGIN: segment binary file download: */
static void
restore_binary_file(char *filename, struct callback_data *data)
{
  FILE *file = fopen_with_cleanup(filename, FOPEN_RB);
  gdb_byte *buf;
  long len;
  long total_file_bytes;
  long bytes_to_read_from_file;

  CORE_ADDR addrp;

  /* Get the file size for reading: */
  if (fseek(file, 0L, SEEK_END) == 0)
    total_file_bytes = ftell(file);
  else
    perror_with_name(filename);

  if (total_file_bytes <= (int)data->load_start)
    error(_("Start address is greater than length of binary file %s."),
          filename);

  bytes_to_read_from_file = (int)data->load_end;
  if (bytes_to_read_from_file == 0)
    bytes_to_read_from_file = total_file_bytes;
  if (data->load_start > 0)
    bytes_to_read_from_file -= (int)data->load_start;

  if (bytes_to_read_from_file > total_file_bytes)
    bytes_to_read_from_file = total_file_bytes;

  printf_filtered("Restoring binary file %s into memory (0x%s to 0x%s)\n",
                  filename,
                  paddr_nz(data->load_start + data->load_offset),
                  paddr_nz(data->load_start + data->load_offset + bytes_to_read_from_file));

  /* Now set the file pos to the requested load start pos: */
  if (fseek(file, (long)data->load_start, SEEK_SET) != 0)
    perror_with_name(filename);

  if (bytes_to_read_from_file > g_max_binary_file_chunk)
    len = g_max_binary_file_chunk;
  else
    len = bytes_to_read_from_file;

  buf = (gdb_byte *)xmalloc(len);
  make_cleanup(xfree, buf);

  addrp = (data->load_start + data->load_offset);
  /* BYTES_TO_READ_FROM_FILE decreases each time through this loop;
     we read g_max_binary_file_chunk or less bytes at each iteration.  */
  while (bytes_to_read_from_file > 0)
    {
      int max_errors;

      /* The last chunk we shall be reading -- at this point our LEN buffer
         is larger than the remaining number of bytes to be read; cap it
         so we do NOT read off the end of the file. */
      if (len > bytes_to_read_from_file)
        len = bytes_to_read_from_file;

      if (fread(buf, 1, len, file) != (size_t)len)
	perror_with_name(filename);

      max_errors = 2;
      while (max_errors > 0)
        {
           printf_unfiltered(_("Writing 0x%s bytes to 0x%s\n"), paddr_nz(len),
			     paddr_nz(addrp));
           gdb_flush (gdb_stdout);
           if (target_write_memory(addrp, buf, (int)len) == 0)
             {
               addrp += len;
               break;
             }
           else
             {
	       warning(_("restore: memory write failed - retrying."));
               max_errors--;
             }
        }
      if (max_errors == 0)
        error ("restore: memory write failed.");

      bytes_to_read_from_file -= len;
    }
}
Exemplo n.º 11
0
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;
	    }
	}
      }
  }
}
Exemplo n.º 12
0
/* Start a low level flash write for the specified region */
static int nrf5_ll_flash_write(struct nrf5_info *chip, uint32_t offset, const uint8_t *buffer, uint32_t bytes)
{
	struct target *target = chip->target;
	uint32_t buffer_size = 8192;
	struct working_area *write_algorithm;
	struct working_area *source;
	uint32_t address = NRF5_FLASH_BASE + offset;
	struct reg_param reg_params[4];
	struct armv7m_algorithm armv7m_info;
	int retval = ERROR_OK;


	LOG_DEBUG("Writing buffer to flash offset=0x%"PRIx32" bytes=0x%"PRIx32, offset, bytes);
	assert(bytes % 4 == 0);

	/* allocate working area with flash programming code */
	if (target_alloc_working_area(target, sizeof(nrf5_flash_write_code),
			&write_algorithm) != ERROR_OK) {
		LOG_WARNING("no working area available, falling back to slow memory writes");

		for (; bytes > 0; bytes -= 4) {
			retval = target_write_memory(chip->target, offset, 4, 1, buffer);
			if (retval != ERROR_OK)
				return retval;

			retval = nrf5_wait_for_nvmc(chip);
			if (retval != ERROR_OK)
				return retval;

			offset += 4;
			buffer += 4;
		}

		return ERROR_OK;
	}

	LOG_WARNING("using fast async flash loader. This is currently supported");
	LOG_WARNING("only with ST-Link and CMSIS-DAP. If you have issues, add");
	LOG_WARNING("\"set WORKAREASIZE 0\" before sourcing nrf51.cfg/nrf52.cfg to disable it");

	retval = target_write_buffer(target, write_algorithm->address,
				sizeof(nrf5_flash_write_code),
				nrf5_flash_write_code);
	if (retval != ERROR_OK)
		return retval;

	/* memory buffer */
	while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK) {
		buffer_size /= 2;
		buffer_size &= ~3UL; /* Make sure it's 4 byte aligned */
		if (buffer_size <= 256) {
			/* free working area, write algorithm already allocated */
			target_free_working_area(target, write_algorithm);

			LOG_WARNING("No large enough working area available, can't do block memory writes");
			return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
		}
	}

	armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
	armv7m_info.core_mode = ARM_MODE_THREAD;

	init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);	/* byte count */
	init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);	/* buffer start */
	init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);	/* buffer end */
	init_reg_param(&reg_params[3], "r3", 32, PARAM_IN_OUT);	/* target address */

	buf_set_u32(reg_params[0].value, 0, 32, bytes);
	buf_set_u32(reg_params[1].value, 0, 32, source->address);
	buf_set_u32(reg_params[2].value, 0, 32, source->address + source->size);
	buf_set_u32(reg_params[3].value, 0, 32, address);

	retval = target_run_flash_async_algorithm(target, buffer, bytes/4, 4,
			0, NULL,
			4, reg_params,
			source->address, source->size,
			write_algorithm->address, 0,
			&armv7m_info);

	target_free_working_area(target, source);
	target_free_working_area(target, write_algorithm);

	destroy_reg_param(&reg_params[0]);
	destroy_reg_param(&reg_params[1]);
	destroy_reg_param(&reg_params[2]);
	destroy_reg_param(&reg_params[3]);

	return retval;
}
Exemplo n.º 13
0
static int do_semihosting(struct target *target)
{
	struct arm *arm = target_to_arm(target);
	uint32_t r0 = buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32);
	uint32_t r1 = buf_get_u32(arm->core_cache->reg_list[1].value, 0, 32);
	uint8_t params[16];
	int retval, result;

	/*
	 * TODO: lots of security issues are not considered yet, such as:
	 * - no validation on target provided file descriptors
	 * - no safety checks on opened/deleted/renamed file paths
	 * Beware the target app you use this support with.
	 *
	 * TODO: explore mapping requests to GDB's "File-I/O Remote
	 * Protocol Extension" ... when GDB is active.
	 */
	switch (r0) {
	case 0x01:	/* SYS_OPEN */
		retval = target_read_memory(target, r1, 4, 3, params);
		if (retval != ERROR_OK)
			return retval;
		else {
			uint32_t a = target_buffer_get_u32(target, params+0);
			uint32_t m = target_buffer_get_u32(target, params+4);
			uint32_t l = target_buffer_get_u32(target, params+8);
			if (l <= 255 && m <= 11) {
				uint8_t fn[256];
				retval = target_read_memory(target, a, 1, l, fn);
				if (retval != ERROR_OK)
					return retval;
				fn[l] = 0;
				if (strcmp((char *)fn, ":tt") == 0) {
					if (m < 4)
						result = dup(STDIN_FILENO);
					else
						result = dup(STDOUT_FILENO);
				} else {
					/* cygwin requires the permission setting
					 * otherwise it will fail to reopen a previously
					 * written file */
					result = open((char *)fn, open_modeflags[m], 0644);
				}
				arm->semihosting_errno =  errno;
			} else {
				result = -1;
				arm->semihosting_errno = EINVAL;
			}
		}
		break;

	case 0x02:	/* SYS_CLOSE */
		retval = target_read_memory(target, r1, 4, 1, params);
		if (retval != ERROR_OK)
			return retval;
		else {
			int fd = target_buffer_get_u32(target, params+0);
			result = close(fd);
			arm->semihosting_errno = errno;
		}
		break;

	case 0x03:	/* SYS_WRITEC */
		{
			unsigned char c;
			retval = target_read_memory(target, r1, 1, 1, &c);
			if (retval != ERROR_OK)
				return retval;
			putchar(c);
			result = 0;
		}
		break;

	case 0x04:	/* SYS_WRITE0 */
		do {
			unsigned char c;
			retval = target_read_memory(target, r1++, 1, 1, &c);
			if (retval != ERROR_OK)
				return retval;
			if (!c)
				break;
			putchar(c);
		} while (1);
		result = 0;
		break;

	case 0x05:	/* SYS_WRITE */
		retval = target_read_memory(target, r1, 4, 3, params);
		if (retval != ERROR_OK)
			return retval;
		else {
			int fd = target_buffer_get_u32(target, params+0);
			uint32_t a = target_buffer_get_u32(target, params+4);
			size_t l = target_buffer_get_u32(target, params+8);
			uint8_t *buf = malloc(l);
			if (!buf) {
				result = -1;
				arm->semihosting_errno = ENOMEM;
			} else {
				retval = target_read_buffer(target, a, l, buf);
				if (retval != ERROR_OK) {
					free(buf);
					return retval;
				}
				result = write(fd, buf, l);
				arm->semihosting_errno = errno;
				if (result >= 0)
					result = l - result;
				free(buf);
			}
		}
		break;

	case 0x06:	/* SYS_READ */
		retval = target_read_memory(target, r1, 4, 3, params);
		if (retval != ERROR_OK)
			return retval;
		else {
			int fd = target_buffer_get_u32(target, params+0);
			uint32_t a = target_buffer_get_u32(target, params+4);
			ssize_t l = target_buffer_get_u32(target, params+8);
			uint8_t *buf = malloc(l);
			if (!buf) {
				result = -1;
				arm->semihosting_errno = ENOMEM;
			} else {
				result = read(fd, buf, l);
				arm->semihosting_errno = errno;
				if (result >= 0) {
					retval = target_write_buffer(target, a, result, buf);
					if (retval != ERROR_OK) {
						free(buf);
						return retval;
					}
					result = l - result;
				}
				free(buf);
			}
		}
		break;

	case 0x07:	/* SYS_READC */
		result = getchar();
		break;

	case 0x08:	/* SYS_ISERROR */
		retval = target_read_memory(target, r1, 4, 1, params);
		if (retval != ERROR_OK)
			return retval;
		result = (target_buffer_get_u32(target, params+0) != 0);
		break;

	case 0x09:	/* SYS_ISTTY */
		retval = target_read_memory(target, r1, 4, 1, params);
		if (retval != ERROR_OK)
			return retval;
		result = isatty(target_buffer_get_u32(target, params+0));
		break;

	case 0x0a:	/* SYS_SEEK */
		retval = target_read_memory(target, r1, 4, 2, params);
		if (retval != ERROR_OK)
			return retval;
		else {
			int fd = target_buffer_get_u32(target, params+0);
			off_t pos = target_buffer_get_u32(target, params+4);
			result = lseek(fd, pos, SEEK_SET);
			arm->semihosting_errno = errno;
			if (result == pos)
				result = 0;
		}
		break;

	case 0x0c:	/* SYS_FLEN */
		retval = target_read_memory(target, r1, 4, 1, params);
		if (retval != ERROR_OK)
			return retval;
		else {
			int fd = target_buffer_get_u32(target, params+0);
			struct stat buf;
			result = fstat(fd, &buf);
			if (result == -1) {
				arm->semihosting_errno = errno;
				result = -1;
				break;
			}
			result = buf.st_size;
		}
		break;

	case 0x0e:	/* SYS_REMOVE */
		retval = target_read_memory(target, r1, 4, 2, params);
		if (retval != ERROR_OK)
			return retval;
		else {
			uint32_t a = target_buffer_get_u32(target, params+0);
			uint32_t l = target_buffer_get_u32(target, params+4);
			if (l <= 255) {
				uint8_t fn[256];
				retval = target_read_memory(target, a, 1, l, fn);
				if (retval != ERROR_OK)
					return retval;
				fn[l] = 0;
				result = remove((char *)fn);
				arm->semihosting_errno =  errno;
			} else {
				result = -1;
				arm->semihosting_errno = EINVAL;
			}
		}
		break;

	case 0x0f:	/* SYS_RENAME */
		retval = target_read_memory(target, r1, 4, 4, params);
		if (retval != ERROR_OK)
			return retval;
		else {
			uint32_t a1 = target_buffer_get_u32(target, params+0);
			uint32_t l1 = target_buffer_get_u32(target, params+4);
			uint32_t a2 = target_buffer_get_u32(target, params+8);
			uint32_t l2 = target_buffer_get_u32(target, params+12);
			if (l1 <= 255 && l2 <= 255) {
				uint8_t fn1[256], fn2[256];
				retval = target_read_memory(target, a1, 1, l1, fn1);
				if (retval != ERROR_OK)
					return retval;
				retval = target_read_memory(target, a2, 1, l2, fn2);
				if (retval != ERROR_OK)
					return retval;
				fn1[l1] = 0;
				fn2[l2] = 0;
				result = rename((char *)fn1, (char *)fn2);
				arm->semihosting_errno =  errno;
			} else {
				result = -1;
				arm->semihosting_errno = EINVAL;
			}
		}
		break;

	case 0x11:	/* SYS_TIME */
		result = time(NULL);
		break;

	case 0x13:	/* SYS_ERRNO */
		result = arm->semihosting_errno;
		break;

	case 0x15:	/* SYS_GET_CMDLINE */
		retval = target_read_memory(target, r1, 4, 2, params);
		if (retval != ERROR_OK)
			return retval;
		else {
			uint32_t a = target_buffer_get_u32(target, params+0);
			uint32_t l = target_buffer_get_u32(target, params+4);
			char *arg = "foobar";
			uint32_t s = strlen(arg) + 1;
			if (l < s)
				result = -1;
			else {
				retval = target_write_buffer(target, a, s, (uint8_t *)arg);
				if (retval != ERROR_OK)
					return retval;
				result = 0;
			}
		}
		break;

	case 0x16:	/* SYS_HEAPINFO */
		retval = target_read_memory(target, r1, 4, 1, params);
		if (retval != ERROR_OK)
			return retval;
		else {
			uint32_t a = target_buffer_get_u32(target, params+0);
			/* tell the remote we have no idea */
			memset(params, 0, 4*4);
			retval = target_write_memory(target, a, 4, 4, params);
			if (retval != ERROR_OK)
				return retval;
			result = 0;
		}
		break;

	case 0x18:	/* angel_SWIreason_ReportException */
		switch (r1) {
		case 0x20026:	/* ADP_Stopped_ApplicationExit */
			fprintf(stderr, "semihosting: *** application exited ***\n");
			break;
		case 0x20000:	/* ADP_Stopped_BranchThroughZero */
		case 0x20001:	/* ADP_Stopped_UndefinedInstr */
		case 0x20002:	/* ADP_Stopped_SoftwareInterrupt */
		case 0x20003:	/* ADP_Stopped_PrefetchAbort */
		case 0x20004:	/* ADP_Stopped_DataAbort */
		case 0x20005:	/* ADP_Stopped_AddressException */
		case 0x20006:	/* ADP_Stopped_IRQ */
		case 0x20007:	/* ADP_Stopped_FIQ */
		case 0x20020:	/* ADP_Stopped_BreakPoint */
		case 0x20021:	/* ADP_Stopped_WatchPoint */
		case 0x20022:	/* ADP_Stopped_StepComplete */
		case 0x20023:	/* ADP_Stopped_RunTimeErrorUnknown */
		case 0x20024:	/* ADP_Stopped_InternalError */
		case 0x20025:	/* ADP_Stopped_UserInterruption */
		case 0x20027:	/* ADP_Stopped_StackOverflow */
		case 0x20028:	/* ADP_Stopped_DivisionByZero */
		case 0x20029:	/* ADP_Stopped_OSSpecific */
		default:
			fprintf(stderr, "semihosting: exception %#x\n",
					(unsigned) r1);
		}
		return target_call_event_callbacks(target, TARGET_EVENT_HALTED);

	case 0x12:	/* SYS_SYSTEM */
		/* Provide SYS_SYSTEM functionality.  Uses the
		 * libc system command, there may be a reason *NOT*
		 * to use this, but as I can't think of one, I
		 * implemented it this way.
		 */
		retval = target_read_memory(target, r1, 4, 2, params);
		if (retval != ERROR_OK)
			return retval;
		else {
			uint32_t len = target_buffer_get_u32(target, params+4);
			uint32_t c_ptr = target_buffer_get_u32(target, params);
			uint8_t cmd[256];
			if (len > 255) {
				result = -1;
				arm->semihosting_errno = EINVAL;
			} else {
				memset(cmd, 0x0, 256);
				retval = target_read_memory(target, c_ptr, 1, len, cmd);
				if (retval != ERROR_OK)
					return retval;
				else
					result = system((const char *)cmd);
			}
		}
		break;
	case 0x0d:	/* SYS_TMPNAM */
	case 0x10:	/* SYS_CLOCK */
	case 0x17:	/* angel_SWIreason_EnterSVC */
	case 0x30:	/* SYS_ELAPSED */
	case 0x31:	/* SYS_TICKFREQ */
	default:
		fprintf(stderr, "semihosting: unsupported call %#x\n",
				(unsigned) r0);
		result = -1;
		arm->semihosting_errno = ENOTSUP;
	}

	/* resume execution to the original mode */

	/* REVISIT this looks wrong ... ARM11 and Cortex-A8
	 * should work this way at least sometimes.
	 */
	if (is_arm7_9(target_to_arm7_9(target))) {
		uint32_t spsr;

		/* return value in R0 */
		buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, result);
		arm->core_cache->reg_list[0].dirty = 1;

		/* LR --> PC */
		buf_set_u32(arm->core_cache->reg_list[15].value, 0, 32,
			buf_get_u32(arm_reg_current(arm, 14)->value, 0, 32));
		arm->core_cache->reg_list[15].dirty = 1;

		/* saved PSR --> current PSR */
		spsr = buf_get_u32(arm->spsr->value, 0, 32);

		/* REVISIT should this be arm_set_cpsr(arm, spsr)
		 * instead of a partially unrolled version?
		 */

		buf_set_u32(arm->cpsr->value, 0, 32, spsr);
		arm->cpsr->dirty = 1;
		arm->core_mode = spsr & 0x1f;
		if (spsr & 0x20)
			arm->core_state = ARM_STATE_THUMB;

	} else {
		/* resume execution, this will be pc+2 to skip over the
		 * bkpt instruction */

		/* return result in R0 */
		buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, result);
		arm->core_cache->reg_list[0].dirty = 1;
	}

	return target_resume(target, 1, 0, 0, 0);
}
Exemplo n.º 14
0
static void
remote_fileio_func_read (char *buf)
{
  long target_fd, num;
  LONGEST lnum;
  CORE_ADDR ptrval;
  int fd, ret;
  gdb_byte *buffer;
  size_t length;
  off_t old_offset, new_offset;

  /* 1. Parameter: file descriptor */
  if (remote_fileio_extract_int (&buf, &target_fd))
    {
      remote_fileio_ioerror ();
      return;
    }
  fd = remote_fileio_map_fd ((int) target_fd);
  if (fd == FIO_FD_INVALID)
    {
      remote_fileio_badfd ();
      return;
    }
  /* 2. Parameter: buffer pointer */
  if (remote_fileio_extract_long (&buf, &lnum))
    {
      remote_fileio_ioerror ();
      return;
    }
  ptrval = (CORE_ADDR) lnum;
  /* 3. Parameter: buffer length */
  if (remote_fileio_extract_int (&buf, &num))
    {
      remote_fileio_ioerror ();
      return;
    }
  length = (size_t) num;

  switch (fd)
    {
      case FIO_FD_CONSOLE_OUT:
	remote_fileio_badfd ();
	return;
      case FIO_FD_CONSOLE_IN:
	{
	  static char *remaining_buf = NULL;
	  static int remaining_length = 0;

	  buffer = (gdb_byte *) xmalloc (16384);
	  if (remaining_buf)
	    {
	      remote_fio_no_longjmp = 1;
	      if (remaining_length > length)
		{
		  memcpy (buffer, remaining_buf, length);
		  memmove (remaining_buf, remaining_buf + length,
			   remaining_length - length);
		  remaining_length -= length;
		  ret = length;
		}
	      else
		{
		  memcpy (buffer, remaining_buf, remaining_length);
		  xfree (remaining_buf);
		  remaining_buf = NULL;
		  ret = remaining_length;
		}
	    }
	  else
	    {
	      /* Windows (at least XP and Server 2003) has difficulty
		 with large reads from consoles.  If a handle is
		 backed by a real console device, overly large reads
		 from the handle will fail and set errno == ENOMEM.
		 On a Windows Server 2003 system where I tested,
		 reading 26608 bytes from the console was OK, but
		 anything above 26609 bytes would fail.  The limit has
		 been observed to vary on different systems.  So, we
		 limit this read to something smaller than that - by a
		 safe margin, in case the limit depends on system
		 resources or version.  */
	      ret = ui_file_read (gdb_stdtargin, (char *) buffer, 16383);
	      remote_fio_no_longjmp = 1;
	      if (ret > 0 && (size_t)ret > length)
		{
		  remaining_buf = (char *) xmalloc (ret - length);
		  remaining_length = ret - length;
		  memcpy (remaining_buf, buffer + length, remaining_length);
		  ret = length;
		}
	    }
	}
	break;
      default:
	buffer = (gdb_byte *) xmalloc (length);
	/* POSIX defines EINTR behaviour of read in a weird way.  It's allowed
	   for read() to return -1 even if "some" bytes have been read.  It
	   has been corrected in SUSv2 but that doesn't help us much...
	   Therefore a complete solution must check how many bytes have been
	   read on EINTR to return a more reliable value to the target */
	old_offset = lseek (fd, 0, SEEK_CUR);
	remote_fio_no_longjmp = 1;
	ret = read (fd, buffer, length);
	if (ret < 0 && errno == EINTR)
	  {
	    new_offset = lseek (fd, 0, SEEK_CUR);
	    /* If some data has been read, return the number of bytes read.
	       The Ctrl-C flag is set in remote_fileio_reply() anyway.  */
	    if (old_offset != new_offset)
	      ret = new_offset - old_offset;
	  }
	break;
    }

  if (ret > 0)
    {
      errno = target_write_memory (ptrval, buffer, ret);
      if (errno != 0)
	ret = -1;
    }

  if (ret < 0)
    remote_fileio_return_errno (-1);
  else
    remote_fileio_return_success (ret);

  xfree (buffer);
}
Exemplo n.º 15
0
void
store_inferior_registers (int regno)
{
  struct regs inferior_registers;
  struct fp_status inferior_fp_registers;
  int wanna_store = INT_REGS + STACK_REGS + FP_REGS;
  int store_pid;

  /* NOTE: cagney/2002-12-02: See comment in fetch_inferior_registers
     about threaded assumptions.  */
  store_pid = TIDGET (inferior_ptid);
  if (store_pid == 0)
    store_pid = PIDGET (inferior_ptid);

  /* First decide which pieces of machine-state we need to modify.  
     Default for regno == -1 case is all pieces.  */
  if (regno >= 0)
    {
      if (FP0_REGNUM <= regno && regno < FP0_REGNUM + 32)
	{
	  wanna_store = FP_REGS;
	}
      else
	{
	  if (regno == SP_REGNUM)
	    wanna_store = INT_REGS + STACK_REGS;
	  else if (regno < L0_REGNUM || regno > I7_REGNUM)
	    wanna_store = INT_REGS;
	  else if (regno == FPS_REGNUM)
	    wanna_store = FP_REGS;
	  else
	    wanna_store = STACK_REGS;
	}
    }

  /* See if we're forcing the stores to happen now, or deferring. */
  if (regno == -2)
    {
      wanna_store = deferred_stores;
      deferred_stores = 0;
    }
  else
    {
      if (wanna_store == STACK_REGS)
	{
	  /* Fall through and just store one stack reg.  If we deferred
	     it, we'd have to store them all, or remember more info.  */
	}
      else
	{
	  deferred_stores |= wanna_store;
	  return;
	}
    }

  if (wanna_store & STACK_REGS)
    {
      CORE_ADDR sp = *(unsigned int *) & registers[REGISTER_BYTE (SP_REGNUM)];

      if (regno < 0 || regno == SP_REGNUM)
	{
	  if (!register_valid[L0_REGNUM + 5])
	    internal_error (__FILE__, __LINE__, "failed internal consistency check");
	  target_write_memory (sp,
			       &registers[REGISTER_BYTE (L0_REGNUM)],
			       16 * REGISTER_RAW_SIZE (L0_REGNUM));
	}
      else
	{
	  if (!register_valid[regno])
	    internal_error (__FILE__, __LINE__, "failed internal consistency check");
	  target_write_memory (sp + REGISTER_BYTE (regno) - REGISTER_BYTE (L0_REGNUM),
			       &registers[REGISTER_BYTE (regno)],
			       REGISTER_RAW_SIZE (regno));
	}

    }

  if (wanna_store & INT_REGS)
    {
      if (!register_valid[G1_REGNUM])
	internal_error (__FILE__, __LINE__, "failed internal consistency check");

      memcpy (&inferior_registers.r_g1, &registers[REGISTER_BYTE (G1_REGNUM)],
	      15 * REGISTER_RAW_SIZE (G1_REGNUM));

      inferior_registers.r_ps =
	*(int *) &registers[REGISTER_BYTE (PS_REGNUM)];
      inferior_registers.r_pc =
	*(int *) &registers[REGISTER_BYTE (PC_REGNUM)];
      inferior_registers.r_npc =
	*(int *) &registers[REGISTER_BYTE (NPC_REGNUM)];
      inferior_registers.r_y =
	*(int *) &registers[REGISTER_BYTE (Y_REGNUM)];

      if (0 != ptrace (PTRACE_SETREGS, store_pid,
		       (PTRACE_ARG3_TYPE) & inferior_registers, 0))
	perror ("ptrace_setregs");
    }

  if (wanna_store & FP_REGS)
    {
      if (!register_valid[FP0_REGNUM + 9])
	internal_error (__FILE__, __LINE__, "failed internal consistency check");
      memcpy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
	      sizeof inferior_fp_registers.fpu_fr);
      memcpy (&inferior_fp_registers.Fpu_fsr,
	      &registers[REGISTER_BYTE (FPS_REGNUM)], sizeof (FPU_FSR_TYPE));
      if (0 !=
	  ptrace (PTRACE_SETFPREGS, store_pid,
		  (PTRACE_ARG3_TYPE) & inferior_fp_registers, 0))
	perror ("ptrace_setfpregs");
    }
}
Exemplo n.º 16
0
static void
remote_fileio_func_stat (char *buf)
{
  CORE_ADDR statptr, nameptr;
  int ret, namelength;
  char *pathname;
  LONGEST lnum;
  struct stat st;
  struct fio_stat fst;

  /* 1. Parameter: Ptr to pathname / length incl. trailing zero */
  if (remote_fileio_extract_ptr_w_len (&buf, &nameptr, &namelength))
    {
      remote_fileio_ioerror ();
      return;
    }

  /* 2. Parameter: Ptr to struct stat */
  if (remote_fileio_extract_long (&buf, &lnum))
    {
      remote_fileio_ioerror ();
      return;
    }
  statptr = (CORE_ADDR) lnum;
  
  /* Request pathname using 'm' packet */
  pathname = alloca (namelength);
  if (target_read_memory (nameptr, (gdb_byte *) pathname, namelength) != 0)
    {
      remote_fileio_ioerror ();
      return;
    }

  remote_fio_no_longjmp = 1;
  ret = stat (pathname, &st);

  if (ret == -1)
    {
      remote_fileio_return_errno (-1);
      return;
    }
  /* Only operate on regular files and directories.  */
  if (!ret && !S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode))
    {
      remote_fileio_reply (-1, FILEIO_EACCES);
      return;
    }
  if (statptr)
    {
      host_to_fileio_stat (&st, &fst);
      host_to_fileio_uint (0, fst.fst_dev);

      errno = target_write_memory (statptr, (gdb_byte *) &fst, sizeof fst);
      if (errno != 0)
	{
	  remote_fileio_return_errno (-1);
	  return;
	}
    }
  remote_fileio_return_success (ret);
}
Exemplo n.º 17
0
int
agent_run_command (int pid, const char *cmd, int len)
{
  int fd;
  int tid = agent_get_helper_thread_id ();
  ptid_t ptid = ptid_build (pid, tid, 0);

#ifdef GDBSERVER
  int ret = write_inferior_memory (ipa_sym_addrs.addr_cmd_buf,
				   (const unsigned char *) cmd, len);
#else
  int ret = target_write_memory (ipa_sym_addrs.addr_cmd_buf, cmd, len);
#endif

  if (ret != 0)
    {
      warning (_("unable to write"));
      return -1;
    }

  DEBUG_AGENT ("agent: resumed helper thread\n");

  /* Resume helper thread.  */
#ifdef GDBSERVER
{
  struct thread_resume resume_info;

  resume_info.thread = ptid;
  resume_info.kind = resume_continue;
  resume_info.sig = GDB_SIGNAL_0;
  (*the_target->resume) (&resume_info, 1);
}
#else
 target_resume (ptid, 0, GDB_SIGNAL_0);
#endif

  fd = gdb_connect_sync_socket (pid);
  if (fd >= 0)
    {
      char buf[1] = "";
      int ret;

      DEBUG_AGENT ("agent: signalling helper thread\n");

      do
	{
	  ret = write (fd, buf, 1);
	} while (ret == -1 && errno == EINTR);

	DEBUG_AGENT ("agent: waiting for helper thread's response\n");

      do
	{
	  ret = read (fd, buf, 1);
	} while (ret == -1 && errno == EINTR);

      close (fd);

      DEBUG_AGENT ("agent: helper thread's response received\n");
    }
  else
    return -1;

  /* Need to read response with the inferior stopped.  */
  if (!ptid_equal (ptid, null_ptid))
    {
      struct target_waitstatus status;
      int was_non_stop = non_stop;
      /* Stop thread PTID.  */
      DEBUG_AGENT ("agent: stop helper thread\n");
#ifdef GDBSERVER
      {
	struct thread_resume resume_info;

	resume_info.thread = ptid;
	resume_info.kind = resume_stop;
	resume_info.sig = GDB_SIGNAL_0;
	(*the_target->resume) (&resume_info, 1);
      }

      non_stop = 1;
      mywait (ptid, &status, 0, 0);
#else
      non_stop = 1;
      target_stop (ptid);

      memset (&status, 0, sizeof (status));
      target_wait (ptid, &status, 0);
#endif
      non_stop = was_non_stop;
    }

  if (fd >= 0)
    {
#ifdef GDBSERVER
      if (read_inferior_memory (ipa_sym_addrs.addr_cmd_buf,
				(unsigned char *) cmd, IPA_CMD_BUF_SIZE))
#else
      if (target_read_memory (ipa_sym_addrs.addr_cmd_buf, (gdb_byte *) cmd,
			      IPA_CMD_BUF_SIZE))
#endif
	{
	  warning (_("Error reading command response"));
	  return -1;
	}
    }

  return 0;
}
Exemplo n.º 18
0
void
store_inferior_registers (int regno)
{
  int whatregs = 0;

  if (regno == -1)
    whatregs = WHATREGS_FLOAT | WHATREGS_GEN | WHATREGS_STACK;
  else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
    whatregs = WHATREGS_STACK;
  else if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32)
    whatregs = WHATREGS_FLOAT;
  else if (regno == SP_REGNUM)
    whatregs = WHATREGS_STACK | WHATREGS_GEN;
  else
    whatregs = WHATREGS_GEN;

  if (whatregs & WHATREGS_GEN)
    {
      struct econtext ec;	/* general regs */
      int retval;

      ec.tbr = read_register (TBR_REGNUM);
      memcpy (&ec.g1, &registers[REGISTER_BYTE (G1_REGNUM)],
	      4 * REGISTER_RAW_SIZE (G1_REGNUM));

      ec.psr = read_register (PS_REGNUM);
      ec.y = read_register (Y_REGNUM);
      ec.pc = read_register (PC_REGNUM);
      ec.npc = read_register (NPC_REGNUM);
      ec.wim = read_register (WIM_REGNUM);

      memcpy (ec.o, &registers[REGISTER_BYTE (O0_REGNUM)],
	      8 * REGISTER_RAW_SIZE (O0_REGNUM));

      errno = 0;
      retval = ptrace (PTRACE_SETREGS, PIDGET (inferior_ptid),
                       (PTRACE_ARG3_TYPE) & ec, 0);
      if (errno)
	perror_with_name ("ptrace(PTRACE_SETREGS)");
    }

  if (whatregs & WHATREGS_STACK)
    {
      int regoffset;
      CORE_ADDR sp;

      sp = read_register (SP_REGNUM);

      if (regno == -1 || regno == SP_REGNUM)
	{
	  if (!register_valid[L0_REGNUM + 5])
	    internal_error (__FILE__, __LINE__, "failed internal consistency check");
	  target_write_memory (sp + FRAME_SAVED_I0,
			      &registers[REGISTER_BYTE (I0_REGNUM)],
			      8 * REGISTER_RAW_SIZE (I0_REGNUM));

	  target_write_memory (sp + FRAME_SAVED_L0,
			      &registers[REGISTER_BYTE (L0_REGNUM)],
			      8 * REGISTER_RAW_SIZE (L0_REGNUM));
	}
      else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
	{
	  if (!register_valid[regno])
	    internal_error (__FILE__, __LINE__, "failed internal consistency check");
	  if (regno >= L0_REGNUM && regno <= L0_REGNUM + 7)
	    regoffset = REGISTER_BYTE (regno) - REGISTER_BYTE (L0_REGNUM)
	      + FRAME_SAVED_L0;
	  else
	    regoffset = REGISTER_BYTE (regno) - REGISTER_BYTE (I0_REGNUM)
	      + FRAME_SAVED_I0;
	  target_write_memory (sp + regoffset, 
			      &registers[REGISTER_BYTE (regno)],
			      REGISTER_RAW_SIZE (regno));
	}
    }

  if (whatregs & WHATREGS_FLOAT)
    {
      struct fcontext fc;	/* fp regs */
      int retval;

/* We read fcontext first so that we can get good values for fq_t... */
      errno = 0;
      retval = ptrace (PTRACE_GETFPREGS, PIDGET (inferior_ptid),
                       (PTRACE_ARG3_TYPE) & fc, 0);
      if (errno)
	perror_with_name ("ptrace(PTRACE_GETFPREGS)");

      memcpy (fc.f.fregs, &registers[REGISTER_BYTE (FP0_REGNUM)],
	      32 * REGISTER_RAW_SIZE (FP0_REGNUM));

      fc.fsr = read_register (FPS_REGNUM);

      errno = 0;
      retval = ptrace (PTRACE_SETFPREGS, PIDGET (inferior_ptid),
                       (PTRACE_ARG3_TYPE) & fc, 0);
      if (errno)
	perror_with_name ("ptrace(PTRACE_SETFPREGS)");
    }
}
Exemplo n.º 19
0
/* call LPC1700/LPC2000 IAP function
 * uses 180 bytes working area
 * 0x0 to 0x7: jump gate (BX to thumb state, b -2 to wait)
 * 0x8 to 0x1f: command parameter table (1+5 words)
 * 0x20 to 0x33: command result table (1+4 words)
 * 0x34 to 0xb3: stack (only 128b needed)
 */
static int lpc2000_iap_call(struct flash_bank *bank,
	int code,
	uint32_t param_table[5],
	uint32_t result_table[4])
{
	int retval;
	struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv;
	struct target *target = bank->target;
	struct mem_param mem_params[2];
	struct reg_param reg_params[5];
	struct arm_algorithm arm_algo;	/* for LPC2000 */
	struct armv7m_algorithm armv7m_info;	/* for LPC1700 */
	uint32_t status_code;
	uint32_t iap_entry_point = 0;	/* to make compiler happier */

	/* regrab previously allocated working_area, or allocate a new one */
	if (!lpc2000_info->iap_working_area) {
		uint8_t jump_gate[8];

		/* make sure we have a working area */
		if (target_alloc_working_area(target, 180,
				&lpc2000_info->iap_working_area) != ERROR_OK) {
			LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
			return ERROR_FLASH_OPERATION_FAILED;
		}

		/* write IAP code to working area */
		switch (lpc2000_info->variant) {
			case lpc1700:
				target_buffer_set_u32(target, jump_gate, ARMV4_5_T_BX(12));
				target_buffer_set_u32(target, jump_gate + 4, ARMV5_T_BKPT(0));
				break;
			case lpc2000_v1:
			case lpc2000_v2:
				target_buffer_set_u32(target, jump_gate, ARMV4_5_BX(12));
				target_buffer_set_u32(target, jump_gate + 4, ARMV4_5_B(0xfffffe, 0));
				break;
			default:
				LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
				exit(-1);
		}

		retval = target_write_memory(target,
				lpc2000_info->iap_working_area->address, 4, 2, jump_gate);
		if (retval != ERROR_OK) {
			LOG_ERROR(
				"Write memory at address 0x%8.8" PRIx32 " failed (check work_area definition)",
				lpc2000_info->iap_working_area->address);
			return retval;
		}
	}

	switch (lpc2000_info->variant) {
		case lpc1700:
			armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
			armv7m_info.core_mode = ARMV7M_MODE_ANY;
			iap_entry_point = 0x1fff1ff1;
			break;
		case lpc2000_v1:
		case lpc2000_v2:
			arm_algo.common_magic = ARM_COMMON_MAGIC;
			arm_algo.core_mode = ARM_MODE_SVC;
			arm_algo.core_state = ARM_STATE_ARM;
			iap_entry_point = 0x7ffffff1;
			break;
		default:
			LOG_ERROR("BUG: unknown lpc2000->variant encountered");
			exit(-1);
	}

	/* command parameter table */
	init_mem_param(&mem_params[0], lpc2000_info->iap_working_area->address + 8, 6 * 4,
		PARAM_OUT);
	target_buffer_set_u32(target, mem_params[0].value, code);
	target_buffer_set_u32(target, mem_params[0].value + 0x04, param_table[0]);
	target_buffer_set_u32(target, mem_params[0].value + 0x08, param_table[1]);
	target_buffer_set_u32(target, mem_params[0].value + 0x0c, param_table[2]);
	target_buffer_set_u32(target, mem_params[0].value + 0x10, param_table[3]);
	target_buffer_set_u32(target, mem_params[0].value + 0x14, param_table[4]);

	init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
	buf_set_u32(reg_params[0].value, 0, 32, lpc2000_info->iap_working_area->address + 0x08);

	/* command result table */
	init_mem_param(&mem_params[1],
		lpc2000_info->iap_working_area->address + 0x20,
		5 * 4,
		PARAM_IN);

	init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
	buf_set_u32(reg_params[1].value, 0, 32, lpc2000_info->iap_working_area->address + 0x20);

	/* IAP entry point */
	init_reg_param(&reg_params[2], "r12", 32, PARAM_OUT);
	buf_set_u32(reg_params[2].value, 0, 32, iap_entry_point);

	switch (lpc2000_info->variant) {
		case lpc1700:
			/* IAP stack */
			init_reg_param(&reg_params[3], "sp", 32, PARAM_OUT);
			buf_set_u32(reg_params[3].value, 0, 32,
					lpc2000_info->iap_working_area->address + 0xb4);

			/* return address */
			init_reg_param(&reg_params[4], "lr", 32, PARAM_OUT);
			buf_set_u32(reg_params[4].value, 0, 32,
					(lpc2000_info->iap_working_area->address + 0x04) | 1);
			/* bit0 of LR = 1 to return in Thumb mode */

			target_run_algorithm(target, 2, mem_params, 5, reg_params,
					lpc2000_info->iap_working_area->address, 0, 10000, &armv7m_info);
			break;
		case lpc2000_v1:
		case lpc2000_v2:
			/* IAP stack */
			init_reg_param(&reg_params[3], "sp_svc", 32, PARAM_OUT);
			buf_set_u32(reg_params[3].value, 0, 32,
					lpc2000_info->iap_working_area->address + 0xb4);

			/* return address */
			init_reg_param(&reg_params[4], "lr_svc", 32, PARAM_OUT);
			buf_set_u32(reg_params[4].value, 0, 32,
					lpc2000_info->iap_working_area->address + 0x04);

			target_run_algorithm(target, 2, mem_params, 5, reg_params,
					lpc2000_info->iap_working_area->address,
					lpc2000_info->iap_working_area->address + 0x4,
					10000, &arm_algo);
			break;
		default:
			LOG_ERROR("BUG: unknown lpc2000->variant encountered");
			exit(-1);
	}

	status_code = target_buffer_get_u32(target, mem_params[1].value);
	result_table[0] = target_buffer_get_u32(target, mem_params[1].value + 0x04);
	result_table[1] = target_buffer_get_u32(target, mem_params[1].value + 0x08);
	result_table[2] = target_buffer_get_u32(target, mem_params[1].value + 0x0c);
	result_table[3] = target_buffer_get_u32(target, mem_params[1].value + 0x10);

	LOG_DEBUG("IAP command = %i (0x%8.8" PRIx32 ", 0x%8.8" PRIx32
			", 0x%8.8" PRIx32 ", 0x%8.8" PRIx32 ", 0x%8.8"
			PRIx32 ") completed with result = %8.8" PRIx32,
			code, param_table[0], param_table[1], param_table[2],
			param_table[3], param_table[4], status_code);

	destroy_mem_param(&mem_params[0]);
	destroy_mem_param(&mem_params[1]);

	destroy_reg_param(&reg_params[0]);
	destroy_reg_param(&reg_params[1]);
	destroy_reg_param(&reg_params[2]);
	destroy_reg_param(&reg_params[3]);
	destroy_reg_param(&reg_params[4]);

	return status_code;
}
Exemplo n.º 20
0
void
sparc_collect_rwindow (const struct regcache *regcache,
		       CORE_ADDR sp, int regnum)
{
  int offset = 0;
  gdb_byte buf[8];
  int i;

  if (sp & 1)
    {
      /* Registers are 64-bit.  */
      sp += BIAS;

      for (i = SPARC_L0_REGNUM; i <= SPARC_I7_REGNUM; i++)
	{
	  if (regnum == -1 || regnum == SPARC_SP_REGNUM || regnum == i)
	    {
	      regcache_raw_collect (regcache, i, buf);

	      /* Handle StackGhost.  */
	      if (i == SPARC_I7_REGNUM)
		{
		  ULONGEST wcookie = sparc_fetch_wcookie ();
		  ULONGEST i7 = extract_unsigned_integer (buf + offset, 8);

		  store_unsigned_integer (buf, 8, i7 ^ wcookie);
		}

	      target_write_memory (sp + ((i - SPARC_L0_REGNUM) * 8), buf, 8);
	    }
	}
    }
  else
    {
      /* Registers are 32-bit.  Toss any sign-extension of the stack
	 pointer.  */
      sp &= 0xffffffffUL;

      /* Only use the bottom half if we're in 64-bit mode.  */
      if (gdbarch_ptr_bit (current_gdbarch) == 64)
	offset = 4;

      for (i = SPARC_L0_REGNUM; i <= SPARC_I7_REGNUM; i++)
	{
	  if (regnum == -1 || regnum == SPARC_SP_REGNUM || regnum == i)
	    {
	      regcache_raw_collect (regcache, i, buf);

	      /* Handle StackGhost.  */
	      if (i == SPARC_I7_REGNUM)
		{
		  ULONGEST wcookie = sparc_fetch_wcookie ();
		  ULONGEST i7 = extract_unsigned_integer (buf + offset, 4);

		  store_unsigned_integer (buf + offset, 4, i7 ^ wcookie);
		}

	      target_write_memory (sp + ((i - SPARC_L0_REGNUM) * 4),
				   buf + offset, 4);
	    }
	}
    }
}
Exemplo n.º 21
0
/* The write routine stub. */
static int nuc1x_write(struct flash_bank *bank, const uint8_t *buffer,
		uint32_t offset, uint32_t count)
{
	struct target *target = bank->target;
	uint32_t i, timeout, status;

	if (bank->target->state != TARGET_HALTED) {
		LOG_ERROR("Target not halted");
		return ERROR_TARGET_NOT_HALTED;
	}

	LOG_INFO("Novoton NUC: FLASH Write ...");

	int retval = nuc1x_reset2lprom(bank);
	if (retval != ERROR_OK)
		return retval;

	retval = nuc1x_init_iap(bank);
	if (retval != ERROR_OK)
		return retval;

	retval = nuc1x_unlock(bank);
	if (retval != ERROR_OK)
		return retval;

	retval = target_write_u32(target, NUC1X_FLASH_ISPCMD, ISPCMD_WRITE);
	if (retval != ERROR_OK)
		return retval;

	/* program command */
	for (i = 0; i < count; i += 4) {

		LOG_DEBUG("write longword @ %08" PRIX32, (uint32_t)(offset + i));

		uint8_t padding[4] = {0xff, 0xff, 0xff, 0xff};
		memcpy(padding, buffer + i, MIN(4, count-i));

		retval = target_write_u32(target, NUC1X_FLASH_ISPADR, bank->base + offset + i);
		if (retval != ERROR_OK)
			return retval;
		retval = target_write_memory(target, NUC1X_FLASH_ISPDAT, 4, 1, padding);
		if (retval != ERROR_OK)
			return retval;
		retval = target_write_u32(target, NUC1X_FLASH_ISPTRG, ISPTRG_ISPGO);
		if (retval != ERROR_OK)
			return retval;

		/* wait for busy to clear - check the GO flag */
		timeout = 100;
		for (;;) {
			retval = target_read_u32(target, NUC1X_FLASH_ISPTRG, &status);
			if (retval != ERROR_OK)
				return retval;
				LOG_DEBUG("status: 0x%" PRIx32 "", status);
			if (status == 0)
				break;
			if (timeout-- <= 0) {
				LOG_DEBUG("timed out waiting for flash");
				return ERROR_FAIL;
			}
			busy_sleep(1);	/* can use busy sleep for short times. */
		}

		/* check for failure */
		retval = target_read_u32(target, NUC1X_FLASH_ISPCON, &status);
		if (retval != ERROR_OK)
			return retval;
		if ((status & ISPCON_ISPFF) != 0) {
			LOG_DEBUG("failure: 0x%" PRIx32 "", status);
			/* if bit is set, then must write to it to clear it. */
			retval = target_write_u32(target, NUC1X_FLASH_ISPCON, ISPCON_ISPFF);
			if (retval != ERROR_OK)
				return retval;
		} else {
			LOG_DEBUG("writed OK");
		}
	}

	retval = nuc1x_reset(bank);
	if (retval != ERROR_OK)
		return retval;

	/* done, */
	LOG_DEBUG("Write done.");

	return ERROR_OK;
}