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