@define mksnapas(file) { @local ns, as, dom, nmap, mp, idx, ip, i; @local get, put, map, lookmap, rs; // this needs to match the conventions in l1/fnsnap.c ns = @names clp64le { typedef struct Map { @0x00 uint64 lo; @0x08 uint64 hi; @0x10; } Map; @0x0 uint32 nmap; @0x4 Map map[]; }; as = mksas(mapfile(file)); dom = mkdom(ns, as); nmap = dom`nmap; mp = dom`map; rs = []; idx = []; ip = (void*)(mp+nmap); for(i = 0; i < nmap; i++){ // printf("%016x-%016x\n", mp->lo, mp->hi); append(idx, [ mp->lo, mp->hi, ip ]); append(rs, mkrange(mp->lo, mp->hi-mp->lo)); ip += mp->hi-mp->lo; mp++; } rs = apply(vector, rs); @define map(this){ return rs; } @define ismapped(this, r){ return isrinr(r, rs); } @define lookmap(a) { @local i; for(i = 0; i < nmap; i++) if(idx[i][0] <= a && a < idx[i][1]) return idx[i]; return nil; } @define get(this, r){ @local b, l, m; b = rangebeg(r); l = rangelen(r); m = lookmap(b); if(m == nil) error("snapas: memory access out of bounds (%x)", b); if(b+l > m[1]) error("snapas: memory access spans boundary (%x-%x)", b, b+l); b -= m[0]; return getbytes(m[2]+b, l); } @define put(this, r, bytes){ error("attempt to put on snapas"); } return mkas([ "map" : map, "get" : get, "put" : put, "ismapped" : ismapped ]); }