Blob


1 /*
2 * File map routines
3 */
4 #include <u.h>
5 #include <libc.h>
6 #include <bio.h>
7 #include <mach.h>
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);
14 Map*
15 allocmap(void)
16 {
17 return mallocz(sizeof(Map), 1);
18 }
20 void
21 freemap(Map *map)
22 {
23 if(map == nil)
24 return;
25 free(map->seg);
26 free(map);
27 }
29 int
30 addseg(Map *map, Seg seg)
31 {
32 Seg *ss;
34 if(map == nil){
35 werrstr("invalid map");
36 return -1;
37 }
39 ss = realloc(map->seg, (map->nseg+1)*sizeof(ss[0]));
40 if(ss == nil)
41 return -1;
42 map->seg = ss;
43 if(seg.rw == 0){
44 if(seg.name && strcmp(seg.name, "zero") == 0)
45 seg.rw = zerorw;
46 else if(seg.p)
47 seg.rw = datarw;
48 else
49 seg.rw = fdrw;
50 }
51 map->seg[map->nseg] = seg;
52 return map->nseg++;
53 }
55 int
56 findseg(Map *map, char *name, char *file)
57 {
58 int i;
60 if(map == nil)
61 return -1;
62 for(i=0; i<map->nseg; i++){
63 if(name && (!map->seg[i].name || strcmp(map->seg[i].name, name) != 0))
64 continue;
65 if(file && (!map->seg[i].file || strcmp(map->seg[i].file, file) != 0))
66 continue;
67 return i;
68 }
69 werrstr("segment %s in %s not found", name, file);
70 return -1;
71 }
73 int
74 addrtoseg(Map *map, u64int addr, Seg *sp)
75 {
76 int i;
77 Seg *s;
79 if(map == nil){
80 werrstr("no map");
81 return -1;
82 }
83 for(i=map->nseg-1; i>=0; i--){
84 s = &map->seg[i];
85 if(s->base <= addr && addr-s->base < s->size){
86 if(sp)
87 *sp = *s;
88 return i;
89 }
90 }
91 werrstr("address 0x%lux is not mapped", addr);
92 return -1;
93 }
95 int
96 addrtosegafter(Map *map, u64int addr, Seg *sp)
97 {
98 int i;
99 Seg *s, *best;
100 ulong bdist;
102 if(map == nil){
103 werrstr("no map");
104 return -1;
107 /*
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
111 * too complicated.
112 */
113 best = nil;
114 bdist = 0;
115 for(i=map->nseg-1; i>=0; i--){
116 s = &map->seg[i];
117 if(s->base > addr){
118 if(best==nil || s->base-addr < bdist){
119 bdist = s->base - addr;
120 best = s;
124 if(best){
125 if(sp)
126 *sp = *best;
127 return best-map->seg;
129 werrstr("nothing mapped after address 0x%lux", addr);
130 return -1;
133 void
134 removeseg(Map *map, int i)
136 if(map == nil)
137 return;
138 if(i < 0 || i >= map->nseg)
139 return;
140 memmove(&map->seg[i], &map->seg[i+1], (map->nseg-(i+1))*sizeof(Seg));
141 map->nseg--;
144 int
145 get1(Map *map, u64int addr, uchar *a, uint n)
147 return mrw(map, addr, a, n, 1);
150 int
151 get2(Map *map, u64int addr, u16int *u)
153 u16int v;
155 if(mrw(map, addr, &v, 2, 1) < 0)
156 return -1;
157 *u = mach->swap2(v);
158 return 2;
161 int
162 get4(Map *map, u64int addr, u32int *u)
164 u32int v;
166 if(mrw(map, addr, &v, 4, 1) < 0)
167 return -1;
168 *u = mach->swap4(v);
169 return 4;
172 int
173 get8(Map *map, u64int addr, u64int *u)
175 u64int v;
177 if(mrw(map, addr, &v, 8, 1) < 0)
178 return -1;
179 *u = mach->swap8(v);
180 return 8;
183 int
184 geta(Map *map, u64int addr, u64int *u)
186 u32int v;
188 if(machcpu == &machamd64)
189 return get8(map, addr, u);
190 if(get4(map, addr, &v) < 0)
191 return -1;
192 *u = v;
193 return 4;
196 int
197 put1(Map *map, u64int addr, uchar *a, uint n)
199 return mrw(map, addr, a, n, 0);
202 int
203 put2(Map *map, u64int addr, u16int u)
205 u = mach->swap2(u);
206 return mrw(map, addr, &u, 2, 0);
209 int
210 put4(Map *map, u64int addr, u32int u)
212 u = mach->swap4(u);
213 return mrw(map, addr, &u, 4, 0);
216 int
217 put8(Map *map, u64int addr, u64int u)
219 u = mach->swap8(u);
220 return mrw(map, addr, &u, 8, 0);
223 static Seg*
224 reloc(Map *map, u64int addr, uint n, u64int *off, uint *nn)
226 int i;
227 ulong o;
229 if(map == nil){
230 werrstr("invalid map");
231 return nil;
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)
238 continue;
239 if(o+n > map->seg[i].size)
240 *nn = map->seg[i].size - o;
241 else
242 *nn = n;
243 *off = o;
244 return &map->seg[i];
247 werrstr("address 0x%lux not mapped", addr);
248 return nil;
251 static int
252 mrw(Map *map, u64int addr, void *a, uint n, int r)
254 uint nn;
255 uint tot;
256 Seg *s;
257 u64int off;
259 for(tot=0; tot<n; tot+=nn){
260 s = reloc(map, addr+tot, n-tot, &off, &nn);
261 if(s == nil)
262 return -1;
263 if(s->rw(map, s, off, a, nn, r) < 0)
264 return -1;
266 return 0;
269 static int
270 fdrw(Map *map, Seg *seg, u64int addr, void *a, uint n, int r)
272 int nn;
273 uint tot;
274 ulong off;
276 USED(map);
277 off = seg->offset + addr;
278 for(tot=0; tot<n; tot+=nn){
279 if(r)
280 nn = pread(seg->fd, a, n-tot, off+tot);
281 else
282 nn = pwrite(seg->fd, a, n-tot, off+tot);
283 if(nn < 0)
284 return -1;
285 if(nn == 0){
286 werrstr("partial %s at address 0x%lux in %s",
287 r ? "read" : "write", off+tot, seg->file);
288 return -1;
291 return 0;
294 static int
295 zerorw(Map *map, Seg *seg, u64int addr, void *a, uint n, int r)
297 USED(map);
298 USED(seg);
299 USED(addr);
301 if(r==0){
302 werrstr("cannot write zero segment");
303 return -1;
305 memset(a, 0, n);
306 return 0;
309 static int
310 datarw(Map *map, Seg *seg, u64int addr, void *a, uint n, int r)
312 USED(map);
314 if(r)
315 memmove(a, seg->p+addr, n);
316 else
317 memmove(seg->p+addr, a, n);
318 return 0;