URI:
       tmap.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tmap.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 }