Print this page
5261 libm should stop using synonyms.h
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libm/common/m9x/__fex_sym.c
+++ new/usr/src/lib/libm/common/m9x/__fex_sym.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
20 20 */
21 21
22 22 /*
23 23 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
24 24 */
25 25 /*
26 26 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
27 27 * Use is subject to license terms.
28 28 */
29 29
30 -#include "fenv_synonyms.h"
31 30 #include <elf.h>
32 31 #include <stdio.h>
33 32 #include <stdlib.h>
34 33 #include <unistd.h>
35 34 #include <fcntl.h>
36 35 #include <procfs.h>
37 36 #include <string.h>
38 37 #include <sys/stat.h>
39 38
40 39 #if defined(__sparcv9) || defined(__amd64)
41 40
42 41 #define Elf_Ehdr Elf64_Ehdr
43 42 #define Elf_Phdr Elf64_Phdr
44 43 #define Elf_Shdr Elf64_Shdr
45 44 #define Elf_Sym Elf64_Sym
46 45 #define ELF_ST_BIND ELF64_ST_BIND
47 46 #define ELF_ST_TYPE ELF64_ST_TYPE
48 47
49 48 #else
50 49
51 50 #define Elf_Ehdr Elf32_Ehdr
52 51 #define Elf_Phdr Elf32_Phdr
53 52 #define Elf_Shdr Elf32_Shdr
54 53 #define Elf_Sym Elf32_Sym
55 54 #define ELF_ST_BIND ELF32_ST_BIND
56 55 #define ELF_ST_TYPE ELF32_ST_TYPE
57 56
58 57 #endif /* __sparcv9 */
59 58
60 59 /* semi-permanent data established by __fex_sym_init */
61 60 static prmap_t *pm = NULL; /* prmap_t array */
62 61 static int npm = 0; /* number of entries in pm */
63 62
64 63 /* transient data modified by __fex_sym */
65 64 static prmap_t *lpm = NULL; /* prmap_t found in last call */
66 65 static Elf_Phdr *ph = NULL; /* program header array */
67 66 static int phsize = 0; /* size of ph */
68 67 static int nph; /* number of entries in ph */
69 68 static char *stbuf = NULL; /* symbol and string table buffer */
70 69 static int stbufsize = 0; /* size of stbuf */
71 70 static int stoffset; /* offset of string table in stbuf */
72 71 static int nsyms; /* number of symbols in stbuf */
73 72
74 73 /* get a current prmap_t list (must call this before each stack trace) */
75 74 void
76 75 __fex_sym_init()
77 76 {
78 77 struct stat statbuf;
79 78 long n;
80 79 int i;
81 80
82 81 /* clear out the previous prmap_t list */
83 82 if (pm != NULL)
84 83 free(pm);
85 84 pm = lpm = NULL;
86 85 npm = 0;
87 86
88 87 /* get the current prmap_t list */
89 88 if (stat("/proc/self/map", &statbuf) < 0 || statbuf.st_size <= 0 ||
90 89 (pm = (prmap_t*)malloc(statbuf.st_size)) == NULL)
91 90 return;
92 91 if ((i = open("/proc/self/map", O_RDONLY)) < 0)
93 92 {
94 93 free(pm);
95 94 pm = NULL;
96 95 return;
97 96 }
98 97 n = read(i, pm, statbuf.st_size);
99 98 close(i);
100 99 if (n != statbuf.st_size)
101 100 {
102 101 free(pm);
103 102 pm = NULL;
104 103 }
105 104 else
106 105 npm = (int) (n / sizeof(prmap_t));
107 106 }
108 107
109 108 /* read ELF program headers and symbols; return -1 on error, 0 otherwise */
110 109 static int
111 110 __fex_read_syms(int fd)
112 111 {
113 112 Elf_Ehdr h;
114 113 Elf_Shdr *sh;
115 114 int i, size;
116 115
117 116 /* read the ELF header */
118 117 if (read(fd, &h, sizeof(h)) != sizeof(h))
119 118 return -1;
120 119 if (h.e_ident[EI_MAG0] != ELFMAG0 ||
121 120 h.e_ident[EI_MAG1] != ELFMAG1 ||
122 121 h.e_ident[EI_MAG2] != ELFMAG2 ||
123 122 h.e_ident[EI_MAG3] != ELFMAG3 ||
124 123 h.e_phentsize != sizeof(Elf_Phdr) ||
125 124 h.e_shentsize != sizeof(Elf_Shdr))
126 125 return -1;
127 126
128 127 /* get space for the program headers */
129 128 size = h.e_phnum * h.e_phentsize;
130 129 if (size > phsize)
131 130 {
132 131 if (ph)
133 132 free(ph);
134 133 phsize = nph = 0;
135 134 if ((ph = (Elf_Phdr*)malloc(size)) == NULL)
136 135 return -1;
137 136 phsize = size;
138 137 }
139 138
140 139 /* read the program headers */
141 140 if (lseek(fd, h.e_phoff, SEEK_SET) != h.e_phoff ||
142 141 read(fd, ph, size) != (ssize_t)size)
143 142 {
144 143 nph = 0;
145 144 return -1;
146 145 }
147 146 nph = h.e_phnum;
148 147
149 148 /* read the section headers */
150 149 size = h.e_shnum * h.e_shentsize;
151 150 if ((sh = (Elf_Shdr*)malloc(size)) == NULL)
152 151 return -1;
153 152 if (lseek(fd, h.e_shoff, SEEK_SET) != h.e_shoff ||
154 153 read(fd, sh, size) != (ssize_t)size)
155 154 {
156 155 free(sh);
157 156 return -1;
158 157 }
159 158
160 159 /* find the symtab section header */
161 160 for (i = 0; i < h.e_shnum; i++)
162 161 {
163 162 if (sh[i].sh_type == SHT_SYMTAB)
164 163 break; /* assume there is only one */
165 164 }
166 165 if (i == h.e_shnum || sh[i].sh_size == 0 ||
167 166 sh[i].sh_entsize != sizeof(Elf_Sym) ||
168 167 sh[i].sh_link < 1 || sh[i].sh_link >= h.e_shnum ||
169 168 sh[sh[i].sh_link].sh_type != SHT_STRTAB ||
170 169 sh[sh[i].sh_link].sh_size == 0)
171 170 {
172 171 free(sh);
173 172 return -1;
174 173 }
175 174
176 175 /* get space for the symbol and string tables */
177 176 size = (int) (sh[i].sh_size + sh[sh[i].sh_link].sh_size);
178 177 if (size > stbufsize)
179 178 {
180 179 if (stbuf)
181 180 free(stbuf);
182 181 stbufsize = nsyms = 0;
183 182 if ((stbuf = (char*)malloc(size)) == NULL)
184 183 {
185 184 free(sh);
186 185 return -1;
187 186 }
188 187 stbufsize = size;
189 188 }
190 189
191 190 /* read the symbol and string tables */
192 191 if (lseek(fd, sh[i].sh_offset, SEEK_SET) != sh[i].sh_offset ||
193 192 read(fd, stbuf, sh[i].sh_size) != sh[i].sh_size ||
194 193 lseek(fd, sh[sh[i].sh_link].sh_offset, SEEK_SET) !=
195 194 sh[sh[i].sh_link].sh_offset ||
196 195 read(fd, stbuf + sh[i].sh_size, sh[sh[i].sh_link].sh_size) !=
197 196 sh[sh[i].sh_link].sh_size)
198 197 {
199 198 free(sh);
200 199 return (-1);
201 200 }
202 201 nsyms = (int) (sh[i].sh_size / sh[i].sh_entsize);
203 202 stoffset = (int) sh[i].sh_size;
204 203
205 204 free(sh);
206 205 return (0);
207 206 }
208 207
209 208 /* find the symbol corresponding to the given text address;
210 209 return NULL on error, symbol address otherwise */
211 210 char *
212 211 __fex_sym(char *a, char **name)
213 212 {
214 213 Elf_Sym *s;
215 214 unsigned long fo, va, value;
216 215 int fd, i, j, nm;
217 216 char fname[PRMAPSZ+20];
218 217
219 218 /* see if the last prmap_t found contains the indicated address */
220 219 if (lpm)
221 220 {
222 221 if (a >= (char*)lpm->pr_vaddr && a < (char*)lpm->pr_vaddr +
223 222 lpm->pr_size)
224 223 goto cont;
225 224 }
226 225
227 226 /* look for a prmap_t that contains the indicated address */
228 227 for (i = 0; i < npm; i++)
229 228 {
230 229 if (a >= (char*)pm[i].pr_vaddr && a < (char*)pm[i].pr_vaddr +
231 230 pm[i].pr_size)
232 231 break;
233 232 }
234 233 if (i == npm)
235 234 return NULL;
236 235
237 236 /* get an open file descriptor for the mapped object */
238 237 if (pm[i].pr_mapname[0] == '\0')
239 238 return NULL;
240 239 strcpy(fname, "/proc/self/object/");
241 240 strncat(fname, pm[i].pr_mapname, PRMAPSZ);
242 241 fd = open(fname, O_RDONLY);
243 242 if (fd < 0)
244 243 return NULL;
245 244
246 245 /* read the program headers and symbols */
247 246 lpm = NULL;
248 247 j = __fex_read_syms(fd);
249 248 close(fd);
250 249 if (j < 0)
251 250 return NULL;
252 251 lpm = &pm[i];
253 252
254 253 cont:
255 254 /* compute the file offset corresponding to the mapped address */
256 255 fo = (a - (char*)lpm->pr_vaddr) + lpm->pr_offset;
257 256
258 257 /* find the program header containing the file offset */
259 258 for (i = 0; i < nph; i++)
260 259 {
261 260 if (ph[i].p_type == PT_LOAD && fo >= ph[i].p_offset &&
262 261 fo < ph[i].p_offset + ph[i].p_filesz)
263 262 break;
264 263 }
265 264 if (i == nph)
266 265 return NULL;
267 266
268 267 /* compute the virtual address corresponding to the file offset */
269 268 va = (fo - ph[i].p_offset) + ph[i].p_vaddr;
270 269
271 270 /* find the symbol in this segment with the highest value
272 271 less than or equal to the virtual address */
273 272 s = (Elf_Sym*)stbuf;
274 273 value = nm = 0;
275 274 for (j = 0; j < nsyms; j++)
276 275 {
277 276 if (s[j].st_name == 0 || s[j].st_shndx == SHN_UNDEF ||
278 277 (ELF_ST_BIND(s[j].st_info) != STB_LOCAL &&
279 278 ELF_ST_BIND(s[j].st_info) != STB_GLOBAL &&
280 279 ELF_ST_BIND(s[j].st_info) != STB_WEAK) ||
281 280 (ELF_ST_TYPE(s[j].st_info) != STT_NOTYPE &&
282 281 ELF_ST_TYPE(s[j].st_info) != STT_OBJECT &&
283 282 ELF_ST_TYPE(s[j].st_info) != STT_FUNC))
284 283 {
285 284 continue;
286 285 }
287 286
288 287 if (s[j].st_value < ph[i].p_vaddr || s[j].st_value >= ph[i].p_vaddr
289 288 + ph[i].p_memsz)
290 289 {
291 290 continue;
292 291 }
293 292
294 293 if (s[j].st_value < value || s[j].st_value > va)
295 294 continue;
296 295
297 296 value = s[j].st_value;
298 297 nm = s[j].st_name;
299 298 }
300 299 if (nm == 0)
301 300 return NULL;
302 301
303 302 /* pass back the name and return the mapped address of the symbol */
304 303 *name = stbuf + stoffset + nm;
305 304 fo = (value - ph[i].p_vaddr) + ph[i].p_offset;
306 305 return (char*)lpm->pr_vaddr + (fo - lpm->pr_offset);
307 306 }
↓ open down ↓ |
267 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX