access.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. /*
  10. * functions to read and write an executable or file image
  11. */
  12. #include <u.h>
  13. #include <libc.h>
  14. #include <bio.h>
  15. #include <mach.h>
  16. static int mget(Map*, uint64_t, void*, int);
  17. static int mput(Map*, uint64_t, void*, int);
  18. static struct segment* reloc(Map*, uint64_t, int64_t*);
  19. /*
  20. * routines to get/put various types
  21. */
  22. int
  23. geta(Map *map, uint64_t addr, uint64_t *x)
  24. {
  25. uint32_t l;
  26. uint64_t vl;
  27. if (mach->szaddr == 8){
  28. if (get8(map, addr, &vl) < 0)
  29. return -1;
  30. *x = vl;
  31. return 1;
  32. }
  33. if (get4(map, addr, &l) < 0)
  34. return -1;
  35. *x = l;
  36. return 1;
  37. }
  38. int
  39. get8(Map *map, uint64_t addr, uint64_t *x)
  40. {
  41. if (!map) {
  42. werrstr("get8: invalid map");
  43. return -1;
  44. }
  45. if (map->nsegs == 1 && map->seg[0].fd < 0) {
  46. *x = addr;
  47. return 1;
  48. }
  49. if (mget(map, addr, x, 8) < 0)
  50. return -1;
  51. *x = machdata->swav(*x);
  52. return 1;
  53. }
  54. int
  55. get4(Map *map, uint64_t addr, uint32_t *x)
  56. {
  57. if (!map) {
  58. werrstr("get4: invalid map");
  59. return -1;
  60. }
  61. if (map->nsegs == 1 && map->seg[0].fd < 0) {
  62. *x = addr;
  63. return 1;
  64. }
  65. if (mget(map, addr, x, 4) < 0)
  66. return -1;
  67. *x = machdata->swal(*x);
  68. return 1;
  69. }
  70. int
  71. get2(Map *map, uint64_t addr, uint16_t *x)
  72. {
  73. if (!map) {
  74. werrstr("get2: invalid map");
  75. return -1;
  76. }
  77. if (map->nsegs == 1 && map->seg[0].fd < 0) {
  78. *x = addr;
  79. return 1;
  80. }
  81. if (mget(map, addr, x, 2) < 0)
  82. return -1;
  83. *x = machdata->swab(*x);
  84. return 1;
  85. }
  86. int
  87. get1(Map *map, uint64_t addr, uint8_t *x, int size)
  88. {
  89. uint8_t *cp;
  90. if (!map) {
  91. werrstr("get1: invalid map");
  92. return -1;
  93. }
  94. if (map->nsegs == 1 && map->seg[0].fd < 0) {
  95. cp = (uint8_t*)&addr;
  96. while (cp < (uint8_t*)(&addr+1) && size-- > 0)
  97. *x++ = *cp++;
  98. while (size-- > 0)
  99. *x++ = 0;
  100. } else
  101. return mget(map, addr, x, size);
  102. return 1;
  103. }
  104. int
  105. puta(Map *map, uint64_t addr, uint64_t v)
  106. {
  107. if (mach->szaddr == 8)
  108. return put8(map, addr, v);
  109. return put4(map, addr, v);
  110. }
  111. int
  112. put8(Map *map, uint64_t addr, uint64_t v)
  113. {
  114. if (!map) {
  115. werrstr("put8: invalid map");
  116. return -1;
  117. }
  118. v = machdata->swav(v);
  119. return mput(map, addr, &v, 8);
  120. }
  121. int
  122. put4(Map *map, uint64_t addr, uint32_t v)
  123. {
  124. if (!map) {
  125. werrstr("put4: invalid map");
  126. return -1;
  127. }
  128. v = machdata->swal(v);
  129. return mput(map, addr, &v, 4);
  130. }
  131. int
  132. put2(Map *map, uint64_t addr, uint16_t v)
  133. {
  134. if (!map) {
  135. werrstr("put2: invalid map");
  136. return -1;
  137. }
  138. v = machdata->swab(v);
  139. return mput(map, addr, &v, 2);
  140. }
  141. int
  142. put1(Map *map, uint64_t addr, uint8_t *v, int size)
  143. {
  144. if (!map) {
  145. werrstr("put1: invalid map");
  146. return -1;
  147. }
  148. return mput(map, addr, v, size);
  149. }
  150. static int
  151. spread(struct segment *s, void *buf, int n, uint64_t off)
  152. {
  153. uint64_t base;
  154. static struct {
  155. struct segment *s;
  156. char a[8192];
  157. uint64_t off;
  158. } cache;
  159. if(s->cache){
  160. base = off&~(sizeof cache.a-1);
  161. if(cache.s != s || cache.off != base){
  162. cache.off = ~0;
  163. if(seek(s->fd, base, 0) >= 0
  164. && readn(s->fd, cache.a, sizeof cache.a) == sizeof cache.a){
  165. cache.s = s;
  166. cache.off = base;
  167. }
  168. }
  169. if(cache.s == s && cache.off == base){
  170. off &= sizeof cache.a-1;
  171. if(off+n > sizeof cache.a)
  172. n = sizeof cache.a - off;
  173. memmove(buf, cache.a+off, n);
  174. return n;
  175. }
  176. }
  177. return pread(s->fd, buf, n, off);
  178. }
  179. static int
  180. mget(Map *map, uint64_t addr, void *buf, int size)
  181. {
  182. uint64_t off;
  183. int i, j, k;
  184. struct segment *s;
  185. s = reloc(map, addr, (int64_t*)&off);
  186. if (!s)
  187. return -1;
  188. if (s->fd < 0) {
  189. werrstr("unreadable map");
  190. return -1;
  191. }
  192. for (i = j = 0; i < 2; i++) { /* in case read crosses page */
  193. k = spread(s, (void*)((uint8_t *)buf+j), size-j, off+j);
  194. if (k < 0) {
  195. werrstr("can't read address %p: %r", addr);
  196. return -1;
  197. }
  198. j += k;
  199. if (j == size)
  200. return j;
  201. }
  202. werrstr("partial read at address %p (size %d j %d)", addr, size, j);
  203. return -1;
  204. }
  205. static int
  206. mput(Map *map, uint64_t addr, void *buf, int size)
  207. {
  208. int64_t off;
  209. int i, j, k;
  210. struct segment *s;
  211. s = reloc(map, addr, &off);
  212. if (!s)
  213. return -1;
  214. if (s->fd < 0) {
  215. werrstr("unwritable map");
  216. return -1;
  217. }
  218. seek(s->fd, off, 0);
  219. for (i = j = 0; i < 2; i++) { /* in case read crosses page */
  220. k = write(s->fd, buf, size-j);
  221. if (k < 0) {
  222. werrstr("can't write address %p: %r", addr);
  223. return -1;
  224. }
  225. j += k;
  226. if (j == size)
  227. return j;
  228. }
  229. werrstr("partial write at address %p", addr);
  230. return -1;
  231. }
  232. /*
  233. * convert address to file offset; returns nonzero if ok
  234. */
  235. static struct segment*
  236. reloc(Map *map, uint64_t addr, int64_t *offp)
  237. {
  238. int i;
  239. for (i = 0; i < map->nsegs; i++) {
  240. if (map->seg[i].inuse)
  241. if (map->seg[i].b <= addr && addr < map->seg[i].e) {
  242. *offp = addr + map->seg[i].f - map->seg[i].b;
  243. return &map->seg[i];
  244. }
  245. }
  246. werrstr("can't translate address %p", addr);
  247. return 0;
  248. }