access.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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*, ulong, char*, int);
  9. static int mput(Map*, ulong, char*, int);
  10. static struct segment* reloc(Map*, ulong, long*);
  11. /*
  12. * routines to get/put various types
  13. */
  14. int
  15. get8(Map *map, ulong addr, vlong *x)
  16. {
  17. if (!map) {
  18. werrstr("get8: invalid map");
  19. return -1;
  20. }
  21. if (map->nsegs == 1 && map->seg[0].fd < 0) {
  22. *x = (vlong)addr;
  23. return 1;
  24. }
  25. if (mget(map, addr, (char *)x, 8) < 0)
  26. return -1;
  27. *x = machdata->swav(*x);
  28. return (1);
  29. }
  30. int
  31. get4(Map *map, ulong addr, long *x)
  32. {
  33. if (!map) {
  34. werrstr("get4: 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, (char *)x, 4) < 0)
  42. return -1;
  43. *x = machdata->swal(*x);
  44. return (1);
  45. }
  46. int
  47. get2(Map *map, ulong addr, ushort *x)
  48. {
  49. if (!map) {
  50. werrstr("get2: 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, (char *)x, 2) < 0)
  58. return -1;
  59. *x = machdata->swab(*x);
  60. return (1);
  61. }
  62. int
  63. get1(Map *map, ulong addr, uchar *x, int size)
  64. {
  65. uchar *cp;
  66. if (!map) {
  67. werrstr("get1: invalid map");
  68. return -1;
  69. }
  70. if (map->nsegs == 1 && map->seg[0].fd < 0) {
  71. cp = (uchar*)&addr;
  72. while (cp < (uchar*)(&addr+1) && size-- > 0)
  73. *x++ = *cp++;
  74. while (size-- > 0)
  75. *x++ = 0;
  76. } else
  77. return mget(map, addr, (char*)x, size);
  78. return 1;
  79. }
  80. int
  81. put8(Map *map, ulong addr, vlong v)
  82. {
  83. if (!map) {
  84. werrstr("put8: invalid map");
  85. return -1;
  86. }
  87. v = machdata->swav(v);
  88. return mput(map, addr, (char *)&v, 8);
  89. }
  90. int
  91. put4(Map *map, ulong addr, long v)
  92. {
  93. if (!map) {
  94. werrstr("put4: invalid map");
  95. return -1;
  96. }
  97. v = machdata->swal(v);
  98. return mput(map, addr, (char *)&v, 4);
  99. }
  100. int
  101. put2(Map *map, ulong addr, ushort v)
  102. {
  103. if (!map) {
  104. werrstr("put2: invalid map");
  105. return -1;
  106. }
  107. v = machdata->swab(v);
  108. return mput(map, addr, (char *)&v, 2);
  109. }
  110. int
  111. put1(Map *map, ulong addr, uchar *v, int size)
  112. {
  113. if (!map) {
  114. werrstr("put1: invalid map");
  115. return -1;
  116. }
  117. return mput(map, addr, (char *)v, size);
  118. }
  119. static int
  120. mget(Map *map, ulong addr, char *buf, int size)
  121. {
  122. long off;
  123. uvlong voff;
  124. int i, j, k;
  125. struct segment *s;
  126. s = reloc(map, addr, &off);
  127. if (!s)
  128. return -1;
  129. if (s->fd < 0) {
  130. werrstr("unreadable map");
  131. return -1;
  132. }
  133. voff = (ulong)off;
  134. seek(s->fd, voff, 0);
  135. for (i = j = 0; i < 2; i++) { /* in case read crosses page */
  136. k = read(s->fd, buf, size-j);
  137. if (k < 0) {
  138. werrstr("can't read address %lux: %r", addr);
  139. return -1;
  140. }
  141. j += k;
  142. if (j == size)
  143. return j;
  144. }
  145. werrstr("partial read at address %lux", addr);
  146. return -1;
  147. }
  148. static int
  149. mput(Map *map, ulong addr, char *buf, int size)
  150. {
  151. long off;
  152. vlong voff;
  153. int i, j, k;
  154. struct segment *s;
  155. s = reloc(map, addr, &off);
  156. if (!s)
  157. return -1;
  158. if (s->fd < 0) {
  159. werrstr("unwritable map");
  160. return -1;
  161. }
  162. voff = (ulong)off;
  163. seek(s->fd, voff, 0);
  164. for (i = j = 0; i < 2; i++) { /* in case read crosses page */
  165. k = write(s->fd, buf, size-j);
  166. if (k < 0) {
  167. werrstr("can't write address %lux: %r", addr);
  168. return -1;
  169. }
  170. j += k;
  171. if (j == size)
  172. return j;
  173. }
  174. werrstr("partial write at address %lux", addr);
  175. return -1;
  176. }
  177. /*
  178. * convert address to file offset; returns nonzero if ok
  179. */
  180. static struct segment*
  181. reloc(Map *map, ulong addr, long *offp)
  182. {
  183. int i;
  184. for (i = 0; i < map->nsegs; i++) {
  185. if (map->seg[i].inuse)
  186. if (map->seg[i].b <= addr && addr < map->seg[i].e) {
  187. *offp = addr + map->seg[i].f - map->seg[i].b;
  188. return &map->seg[i];
  189. }
  190. }
  191. werrstr("can't translate address %lux", addr);
  192. return 0;
  193. }