9 static int fdrw(Map*, Seg*, u64int, void*, uint, int);
10 static int zerorw(Map*, Seg*, u64int, void*, uint, int);
11 static int mrw(Map*, u64int, void*, uint, int);
12 static int datarw(Map*, Seg*, u64int, void*, uint, int);
17 return mallocz(sizeof(Map), 1);
30 addseg(Map *map, Seg seg)
35 werrstr("invalid map");
39 ss = realloc(map->seg, (map->nseg+1)*sizeof(ss[0]));
44 if(seg.name && strcmp(seg.name, "zero") == 0)
51 map->seg[map->nseg] = seg;
56 findseg(Map *map, char *name, char *file)
62 for(i=0; i<map->nseg; i++){
63 if(name && (!map->seg[i].name || strcmp(map->seg[i].name, name) != 0))
65 if(file && (!map->seg[i].file || strcmp(map->seg[i].file, file) != 0))
69 werrstr("segment %s in %s not found", name, file);
74 addrtoseg(Map *map, u64int addr, Seg *sp)
83 for(i=map->nseg-1; i>=0; i--){
85 if(s->base <= addr && addr-s->base < s->size){
91 werrstr("address 0x%lux is not mapped", addr);
96 addrtosegafter(Map *map, u64int addr, Seg *sp)
108 * If segments were sorted this would be easier,
109 * but since segments may overlap, sorting also
110 * requires splitting and rejoining, and that's just
115 for(i=map->nseg-1; i>=0; i--){
118 if(best==nil || s->base-addr < bdist){
119 bdist = s->base - addr;
127 return best-map->seg;
129 werrstr("nothing mapped after address 0x%lux", addr);
134 removeseg(Map *map, int i)
138 if(i < 0 || i >= map->nseg)
140 memmove(&map->seg[i], &map->seg[i+1], (map->nseg-(i+1))*sizeof(Seg));
145 get1(Map *map, u64int addr, uchar *a, uint n)
147 return mrw(map, addr, a, n, 1);
151 get2(Map *map, u64int addr, u16int *u)
155 if(mrw(map, addr, &v, 2, 1) < 0)
162 get4(Map *map, u64int addr, u32int *u)
166 if(mrw(map, addr, &v, 4, 1) < 0)
173 get8(Map *map, u64int addr, u64int *u)
177 if(mrw(map, addr, &v, 8, 1) < 0)
184 geta(Map *map, u64int addr, u64int *u)
188 if(machcpu == &machamd64)
189 return get8(map, addr, u);
190 if(get4(map, addr, &v) < 0)
197 put1(Map *map, u64int addr, uchar *a, uint n)
199 return mrw(map, addr, a, n, 0);
203 put2(Map *map, u64int addr, u16int u)
206 return mrw(map, addr, &u, 2, 0);
210 put4(Map *map, u64int addr, u32int u)
213 return mrw(map, addr, &u, 4, 0);
217 put8(Map *map, u64int addr, u64int u)
220 return mrw(map, addr, &u, 8, 0);
224 reloc(Map *map, u64int addr, uint n, u64int *off, uint *nn)
230 werrstr("invalid map");
234 for(i=map->nseg-1; i>=0; i--){
235 if(map->seg[i].base <= addr){
236 o = addr - map->seg[i].base;
237 if(o >= map->seg[i].size)
239 if(o+n > map->seg[i].size)
240 *nn = map->seg[i].size - o;
247 werrstr("address 0x%lux not mapped", addr);
252 mrw(Map *map, u64int addr, void *a, uint n, int r)
259 for(tot=0; tot<n; tot+=nn){
260 s = reloc(map, addr+tot, n-tot, &off, &nn);
263 if(s->rw(map, s, off, a, nn, r) < 0)
270 fdrw(Map *map, Seg *seg, u64int addr, void *a, uint n, int r)
277 off = seg->offset + addr;
278 for(tot=0; tot<n; tot+=nn){
280 nn = pread(seg->fd, a, n-tot, off+tot);
282 nn = pwrite(seg->fd, a, n-tot, off+tot);
286 werrstr("partial %s at address 0x%lux in %s",
287 r ? "read" : "write", off+tot, seg->file);
295 zerorw(Map *map, Seg *seg, u64int addr, void *a, uint n, int r)
302 werrstr("cannot write zero segment");
310 datarw(Map *map, Seg *seg, u64int addr, void *a, uint n, int r)
315 memmove(a, seg->p+addr, n);
317 memmove(seg->p+addr, a, n);