plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

map.c (5086B)


      1 /*
      2  * File map routines
      3  */
      4 #include <u.h>
      5 #include <libc.h>
      6 #include <bio.h>
      7 #include <mach.h>
      8 
      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);
     13 
     14 Map*
     15 allocmap(void)
     16 {
     17 	return mallocz(sizeof(Map), 1);
     18 }
     19 
     20 void
     21 freemap(Map *map)
     22 {
     23 	if(map == nil)
     24 		return;
     25 	free(map->seg);
     26 	free(map);
     27 }
     28 
     29 int
     30 addseg(Map *map, Seg seg)
     31 {
     32 	Seg *ss;
     33 
     34 	if(map == nil){
     35 		werrstr("invalid map");
     36 		return -1;
     37 	}
     38 
     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 }
     54 
     55 int
     56 findseg(Map *map, char *name, char *file)
     57 {
     58 	int i;
     59 
     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 }
     72 
     73 int
     74 addrtoseg(Map *map, u64int addr, Seg *sp)
     75 {
     76 	int i;
     77 	Seg *s;
     78 
     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 }
     94 
     95 int
     96 addrtosegafter(Map *map, u64int addr, Seg *sp)
     97 {
     98 	int i;
     99 	Seg *s, *best;
    100 	ulong bdist;
    101 
    102 	if(map == nil){
    103 		werrstr("no map");
    104 		return -1;
    105 	}
    106 
    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;
    121 			}
    122 		}
    123 	}
    124 	if(best){
    125 		if(sp)
    126 			*sp = *best;
    127 		return best-map->seg;
    128 	}
    129 	werrstr("nothing mapped after address 0x%lux", addr);
    130 	return -1;
    131 }
    132 
    133 void
    134 removeseg(Map *map, int i)
    135 {
    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--;
    142 }
    143 
    144 int
    145 get1(Map *map, u64int addr, uchar *a, uint n)
    146 {
    147 	return mrw(map, addr, a, n, 1);
    148 }
    149 
    150 int
    151 get2(Map *map, u64int addr, u16int *u)
    152 {
    153 	u16int v;
    154 
    155 	if(mrw(map, addr, &v, 2, 1) < 0)
    156 		return -1;
    157 	*u = mach->swap2(v);
    158 	return 2;
    159 }
    160 
    161 int
    162 get4(Map *map, u64int addr, u32int *u)
    163 {
    164 	u32int v;
    165 
    166 	if(mrw(map, addr, &v, 4, 1) < 0)
    167 		return -1;
    168 	*u = mach->swap4(v);
    169 	return 4;
    170 }
    171 
    172 int
    173 get8(Map *map, u64int addr, u64int *u)
    174 {
    175 	u64int v;
    176 
    177 	if(mrw(map, addr, &v, 8, 1) < 0)
    178 		return -1;
    179 	*u = mach->swap8(v);
    180 	return 8;
    181 }
    182 
    183 int
    184 geta(Map *map, u64int addr, u64int *u)
    185 {
    186 	u32int v;
    187 
    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;
    194 }
    195 
    196 int
    197 put1(Map *map, u64int addr, uchar *a, uint n)
    198 {
    199 	return mrw(map, addr, a, n, 0);
    200 }
    201 
    202 int
    203 put2(Map *map, u64int addr, u16int u)
    204 {
    205 	u = mach->swap2(u);
    206 	return mrw(map, addr, &u, 2, 0);
    207 }
    208 
    209 int
    210 put4(Map *map, u64int addr, u32int u)
    211 {
    212 	u = mach->swap4(u);
    213 	return mrw(map, addr, &u, 4, 0);
    214 }
    215 
    216 int
    217 put8(Map *map, u64int addr, u64int u)
    218 {
    219 	u = mach->swap8(u);
    220 	return mrw(map, addr, &u, 8, 0);
    221 }
    222 
    223 static Seg*
    224 reloc(Map *map, u64int addr, uint n, u64int *off, uint *nn)
    225 {
    226 	int i;
    227 	ulong o;
    228 
    229 	if(map == nil){
    230 		werrstr("invalid map");
    231 		return nil;
    232 	}
    233 
    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];
    245 		}
    246 	}
    247 	werrstr("address 0x%lux not mapped", addr);
    248 	return nil;
    249 }
    250 
    251 static int
    252 mrw(Map *map, u64int addr, void *a, uint n, int r)
    253 {
    254 	uint nn;
    255 	uint tot;
    256 	Seg *s;
    257 	u64int off;
    258 
    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;
    265 	}
    266 	return 0;
    267 }
    268 
    269 static int
    270 fdrw(Map *map, Seg *seg, u64int addr, void *a, uint n, int r)
    271 {
    272 	int nn;
    273 	uint tot;
    274 	ulong off;
    275 
    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;
    289 		}
    290 	}
    291 	return 0;
    292 }
    293 
    294 static int
    295 zerorw(Map *map, Seg *seg, u64int addr, void *a, uint n, int r)
    296 {
    297 	USED(map);
    298 	USED(seg);
    299 	USED(addr);
    300 
    301 	if(r==0){
    302 		werrstr("cannot write zero segment");
    303 		return -1;
    304 	}
    305 	memset(a, 0, n);
    306 	return 0;
    307 }
    308 
    309 static int
    310 datarw(Map *map, Seg *seg, u64int addr, void *a, uint n, int r)
    311 {
    312 	USED(map);
    313 
    314 	if(r)
    315 		memmove(a, seg->p+addr, n);
    316 	else
    317 		memmove(seg->p+addr, a, n);
    318 	return 0;
    319 }