Print this page
smatch clean rtld
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/sgs/rtld/i386/i386_elf.c
+++ new/usr/src/cmd/sgs/rtld/i386/i386_elf.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 (c) 1988 AT&T
24 24 * All Rights Reserved
25 25 *
26 26 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
27 27 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
28 28 */
29 29
30 30 /*
31 31 * x86 machine dependent and ELF file class dependent functions.
32 32 * Contains routines for performing function binding and symbol relocations.
33 33 */
34 34
35 35 #include <stdio.h>
36 36 #include <sys/elf.h>
37 37 #include <sys/elf_386.h>
38 38 #include <sys/mman.h>
39 39 #include <dlfcn.h>
40 40 #include <synch.h>
41 41 #include <string.h>
42 42 #include <debug.h>
43 43 #include <reloc.h>
44 44 #include <conv.h>
45 45 #include "_rtld.h"
46 46 #include "_audit.h"
47 47 #include "_elf.h"
48 48 #include "_inline_gen.h"
49 49 #include "_inline_reloc.h"
50 50 #include "msg.h"
51 51
52 52 extern void elf_rtbndr(Rt_map *, ulong_t, caddr_t);
53 53
54 54 int
55 55 elf_mach_flags_check(Rej_desc *rej, Ehdr *ehdr)
56 56 {
57 57 /*
58 58 * Check machine type and flags.
59 59 */
60 60 if (ehdr->e_flags != 0) {
61 61 rej->rej_type = SGS_REJ_BADFLAG;
62 62 rej->rej_info = (uint_t)ehdr->e_flags;
63 63 return (0);
64 64 }
65 65 return (1);
66 66 }
67 67
68 68 void
69 69 ldso_plt_init(Rt_map *lmp)
70 70 {
71 71 /*
72 72 * There is no need to analyze ld.so because we don't map in any of
73 73 * its dependencies. However we may map these dependencies in later
74 74 * (as if ld.so had dlopened them), so initialize the plt and the
75 75 * permission information.
76 76 */
77 77 if (PLTGOT(lmp))
78 78 elf_plt_init((PLTGOT(lmp)), (caddr_t)lmp);
79 79 }
80 80
81 81 static const uchar_t dyn_plt_template[] = {
82 82 /* 0x00 */ 0x55, /* pushl %ebp */
83 83 /* 0x01 */ 0x8b, 0xec, /* movl %esp, %ebp */
84 84 /* 0x03 */ 0x68, 0x00, 0x00, 0x00, 0x00, /* pushl trace_fields */
85 85 /* 0x08 */ 0xe9, 0xfc, 0xff, 0xff, 0xff, 0xff /* jmp elf_plt_trace */
86 86 };
87 87 int dyn_plt_ent_size = sizeof (dyn_plt_template);
88 88
89 89 /*
90 90 * the dynamic plt entry is:
91 91 *
92 92 * pushl %ebp
93 93 * movl %esp, %ebp
94 94 * pushl tfp
95 95 * jmp elf_plt_trace
96 96 * dyn_data:
97 97 * .align 4
98 98 * uintptr_t reflmp
99 99 * uintptr_t deflmp
100 100 * uint_t symndx
101 101 * uint_t sb_flags
102 102 * Sym symdef
103 103 */
104 104 static caddr_t
105 105 elf_plt_trace_write(uint_t roffset, Rt_map *rlmp, Rt_map *dlmp, Sym *sym,
106 106 uint_t symndx, uint_t pltndx, caddr_t to, uint_t sb_flags, int *fail)
107 107 {
108 108 extern int elf_plt_trace();
109 109 ulong_t got_entry;
110 110 uchar_t *dyn_plt;
111 111 uintptr_t *dyndata;
112 112
113 113 /*
114 114 * We only need to add the glue code if there is an auditing
115 115 * library that is interested in this binding.
116 116 */
117 117 dyn_plt = (uchar_t *)((uintptr_t)AUDINFO(rlmp)->ai_dynplts +
118 118 (pltndx * dyn_plt_ent_size));
119 119
120 120 /*
121 121 * Have we initialized this dynamic plt entry yet? If we haven't do it
122 122 * now. Otherwise this function has been called before, but from a
123 123 * different plt (ie. from another shared object). In that case
124 124 * we just set the plt to point to the new dyn_plt.
125 125 */
126 126 if (*dyn_plt == 0) {
127 127 Sym *symp;
128 128 Word symvalue;
129 129 Lm_list *lml = LIST(rlmp);
130 130
131 131 (void) memcpy((void *)dyn_plt, dyn_plt_template,
132 132 sizeof (dyn_plt_template));
133 133 dyndata = (uintptr_t *)((uintptr_t)dyn_plt +
134 134 ROUND(sizeof (dyn_plt_template), M_WORD_ALIGN));
135 135
136 136 /*
137 137 * relocate:
138 138 * pushl dyn_data
139 139 */
140 140 symvalue = (Word)dyndata;
141 141 if (do_reloc_rtld(R_386_32, &dyn_plt[4], &symvalue,
142 142 MSG_ORIG(MSG_SYM_LADYNDATA),
143 143 MSG_ORIG(MSG_SPECFIL_DYNPLT), lml) == 0) {
144 144 *fail = 1;
145 145 return (0);
146 146 }
147 147
148 148 /*
149 149 * jmps are relative, so I need to figure out the relative
150 150 * address to elf_plt_trace.
151 151 *
152 152 * relocating:
153 153 * jmp elf_plt_trace
154 154 */
155 155 symvalue = (ulong_t)(elf_plt_trace) - (ulong_t)(dyn_plt + 9);
156 156 if (do_reloc_rtld(R_386_PC32, &dyn_plt[9], &symvalue,
157 157 MSG_ORIG(MSG_SYM_ELFPLTTRACE),
158 158 MSG_ORIG(MSG_SPECFIL_DYNPLT), lml) == 0) {
159 159 *fail = 1;
160 160 return (0);
161 161 }
162 162
163 163 *dyndata++ = (uintptr_t)rlmp;
164 164 *dyndata++ = (uintptr_t)dlmp;
165 165 *dyndata++ = (uint_t)symndx;
166 166 *dyndata++ = (uint_t)sb_flags;
167 167 symp = (Sym *)dyndata;
168 168 *symp = *sym;
169 169 symp->st_name += (Word)STRTAB(dlmp);
170 170 symp->st_value = (Addr)to;
171 171 }
172 172
173 173 got_entry = (ulong_t)roffset;
174 174 *(ulong_t *)got_entry = (ulong_t)dyn_plt;
175 175 return ((caddr_t)dyn_plt);
176 176 }
177 177
178 178 /*
179 179 * Function binding routine - invoked on the first call to a function through
180 180 * the procedure linkage table;
181 181 * passes first through an assembly language interface.
182 182 *
183 183 * Takes the offset into the relocation table of the associated
184 184 * relocation entry and the address of the link map (rt_private_map struct)
185 185 * for the entry.
186 186 *
187 187 * Returns the address of the function referenced after re-writing the PLT
188 188 * entry to invoke the function directly.
189 189 *
190 190 * On error, causes process to terminate with a signal.
191 191 */
192 192 ulong_t
193 193 elf_bndr(Rt_map *lmp, ulong_t reloff, caddr_t from)
194 194 {
195 195 Rt_map *nlmp, *llmp;
196 196 ulong_t addr, symval, rsymndx;
197 197 char *name;
198 198 Rel *rptr;
199 199 Sym *rsym, *nsym;
200 200 uint_t binfo, sb_flags = 0, dbg_class;
201 201 Slookup sl;
202 202 Sresult sr;
203 203 int entry, lmflags;
204 204 Lm_list *lml;
205 205
206 206 /*
207 207 * For compatibility with libthread (TI_VERSION 1) we track the entry
208 208 * value. A zero value indicates we have recursed into ld.so.1 to
209 209 * further process a locking request. Under this recursion we disable
210 210 * tsort and cleanup activities.
211 211 */
212 212 entry = enter(0);
213 213
214 214 lml = LIST(lmp);
↓ open down ↓ |
214 lines elided |
↑ open up ↑ |
215 215 if ((lmflags = lml->lm_flags) & LML_FLG_RTLDLM) {
216 216 dbg_class = dbg_desc->d_class;
217 217 dbg_desc->d_class = 0;
218 218 }
219 219
220 220 /*
221 221 * Perform some basic sanity checks. If we didn't get a load map or
222 222 * the relocation offset is invalid then its possible someone has walked
223 223 * over the .got entries or jumped to plt0 out of the blue.
224 224 */
225 - if (!lmp || ((reloff % sizeof (Rel)) != 0)) {
225 + if ((reloff % sizeof (Rel)) != 0) {
226 226 Conv_inv_buf_t inv_buf;
227 227
228 228 eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_PLTREF),
229 229 conv_reloc_386_type(R_386_JMP_SLOT, 0, &inv_buf),
230 230 EC_NATPTR(lmp), EC_XWORD(reloff), EC_NATPTR(from));
231 231 rtldexit(lml, 1);
232 232 }
233 233
234 234 /*
235 235 * Use relocation entry to get symbol table entry and symbol name.
236 236 */
237 237 addr = (ulong_t)JMPREL(lmp);
238 238 rptr = (Rel *)(addr + reloff);
239 239 rsymndx = ELF_R_SYM(rptr->r_info);
240 240 rsym = (Sym *)((ulong_t)SYMTAB(lmp) + (rsymndx * SYMENT(lmp)));
241 241 name = (char *)(STRTAB(lmp) + rsym->st_name);
242 242
243 243 /*
244 244 * Determine the last link-map of this list, this'll be the starting
245 245 * point for any tsort() processing.
246 246 */
247 247 llmp = lml->lm_tail;
248 248
249 249 /*
250 250 * Find definition for symbol. Initialize the symbol lookup, and
251 251 * symbol result, data structures.
252 252 */
253 253 SLOOKUP_INIT(sl, name, lmp, lml->lm_head, ld_entry_cnt, 0,
254 254 rsymndx, rsym, 0, LKUP_DEFT);
255 255 SRESULT_INIT(sr, name);
256 256
257 257 if (lookup_sym(&sl, &sr, &binfo, NULL) == 0) {
258 258 eprintf(lml, ERR_FATAL, MSG_INTL(MSG_REL_NOSYM), NAME(lmp),
259 259 demangle(name));
260 260 rtldexit(lml, 1);
261 261 }
262 262
263 263 name = (char *)sr.sr_name;
264 264 nlmp = sr.sr_dmap;
265 265 nsym = sr.sr_sym;
266 266
267 267 symval = nsym->st_value;
268 268
269 269 if (!(FLAGS(nlmp) & FLG_RT_FIXED) &&
270 270 (nsym->st_shndx != SHN_ABS))
271 271 symval += ADDR(nlmp);
272 272 if ((lmp != nlmp) && ((FLAGS1(nlmp) & FL1_RT_NOINIFIN) == 0)) {
273 273 /*
274 274 * Record that this new link map is now bound to the caller.
275 275 */
276 276 if (bind_one(lmp, nlmp, BND_REFER) == 0)
277 277 rtldexit(lml, 1);
278 278 }
279 279
280 280 if ((lml->lm_tflags | AFLAGS(lmp) | AFLAGS(nlmp)) &
281 281 LML_TFLG_AUD_SYMBIND) {
282 282 uint_t symndx = (((uintptr_t)nsym -
283 283 (uintptr_t)SYMTAB(nlmp)) / SYMENT(nlmp));
284 284 symval = audit_symbind(lmp, nlmp, nsym, symndx, symval,
285 285 &sb_flags);
286 286 }
287 287
288 288 if (!(rtld_flags & RT_FL_NOBIND)) {
289 289 addr = rptr->r_offset;
290 290 if (!(FLAGS(lmp) & FLG_RT_FIXED))
291 291 addr += ADDR(lmp);
292 292 if (((lml->lm_tflags | AFLAGS(lmp)) &
293 293 (LML_TFLG_AUD_PLTENTER | LML_TFLG_AUD_PLTEXIT)) &&
294 294 AUDINFO(lmp)->ai_dynplts) {
295 295 int fail = 0;
296 296 uint_t pltndx = reloff / sizeof (Rel);
297 297 uint_t symndx = (((uintptr_t)nsym -
298 298 (uintptr_t)SYMTAB(nlmp)) / SYMENT(nlmp));
299 299
300 300 symval = (ulong_t)elf_plt_trace_write(addr, lmp, nlmp,
301 301 nsym, symndx, pltndx, (caddr_t)symval, sb_flags,
302 302 &fail);
303 303 if (fail)
304 304 rtldexit(lml, 1);
305 305 } else {
306 306 /*
307 307 * Write standard PLT entry to jump directly
308 308 * to newly bound function.
309 309 */
310 310 *(ulong_t *)addr = symval;
311 311 }
312 312 }
313 313
314 314 /*
315 315 * Print binding information and rebuild PLT entry.
316 316 */
317 317 DBG_CALL(Dbg_bind_global(lmp, (Addr)from, (Off)(from - ADDR(lmp)),
318 318 (Xword)(reloff / sizeof (Rel)), PLT_T_FULL, nlmp, (Addr)symval,
319 319 nsym->st_value, name, binfo));
320 320
321 321 /*
322 322 * Complete any processing for newly loaded objects. Note we don't
323 323 * know exactly where any new objects are loaded (we know the object
324 324 * that supplied the symbol, but others may have been loaded lazily as
325 325 * we searched for the symbol), so sorting starts from the last
326 326 * link-map know on entry to this routine.
327 327 */
328 328 if (entry)
329 329 load_completion(llmp);
330 330
331 331 /*
332 332 * Some operations like dldump() or dlopen()'ing a relocatable object
333 333 * result in objects being loaded on rtld's link-map, make sure these
334 334 * objects are initialized also.
335 335 */
336 336 if ((LIST(nlmp)->lm_flags & LML_FLG_RTLDLM) && LIST(nlmp)->lm_init)
337 337 load_completion(nlmp);
338 338
339 339 /*
340 340 * Make sure the object to which we've bound has had it's .init fired.
341 341 * Cleanup before return to user code.
342 342 */
343 343 if (entry) {
344 344 is_dep_init(nlmp, lmp);
345 345 leave(lml, 0);
346 346 }
347 347
348 348 if (lmflags & LML_FLG_RTLDLM)
349 349 dbg_desc->d_class = dbg_class;
350 350
351 351 return (symval);
352 352 }
353 353
354 354 /*
355 355 * Read and process the relocations for one link object, we assume all
356 356 * relocation sections for loadable segments are stored contiguously in
357 357 * the file.
358 358 */
359 359 int
360 360 elf_reloc(Rt_map *lmp, uint_t plt, int *in_nfavl, APlist **textrel)
361 361 {
362 362 ulong_t relbgn, relend, relsiz, basebgn, pltbgn, pltend;
363 363 ulong_t _pltbgn, _pltend;
364 364 ulong_t dsymndx, roffset, rsymndx, psymndx = 0;
365 365 uchar_t rtype;
366 366 long value, pvalue;
367 367 Sym *symref, *psymref, *symdef, *psymdef;
368 368 Syminfo *sip;
369 369 char *name, *pname;
370 370 Rt_map *_lmp, *plmp;
371 371 int ret = 1, noplt = 0;
372 372 int relacount = RELACOUNT(lmp), plthint = 0;
373 373 Rel *rel;
374 374 uint_t binfo, pbinfo;
375 375 APlist *bound = NULL;
376 376
377 377 /*
378 378 * Although only necessary for lazy binding, initialize the first
379 379 * global offset entry to go to elf_rtbndr(). dbx(1) seems
380 380 * to find this useful.
381 381 */
382 382 if ((plt == 0) && PLTGOT(lmp)) {
383 383 mmapobj_result_t *mpp;
384 384
385 385 /*
386 386 * Make sure the segment is writable.
387 387 */
388 388 if ((((mpp =
389 389 find_segment((caddr_t)PLTGOT(lmp), lmp)) != NULL) &&
390 390 ((mpp->mr_prot & PROT_WRITE) == 0)) &&
391 391 ((set_prot(lmp, mpp, 1) == 0) ||
392 392 (aplist_append(textrel, mpp, AL_CNT_TEXTREL) == NULL)))
393 393 return (0);
394 394
395 395 elf_plt_init(PLTGOT(lmp), (caddr_t)lmp);
396 396 }
397 397
398 398 /*
399 399 * Initialize the plt start and end addresses.
400 400 */
401 401 if ((pltbgn = (ulong_t)JMPREL(lmp)) != 0)
402 402 pltend = pltbgn + (ulong_t)(PLTRELSZ(lmp));
403 403
404 404 relsiz = (ulong_t)(RELENT(lmp));
405 405 basebgn = ADDR(lmp);
406 406
407 407 if (PLTRELSZ(lmp))
408 408 plthint = PLTRELSZ(lmp) / relsiz;
409 409
410 410 /*
411 411 * If we've been called upon to promote an RTLD_LAZY object to an
412 412 * RTLD_NOW then we're only interested in scaning the .plt table.
413 413 * An uninitialized .plt is the case where the associated got entry
414 414 * points back to the plt itself. Determine the range of the real .plt
415 415 * entries using the _PROCEDURE_LINKAGE_TABLE_ symbol.
416 416 */
417 417 if (plt) {
418 418 Slookup sl;
419 419 Sresult sr;
420 420
421 421 relbgn = pltbgn;
422 422 relend = pltend;
423 423 if (!relbgn || (relbgn == relend))
424 424 return (1);
425 425
426 426 /*
427 427 * Initialize the symbol lookup, and symbol result, data
428 428 * structures.
429 429 */
430 430 SLOOKUP_INIT(sl, MSG_ORIG(MSG_SYM_PLT), lmp, lmp, ld_entry_cnt,
431 431 elf_hash(MSG_ORIG(MSG_SYM_PLT)), 0, 0, 0, LKUP_DEFT);
432 432 SRESULT_INIT(sr, MSG_ORIG(MSG_SYM_PLT));
433 433
434 434 if (elf_find_sym(&sl, &sr, &binfo, NULL) == 0)
435 435 return (1);
436 436
437 437 symdef = sr.sr_sym;
438 438 _pltbgn = symdef->st_value;
439 439 if (!(FLAGS(lmp) & FLG_RT_FIXED) &&
440 440 (symdef->st_shndx != SHN_ABS))
441 441 _pltbgn += basebgn;
442 442 _pltend = _pltbgn + (((PLTRELSZ(lmp) / relsiz)) *
443 443 M_PLT_ENTSIZE) + M_PLT_RESERVSZ;
444 444
445 445 } else {
446 446 /*
447 447 * The relocation sections appear to the run-time linker as a
448 448 * single table. Determine the address of the beginning and end
449 449 * of this table. There are two different interpretations of
450 450 * the ABI at this point:
451 451 *
452 452 * o The REL table and its associated RELSZ indicate the
453 453 * concatenation of *all* relocation sections (this is the
454 454 * model our link-editor constructs).
455 455 *
456 456 * o The REL table and its associated RELSZ indicate the
457 457 * concatenation of all *but* the .plt relocations. These
458 458 * relocations are specified individually by the JMPREL and
459 459 * PLTRELSZ entries.
460 460 *
461 461 * Determine from our knowledege of the relocation range and
462 462 * .plt range, the range of the total relocation table. Note
463 463 * that one other ABI assumption seems to be that the .plt
464 464 * relocations always follow any other relocations, the
465 465 * following range checking drops that assumption.
466 466 */
467 467 relbgn = (ulong_t)(REL(lmp));
468 468 relend = relbgn + (ulong_t)(RELSZ(lmp));
469 469 if (pltbgn) {
470 470 if (!relbgn || (relbgn > pltbgn))
471 471 relbgn = pltbgn;
472 472 if (!relbgn || (relend < pltend))
473 473 relend = pltend;
474 474 }
475 475 }
476 476 if (!relbgn || (relbgn == relend)) {
477 477 DBG_CALL(Dbg_reloc_run(lmp, 0, plt, DBG_REL_NONE));
478 478 return (1);
479 479 }
480 480 DBG_CALL(Dbg_reloc_run(lmp, M_REL_SHT_TYPE, plt, DBG_REL_START));
481 481
482 482 /*
483 483 * If we're processing a dynamic executable in lazy mode there is no
484 484 * need to scan the .rel.plt table, however if we're processing a shared
485 485 * object in lazy mode the .got addresses associated to each .plt must
486 486 * be relocated to reflect the location of the shared object.
487 487 */
488 488 if (pltbgn && ((MODE(lmp) & RTLD_NOW) == 0) &&
489 489 (FLAGS(lmp) & FLG_RT_FIXED))
490 490 noplt = 1;
491 491
492 492 sip = SYMINFO(lmp);
493 493 /*
494 494 * Loop through relocations.
495 495 */
496 496 while (relbgn < relend) {
497 497 mmapobj_result_t *mpp;
498 498 uint_t sb_flags = 0;
499 499
500 500 rtype = ELF_R_TYPE(((Rel *)relbgn)->r_info, M_MACH);
501 501
502 502 /*
503 503 * If this is a RELATIVE relocation in a shared object (the
504 504 * common case), and if we are not debugging, then jump into a
505 505 * tighter relocation loop (elf_reloc_relative).
506 506 */
507 507 if ((rtype == R_386_RELATIVE) &&
508 508 ((FLAGS(lmp) & FLG_RT_FIXED) == 0) && (DBG_ENABLED == 0)) {
509 509 if (relacount) {
510 510 relbgn = elf_reloc_relative_count(relbgn,
511 511 relacount, relsiz, basebgn, lmp,
512 512 textrel, 0);
513 513 relacount = 0;
514 514 } else {
515 515 relbgn = elf_reloc_relative(relbgn, relend,
516 516 relsiz, basebgn, lmp, textrel, 0);
517 517 }
518 518 if (relbgn >= relend)
519 519 break;
520 520 rtype = ELF_R_TYPE(((Rel *)relbgn)->r_info, M_MACH);
521 521 }
522 522
523 523 roffset = ((Rel *)relbgn)->r_offset;
524 524
525 525 /*
526 526 * If this is a shared object, add the base address to offset.
527 527 */
528 528 if (!(FLAGS(lmp) & FLG_RT_FIXED)) {
529 529 /*
530 530 * If we're processing lazy bindings, we have to step
531 531 * through the plt entries and add the base address
532 532 * to the corresponding got entry.
533 533 */
534 534 if (plthint && (plt == 0) &&
535 535 (rtype == R_386_JMP_SLOT) &&
536 536 ((MODE(lmp) & RTLD_NOW) == 0)) {
537 537 relbgn = elf_reloc_relative_count(relbgn,
538 538 plthint, relsiz, basebgn, lmp, textrel, 0);
539 539 plthint = 0;
540 540 continue;
541 541 }
542 542 roffset += basebgn;
543 543 }
544 544
545 545 rsymndx = ELF_R_SYM(((Rel *)relbgn)->r_info);
546 546 rel = (Rel *)relbgn;
547 547 relbgn += relsiz;
548 548
549 549 /*
550 550 * Optimizations.
551 551 */
552 552 if (rtype == R_386_NONE)
553 553 continue;
554 554 if (noplt && ((ulong_t)rel >= pltbgn) &&
555 555 ((ulong_t)rel < pltend)) {
556 556 relbgn = pltend;
557 557 continue;
558 558 }
559 559
560 560 /*
561 561 * If we're promoting plts, determine if this one has already
562 562 * been written.
563 563 */
564 564 if (plt && ((*(ulong_t *)roffset < _pltbgn) ||
565 565 (*(ulong_t *)roffset > _pltend)))
566 566 continue;
567 567
568 568 /*
569 569 * If this relocation is not against part of the image
570 570 * mapped into memory we skip it.
571 571 */
572 572 if ((mpp = find_segment((caddr_t)roffset, lmp)) == NULL) {
573 573 elf_reloc_bad(lmp, (void *)rel, rtype, roffset,
574 574 rsymndx);
575 575 continue;
576 576 }
577 577
578 578 binfo = 0;
579 579 /*
580 580 * If a symbol index is specified then get the symbol table
581 581 * entry, locate the symbol definition, and determine its
582 582 * address.
583 583 */
584 584 if (rsymndx) {
585 585 /*
586 586 * If a Syminfo section is provided, determine if this
587 587 * symbol is deferred, and if so, skip this relocation.
588 588 */
589 589 if (sip && is_sym_deferred((ulong_t)rel, basebgn, lmp,
590 590 textrel, sip, rsymndx))
591 591 continue;
592 592
593 593 /*
594 594 * Get the local symbol table entry.
595 595 */
596 596 symref = (Sym *)((ulong_t)SYMTAB(lmp) +
597 597 (rsymndx * SYMENT(lmp)));
598 598
599 599 /*
600 600 * If this is a local symbol, just use the base address.
601 601 * (we should have no local relocations in the
602 602 * executable).
603 603 */
604 604 if (ELF_ST_BIND(symref->st_info) == STB_LOCAL) {
605 605 value = basebgn;
606 606 name = NULL;
607 607
608 608 /*
609 609 * Special case TLS relocations.
610 610 */
611 611 if (rtype == R_386_TLS_DTPMOD32) {
612 612 /*
613 613 * Use the TLS modid.
614 614 */
615 615 value = TLSMODID(lmp);
616 616
617 617 } else if (rtype == R_386_TLS_TPOFF) {
618 618 if ((value = elf_static_tls(lmp, symref,
619 619 rel, rtype, 0, roffset, 0)) == 0) {
620 620 ret = 0;
621 621 break;
622 622 }
623 623 }
624 624 } else {
625 625 /*
626 626 * If the symbol index is equal to the previous
627 627 * symbol index relocation we processed then
628 628 * reuse the previous values. (Note that there
629 629 * have been cases where a relocation exists
630 630 * against a copy relocation symbol, our ld(1)
631 631 * should optimize this away, but make sure we
632 632 * don't use the same symbol information should
633 633 * this case exist).
634 634 */
635 635 if ((rsymndx == psymndx) &&
636 636 (rtype != R_386_COPY)) {
637 637 /* LINTED */
638 638 if (psymdef == 0) {
639 639 DBG_CALL(Dbg_bind_weak(lmp,
640 640 (Addr)roffset, (Addr)
641 641 (roffset - basebgn), name));
642 642 continue;
643 643 }
644 644 /* LINTED */
645 645 value = pvalue;
646 646 /* LINTED */
647 647 name = pname;
648 648 /* LINTED */
649 649 symdef = psymdef;
650 650 /* LINTED */
651 651 symref = psymref;
652 652 /* LINTED */
653 653 _lmp = plmp;
654 654 /* LINTED */
655 655 binfo = pbinfo;
656 656
657 657 if ((LIST(_lmp)->lm_tflags |
658 658 AFLAGS(_lmp)) &
659 659 LML_TFLG_AUD_SYMBIND) {
660 660 value = audit_symbind(lmp, _lmp,
661 661 /* LINTED */
662 662 symdef, dsymndx, value,
663 663 &sb_flags);
664 664 }
665 665 } else {
666 666 Slookup sl;
667 667 Sresult sr;
668 668
669 669 /*
670 670 * Lookup the symbol definition.
671 671 * Initialize the symbol lookup, and
672 672 * symbol result, data structures.
673 673 */
674 674 name = (char *)(STRTAB(lmp) +
675 675 symref->st_name);
676 676
677 677 SLOOKUP_INIT(sl, name, lmp, 0,
678 678 ld_entry_cnt, 0, rsymndx, symref,
679 679 rtype, LKUP_STDRELOC);
680 680 SRESULT_INIT(sr, name);
681 681 symdef = NULL;
682 682
683 683 if (lookup_sym(&sl, &sr, &binfo,
684 684 in_nfavl)) {
685 685 name = (char *)sr.sr_name;
686 686 _lmp = sr.sr_dmap;
687 687 symdef = sr.sr_sym;
688 688 }
689 689
690 690 /*
691 691 * If the symbol is not found and the
692 692 * reference was not to a weak symbol,
693 693 * report an error. Weak references
694 694 * may be unresolved.
695 695 */
696 696 /* BEGIN CSTYLED */
697 697 if (symdef == 0) {
698 698 if (sl.sl_bind != STB_WEAK) {
699 699 if (elf_reloc_error(lmp, name,
700 700 rel, binfo))
701 701 continue;
702 702
703 703 ret = 0;
704 704 break;
705 705
706 706 } else {
707 707 psymndx = rsymndx;
708 708 psymdef = 0;
709 709
710 710 DBG_CALL(Dbg_bind_weak(lmp,
711 711 (Addr)roffset, (Addr)
712 712 (roffset - basebgn), name));
713 713 continue;
714 714 }
715 715 }
716 716 /* END CSTYLED */
717 717
718 718 /*
719 719 * If symbol was found in an object
720 720 * other than the referencing object
721 721 * then record the binding.
722 722 */
723 723 if ((lmp != _lmp) && ((FLAGS1(_lmp) &
724 724 FL1_RT_NOINIFIN) == 0)) {
725 725 if (aplist_test(&bound, _lmp,
726 726 AL_CNT_RELBIND) == 0) {
727 727 ret = 0;
728 728 break;
729 729 }
730 730 }
731 731
732 732 /*
733 733 * Calculate the location of definition;
734 734 * symbol value plus base address of
735 735 * containing shared object.
736 736 */
737 737 if (IS_SIZE(rtype))
738 738 value = symdef->st_size;
739 739 else
740 740 value = symdef->st_value;
741 741
742 742 if (!(FLAGS(_lmp) & FLG_RT_FIXED) &&
743 743 !(IS_SIZE(rtype)) &&
744 744 (symdef->st_shndx != SHN_ABS) &&
745 745 (ELF_ST_TYPE(symdef->st_info) !=
746 746 STT_TLS))
747 747 value += ADDR(_lmp);
748 748
749 749 /*
750 750 * Retain this symbol index and the
751 751 * value in case it can be used for the
752 752 * subsequent relocations.
753 753 */
754 754 if (rtype != R_386_COPY) {
755 755 psymndx = rsymndx;
756 756 pvalue = value;
757 757 pname = name;
758 758 psymdef = symdef;
759 759 psymref = symref;
760 760 plmp = _lmp;
761 761 pbinfo = binfo;
762 762 }
763 763 if ((LIST(_lmp)->lm_tflags |
764 764 AFLAGS(_lmp)) &
765 765 LML_TFLG_AUD_SYMBIND) {
766 766 dsymndx = (((uintptr_t)symdef -
767 767 (uintptr_t)SYMTAB(_lmp)) /
768 768 SYMENT(_lmp));
769 769 value = audit_symbind(lmp, _lmp,
770 770 symdef, dsymndx, value,
771 771 &sb_flags);
772 772 }
773 773 }
774 774
775 775 /*
776 776 * If relocation is PC-relative, subtract
777 777 * offset address.
778 778 */
779 779 if (IS_PC_RELATIVE(rtype))
780 780 value -= roffset;
781 781
782 782 /*
783 783 * Special case TLS relocations.
784 784 */
785 785 if (rtype == R_386_TLS_DTPMOD32) {
786 786 /*
787 787 * Relocation value is the TLS modid.
788 788 */
789 789 value = TLSMODID(_lmp);
790 790
791 791 } else if (rtype == R_386_TLS_TPOFF) {
792 792 if ((value = elf_static_tls(_lmp,
793 793 symdef, rel, rtype, name, roffset,
794 794 value)) == 0) {
795 795 ret = 0;
796 796 break;
797 797 }
798 798 }
799 799 }
800 800 } else {
801 801 /*
802 802 * Special cases.
803 803 */
804 804 if (rtype == R_386_TLS_DTPMOD32) {
805 805 /*
806 806 * TLS relocation value is the TLS modid.
807 807 */
808 808 value = TLSMODID(lmp);
809 809 } else
810 810 value = basebgn;
811 811
812 812 name = NULL;
813 813 }
814 814
815 815 DBG_CALL(Dbg_reloc_in(LIST(lmp), ELF_DBG_RTLD, M_MACH,
816 816 M_REL_SHT_TYPE, rel, NULL, 0, name));
817 817
818 818 /*
819 819 * Make sure the segment is writable.
820 820 */
821 821 if (((mpp->mr_prot & PROT_WRITE) == 0) &&
822 822 ((set_prot(lmp, mpp, 1) == 0) ||
823 823 (aplist_append(textrel, mpp, AL_CNT_TEXTREL) == NULL))) {
824 824 ret = 0;
825 825 break;
826 826 }
827 827
828 828 /*
829 829 * Call relocation routine to perform required relocation.
830 830 */
831 831 switch (rtype) {
832 832 case R_386_COPY:
833 833 if (elf_copy_reloc(name, symref, lmp, (void *)roffset,
834 834 symdef, _lmp, (const void *)value) == 0)
835 835 ret = 0;
836 836 break;
837 837 case R_386_JMP_SLOT:
838 838 if (((LIST(lmp)->lm_tflags | AFLAGS(lmp)) &
839 839 (LML_TFLG_AUD_PLTENTER | LML_TFLG_AUD_PLTEXIT)) &&
840 840 AUDINFO(lmp)->ai_dynplts) {
841 841 int fail = 0;
842 842 int pltndx = (((ulong_t)rel -
843 843 (uintptr_t)JMPREL(lmp)) / relsiz);
844 844 int symndx = (((uintptr_t)symdef -
845 845 (uintptr_t)SYMTAB(_lmp)) / SYMENT(_lmp));
846 846
847 847 (void) elf_plt_trace_write(roffset, lmp, _lmp,
848 848 symdef, symndx, pltndx, (caddr_t)value,
849 849 sb_flags, &fail);
850 850 if (fail)
851 851 ret = 0;
852 852 } else {
853 853 /*
854 854 * Write standard PLT entry to jump directly
855 855 * to newly bound function.
856 856 */
857 857 DBG_CALL(Dbg_reloc_apply_val(LIST(lmp),
858 858 ELF_DBG_RTLD, (Xword)roffset,
859 859 (Xword)value));
860 860 *(ulong_t *)roffset = value;
861 861 }
862 862 break;
863 863 default:
864 864 /*
865 865 * Write the relocation out.
866 866 */
867 867 if (do_reloc_rtld(rtype, (uchar_t *)roffset,
868 868 (Word *)&value, name, NAME(lmp), LIST(lmp)) == 0)
869 869 ret = 0;
870 870
871 871 DBG_CALL(Dbg_reloc_apply_val(LIST(lmp), ELF_DBG_RTLD,
872 872 (Xword)roffset, (Xword)value));
873 873 }
874 874
875 875 if ((ret == 0) &&
876 876 ((LIST(lmp)->lm_flags & LML_FLG_TRC_WARN) == 0))
877 877 break;
878 878
879 879 if (binfo) {
880 880 DBG_CALL(Dbg_bind_global(lmp, (Addr)roffset,
881 881 (Off)(roffset - basebgn), (Xword)(-1), PLT_T_FULL,
882 882 _lmp, (Addr)value, symdef->st_value, name, binfo));
883 883 }
884 884 }
885 885
886 886 return (relocate_finish(lmp, bound, ret));
887 887 }
888 888
889 889 /*
890 890 * Initialize the first few got entries so that function calls go to
891 891 * elf_rtbndr:
892 892 *
893 893 * GOT[GOT_XLINKMAP] = the address of the link map
894 894 * GOT[GOT_XRTLD] = the address of rtbinder
895 895 */
896 896 void
897 897 elf_plt_init(void *got, caddr_t l)
898 898 {
899 899 uint_t *_got;
900 900 /* LINTED */
901 901 Rt_map *lmp = (Rt_map *)l;
902 902
903 903 _got = (uint_t *)got + M_GOT_XLINKMAP;
904 904 *_got = (uint_t)lmp;
905 905 _got = (uint_t *)got + M_GOT_XRTLD;
906 906 *_got = (uint_t)elf_rtbndr;
907 907 }
908 908
909 909 /*
910 910 * For SVR4 Intel compatability. USL uses /usr/lib/libc.so.1 as the run-time
911 911 * linker, so the interpreter's address will differ from /usr/lib/ld.so.1.
912 912 * Further, USL has special _iob[] and _ctype[] processing that makes up for the
913 913 * fact that these arrays do not have associated copy relocations. So we try
914 914 * and make up for that here. Any relocations found will be added to the global
915 915 * copy relocation list and will be processed in setup().
916 916 */
917 917 static int
918 918 _elf_copy_reloc(const char *name, Rt_map *rlmp, Rt_map *dlmp)
919 919 {
920 920 Sym *symref, *symdef;
921 921 caddr_t ref, def;
922 922 Rt_map *_lmp;
923 923 Rel rel;
924 924 Slookup sl;
925 925 Sresult sr;
926 926 uint_t binfo;
927 927
928 928 /*
929 929 * Determine if the special symbol exists as a reference in the dynamic
930 930 * executable, and that an associated definition exists in libc.so.1.
931 931 *
932 932 * Initialize the symbol lookup, and symbol result, data structures.
933 933 */
934 934 SLOOKUP_INIT(sl, name, rlmp, rlmp, ld_entry_cnt, 0, 0, 0, 0,
935 935 LKUP_FIRST);
936 936 SRESULT_INIT(sr, name);
937 937
938 938 if (lookup_sym(&sl, &sr, &binfo, NULL) == 0)
939 939 return (1);
940 940 symref = sr.sr_sym;
941 941
942 942 SLOOKUP_INIT(sl, name, rlmp, dlmp, ld_entry_cnt, 0, 0, 0, 0,
943 943 LKUP_DEFT);
944 944 SRESULT_INIT(sr, name);
945 945
946 946 if (lookup_sym(&sl, &sr, &binfo, NULL) == 0)
947 947 return (1);
948 948
949 949 _lmp = sr.sr_dmap;
950 950 symdef = sr.sr_sym;
951 951
952 952 if (strcmp(NAME(sr.sr_dmap), MSG_ORIG(MSG_PTH_LIBC)))
953 953 return (1);
954 954
955 955 /*
956 956 * Determine the reference and definition addresses.
957 957 */
958 958 ref = (void *)(symref->st_value);
959 959 if (!(FLAGS(rlmp) & FLG_RT_FIXED))
960 960 ref += ADDR(rlmp);
961 961 def = (void *)(symdef->st_value);
962 962 if (!(FLAGS(sr.sr_dmap) & FLG_RT_FIXED))
963 963 def += ADDR(_lmp);
964 964
965 965 /*
966 966 * Set up a relocation entry for debugging and call the generic copy
967 967 * relocation function to provide symbol size error checking and to
968 968 * record the copy relocation that must be performed.
969 969 */
970 970 rel.r_offset = (Addr)ref;
971 971 rel.r_info = (Word)R_386_COPY;
972 972 DBG_CALL(Dbg_reloc_in(LIST(rlmp), ELF_DBG_RTLD, M_MACH, M_REL_SHT_TYPE,
973 973 &rel, NULL, 0, name));
974 974
975 975 return (elf_copy_reloc((char *)name, symref, rlmp, (void *)ref, symdef,
976 976 _lmp, (void *)def));
977 977 }
978 978
979 979 int
980 980 elf_copy_gen(Rt_map *lmp)
981 981 {
982 982 if (interp && ((ulong_t)interp->i_faddr !=
983 983 r_debug.rtd_rdebug.r_ldbase) &&
984 984 !(strcmp(interp->i_name, MSG_ORIG(MSG_PTH_LIBC)))) {
985 985
986 986 DBG_CALL(Dbg_reloc_run(lmp, M_REL_SHT_TYPE, 0,
987 987 DBG_REL_START));
988 988
989 989 if (_elf_copy_reloc(MSG_ORIG(MSG_SYM_CTYPE), lmp,
990 990 (Rt_map *)NEXT(lmp)) == 0)
991 991 return (0);
992 992 if (_elf_copy_reloc(MSG_ORIG(MSG_SYM_IOB), lmp,
993 993 (Rt_map *)NEXT(lmp)) == 0)
994 994 return (0);
995 995 }
996 996 return (1);
997 997 }
998 998
999 999 /*
1000 1000 * Plt writing interface to allow debugging initialization to be generic.
1001 1001 */
1002 1002 Pltbindtype
1003 1003 /* ARGSUSED1 */
1004 1004 elf_plt_write(uintptr_t addr, uintptr_t vaddr, void *rptr, uintptr_t symval,
1005 1005 Xword pltndx)
1006 1006 {
1007 1007 Rel *rel = (Rel*)rptr;
1008 1008 uintptr_t pltaddr;
1009 1009
1010 1010 pltaddr = addr + rel->r_offset;
1011 1011 *(ulong_t *)pltaddr = (ulong_t)symval;
1012 1012 DBG_CALL(pltcntfull++);
1013 1013 return (PLT_T_FULL);
1014 1014 }
1015 1015
1016 1016 /*
1017 1017 * Provide a machine specific interface to the conversion routine. By calling
1018 1018 * the machine specific version, rather than the generic version, we insure that
1019 1019 * the data tables/strings for all known machine versions aren't dragged into
1020 1020 * ld.so.1.
1021 1021 */
1022 1022 const char *
1023 1023 _conv_reloc_type(uint_t rel)
1024 1024 {
1025 1025 static Conv_inv_buf_t inv_buf;
1026 1026
1027 1027 return (conv_reloc_386_type(rel, 0, &inv_buf));
1028 1028 }
↓ open down ↓ |
793 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX