2
0

uaccess.c 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. /*
  2. * Helper routines to provide target memory access for semihosting
  3. * syscalls in system emulation mode.
  4. *
  5. * Copyright (c) 2007 CodeSourcery.
  6. *
  7. * This code is licensed under the GPL
  8. */
  9. #include "qemu/osdep.h"
  10. #include "exec/cpu-all.h"
  11. #include "exec/exec-all.h"
  12. #include "semihosting/uaccess.h"
  13. void *uaccess_lock_user(CPUArchState *env, target_ulong addr,
  14. target_ulong len, bool copy)
  15. {
  16. void *p = malloc(len);
  17. if (p && copy) {
  18. if (cpu_memory_rw_debug(env_cpu(env), addr, p, len, 0)) {
  19. free(p);
  20. p = NULL;
  21. }
  22. }
  23. return p;
  24. }
  25. ssize_t uaccess_strlen_user(CPUArchState *env, target_ulong addr)
  26. {
  27. int mmu_idx = cpu_mmu_index(env_cpu(env), false);
  28. size_t len = 0;
  29. while (1) {
  30. size_t left_in_page;
  31. int flags;
  32. void *h;
  33. /* Find the number of bytes remaining in the page. */
  34. left_in_page = TARGET_PAGE_SIZE - (addr & ~TARGET_PAGE_MASK);
  35. flags = probe_access_flags(env, addr, 0, MMU_DATA_LOAD,
  36. mmu_idx, true, &h, 0);
  37. if (flags & TLB_INVALID_MASK) {
  38. return -1;
  39. }
  40. if (flags & TLB_MMIO) {
  41. do {
  42. uint8_t c;
  43. if (cpu_memory_rw_debug(env_cpu(env), addr, &c, 1, 0)) {
  44. return -1;
  45. }
  46. if (c == 0) {
  47. return len;
  48. }
  49. addr++;
  50. len++;
  51. if (len > INT32_MAX) {
  52. return -1;
  53. }
  54. } while (--left_in_page != 0);
  55. } else {
  56. char *p = memchr(h, 0, left_in_page);
  57. if (p) {
  58. len += p - (char *)h;
  59. return len <= INT32_MAX ? (ssize_t)len : -1;
  60. }
  61. addr += left_in_page;
  62. len += left_in_page;
  63. if (len > INT32_MAX) {
  64. return -1;
  65. }
  66. }
  67. }
  68. }
  69. char *uaccess_lock_user_string(CPUArchState *env, target_ulong addr)
  70. {
  71. ssize_t len = uaccess_strlen_user(env, addr);
  72. if (len < 0) {
  73. return NULL;
  74. }
  75. return uaccess_lock_user(env, addr, len + 1, true);
  76. }
  77. void uaccess_unlock_user(CPUArchState *env, void *p,
  78. target_ulong addr, target_ulong len)
  79. {
  80. if (len) {
  81. cpu_memory_rw_debug(env_cpu(env), addr, p, len, 1);
  82. }
  83. free(p);
  84. }