Print this page
5547 libproc's fake_elf should give up if there's no .hash
5546 libproc's fake_elf may free stack junk when reading corrupt dumps
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libproc/common/Psymtab_machelf32.c
+++ new/usr/src/lib/libproc/common/Psymtab_machelf32.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
20 20 */
21 21
22 22 /*
23 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 #include <assert.h>
28 28 #include <stdio.h>
29 29 #include <stdlib.h>
30 30 #include <stddef.h>
31 31 #include <string.h>
32 32 #include <memory.h>
33 33 #include <sys/sysmacros.h>
34 34 #include <sys/machelf.h>
35 35
36 36 #include "Pcontrol.h"
37 37 #include "Psymtab_machelf.h"
38 38
39 39
40 40 /*
41 41 * This file contains code for use by Psymtab.c that is compiled once
42 42 * for each supported ELFCLASS.
43 43 *
44 44 * When processing ELF files, it is common to encounter a situation where
45 45 * a program with one ELFCLASS (32 or 64-bit) is required to examine a
46 46 * file with a different ELFCLASS. For example, the 32-bit linker (ld) may
47 47 * be used to link a 64-bit program. The simplest solution to this problem
48 48 * is to duplicate each such piece of code, modifying only the data types,
49 49 * and to use if statements to select the code to run. The problem with
50 50 * doing it that way is that the resulting code is difficult to maintain.
51 51 * It is inevitable that the copies will not always get modified identically,
52 52 * and will drift apart. The only robust solution is to generate the
53 53 * multiple instances of code automatically from a single piece of code.
54 54 *
55 55 * The solution used within the Solaris linker is to write the code once,
56 56 * using the data types defined in sys/machelf.h, and then to compile that
57 57 * code twice, once with _ELF64 defined (to generate ELFCLASS64 code) and
58 58 * once without (to generate ELFCLASS32). We use the same approach here.
59 59 *
60 60 * Note that the _ELF64 definition does not refer to the ELFCLASS of
61 61 * the resulting code, but rather, to the ELFCLASS of the data it
62 62 * examines. By repeating the above double-compilation for both 32-bit
63 63 * and 64-bit builds, we end up with 4 instances, which collectively
64 64 * can handle any combination of program and ELF data class:
65 65 *
66 66 * \ Compilation class
67 67 * \ 32 64
68 68 * \------------------
69 69 * |
70 70 * 32 | X X
71 71 * ELF Data Class |
72 72 * 64 | X X
73 73 */
74 74
75 75
76 76
77 77 /*
78 78 * Read data from the specified process and construct an in memory
79 79 * image of an ELF file that will let us use libelf for most of the
80 80 * work we need to later (e.g. symbol table lookups). This is used
81 81 * in cases where no usable on-disk image for the process is available.
82 82 * We need sections for the dynsym, dynstr, and plt, and we need
83 83 * the program headers from the text section. The former is used in
84 84 * Pbuild_file_symtab(); the latter is used in several functions in
85 85 * Pcore.c to reconstruct the origin of each mapping from the load
86 86 * object that spawned it.
87 87 *
88 88 * Here are some useful pieces of elf trivia that will help
89 89 * to elucidate this code.
90 90 *
91 91 * All the information we need about the dynstr can be found in these
92 92 * two entries in the dynamic section:
93 93 *
94 94 * DT_STRTAB base of dynstr
95 95 * DT_STRSZ size of dynstr
96 96 *
97 97 * So deciphering the dynstr is pretty straightforward.
98 98 *
99 99 * The dynsym is a little trickier.
100 100 *
101 101 * DT_SYMTAB base of dynsym
102 102 * DT_SYMENT size of a dynstr entry (Elf{32,64}_Sym)
103 103 * DT_HASH base of hash table for dynamic lookups
104 104 *
105 105 * The DT_SYMTAB entry gives us any easy way of getting to the base
106 106 * of the dynsym, but getting the size involves rooting around in the
107 107 * dynamic lookup hash table. Here's the layout of the hash table:
108 108 *
109 109 * +-------------------+
110 110 * | nbucket | All values are 32-bit
111 111 * +-------------------+ (Elf32_Word or Elf64_Word)
112 112 * | nchain |
113 113 * +-------------------+
114 114 * | bucket[0] |
115 115 * | . . . |
116 116 * | bucket[nbucket-1] |
117 117 * +-------------------+
118 118 * | chain[0] |
119 119 * | . . . |
120 120 * | chain[nchain-1] |
121 121 * +-------------------+
122 122 * (figure 5-12 from the SYS V Generic ABI)
123 123 *
124 124 * Symbols names are hashed into a particular bucket which contains
125 125 * an index into the symbol table. Each entry in the symbol table
126 126 * has a corresponding entry in the chain table which tells the
127 127 * consumer where the next entry in the hash chain is. We can use
128 128 * the nchain field to find out the size of the dynsym.
129 129 *
130 130 * If there is a dynsym present, there may also be an optional
131 131 * section called the SUNW_ldynsym that augments the dynsym by
132 132 * providing local function symbols. When the Solaris linker lays
133 133 * out a file that has both of these sections, it makes sure that
134 134 * the data for the two sections is adjacent with the SUNW_ldynsym
135 135 * in front. This allows the runtime linker to treat these two
136 136 * symbol tables as being a single larger table. There are two
137 137 * items in the dynamic section for this:
138 138 *
139 139 * DT_SUNW_SYMTAB base of the SUNW_ldynsym
140 140 * DT_SUNW_SYMSZ total size of SUNW_ldynsym and dynsym
141 141 * added together. We can figure out the
142 142 * size of the SUNW_ldynsym section by
143 143 * subtracting the size of the dynsym
144 144 * (described above) from this value.
145 145 *
146 146 * We can figure out the size of the .plt section, but it takes some
147 147 * doing. We need to use the following information:
148 148 *
149 149 * DT_PLTGOT GOT PLT entry offset (on x86) or PLT offset (on sparc)
150 150 * DT_JMPREL base of the PLT's relocation section
151 151 * DT_PLTRELSZ size of the PLT's relocation section
152 152 * DT_PLTREL type of the PLT's relocation section
153 153 *
154 154 * We can use the number of relocation entries to calculate the size of
155 155 * the PLT. We get the address of the PLT by looking up the
156 156 * _PROCEDURE_LINKAGE_TABLE_ symbol.
157 157 *
158 158 * For more information, check out the System V Generic ABI.
159 159 */
160 160
161 161
162 162 /*
163 163 * The fake_elfXX() function generated by this file uses the following
164 164 * string as the string table for the section names. Since it is critical
165 165 * to count correctly, and to improve readability, the SHSTR_NDX_ macros
166 166 * supply the proper offset for each name within the string.
167 167 */
168 168 static char shstr[] =
169 169 ".shstrtab\0.dynsym\0.dynstr\0.dynamic\0.plt\0.SUNW_ldynsym";
170 170
171 171 /* Offsets within shstr for each name */
172 172 #define SHSTR_NDX_shstrtab 0
173 173 #define SHSTR_NDX_dynsym 10
174 174 #define SHSTR_NDX_dynstr 18
175 175 #define SHSTR_NDX_dynamic 26
176 176 #define SHSTR_NDX_plt 35
177 177 #define SHSTR_NDX_SUNW_ldynsym 40
178 178
179 179
180 180 /*
181 181 * Section header alignment for 32 and 64-bit ELF files differs
182 182 */
183 183 #ifdef _ELF64
184 184 #define SH_ADDRALIGN 8
185 185 #else
186 186 #define SH_ADDRALIGN 4
187 187 #endif
188 188
189 189 /*
190 190 * This is the smallest number of PLT relocation entries allowed in a proper
191 191 * .plt section.
192 192 */
193 193 #ifdef __sparc
194 194 #define PLTREL_MIN_ENTRIES 4 /* SPARC psABI 3.0 and SCD 2.4 */
195 195 #else
196 196 #ifdef __lint
197 197 /*
198 198 * On x86, lint would complain about unsigned comparison with
199 199 * PLTREL_MIN_ENTRIES. This define fakes up the value of PLTREL_MIN_ENTRIES
200 200 * and silences lint. On SPARC, there is no such issue.
201 201 */
202 202 #define PLTREL_MIN_ENTRIES 1
203 203 #else
204 204 #define PLTREL_MIN_ENTRIES 0
205 205 #endif
206 206 #endif
207 207
208 208 #ifdef _ELF64
209 209 Elf *
210 210 fake_elf64(struct ps_prochandle *P, file_info_t *fptr, uintptr_t addr,
211 211 Ehdr *ehdr, uint_t phnum, Phdr *phdr)
212 212 #else
213 213 Elf *
214 214 fake_elf32(struct ps_prochandle *P, file_info_t *fptr, uintptr_t addr,
215 215 Ehdr *ehdr, uint_t phnum, Phdr *phdr)
216 216 #endif
217 217 {
218 218 enum {
219 219 DI_PLTGOT,
220 220 DI_JMPREL,
221 221 DI_PLTRELSZ,
222 222 DI_PLTREL,
223 223 DI_SYMTAB,
224 224 DI_HASH,
225 225 DI_SYMENT,
226 226 DI_STRTAB,
227 227 DI_STRSZ,
228 228 DI_SUNW_SYMTAB,
229 229 DI_SUNW_SYMSZ,
230 230 DI_NENT
231 231 };
232 232 /*
233 233 * Mask of dynamic options that must be present in a well
234 234 * formed dynamic section. We need all of these in order to
235 235 * put together a complete set of elf sections. They are
236 236 * mandatory in both executables and shared objects so if one
237 237 * of them is missing, we're in some trouble and should abort.
238 238 * The PLT items are expected, but we will let them slide if
239 239 * need be. The DI_SUNW_SYM* items are completely optional, so
240 240 * we use them if they are present and ignore them otherwise.
241 241 */
↓ open down ↓ |
241 lines elided |
↑ open up ↑ |
242 242 const int di_req_mask = (1 << DI_SYMTAB) | (1 << DI_HASH) |
243 243 (1 << DI_SYMENT) | (1 << DI_STRTAB) | (1 << DI_STRSZ);
244 244 int di_mask = 0;
245 245 size_t size = 0;
246 246 caddr_t elfdata = NULL;
247 247 Elf *elf;
248 248 size_t dynsym_size = 0, ldynsym_size;
249 249 int dynstr_shndx;
250 250 Ehdr *ep;
251 251 Shdr *sp;
252 - Dyn *dp;
252 + Dyn *dp = NULL;
253 253 Dyn *d[DI_NENT] = { 0 };
254 254 uint_t i;
255 255 Off off;
256 256 size_t pltsz = 0, pltentries = 0;
257 257 uintptr_t hptr = NULL;
258 258 Word hnchains, hnbuckets;
259 259
260 260 if (ehdr->e_type == ET_DYN)
261 261 phdr->p_vaddr += addr;
262 262
263 263 if (P->rap != NULL) {
264 264 if (rd_get_dyns(P->rap, addr, (void **)&dp, NULL) != RD_OK)
265 265 goto bad;
266 266 } else {
267 267 if ((dp = malloc(phdr->p_filesz)) == NULL)
268 268 goto bad;
269 269 if (Pread(P, dp, phdr->p_filesz, phdr->p_vaddr) !=
270 270 phdr->p_filesz)
271 271 goto bad;
272 272 }
273 273
274 274 /*
275 275 * Iterate over the items in the dynamic section, grabbing
276 276 * the address of items we want and saving them in dp[].
277 277 */
278 278 for (i = 0; i < phdr->p_filesz / sizeof (Dyn); i++) {
279 279 switch (dp[i].d_tag) {
280 280 /* For the .plt section */
281 281 case DT_PLTGOT:
282 282 d[DI_PLTGOT] = &dp[i];
283 283 break;
284 284 case DT_JMPREL:
285 285 d[DI_JMPREL] = &dp[i];
286 286 break;
287 287 case DT_PLTRELSZ:
288 288 d[DI_PLTRELSZ] = &dp[i];
289 289 break;
290 290 case DT_PLTREL:
291 291 d[DI_PLTREL] = &dp[i];
292 292 break;
293 293
294 294 /* For the .dynsym section */
295 295 case DT_SYMTAB:
296 296 d[DI_SYMTAB] = &dp[i];
297 297 di_mask |= (1 << DI_SYMTAB);
298 298 break;
299 299 case DT_HASH:
300 300 d[DI_HASH] = &dp[i];
301 301 di_mask |= (1 << DI_HASH);
302 302 break;
303 303 case DT_SYMENT:
304 304 d[DI_SYMENT] = &dp[i];
305 305 di_mask |= (1 << DI_SYMENT);
306 306 break;
307 307 case DT_SUNW_SYMTAB:
308 308 d[DI_SUNW_SYMTAB] = &dp[i];
309 309 break;
310 310 case DT_SUNW_SYMSZ:
311 311 d[DI_SUNW_SYMSZ] = &dp[i];
312 312 break;
313 313
314 314 /* For the .dynstr section */
315 315 case DT_STRTAB:
316 316 d[DI_STRTAB] = &dp[i];
317 317 di_mask |= (1 << DI_STRTAB);
318 318 break;
319 319 case DT_STRSZ:
320 320 d[DI_STRSZ] = &dp[i];
321 321 di_mask |= (1 << DI_STRSZ);
322 322 break;
323 323 }
324 324 }
325 325
326 326 /* Ensure all required entries were collected */
327 327 if ((di_mask & di_req_mask) != di_req_mask) {
328 328 dprintf("text section missing required dynamic entries\n");
329 329 goto bad;
330 330 }
331 331
332 332 /* SUNW_ldynsym must be adjacent to dynsym. Ignore if not */
333 333 if ((d[DI_SUNW_SYMTAB] != NULL) && (d[DI_SUNW_SYMSZ] != NULL) &&
334 334 ((d[DI_SYMTAB]->d_un.d_ptr <= d[DI_SUNW_SYMTAB]->d_un.d_ptr) ||
335 335 (d[DI_SYMTAB]->d_un.d_ptr >= (d[DI_SUNW_SYMTAB]->d_un.d_ptr +
336 336 d[DI_SUNW_SYMSZ]->d_un.d_val)))) {
337 337 d[DI_SUNW_SYMTAB] = NULL;
338 338 d[DI_SUNW_SYMSZ] = NULL;
339 339 }
340 340
341 341 /* elf header */
342 342 size = sizeof (Ehdr);
343 343
344 344 /* program headers from in-core elf fragment */
345 345 size += phnum * ehdr->e_phentsize;
346 346
347 347 /* unused shdr, and .shstrtab section */
348 348 size += sizeof (Shdr);
349 349 size += sizeof (Shdr);
350 350 size += roundup(sizeof (shstr), SH_ADDRALIGN);
351 351
352 352 if (d[DI_HASH] != NULL) {
353 353 Word hash[2];
354 354
355 355 hptr = d[DI_HASH]->d_un.d_ptr;
356 356 if (ehdr->e_type == ET_DYN)
357 357 hptr += addr;
358 358
↓ open down ↓ |
96 lines elided |
↑ open up ↑ |
359 359 if (Pread(P, hash, sizeof (hash), hptr) != sizeof (hash)) {
360 360 dprintf("Pread of .hash at %lx failed\n",
361 361 (long)(hptr));
362 362 goto bad;
363 363 }
364 364
365 365 hnbuckets = hash[0];
366 366 hnchains = hash[1];
367 367 }
368 368
369 + if ((d[DI_HASH] == NULL) || (hnbuckets == 0) || (hnchains == 0)) {
370 + dprintf("empty or missing .hash\n");
371 + goto bad;
372 + }
373 +
369 374 /*
370 375 * .dynsym and .SUNW_ldynsym sections.
371 376 *
372 377 * The string table section used for the symbol table and
373 378 * dynamic sections lies immediately after the dynsym, so the
374 379 * presence of SUNW_ldynsym changes the dynstr section index.
375 380 */
376 381 if (d[DI_SUNW_SYMTAB] != NULL) {
377 382 size += sizeof (Shdr); /* SUNW_ldynsym shdr */
378 383 ldynsym_size = (size_t)d[DI_SUNW_SYMSZ]->d_un.d_val;
379 384 dynsym_size = ldynsym_size - (d[DI_SYMTAB]->d_un.d_ptr
380 385 - d[DI_SUNW_SYMTAB]->d_un.d_ptr);
381 386 ldynsym_size -= dynsym_size;
382 387 dynstr_shndx = 4;
383 388 } else {
384 389 dynsym_size = sizeof (Sym) * hnchains;
385 390 ldynsym_size = 0;
386 391 dynstr_shndx = 3;
387 392 }
388 393 size += sizeof (Shdr) + ldynsym_size + dynsym_size;
389 394
390 395 /* .dynstr section */
391 396 size += sizeof (Shdr);
392 397 size += roundup(d[DI_STRSZ]->d_un.d_val, SH_ADDRALIGN);
393 398
394 399 /* .dynamic section */
395 400 size += sizeof (Shdr);
396 401 size += roundup(phdr->p_filesz, SH_ADDRALIGN);
397 402
398 403 /* .plt section */
399 404 if (d[DI_PLTGOT] != NULL && d[DI_JMPREL] != NULL &&
400 405 d[DI_PLTRELSZ] != NULL && d[DI_PLTREL] != NULL) {
401 406 size_t pltrelsz = d[DI_PLTRELSZ]->d_un.d_val;
402 407
403 408 if (d[DI_PLTREL]->d_un.d_val == DT_RELA) {
404 409 pltentries = pltrelsz / sizeof (Rela);
405 410 } else if (d[DI_PLTREL]->d_un.d_val == DT_REL) {
406 411 pltentries = pltrelsz / sizeof (Rel);
407 412 } else {
408 413 /* fall back to the platform default */
409 414 #if ((defined(__i386) || defined(__amd64)) && !defined(_ELF64))
410 415 pltentries = pltrelsz / sizeof (Rel);
411 416 dprintf("DI_PLTREL not found, defaulting to Rel");
412 417 #else /* (!(__i386 || __amd64)) || _ELF64 */
413 418 pltentries = pltrelsz / sizeof (Rela);
414 419 dprintf("DI_PLTREL not found, defaulting to Rela");
415 420 #endif /* (!(__i386 || __amd64) || _ELF64 */
416 421 }
417 422
418 423 if (pltentries < PLTREL_MIN_ENTRIES) {
419 424 dprintf("too few PLT relocation entries "
420 425 "(found %lu, expected at least %d)\n",
421 426 (long)pltentries, PLTREL_MIN_ENTRIES);
422 427 goto bad;
423 428 }
424 429 if (pltentries < PLTREL_MIN_ENTRIES + 2)
425 430 goto done_with_plt;
426 431
427 432 /*
428 433 * Now that we know the number of plt relocation entries
429 434 * we can calculate the size of the plt.
430 435 */
431 436 pltsz = (pltentries + M_PLT_XNumber) * M_PLT_ENTSIZE;
432 437 #if defined(__sparc)
433 438 /* The sparc PLT always has a (delay slot) nop at the end */
434 439 pltsz += 4;
435 440 #endif /* __sparc */
436 441
437 442 size += sizeof (Shdr);
438 443 size += roundup(pltsz, SH_ADDRALIGN);
439 444 }
440 445 done_with_plt:
441 446
442 447 if ((elfdata = calloc(1, size)) == NULL)
443 448 goto bad;
444 449
445 450 /* LINTED - alignment */
446 451 ep = (Ehdr *)elfdata;
447 452 (void) memcpy(ep, ehdr, offsetof(Ehdr, e_phoff));
448 453
449 454 ep->e_ehsize = sizeof (Ehdr);
450 455 ep->e_phoff = sizeof (Ehdr);
451 456 ep->e_phentsize = ehdr->e_phentsize;
452 457 ep->e_phnum = phnum;
453 458 ep->e_shoff = ep->e_phoff + phnum * ep->e_phentsize;
454 459 ep->e_shentsize = sizeof (Shdr);
455 460 /*
456 461 * Plt and SUNW_ldynsym sections are optional. C logical
457 462 * binary operators return a 0 or 1 value, so the following
458 463 * adds 1 for each optional section present.
459 464 */
460 465 ep->e_shnum = 5 + (pltsz != 0) + (d[DI_SUNW_SYMTAB] != NULL);
461 466 ep->e_shstrndx = 1;
462 467
463 468 /* LINTED - alignment */
464 469 sp = (Shdr *)(elfdata + ep->e_shoff);
465 470 off = ep->e_shoff + ep->e_shentsize * ep->e_shnum;
466 471
467 472 /*
468 473 * Copying the program headers directly from the process's
469 474 * address space is a little suspect, but since we only
470 475 * use them for their address and size values, this is fine.
471 476 */
472 477 if (Pread(P, &elfdata[ep->e_phoff], phnum * ep->e_phentsize,
473 478 addr + ehdr->e_phoff) != phnum * ep->e_phentsize) {
474 479 dprintf("failed to read program headers\n");
475 480 goto bad;
476 481 }
477 482
478 483 /*
479 484 * The first elf section is always skipped.
480 485 */
481 486 sp++;
482 487
483 488 /*
484 489 * Section Header: .shstrtab
485 490 */
486 491 sp->sh_name = SHSTR_NDX_shstrtab;
487 492 sp->sh_type = SHT_STRTAB;
488 493 sp->sh_flags = SHF_STRINGS;
489 494 sp->sh_addr = 0;
490 495 sp->sh_offset = off;
491 496 sp->sh_size = sizeof (shstr);
492 497 sp->sh_link = 0;
493 498 sp->sh_info = 0;
494 499 sp->sh_addralign = 1;
495 500 sp->sh_entsize = 0;
496 501
497 502 (void) memcpy(&elfdata[off], shstr, sizeof (shstr));
498 503 off += roundup(sp->sh_size, SH_ADDRALIGN);
499 504 sp++;
500 505
501 506 /*
502 507 * Section Header: .SUNW_ldynsym
503 508 */
504 509 if (d[DI_SUNW_SYMTAB] != NULL) {
505 510 sp->sh_name = SHSTR_NDX_SUNW_ldynsym;
506 511 sp->sh_type = SHT_SUNW_LDYNSYM;
507 512 sp->sh_flags = SHF_ALLOC;
508 513 sp->sh_addr = d[DI_SUNW_SYMTAB]->d_un.d_ptr;
509 514 if (ehdr->e_type == ET_DYN)
510 515 sp->sh_addr += addr;
511 516 sp->sh_offset = off;
512 517 sp->sh_size = ldynsym_size;
513 518 sp->sh_link = dynstr_shndx;
514 519 /* Index of 1st global in table that has none == # items */
515 520 sp->sh_info = sp->sh_size / sizeof (Sym);
516 521 sp->sh_addralign = SH_ADDRALIGN;
517 522 sp->sh_entsize = sizeof (Sym);
518 523
519 524 if (Pread(P, &elfdata[off], sp->sh_size,
520 525 sp->sh_addr) != sp->sh_size) {
521 526 dprintf("failed to read .SUNW_ldynsym at %lx\n",
522 527 (long)sp->sh_addr);
523 528 goto bad;
524 529 }
525 530 off += sp->sh_size;
526 531 /* No need to round up ldynsym data. Dynsym data is same type */
527 532 sp++;
528 533 }
529 534
530 535 /*
531 536 * Section Header: .dynsym
532 537 */
533 538 sp->sh_name = SHSTR_NDX_dynsym;
534 539 sp->sh_type = SHT_DYNSYM;
535 540 sp->sh_flags = SHF_ALLOC;
536 541 sp->sh_addr = d[DI_SYMTAB]->d_un.d_ptr;
537 542 if (ehdr->e_type == ET_DYN)
538 543 sp->sh_addr += addr;
539 544 sp->sh_offset = off;
540 545 sp->sh_size = dynsym_size;
541 546 sp->sh_link = dynstr_shndx;
542 547 sp->sh_info = 1; /* Index of 1st global in table */
543 548 sp->sh_addralign = SH_ADDRALIGN;
544 549 sp->sh_entsize = sizeof (Sym);
545 550
546 551 if (Pread(P, &elfdata[off], sp->sh_size,
547 552 sp->sh_addr) != sp->sh_size) {
548 553 dprintf("failed to read .dynsym at %lx\n",
549 554 (long)sp->sh_addr);
550 555 goto bad;
551 556 }
552 557
553 558 off += roundup(sp->sh_size, SH_ADDRALIGN);
554 559 sp++;
555 560
556 561 /*
557 562 * Section Header: .dynstr
558 563 */
559 564 sp->sh_name = SHSTR_NDX_dynstr;
560 565 sp->sh_type = SHT_STRTAB;
561 566 sp->sh_flags = SHF_ALLOC | SHF_STRINGS;
562 567 sp->sh_addr = d[DI_STRTAB]->d_un.d_ptr;
563 568 if (ehdr->e_type == ET_DYN)
564 569 sp->sh_addr += addr;
565 570 sp->sh_offset = off;
566 571 sp->sh_size = d[DI_STRSZ]->d_un.d_val;
567 572 sp->sh_link = 0;
568 573 sp->sh_info = 0;
569 574 sp->sh_addralign = 1;
570 575 sp->sh_entsize = 0;
571 576
572 577 if (Pread(P, &elfdata[off], sp->sh_size,
573 578 sp->sh_addr) != sp->sh_size) {
574 579 dprintf("failed to read .dynstr\n");
575 580 goto bad;
576 581 }
577 582 off += roundup(sp->sh_size, SH_ADDRALIGN);
578 583 sp++;
579 584
580 585 /*
581 586 * Section Header: .dynamic
582 587 */
583 588 sp->sh_name = SHSTR_NDX_dynamic;
584 589 sp->sh_type = SHT_DYNAMIC;
585 590 sp->sh_flags = SHF_WRITE | SHF_ALLOC;
586 591 sp->sh_addr = phdr->p_vaddr;
587 592 if (ehdr->e_type == ET_DYN)
588 593 sp->sh_addr -= addr;
589 594 sp->sh_offset = off;
590 595 sp->sh_size = phdr->p_filesz;
591 596 sp->sh_link = dynstr_shndx;
592 597 sp->sh_info = 0;
593 598 sp->sh_addralign = SH_ADDRALIGN;
594 599 sp->sh_entsize = sizeof (Dyn);
595 600
596 601 (void) memcpy(&elfdata[off], dp, sp->sh_size);
597 602 off += roundup(sp->sh_size, SH_ADDRALIGN);
598 603 sp++;
599 604
600 605 /*
601 606 * Section Header: .plt
602 607 */
603 608 if (pltsz != 0) {
604 609 ulong_t plt_symhash;
605 610 uint_t htmp, ndx;
606 611 uintptr_t strtabptr, strtabname;
607 612 Sym sym, *symtabptr;
608 613 uint_t *hash;
609 614 char strbuf[sizeof ("_PROCEDURE_LINKAGE_TABLE_")];
610 615
611 616 /*
612 617 * Now we need to find the address of the plt by looking
613 618 * up the "_PROCEDURE_LINKAGE_TABLE_" symbol.
614 619 */
615 620
616 621 /* get the address of the symtab and strtab sections */
617 622 strtabptr = d[DI_STRTAB]->d_un.d_ptr;
618 623 symtabptr = (Sym *)(uintptr_t)d[DI_SYMTAB]->d_un.d_ptr;
619 624 if (ehdr->e_type == ET_DYN) {
620 625 strtabptr += addr;
621 626 symtabptr = (Sym*)((uintptr_t)symtabptr + addr);
622 627 }
623 628
624 629 /* find the .hash bucket address for this symbol */
625 630 plt_symhash = elf_hash("_PROCEDURE_LINKAGE_TABLE_");
626 631 htmp = plt_symhash % hnbuckets;
627 632 hash = &((uint_t *)hptr)[2 + htmp];
628 633
629 634 /* read the elf hash bucket index */
630 635 if (Pread(P, &ndx, sizeof (ndx), (uintptr_t)hash) !=
631 636 sizeof (ndx)) {
632 637 dprintf("Pread of .hash at %lx failed\n", (long)hash);
633 638 goto bad;
634 639 }
635 640
636 641 while (ndx) {
637 642 if (Pread(P, &sym, sizeof (sym),
638 643 (uintptr_t)&symtabptr[ndx]) != sizeof (sym)) {
639 644 dprintf("Pread of .symtab at %lx failed\n",
640 645 (long)&symtabptr[ndx]);
641 646 goto bad;
642 647 }
643 648
644 649 strtabname = strtabptr + sym.st_name;
645 650 if (Pread_string(P, strbuf, sizeof (strbuf),
646 651 strtabname) < 0) {
647 652 dprintf("Pread of .strtab at %lx failed\n",
648 653 (long)strtabname);
649 654 goto bad;
650 655 }
651 656
652 657 if (strcmp("_PROCEDURE_LINKAGE_TABLE_", strbuf) == 0)
653 658 break;
654 659
655 660 hash = &((uint_t *)hptr)[2 + hnbuckets + ndx];
656 661 if (Pread(P, &ndx, sizeof (ndx), (uintptr_t)hash) !=
657 662 sizeof (ndx)) {
658 663 dprintf("Pread of .hash at %lx failed\n",
659 664 (long)hash);
660 665 goto bad;
661 666 }
662 667 }
663 668
664 669 #if defined(__sparc)
665 670 if (sym.st_value != d[DI_PLTGOT]->d_un.d_ptr) {
666 671 dprintf("warning: DI_PLTGOT (%lx) doesn't match "
667 672 ".plt symbol pointer (%lx)",
668 673 (long)d[DI_PLTGOT]->d_un.d_ptr,
669 674 (long)sym.st_value);
670 675 }
671 676 #endif /* __sparc */
672 677
673 678 if (ndx == 0) {
674 679 dprintf(
675 680 "Failed to find \"_PROCEDURE_LINKAGE_TABLE_\"\n");
676 681 goto bad;
677 682 }
678 683
679 684 sp->sh_name = SHSTR_NDX_plt;
680 685 sp->sh_type = SHT_PROGBITS;
681 686 sp->sh_flags = SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR;
682 687 sp->sh_addr = sym.st_value;
683 688 if (ehdr->e_type == ET_DYN)
684 689 sp->sh_addr += addr;
685 690 sp->sh_offset = off;
686 691 sp->sh_size = pltsz;
687 692 sp->sh_link = 0;
688 693 sp->sh_info = 0;
689 694 sp->sh_addralign = SH_ADDRALIGN;
690 695 sp->sh_entsize = M_PLT_ENTSIZE;
691 696
692 697 if (Pread(P, &elfdata[off], sp->sh_size, sp->sh_addr) !=
693 698 sp->sh_size) {
694 699 dprintf("failed to read .plt at %lx\n",
695 700 (long)sp->sh_addr);
696 701 goto bad;
697 702 }
698 703 off += roundup(sp->sh_size, SH_ADDRALIGN);
699 704 sp++;
700 705 }
701 706
702 707 /* make sure we didn't write past the end of allocated memory */
703 708 sp++;
704 709 assert(((uintptr_t)(sp) - 1) < ((uintptr_t)elfdata + size));
705 710
706 711 free(dp);
707 712 if ((elf = elf_memory(elfdata, size)) == NULL) {
708 713 free(elfdata);
709 714 return (NULL);
710 715 }
711 716
712 717 fptr->file_elfmem = elfdata;
713 718
714 719 return (elf);
715 720
716 721 bad:
717 722 if (dp != NULL)
718 723 free(dp);
719 724 if (elfdata != NULL)
720 725 free(elfdata);
721 726 return (NULL);
722 727 }
↓ open down ↓ |
344 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX