xref: /inferno-os/utils/libmach/map.c (revision 4eb166cf184c1f102fb79e31b1465ea3e2021c39)
1 /*
2  * file map routines
3  */
4 #include <lib9.h>
5 #include <bio.h>
6 #include "mach.h"
7 
8 Map *
9 newmap(Map *map, int n)
10 {
11 	int size;
12 
13 	size = sizeof(Map)+(n-1)*sizeof(struct segment);
14 	if (map == 0)
15 		map = malloc(size);
16 	else
17 		map = realloc(map, size);
18 	if (map == 0) {
19 		werrstr("out of memory: %r");
20 		return 0;
21 	}
22 	memset(map, 0, size);
23 	map->nsegs = n;
24 	return map;
25 }
26 
27 int
28 setmap(Map *map, int fd, ulong b, ulong e, ulong f, char *name)
29 {
30 	int i;
31 
32 	if (map == 0)
33 		return 0;
34 	for (i = 0; i < map->nsegs; i++)
35 		if (!map->seg[i].inuse)
36 			break;
37 	if (i >= map->nsegs)
38 		return 0;
39 	map->seg[i].b = b;
40 	map->seg[i].e = e;
41 	map->seg[i].f = f;
42 	map->seg[i].inuse = 1;
43 	map->seg[i].name = name;
44 	map->seg[i].fd = fd;
45 	return 1;
46 }
47 
48 static ulong
49 stacktop(int pid)
50 {
51 	char buf[64];
52 	int fd;
53 	int n;
54 	char *cp;
55 
56 	sprint(buf, "/proc/%d/segment", pid);
57 	fd = open(buf, 0);
58 	if (fd < 0)
59 		return 0;
60 	n = read(fd, buf, sizeof(buf)-1);
61 	close(fd);
62 	buf[n] = 0;
63 	if (strncmp(buf, "Stack", 5))
64 		return 0;
65 	for (cp = buf+5; *cp && *cp == ' '; cp++)
66 		;
67 	if (!*cp)
68 		return 0;
69 	cp = strchr(cp, ' ');
70 	if (!cp)
71 		return 0;
72 	while (*cp && *cp == ' ')
73 		cp++;
74 	if (!*cp)
75 		return 0;
76 	return strtoul(cp, 0, 16);
77 }
78 
79 Map*
80 attachproc(int pid, int kflag, int corefd, Fhdr *fp)
81 {
82 	char buf[64], *regs;
83 	int fd;
84 	Map *map;
85 	ulong n;
86 	int mode;
87 
88 	map = newmap(0, 4);
89 	if (!map)
90 		return 0;
91 	if(kflag) {
92 		regs = "kregs";
93 		mode = OREAD;
94 	} else {
95 		regs = "regs";
96 		mode = ORDWR;
97 	}
98 	if (mach->regsize) {
99 		sprint(buf, "/proc/%d/%s", pid, regs);
100 		fd = open(buf, mode);
101 		if(fd < 0) {
102 			free(map);
103 			return 0;
104 		}
105 		setmap(map, fd, 0, mach->regsize, 0, "regs");
106 	}
107 	if (mach->fpregsize) {
108 		sprint(buf, "/proc/%d/fpregs", pid);
109 		fd = open(buf, mode);
110 		if(fd < 0) {
111 			close(map->seg[0].fd);
112 			free(map);
113 			return 0;
114 		}
115 		setmap(map, fd, mach->regsize, mach->regsize+mach->fpregsize, 0, "fpregs");
116 	}
117 	setmap(map, corefd, fp->txtaddr, fp->txtaddr+fp->txtsz, fp->txtaddr, "text");
118 	if(kflag || (ulong) fp->dataddr >= 0x7fffffff) {
119 		setmap(map, corefd, fp->dataddr, 0xffffffff, fp->dataddr, "data");
120 		return map;
121 	}
122 	n = stacktop(pid);
123 	if (n == 0) {
124 		setmap(map, corefd, fp->dataddr, 0x7fffffff, fp->dataddr, "data");
125 		return map;
126 	}
127 	setmap(map, corefd, fp->dataddr, n, fp->dataddr, "data");
128 	return map;
129 }
130 
131 int
132 findseg(Map *map, char *name)
133 {
134 	int i;
135 
136 	if (!map)
137 		return -1;
138 	for (i = 0; i < map->nsegs; i++)
139 		if (map->seg[i].inuse && !strcmp(map->seg[i].name, name))
140 			return i;
141 	return -1;
142 }
143 
144 void
145 unusemap(Map *map, int i)
146 {
147 	if (map != 0 && 0 <= i && i < map->nsegs)
148 		map->seg[i].inuse = 0;
149 }
150 
151 Map*
152 attachremt(int fd, Fhdr *f)
153 {
154 	Map *m;
155 	ulong txt;
156 
157 	m = newmap(0, 3);
158 	if (m == 0)
159 		return 0;
160 
161 	/* Space for mach structures */
162 	txt = f->txtaddr;
163 	if(txt > 8*4096)
164 		txt -= 8*4096;
165 
166 	setmap(m, fd, txt, f->txtaddr+f->txtsz, txt, "*text");
167 	/*setmap(m, fd, f->dataddr, 0xffffffff, f->dataddr, "*data");*/ /* pc heap is < KTZERO */
168 	setmap(m, fd, 4096, 0xffffffff, 4096, "*data");
169 	setmap(m, fd, 0x0, mach->regsize, 0, "kreg");
170 
171 	return m;
172 }
173 
174 Map*
175 loadmap(Map *map, int fd, Fhdr *fp)
176 {
177 	map = newmap(map, 2);
178 	if (map == 0)
179 		return 0;
180 
181 	map->seg[0].b = fp->txtaddr;
182 	map->seg[0].e = fp->txtaddr+fp->txtsz;
183 	map->seg[0].f = fp->txtoff;
184 	map->seg[0].fd = fd;
185 	map->seg[0].inuse = 1;
186 	map->seg[0].name = "text";
187 	map->seg[1].b = fp->dataddr;
188 	map->seg[1].e = fp->dataddr+fp->datsz;
189 	map->seg[1].f = fp->datoff;
190 	map->seg[1].fd = fd;
191 	map->seg[1].inuse = 1;
192 	map->seg[1].name = "data";
193 	return map;
194 }
195 
196 void
197 setmapio(Map *map, int i, Rsegio get, Rsegio put)
198 {
199 	if (map != 0 && 0 <= i && i < map->nsegs) {
200 		map->seg[i].mget = get;
201 		map->seg[i].mput = put;
202 	}
203 }
204