9 static int fdrw(Map*, Seg*, ulong, void*, uint, int);
10 static int zerorw(Map*, Seg*, ulong, void*, uint, int);
11 static int mrw(Map*, ulong, void*, uint, int);
12 static int datarw(Map*, Seg*, ulong, 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, ulong 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, ulong 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, ulong addr, uchar *a, uint n)
147 return mrw(map, addr, a, n, 1);
151 get2(Map *map, ulong addr, u16int *u)
155 if(mrw(map, addr, &v, 2, 1) < 0)
162 get4(Map *map, ulong addr, u32int *u)
166 if(mrw(map, addr, &v, 4, 1) < 0)
173 get8(Map *map, ulong addr, u64int *u)
177 if(mrw(map, addr, &v, 8, 1) < 0)
184 put1(Map *map, ulong addr, uchar *a, uint n)
186 return mrw(map, addr, a, n, 0);
190 put2(Map *map, ulong addr, u16int u)
193 return mrw(map, addr, &u, 2, 0);
197 put4(Map *map, ulong addr, u32int u)
200 return mrw(map, addr, &u, 4, 0);
204 put8(Map *map, ulong addr, u64int u)
207 return mrw(map, addr, &u, 8, 0);
211 reloc(Map *map, ulong addr, uint n, ulong *off, uint *nn)
217 werrstr("invalid map");
221 for(i=map->nseg-1; i>=0; i--){
222 if(map->seg[i].base <= addr){
223 o = addr - map->seg[i].base;
224 if(o >= map->seg[i].size)
226 if(o+n > map->seg[i].size)
227 *nn = map->seg[i].size - o;
234 werrstr("address 0x%lux not mapped", addr);
239 mrw(Map *map, ulong addr, void *a, uint n, int r)
246 for(tot=0; tot<n; tot+=nn){
247 s = reloc(map, addr+tot, n-tot, &off, &nn);
250 if(s->rw(map, s, off, a, nn, r) < 0)
257 fdrw(Map *map, Seg *seg, ulong addr, void *a, uint n, int r)
264 off = seg->offset + addr;
265 for(tot=0; tot<n; tot+=nn){
267 nn = pread(seg->fd, a, n-tot, off+tot);
269 nn = pwrite(seg->fd, a, n-tot, off+tot);
273 werrstr("partial %s at address 0x%lux in %s",
274 r ? "read" : "write", off+tot, seg->file);
282 zerorw(Map *map, Seg *seg, ulong addr, void *a, uint n, int r)
289 werrstr("cannot write zero segment");
297 datarw(Map *map, Seg *seg, ulong addr, void *a, uint n, int r)
302 memmove(a, seg->p+addr, n);
304 memmove(seg->p+addr, a, n);