1 // Derived from Inferno libmach/map.c and
2 // Plan 9 from User Space src/libmach/map.c
3 //
4 // http://code.swtch.com/plan9port/src/tip/src/libmach/map.c
5 // http://code.google.com/p/inferno-os/source/browse/utils/libmach/map.c
6 //
7 //
8 // Copyright © 1994-1999 Lucent Technologies Inc.
9 // Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
10 // Portions Copyright © 1997-1999 Vita Nuova Limited.
11 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
12 // Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
13 // Portions Copyright © 2001-2007 Russ Cox.
14 // Portions Copyright © 2009 The Go Authors. All rights reserved.
15 //
16 // Permission is hereby granted, free of charge, to any person obtaining a copy
17 // of this software and associated documentation files (the "Software"), to deal
18 // in the Software without restriction, including without limitation the rights
19 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
20 // copies of the Software, and to permit persons to whom the Software is
21 // furnished to do so, subject to the following conditions:
22 //
23 // The above copyright notice and this permission notice shall be included in
24 // all copies or substantial portions of the Software.
25 //
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
31 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
32 // THE SOFTWARE.
33
34 /*
35 * file map routines
36 */
37 #include <u.h>
38 #include <libc.h>
39 #include <bio.h>
40 #include <mach.h>
41
42 Map *
43 newmap(Map *map, int n)
44 {
45 int size;
46
47 size = sizeof(Map)+(n-1)*sizeof(Seg);
48 if (map == 0)
49 map = malloc(size);
50 else
51 map = realloc(map, size);
52 if (map == 0) {
53 werrstr("out of memory: %r");
54 return 0;
55 }
56 memset(map, 0, size);
57 map->nsegs = n;
58 return map;
59 }
60
61 int
62 setmap(Map *map, int fd, uvlong b, uvlong e, vlong f, char *name, Maprw *rw)
63 {
64 int i;
65
66 if (map == 0)
67 return 0;
68 for (i = 0; i < map->nsegs; i++)
69 if (!map->seg[i].inuse)
70 break;
71 if (i >= map->nsegs)
72 return 0;
73 map->seg[i].b = b;
74 map->seg[i].e = e;
75 map->seg[i].f = f;
76 map->seg[i].inuse = 1;
77 map->seg[i].name = name;
78 map->seg[i].fd = fd;
79 map->seg[i].rw = rw;
80 return 1;
81 }
82
83 /*
84 static uvlong
85 stacktop(int pid)
86 {
87 char buf[64];
88 int fd;
89 int n;
90 char *cp;
91
92 snprint(buf, sizeof(buf), "/proc/%d/segment", pid);
93 fd = open(buf, 0);
94 if (fd < 0)
95 return 0;
96 n = read(fd, buf, sizeof(buf)-1);
97 close(fd);
98 buf[n] = 0;
99 if (strncmp(buf, "Stack", 5))
100 return 0;
101 for (cp = buf+5; *cp && *cp == ' '; cp++)
102 ;
103 if (!*cp)
104 return 0;
105 cp = strchr(cp, ' ');
106 if (!cp)
107 return 0;
108 while (*cp && *cp == ' ')
109 cp++;
110 if (!*cp)
111 return 0;
112 return strtoull(cp, 0, 16);
113 }
114 */
115
116 int
117 findseg(Map *map, char *name)
118 {
119 int i;
120
121 if (!map)
122 return -1;
123 for (i = 0; i < map->nsegs; i++)
124 if (map->seg[i].inuse && !strcmp(map->seg[i].name, name))
125 return i;
126 return -1;
127 }
128
129 void
130 unusemap(Map *map, int i)
131 {
132 if (map != 0 && 0 <= i && i < map->nsegs)
133 map->seg[i].inuse = 0;
134 }
135
136 int
137 fdrw(Map *map, Seg *s, uvlong addr, void *v, uint n, int isread)
138 {
139 int tot, m;
140
141 for(tot=0; tot<n; tot+=m){
142 if(isread)
143 m = pread(s->fd, (uchar*)v+tot, n-tot, addr+tot);
144 else
145 m = pwrite(s->fd, (uchar*)v+tot, n-tot, addr+tot);
146 if(m == 0){
147 werrstr("short %s", isread ? "read" : "write");
148 return -1;
149 }
150 if(m < 0){
151 werrstr("%s %d at %#llux (+%#llux): %r", isread ? "read" : "write", n, addr, s->f);
152 return -1;
153 }
154 }
155 return 0;
156 }
157
158
159 Map*
160 loadmap(Map *map, int fd, Fhdr *fp)
161 {
162 map = newmap(map, 2);
163 if (map == 0)
164 return 0;
165
166 map->seg[0].b = fp->txtaddr;
167 map->seg[0].e = fp->txtaddr+fp->txtsz;
168 map->seg[0].f = fp->txtoff;
169 map->seg[0].fd = fd;
170 map->seg[0].inuse = 1;
171 map->seg[0].name = "text";
172 map->seg[0].rw = fdrw;
173 map->seg[1].b = fp->dataddr;
174 map->seg[1].e = fp->dataddr+fp->datsz;
175 map->seg[1].f = fp->datoff;
176 map->seg[1].fd = fd;
177 map->seg[1].inuse = 1;
178 map->seg[1].name = "data";
179 map->seg[0].rw = fdrw;
180 return map;
181 }