2 a84cbb2a 2004-04-19 devnull * File map routines
4 a84cbb2a 2004-04-19 devnull #include <u.h>
5 a84cbb2a 2004-04-19 devnull #include <libc.h>
6 a84cbb2a 2004-04-19 devnull #include <bio.h>
7 a84cbb2a 2004-04-19 devnull #include <mach.h>
9 443d6288 2012-02-19 rsc static int fdrw(Map*, Seg*, u64int, void*, uint, int);
10 443d6288 2012-02-19 rsc static int zerorw(Map*, Seg*, u64int, void*, uint, int);
11 443d6288 2012-02-19 rsc static int mrw(Map*, u64int, void*, uint, int);
12 443d6288 2012-02-19 rsc static int datarw(Map*, Seg*, u64int, void*, uint, int);
15 a84cbb2a 2004-04-19 devnull allocmap(void)
17 a84cbb2a 2004-04-19 devnull return mallocz(sizeof(Map), 1);
21 a84cbb2a 2004-04-19 devnull freemap(Map *map)
23 a84cbb2a 2004-04-19 devnull if(map == nil)
25 a84cbb2a 2004-04-19 devnull free(map->seg);
26 a84cbb2a 2004-04-19 devnull free(map);
30 a84cbb2a 2004-04-19 devnull addseg(Map *map, Seg seg)
34 dd944ec7 2005-01-23 devnull if(map == nil){
35 a84cbb2a 2004-04-19 devnull werrstr("invalid map");
36 a84cbb2a 2004-04-19 devnull return -1;
39 a84cbb2a 2004-04-19 devnull ss = realloc(map->seg, (map->nseg+1)*sizeof(ss[0]));
40 a84cbb2a 2004-04-19 devnull if(ss == nil)
41 a84cbb2a 2004-04-19 devnull return -1;
42 a84cbb2a 2004-04-19 devnull map->seg = ss;
43 a8763864 2004-07-09 devnull if(seg.rw == 0){
44 a84cbb2a 2004-04-19 devnull if(seg.name && strcmp(seg.name, "zero") == 0)
45 a84cbb2a 2004-04-19 devnull seg.rw = zerorw;
46 a84cbb2a 2004-04-19 devnull else if(seg.p)
47 a84cbb2a 2004-04-19 devnull seg.rw = datarw;
49 a84cbb2a 2004-04-19 devnull seg.rw = fdrw;
51 a84cbb2a 2004-04-19 devnull map->seg[map->nseg] = seg;
52 a84cbb2a 2004-04-19 devnull return map->nseg++;
56 a84cbb2a 2004-04-19 devnull findseg(Map *map, char *name, char *file)
60 dd944ec7 2005-01-23 devnull if(map == nil)
61 a84cbb2a 2004-04-19 devnull return -1;
62 a84cbb2a 2004-04-19 devnull for(i=0; i<map->nseg; i++){
63 a84cbb2a 2004-04-19 devnull if(name && (!map->seg[i].name || strcmp(map->seg[i].name, name) != 0))
64 a84cbb2a 2004-04-19 devnull continue;
65 a84cbb2a 2004-04-19 devnull if(file && (!map->seg[i].file || strcmp(map->seg[i].file, file) != 0))
66 a84cbb2a 2004-04-19 devnull continue;
67 a84cbb2a 2004-04-19 devnull return i;
69 a84cbb2a 2004-04-19 devnull werrstr("segment %s in %s not found", name, file);
70 a84cbb2a 2004-04-19 devnull return -1;
74 443d6288 2012-02-19 rsc addrtoseg(Map *map, u64int addr, Seg *sp)
79 a84cbb2a 2004-04-19 devnull if(map == nil){
80 a84cbb2a 2004-04-19 devnull werrstr("no map");
81 a84cbb2a 2004-04-19 devnull return -1;
83 a84cbb2a 2004-04-19 devnull for(i=map->nseg-1; i>=0; i--){
84 a84cbb2a 2004-04-19 devnull s = &map->seg[i];
85 a84cbb2a 2004-04-19 devnull if(s->base <= addr && addr-s->base < s->size){
87 a84cbb2a 2004-04-19 devnull *sp = *s;
88 a84cbb2a 2004-04-19 devnull return i;
91 a84cbb2a 2004-04-19 devnull werrstr("address 0x%lux is not mapped", addr);
92 a84cbb2a 2004-04-19 devnull return -1;
96 443d6288 2012-02-19 rsc addrtosegafter(Map *map, u64int addr, Seg *sp)
99 a84cbb2a 2004-04-19 devnull Seg *s, *best;
100 a84cbb2a 2004-04-19 devnull ulong bdist;
102 a84cbb2a 2004-04-19 devnull if(map == nil){
103 a84cbb2a 2004-04-19 devnull werrstr("no map");
104 a84cbb2a 2004-04-19 devnull return -1;
108 a84cbb2a 2004-04-19 devnull * If segments were sorted this would be easier,
109 a84cbb2a 2004-04-19 devnull * but since segments may overlap, sorting also
110 a84cbb2a 2004-04-19 devnull * requires splitting and rejoining, and that's just
111 a84cbb2a 2004-04-19 devnull * too complicated.
113 a84cbb2a 2004-04-19 devnull best = nil;
114 a84cbb2a 2004-04-19 devnull bdist = 0;
115 a84cbb2a 2004-04-19 devnull for(i=map->nseg-1; i>=0; i--){
116 a84cbb2a 2004-04-19 devnull s = &map->seg[i];
117 a84cbb2a 2004-04-19 devnull if(s->base > addr){
118 a84cbb2a 2004-04-19 devnull if(best==nil || s->base-addr < bdist){
119 a84cbb2a 2004-04-19 devnull bdist = s->base - addr;
120 a84cbb2a 2004-04-19 devnull best = s;
124 a84cbb2a 2004-04-19 devnull if(best){
126 a84cbb2a 2004-04-19 devnull *sp = *best;
127 a84cbb2a 2004-04-19 devnull return best-map->seg;
129 a84cbb2a 2004-04-19 devnull werrstr("nothing mapped after address 0x%lux", addr);
130 a84cbb2a 2004-04-19 devnull return -1;
134 a84cbb2a 2004-04-19 devnull removeseg(Map *map, int i)
136 a84cbb2a 2004-04-19 devnull if(map == nil)
138 a84cbb2a 2004-04-19 devnull if(i < 0 || i >= map->nseg)
140 a84cbb2a 2004-04-19 devnull memmove(&map->seg[i], &map->seg[i+1], (map->nseg-(i+1))*sizeof(Seg));
141 a84cbb2a 2004-04-19 devnull map->nseg--;
145 443d6288 2012-02-19 rsc get1(Map *map, u64int addr, uchar *a, uint n)
147 a84cbb2a 2004-04-19 devnull return mrw(map, addr, a, n, 1);
151 443d6288 2012-02-19 rsc get2(Map *map, u64int addr, u16int *u)
153 a84cbb2a 2004-04-19 devnull u16int v;
155 a84cbb2a 2004-04-19 devnull if(mrw(map, addr, &v, 2, 1) < 0)
156 a84cbb2a 2004-04-19 devnull return -1;
157 a84cbb2a 2004-04-19 devnull *u = mach->swap2(v);
158 a84cbb2a 2004-04-19 devnull return 2;
162 443d6288 2012-02-19 rsc get4(Map *map, u64int addr, u32int *u)
164 a84cbb2a 2004-04-19 devnull u32int v;
166 a84cbb2a 2004-04-19 devnull if(mrw(map, addr, &v, 4, 1) < 0)
167 a84cbb2a 2004-04-19 devnull return -1;
168 a84cbb2a 2004-04-19 devnull *u = mach->swap4(v);
169 a84cbb2a 2004-04-19 devnull return 4;
173 443d6288 2012-02-19 rsc get8(Map *map, u64int addr, u64int *u)
175 a84cbb2a 2004-04-19 devnull u64int v;
177 2e965b33 2004-05-05 devnull if(mrw(map, addr, &v, 8, 1) < 0)
178 a84cbb2a 2004-04-19 devnull return -1;
179 a84cbb2a 2004-04-19 devnull *u = mach->swap8(v);
180 a84cbb2a 2004-04-19 devnull return 8;
184 443d6288 2012-02-19 rsc geta(Map *map, u64int addr, u64int *u)
188 443d6288 2012-02-19 rsc if(machcpu == &machamd64)
189 443d6288 2012-02-19 rsc return get8(map, addr, u);
190 443d6288 2012-02-19 rsc if(get4(map, addr, &v) < 0)
197 443d6288 2012-02-19 rsc put1(Map *map, u64int addr, uchar *a, uint n)
199 a84cbb2a 2004-04-19 devnull return mrw(map, addr, a, n, 0);
203 443d6288 2012-02-19 rsc put2(Map *map, u64int addr, u16int u)
205 a84cbb2a 2004-04-19 devnull u = mach->swap2(u);
206 a84cbb2a 2004-04-19 devnull return mrw(map, addr, &u, 2, 0);
210 443d6288 2012-02-19 rsc put4(Map *map, u64int addr, u32int u)
212 a84cbb2a 2004-04-19 devnull u = mach->swap4(u);
213 a84cbb2a 2004-04-19 devnull return mrw(map, addr, &u, 4, 0);
217 443d6288 2012-02-19 rsc put8(Map *map, u64int addr, u64int u)
219 a84cbb2a 2004-04-19 devnull u = mach->swap8(u);
220 a84cbb2a 2004-04-19 devnull return mrw(map, addr, &u, 8, 0);
223 a84cbb2a 2004-04-19 devnull static Seg*
224 443d6288 2012-02-19 rsc reloc(Map *map, u64int addr, uint n, u64int *off, uint *nn)
227 4f0073fe 2004-06-11 devnull ulong o;
229 a84cbb2a 2004-04-19 devnull if(map == nil){
230 a84cbb2a 2004-04-19 devnull werrstr("invalid map");
231 a84cbb2a 2004-04-19 devnull return nil;
234 a84cbb2a 2004-04-19 devnull for(i=map->nseg-1; i>=0; i--){
235 a84cbb2a 2004-04-19 devnull if(map->seg[i].base <= addr){
236 a84cbb2a 2004-04-19 devnull o = addr - map->seg[i].base;
237 a84cbb2a 2004-04-19 devnull if(o >= map->seg[i].size)
238 a84cbb2a 2004-04-19 devnull continue;
239 a84cbb2a 2004-04-19 devnull if(o+n > map->seg[i].size)
240 a84cbb2a 2004-04-19 devnull *nn = map->seg[i].size - o;
242 a84cbb2a 2004-04-19 devnull *nn = n;
243 a84cbb2a 2004-04-19 devnull *off = o;
244 a84cbb2a 2004-04-19 devnull return &map->seg[i];
247 a84cbb2a 2004-04-19 devnull werrstr("address 0x%lux not mapped", addr);
248 a84cbb2a 2004-04-19 devnull return nil;
251 a84cbb2a 2004-04-19 devnull static int
252 443d6288 2012-02-19 rsc mrw(Map *map, u64int addr, void *a, uint n, int r)
254 a84cbb2a 2004-04-19 devnull uint nn;
255 a84cbb2a 2004-04-19 devnull uint tot;
259 a84cbb2a 2004-04-19 devnull for(tot=0; tot<n; tot+=nn){
260 a84cbb2a 2004-04-19 devnull s = reloc(map, addr+tot, n-tot, &off, &nn);
261 a84cbb2a 2004-04-19 devnull if(s == nil)
262 a84cbb2a 2004-04-19 devnull return -1;
263 a84cbb2a 2004-04-19 devnull if(s->rw(map, s, off, a, nn, r) < 0)
264 a84cbb2a 2004-04-19 devnull return -1;
266 a84cbb2a 2004-04-19 devnull return 0;
269 a84cbb2a 2004-04-19 devnull static int
270 443d6288 2012-02-19 rsc fdrw(Map *map, Seg *seg, u64int addr, void *a, uint n, int r)
273 a84cbb2a 2004-04-19 devnull uint tot;
274 4f0073fe 2004-06-11 devnull ulong off;
276 a84cbb2a 2004-04-19 devnull USED(map);
277 a84cbb2a 2004-04-19 devnull off = seg->offset + addr;
278 a84cbb2a 2004-04-19 devnull for(tot=0; tot<n; tot+=nn){
280 a84cbb2a 2004-04-19 devnull nn = pread(seg->fd, a, n-tot, off+tot);
282 a84cbb2a 2004-04-19 devnull nn = pwrite(seg->fd, a, n-tot, off+tot);
283 a84cbb2a 2004-04-19 devnull if(nn < 0)
284 a84cbb2a 2004-04-19 devnull return -1;
285 a84cbb2a 2004-04-19 devnull if(nn == 0){
286 a84cbb2a 2004-04-19 devnull werrstr("partial %s at address 0x%lux in %s",
287 a84cbb2a 2004-04-19 devnull r ? "read" : "write", off+tot, seg->file);
288 a84cbb2a 2004-04-19 devnull return -1;
291 a84cbb2a 2004-04-19 devnull return 0;
294 a84cbb2a 2004-04-19 devnull static int
295 443d6288 2012-02-19 rsc zerorw(Map *map, Seg *seg, u64int addr, void *a, uint n, int r)
297 a84cbb2a 2004-04-19 devnull USED(map);
298 a84cbb2a 2004-04-19 devnull USED(seg);
299 a84cbb2a 2004-04-19 devnull USED(addr);
301 a84cbb2a 2004-04-19 devnull if(r==0){
302 a84cbb2a 2004-04-19 devnull werrstr("cannot write zero segment");
303 a84cbb2a 2004-04-19 devnull return -1;
305 a84cbb2a 2004-04-19 devnull memset(a, 0, n);
306 a84cbb2a 2004-04-19 devnull return 0;
309 a84cbb2a 2004-04-19 devnull static int
310 443d6288 2012-02-19 rsc datarw(Map *map, Seg *seg, u64int addr, void *a, uint n, int r)
312 a84cbb2a 2004-04-19 devnull USED(map);
315 a84cbb2a 2004-04-19 devnull memmove(a, seg->p+addr, n);
317 a84cbb2a 2004-04-19 devnull memmove(seg->p+addr, a, n);
318 a84cbb2a 2004-04-19 devnull return 0;