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