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