xref: /inferno-os/utils/libmach/map.c (revision ddf161d27871e47d85fd56e8403c715af8ce43c8)
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, uvlong b, uvlong e, vlong 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 uvlong
49 stacktop(int pid)
50 {
51 	char buf[64];
52 	int fd;
53 	int n;
54 	char *cp;
55 
56 	snprint(buf, sizeof(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 strtoull(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 	uvlong n;
86 
87 	map = newmap(0, 4);
88 	if (!map)
89 		return 0;
90 	if(kflag)
91 		regs = "kregs";
92 	else
93 		regs = "regs";
94 	if (mach->regsize) {
95 		sprint(buf, "/proc/%d/%s", pid, regs);
96 		fd = open(buf, ORDWR);
97 		if(fd < 0)
98 			fd = open(buf, OREAD);
99 		if(fd < 0) {
100 			free(map);
101 			return 0;
102 		}
103 		setmap(map, fd, 0, mach->regsize, 0, "regs");
104 	}
105 	if (mach->fpregsize) {
106 		sprint(buf, "/proc/%d/fpregs", pid);
107 		fd = open(buf, ORDWR);
108 		if(fd < 0)
109 			fd = open(buf, OREAD);
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 || fp->dataddr >= mach->utop) {
119 		setmap(map, corefd, fp->dataddr, ~0, fp->dataddr, "data");
120 		return map;
121 	}
122 	n = stacktop(pid);
123 	if (n == 0) {
124 		setmap(map, corefd, fp->dataddr, mach->utop, 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 loadmap(Map *map, int fd, Fhdr *fp)
153 {
154 	map = newmap(map, 2);
155 	if (map == 0)
156 		return 0;
157 
158 	map->seg[0].b = fp->txtaddr;
159 	map->seg[0].e = fp->txtaddr+fp->txtsz;
160 	map->seg[0].f = fp->txtoff;
161 	map->seg[0].fd = fd;
162 	map->seg[0].inuse = 1;
163 	map->seg[0].name = "text";
164 	map->seg[1].b = fp->dataddr;
165 	map->seg[1].e = fp->dataddr+fp->datsz;
166 	map->seg[1].f = fp->datoff;
167 	map->seg[1].fd = fd;
168 	map->seg[1].inuse = 1;
169 	map->seg[1].name = "data";
170 	return map;
171 }
172 
173 Map*
174 attachremt(int fd, Fhdr *f)
175 {
176 	Map *m;
177 	ulong txt;
178 
179 	m = newmap(0, 3);
180 	if (m == 0)
181 		return 0;
182 
183 	/* Space for mach structures */
184 	txt = f->txtaddr;
185 	if(txt > 8*4096)
186 		txt -= 8*4096;
187 
188 	setmap(m, fd, txt, f->txtaddr+f->txtsz, txt, "*text");
189 	/*setmap(m, fd, f->dataddr, 0xffffffff, f->dataddr, "*data");*/ /* pc heap is < KTZERO */
190 	setmap(m, fd, 4096, 0xffffffff, 4096, "*data");
191 	setmap(m, fd, 0x0, mach->regsize, 0, "kreg");
192 
193 	return m;
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