xref: /plan9/sys/src/libmach/access.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1*219b2ee8SDavid du Colombier /*
2*219b2ee8SDavid du Colombier  * functions to read and write an executable or file image
3*219b2ee8SDavid du Colombier  */
4*219b2ee8SDavid du Colombier 
5*219b2ee8SDavid du Colombier #include <u.h>
6*219b2ee8SDavid du Colombier #include <libc.h>
7*219b2ee8SDavid du Colombier #include <bio.h>
8*219b2ee8SDavid du Colombier #include <mach.h>
9*219b2ee8SDavid du Colombier 
10*219b2ee8SDavid du Colombier static	int	mget(Map*, ulong, char*, int);
11*219b2ee8SDavid du Colombier static	int	mput(Map*, ulong, char*, int);
12*219b2ee8SDavid du Colombier static int	reloc(Map*, ulong, long*);
13*219b2ee8SDavid du Colombier 
14*219b2ee8SDavid du Colombier /*
15*219b2ee8SDavid du Colombier  * routines to get/put various types
16*219b2ee8SDavid du Colombier  */
17*219b2ee8SDavid du Colombier 
18*219b2ee8SDavid du Colombier int
19*219b2ee8SDavid du Colombier get4(Map *map, ulong addr, long *x)
20*219b2ee8SDavid du Colombier {
21*219b2ee8SDavid du Colombier 	if (!map) {
22*219b2ee8SDavid du Colombier 		werrstr("get4: invalid map");
23*219b2ee8SDavid du Colombier 		return -1;
24*219b2ee8SDavid du Colombier 	}
25*219b2ee8SDavid du Colombier 
26*219b2ee8SDavid du Colombier 	if (map->fd < 0) {
27*219b2ee8SDavid du Colombier 		*x = addr;
28*219b2ee8SDavid du Colombier 		return 1;
29*219b2ee8SDavid du Colombier 	}
30*219b2ee8SDavid du Colombier 	if (mget(map, addr, (char *)x, 4) < 0)
31*219b2ee8SDavid du Colombier 		return -1;
32*219b2ee8SDavid du Colombier 	*x = machdata->swal(*x);
33*219b2ee8SDavid du Colombier 	return (1);
34*219b2ee8SDavid du Colombier }
35*219b2ee8SDavid du Colombier 
36*219b2ee8SDavid du Colombier int
37*219b2ee8SDavid du Colombier get2(Map *map, ulong addr, ushort *x)
38*219b2ee8SDavid du Colombier {
39*219b2ee8SDavid du Colombier 	if (!map) {
40*219b2ee8SDavid du Colombier 		werrstr("get2: invalid map");
41*219b2ee8SDavid du Colombier 		return -1;
42*219b2ee8SDavid du Colombier 	}
43*219b2ee8SDavid du Colombier 
44*219b2ee8SDavid du Colombier 	if (map->fd < 0) {
45*219b2ee8SDavid du Colombier 		*x = addr;
46*219b2ee8SDavid du Colombier 		return 1;
47*219b2ee8SDavid du Colombier 	}
48*219b2ee8SDavid du Colombier 	if (mget(map, addr, (char *)x, 2) < 0)
49*219b2ee8SDavid du Colombier 		return -1;
50*219b2ee8SDavid du Colombier 	*x = machdata->swab(*x);
51*219b2ee8SDavid du Colombier 	return (1);
52*219b2ee8SDavid du Colombier }
53*219b2ee8SDavid du Colombier 
54*219b2ee8SDavid du Colombier int
55*219b2ee8SDavid du Colombier get1(Map *map, ulong addr, uchar *x, int size)
56*219b2ee8SDavid du Colombier {
57*219b2ee8SDavid du Colombier 	uchar *cp;
58*219b2ee8SDavid du Colombier 
59*219b2ee8SDavid du Colombier 	if (!map) {
60*219b2ee8SDavid du Colombier 		werrstr("get1: invalid map");
61*219b2ee8SDavid du Colombier 		return -1;
62*219b2ee8SDavid du Colombier 	}
63*219b2ee8SDavid du Colombier 
64*219b2ee8SDavid du Colombier 	if (map->fd < 0) {
65*219b2ee8SDavid du Colombier 		cp = (uchar*)&addr;
66*219b2ee8SDavid du Colombier 		while (cp < (uchar*)(&addr+1) && size-- > 0)
67*219b2ee8SDavid du Colombier 			*x++ = *cp++;
68*219b2ee8SDavid du Colombier 		while (size-- > 0)
69*219b2ee8SDavid du Colombier 			*x++ = 0;
70*219b2ee8SDavid du Colombier 	} else
71*219b2ee8SDavid du Colombier 		return mget(map, addr, (char*)x, size);
72*219b2ee8SDavid du Colombier 	return 1;
73*219b2ee8SDavid du Colombier }
74*219b2ee8SDavid du Colombier 
75*219b2ee8SDavid du Colombier int
76*219b2ee8SDavid du Colombier put4(Map *map, ulong addr, long v)
77*219b2ee8SDavid du Colombier {
78*219b2ee8SDavid du Colombier 	if (!map || map->fd < 0) {
79*219b2ee8SDavid du Colombier 		werrstr("put4: missing or unopened map");
80*219b2ee8SDavid du Colombier 		return -1;
81*219b2ee8SDavid du Colombier 	}
82*219b2ee8SDavid du Colombier 	v = machdata->swal(v);
83*219b2ee8SDavid du Colombier 	return mput(map, addr, (char *)&v, 4);
84*219b2ee8SDavid du Colombier }
85*219b2ee8SDavid du Colombier 
86*219b2ee8SDavid du Colombier int
87*219b2ee8SDavid du Colombier put2(Map *map, ulong addr, ushort v)
88*219b2ee8SDavid du Colombier {
89*219b2ee8SDavid du Colombier 	if (!map || map->fd < 0) {
90*219b2ee8SDavid du Colombier 		werrstr("put2: missing or unopened map");
91*219b2ee8SDavid du Colombier 		return -1;
92*219b2ee8SDavid du Colombier 	}
93*219b2ee8SDavid du Colombier 	v = machdata->swab(v);
94*219b2ee8SDavid du Colombier 	return mput(map, addr, (char *)&v, 2);
95*219b2ee8SDavid du Colombier }
96*219b2ee8SDavid du Colombier 
97*219b2ee8SDavid du Colombier int
98*219b2ee8SDavid du Colombier put1(Map *map, ulong addr, uchar *v, int size)
99*219b2ee8SDavid du Colombier {
100*219b2ee8SDavid du Colombier 	if (!map || map->fd < 0) {
101*219b2ee8SDavid du Colombier 		werrstr("put1: missing or unopened map");
102*219b2ee8SDavid du Colombier 		return -1;
103*219b2ee8SDavid du Colombier 	}
104*219b2ee8SDavid du Colombier 	return mput(map, addr, (char *)v, size);
105*219b2ee8SDavid du Colombier }
106*219b2ee8SDavid du Colombier 
107*219b2ee8SDavid du Colombier static int
108*219b2ee8SDavid du Colombier mget(Map *map, ulong addr, char *buf, int size)
109*219b2ee8SDavid du Colombier {
110*219b2ee8SDavid du Colombier 	long off;
111*219b2ee8SDavid du Colombier 	int i, j, k;
112*219b2ee8SDavid du Colombier 
113*219b2ee8SDavid du Colombier 	if (reloc(map, addr, &off) < 0)
114*219b2ee8SDavid du Colombier 		return -1;
115*219b2ee8SDavid du Colombier 
116*219b2ee8SDavid du Colombier 	seek(map->fd, off, 0);
117*219b2ee8SDavid du Colombier 	for (i = j = 0; i < 2; i++) {	/* in case read crosses page */
118*219b2ee8SDavid du Colombier 		k = read(map->fd, buf, size-j);
119*219b2ee8SDavid du Colombier 		if (k < 0) {
120*219b2ee8SDavid du Colombier 			werrstr("can't read address %lux: %r", addr);
121*219b2ee8SDavid du Colombier 			return -1;
122*219b2ee8SDavid du Colombier 		}
123*219b2ee8SDavid du Colombier 		j += k;
124*219b2ee8SDavid du Colombier 		if (j == size)
125*219b2ee8SDavid du Colombier 			return j;
126*219b2ee8SDavid du Colombier 	}
127*219b2ee8SDavid du Colombier 	werrstr("partial read at address %lux", addr);
128*219b2ee8SDavid du Colombier 	return -1;
129*219b2ee8SDavid du Colombier }
130*219b2ee8SDavid du Colombier 
131*219b2ee8SDavid du Colombier static int
132*219b2ee8SDavid du Colombier mput(Map *map, ulong addr, char *buf, int size)
133*219b2ee8SDavid du Colombier {
134*219b2ee8SDavid du Colombier 	long off;
135*219b2ee8SDavid du Colombier 	int i, j, k;
136*219b2ee8SDavid du Colombier 
137*219b2ee8SDavid du Colombier 	if (reloc(map, addr,&off) < 0)
138*219b2ee8SDavid du Colombier 		return -1;
139*219b2ee8SDavid du Colombier 
140*219b2ee8SDavid du Colombier 	seek(map->fd, off, 0);
141*219b2ee8SDavid du Colombier 	for (i = j = 0; i < 2; i++) {	/* in case read crosses page */
142*219b2ee8SDavid du Colombier 		k = write(map->fd, buf, size-j);
143*219b2ee8SDavid du Colombier 		if (k < 0) {
144*219b2ee8SDavid du Colombier 			werrstr("can't write address %lux: %r", addr);
145*219b2ee8SDavid du Colombier 			return -1;
146*219b2ee8SDavid du Colombier 		}
147*219b2ee8SDavid du Colombier 		j += k;
148*219b2ee8SDavid du Colombier 		if (j == size)
149*219b2ee8SDavid du Colombier 			return j;
150*219b2ee8SDavid du Colombier 	}
151*219b2ee8SDavid du Colombier 	werrstr("partial write at address %lux", addr);
152*219b2ee8SDavid du Colombier 	return -1;
153*219b2ee8SDavid du Colombier }
154*219b2ee8SDavid du Colombier 
155*219b2ee8SDavid du Colombier /*
156*219b2ee8SDavid du Colombier  *	convert address to file offset; returns nonzero if ok
157*219b2ee8SDavid du Colombier  */
158*219b2ee8SDavid du Colombier static int
159*219b2ee8SDavid du Colombier reloc(Map *map, ulong addr, long *offp)
160*219b2ee8SDavid du Colombier {
161*219b2ee8SDavid du Colombier 	int i;
162*219b2ee8SDavid du Colombier 
163*219b2ee8SDavid du Colombier 	for (i = 0; i < map->nsegs; i++) {
164*219b2ee8SDavid du Colombier 		if (map->seg[i].inuse)
165*219b2ee8SDavid du Colombier 		if (map->seg[i].b <= addr && addr < map->seg[i].e) {
166*219b2ee8SDavid du Colombier 			*offp = addr + map->seg[i].f - map->seg[i].b;
167*219b2ee8SDavid du Colombier 			return 1;
168*219b2ee8SDavid du Colombier 		}
169*219b2ee8SDavid du Colombier 	}
170*219b2ee8SDavid du Colombier 	werrstr("can't translate address %lux", addr);
171*219b2ee8SDavid du Colombier 	return -1;
172*219b2ee8SDavid du Colombier }
173