access.c 4.5 KB

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