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*, 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);
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, ulong 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, ulong 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, ulong addr, uchar *a, uint n)
147 return mrw(map, addr, a, n, 1);
150 int
151 get2(Map *map, ulong 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, ulong 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, ulong 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 put1(Map *map, ulong addr, uchar *a, uint n)
186 return mrw(map, addr, a, n, 0);
189 int
190 put2(Map *map, ulong addr, u16int u)
192 u = mach->swap2(u);
193 return mrw(map, addr, &u, 2, 0);
196 int
197 put4(Map *map, ulong addr, u32int u)
199 u = mach->swap4(u);
200 return mrw(map, addr, &u, 4, 0);
203 int
204 put8(Map *map, ulong addr, u64int u)
206 u = mach->swap8(u);
207 return mrw(map, addr, &u, 8, 0);
210 static Seg*
211 reloc(Map *map, ulong addr, uint n, ulong *off, uint *nn)
213 int i;
214 ulong o;
216 if(map == nil){
217 werrstr("invalid map");
218 return nil;
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)
225 continue;
226 if(o+n > map->seg[i].size)
227 *nn = map->seg[i].size - o;
228 else
229 *nn = n;
230 *off = o;
231 return &map->seg[i];
234 werrstr("address 0x%lux not mapped", addr);
235 return nil;
238 static int
239 mrw(Map *map, ulong addr, void *a, uint n, int r)
241 uint nn;
242 uint tot;
243 Seg *s;
244 ulong off;
246 for(tot=0; tot<n; tot+=nn){
247 s = reloc(map, addr+tot, n-tot, &off, &nn);
248 if(s == nil)
249 return -1;
250 if(s->rw(map, s, off, a, nn, r) < 0)
251 return -1;
253 return 0;
256 static int
257 fdrw(Map *map, Seg *seg, ulong addr, void *a, uint n, int r)
259 int nn;
260 uint tot;
261 ulong off;
263 USED(map);
264 off = seg->offset + addr;
265 for(tot=0; tot<n; tot+=nn){
266 if(r)
267 nn = pread(seg->fd, a, n-tot, off+tot);
268 else
269 nn = pwrite(seg->fd, a, n-tot, off+tot);
270 if(nn < 0)
271 return -1;
272 if(nn == 0){
273 werrstr("partial %s at address 0x%lux in %s",
274 r ? "read" : "write", off+tot, seg->file);
275 return -1;
278 return 0;
281 static int
282 zerorw(Map *map, Seg *seg, ulong addr, void *a, uint n, int r)
284 USED(map);
285 USED(seg);
286 USED(addr);
288 if(r==0){
289 werrstr("cannot write zero segment");
290 return -1;
292 memset(a, 0, n);
293 return 0;
296 static int
297 datarw(Map *map, Seg *seg, ulong addr, void *a, uint n, int r)
299 USED(map);
301 if(r)
302 memmove(a, seg->p+addr, n);
303 else
304 memmove(seg->p+addr, a, n);
305 return 0;