Print this page
3337 x64 link-editor is painfully literal-minded about TLS
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/sgs/libld/common/machrel.amd.c
+++ new/usr/src/cmd/sgs/libld/common/machrel.amd.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) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 */
25 25
26 26 /* Get the x86 version of the relocation engine */
27 27 #define DO_RELOC_LIBLD_X86
28 28
29 29 #include <string.h>
30 30 #include <stdio.h>
31 31 #include <strings.h>
32 32 #include <sys/elf_amd64.h>
33 33 #include <debug.h>
34 34 #include <reloc.h>
35 35 #include <i386/machdep_x86.h>
36 36 #include "msg.h"
37 37 #include "_libld.h"
38 38
39 39 /*
40 40 * This module uses do_reloc_ld() to execute several synthesized relocations.
41 41 * That function expects to be passed two things that we need to construct
42 42 * here:
43 43 *
44 44 * 1) A Rel_desc descriptor for each relocation type, from which the
45 45 * rel_rtype field, and nothing else, is obtained. This is easily
46 46 * handled by constructing the necessary descriptors.
47 47 *
48 48 * 2) A function, which called with the Rel_desc descriptor, returns
49 49 * a string representing the name of the symbol associated with
50 50 * the descriptor. The usual function for this is ld_reloc_sym_name().
51 51 * However, that function will not work in this case, as these synthetic
52 52 * relocations do not have an associated symbol. We supply the
53 53 * syn_rdesc_sym_name() function to simply return the fixed name.
54 54 */
55 55 static Rel_desc rdesc_r_amd64_gotpcrel = {
56 56 NULL, NULL, NULL, 0, 0, 0, R_AMD64_GOTPCREL };
57 57 static Rel_desc rdesc_r_amd64_32 = {
58 58 NULL, NULL, NULL, 0, 0, 0, R_AMD64_32 };
59 59 static Rel_desc rdesc_r_amd64_pc32 = {
60 60 NULL, NULL, NULL, 0, 0, 0, R_AMD64_PC32 };
61 61
62 62 /*ARGSUSED*/
63 63 static const char *
64 64 syn_rdesc_sym_name(Rel_desc *rdesc)
65 65 {
66 66 return (MSG_ORIG(MSG_SYM_PLTENT));
67 67 }
68 68
69 69 /*
70 70 * Search the GOT index list for a GOT entry with a matching reference and the
71 71 * proper addend.
72 72 */
73 73 static Gotndx *
74 74 ld_find_got_ndx(Alist *alp, Gotref gref, Ofl_desc *ofl, Rel_desc *rdesc)
75 75 {
76 76 Aliste idx;
77 77 Gotndx *gnp;
78 78
79 79 assert(rdesc != 0);
80 80
81 81 if ((gref == GOT_REF_TLSLD) && ofl->ofl_tlsldgotndx)
82 82 return (ofl->ofl_tlsldgotndx);
83 83
84 84 for (ALIST_TRAVERSE(alp, idx, gnp)) {
85 85 if ((rdesc->rel_raddend == gnp->gn_addend) &&
86 86 (gnp->gn_gotref == gref)) {
87 87 return (gnp);
88 88 }
89 89 }
90 90 return (NULL);
91 91 }
92 92
93 93 static Xword
94 94 ld_calc_got_offset(Rel_desc *rdesc, Ofl_desc *ofl)
95 95 {
96 96 Os_desc *osp = ofl->ofl_osgot;
97 97 Sym_desc *sdp = rdesc->rel_sym;
98 98 Xword gotndx;
99 99 Gotref gref;
100 100 Gotndx *gnp;
101 101
102 102 if (rdesc->rel_flags & FLG_REL_DTLS)
103 103 gref = GOT_REF_TLSGD;
104 104 else if (rdesc->rel_flags & FLG_REL_MTLS)
105 105 gref = GOT_REF_TLSLD;
106 106 else if (rdesc->rel_flags & FLG_REL_STLS)
107 107 gref = GOT_REF_TLSIE;
108 108 else
109 109 gref = GOT_REF_GENERIC;
110 110
111 111 gnp = ld_find_got_ndx(sdp->sd_GOTndxs, gref, ofl, rdesc);
112 112 assert(gnp);
113 113
114 114 gotndx = (Xword)gnp->gn_gotndx;
115 115
116 116 if ((rdesc->rel_flags & FLG_REL_DTLS) &&
117 117 (rdesc->rel_rtype == R_AMD64_DTPOFF64))
118 118 gotndx++;
119 119
120 120 return ((Xword)(osp->os_shdr->sh_addr + (gotndx * M_GOT_ENTSIZE)));
121 121 }
122 122
123 123 static Word
124 124 ld_init_rel(Rel_desc *reld, Word *typedata, void *reloc)
125 125 {
126 126 Rela *rel = (Rela *)reloc;
127 127
128 128 /* LINTED */
129 129 reld->rel_rtype = (Word)ELF_R_TYPE(rel->r_info, M_MACH);
130 130 reld->rel_roffset = rel->r_offset;
131 131 reld->rel_raddend = rel->r_addend;
132 132 *typedata = 0;
133 133
134 134 reld->rel_flags |= FLG_REL_RELA;
135 135
136 136 return ((Word)ELF_R_SYM(rel->r_info));
137 137 }
138 138
139 139 static void
140 140 ld_mach_eflags(Ehdr *ehdr, Ofl_desc *ofl)
141 141 {
142 142 ofl->ofl_dehdr->e_flags |= ehdr->e_flags;
143 143 }
144 144
145 145 static void
146 146 ld_mach_make_dynamic(Ofl_desc *ofl, size_t *cnt)
147 147 {
148 148 if (!(ofl->ofl_flags & FLG_OF_RELOBJ)) {
149 149 /*
150 150 * Create this entry if we are going to create a PLT table.
151 151 */
152 152 if (ofl->ofl_pltcnt)
153 153 (*cnt)++; /* DT_PLTGOT */
154 154 }
155 155 }
156 156
157 157 static void
158 158 ld_mach_update_odynamic(Ofl_desc *ofl, Dyn **dyn)
159 159 {
160 160 if (((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) && ofl->ofl_pltcnt) {
161 161 (*dyn)->d_tag = DT_PLTGOT;
162 162 if (ofl->ofl_osgot)
163 163 (*dyn)->d_un.d_ptr = ofl->ofl_osgot->os_shdr->sh_addr;
164 164 else
165 165 (*dyn)->d_un.d_ptr = 0;
166 166 (*dyn)++;
167 167 }
168 168 }
169 169
170 170 static Xword
171 171 ld_calc_plt_addr(Sym_desc *sdp, Ofl_desc *ofl)
172 172 {
173 173 Xword value;
174 174
175 175 value = (Xword)(ofl->ofl_osplt->os_shdr->sh_addr) +
176 176 M_PLT_RESERVSZ + ((sdp->sd_aux->sa_PLTndx - 1) * M_PLT_ENTSIZE);
177 177 return (value);
178 178 }
179 179
180 180 /*
181 181 * Build a single plt entry - code is:
182 182 * JMP *name1@GOTPCREL(%rip)
183 183 * PUSHL $index
184 184 * JMP .PLT0
185 185 */
186 186 static uchar_t pltn_entry[M_PLT_ENTSIZE] = {
187 187 /* 0x00 jmpq *name1@GOTPCREL(%rip) */ 0xff, 0x25, 0x00, 0x00, 0x00, 0x00,
188 188 /* 0x06 pushq $index */ 0x68, 0x00, 0x00, 0x00, 0x00,
189 189 /* 0x0b jmpq .plt0(%rip) */ 0xe9, 0x00, 0x00, 0x00, 0x00
190 190 /* 0x10 */
191 191 };
192 192
193 193 static uintptr_t
194 194 plt_entry(Ofl_desc * ofl, Sym_desc * sdp)
195 195 {
196 196 uchar_t *plt0, *pltent, *gotent;
197 197 Sword plt_off;
198 198 Word got_off;
199 199 Xword val1;
200 200 int bswap = (ofl->ofl_flags1 & FLG_OF1_ENCDIFF) != 0;
201 201
202 202 got_off = sdp->sd_aux->sa_PLTGOTndx * M_GOT_ENTSIZE;
203 203 plt_off = M_PLT_RESERVSZ + ((sdp->sd_aux->sa_PLTndx - 1) *
204 204 M_PLT_ENTSIZE);
205 205 plt0 = (uchar_t *)(ofl->ofl_osplt->os_outdata->d_buf);
206 206 pltent = plt0 + plt_off;
207 207 gotent = (uchar_t *)(ofl->ofl_osgot->os_outdata->d_buf) + got_off;
208 208
209 209 bcopy(pltn_entry, pltent, sizeof (pltn_entry));
210 210 /*
211 211 * Fill in the got entry with the address of the next instruction.
212 212 */
213 213 /* LINTED */
214 214 *(Word *)gotent = ofl->ofl_osplt->os_shdr->sh_addr + plt_off +
215 215 M_PLT_INSSIZE;
216 216 if (bswap)
217 217 /* LINTED */
218 218 *(Word *)gotent = ld_bswap_Word(*(Word *)gotent);
219 219
220 220 /*
221 221 * If '-z noreloc' is specified - skip the do_reloc_ld
222 222 * stage.
223 223 */
224 224 if (!OFL_DO_RELOC(ofl))
225 225 return (1);
226 226
227 227 /*
228 228 * patchup:
229 229 * jmpq *name1@gotpcrel(%rip)
230 230 *
231 231 * NOTE: 0x06 represents next instruction.
232 232 */
233 233 val1 = (ofl->ofl_osgot->os_shdr->sh_addr + got_off) -
234 234 (ofl->ofl_osplt->os_shdr->sh_addr + plt_off) - 0x06;
235 235
236 236 if (do_reloc_ld(&rdesc_r_amd64_gotpcrel, &pltent[0x02], &val1,
237 237 syn_rdesc_sym_name, MSG_ORIG(MSG_SPECFIL_PLTENT), bswap,
238 238 ofl->ofl_lml) == 0) {
239 239 ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_PLT_PLTNFAIL),
240 240 sdp->sd_aux->sa_PLTndx, demangle(sdp->sd_name));
241 241 return (S_ERROR);
242 242 }
243 243
244 244 /*
245 245 * patchup:
246 246 * pushq $pltndx
247 247 */
248 248 val1 = (Xword)(sdp->sd_aux->sa_PLTndx - 1);
249 249
250 250 if (do_reloc_ld(&rdesc_r_amd64_32, &pltent[0x07], &val1,
251 251 syn_rdesc_sym_name, MSG_ORIG(MSG_SPECFIL_PLTENT), bswap,
252 252 ofl->ofl_lml) == 0) {
253 253 ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_PLT_PLTNFAIL),
254 254 sdp->sd_aux->sa_PLTndx, demangle(sdp->sd_name));
255 255 return (S_ERROR);
256 256 }
257 257
258 258 /*
259 259 * patchup:
260 260 * jmpq .plt0(%rip)
261 261 * NOTE: 0x10 represents next instruction. The rather complex
262 262 * series of casts is necessary to sign extend an offset into
263 263 * a 64-bit value while satisfying various compiler error
264 264 * checks. Handle with care.
265 265 */
266 266 val1 = (Xword)((intptr_t)((uintptr_t)plt0 -
267 267 (uintptr_t)(&pltent[0x10])));
268 268
269 269 if (do_reloc_ld(&rdesc_r_amd64_pc32, &pltent[0x0c], &val1,
270 270 syn_rdesc_sym_name, MSG_ORIG(MSG_SPECFIL_PLTENT), bswap,
271 271 ofl->ofl_lml) == 0) {
272 272 ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_PLT_PLTNFAIL),
273 273 sdp->sd_aux->sa_PLTndx, demangle(sdp->sd_name));
274 274 return (S_ERROR);
275 275 }
276 276
277 277 return (1);
278 278 }
279 279
280 280 static uintptr_t
281 281 ld_perform_outreloc(Rel_desc * orsp, Ofl_desc * ofl, Boolean *remain_seen)
282 282 {
283 283 Os_desc * relosp, * osp = 0;
284 284 Word ndx;
285 285 Xword roffset, value;
286 286 Sxword raddend;
287 287 Rela rea;
288 288 char *relbits;
289 289 Sym_desc * sdp, * psym = (Sym_desc *)0;
290 290 int sectmoved = 0;
291 291
292 292 raddend = orsp->rel_raddend;
293 293 sdp = orsp->rel_sym;
294 294
295 295 /*
296 296 * If the section this relocation is against has been discarded
297 297 * (-zignore), then also discard (skip) the relocation itself.
298 298 */
299 299 if (orsp->rel_isdesc && ((orsp->rel_flags &
300 300 (FLG_REL_GOT | FLG_REL_BSS | FLG_REL_PLT | FLG_REL_NOINFO)) == 0) &&
301 301 (orsp->rel_isdesc->is_flags & FLG_IS_DISCARD)) {
302 302 DBG_CALL(Dbg_reloc_discard(ofl->ofl_lml, M_MACH, orsp));
303 303 return (1);
304 304 }
305 305
306 306 /*
307 307 * If this is a relocation against a move table, or expanded move
308 308 * table, adjust the relocation entries.
309 309 */
310 310 if (RELAUX_GET_MOVE(orsp))
311 311 ld_adj_movereloc(ofl, orsp);
312 312
313 313 /*
314 314 * If this is a relocation against a section then we need to adjust the
315 315 * raddend field to compensate for the new position of the input section
316 316 * within the new output section.
317 317 */
318 318 if (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION) {
319 319 if (ofl->ofl_parsyms &&
320 320 (sdp->sd_isc->is_flags & FLG_IS_RELUPD) &&
321 321 /* LINTED */
322 322 (psym = ld_am_I_partial(orsp, orsp->rel_raddend))) {
323 323 DBG_CALL(Dbg_move_outsctadj(ofl->ofl_lml, psym));
324 324 sectmoved = 1;
325 325 if (ofl->ofl_flags & FLG_OF_RELOBJ)
326 326 raddend = psym->sd_sym->st_value;
327 327 else
328 328 raddend = psym->sd_sym->st_value -
329 329 psym->sd_isc->is_osdesc->os_shdr->sh_addr;
330 330 /* LINTED */
331 331 raddend += (Off)_elf_getxoff(psym->sd_isc->is_indata);
332 332 if (psym->sd_isc->is_shdr->sh_flags & SHF_ALLOC)
333 333 raddend +=
334 334 psym->sd_isc->is_osdesc->os_shdr->sh_addr;
335 335 } else {
336 336 /* LINTED */
337 337 raddend += (Off)_elf_getxoff(sdp->sd_isc->is_indata);
338 338 if (sdp->sd_isc->is_shdr->sh_flags & SHF_ALLOC)
339 339 raddend +=
340 340 sdp->sd_isc->is_osdesc->os_shdr->sh_addr;
341 341 }
342 342 }
343 343
344 344 value = sdp->sd_sym->st_value;
345 345
346 346 if (orsp->rel_flags & FLG_REL_GOT) {
347 347 /*
348 348 * Note: for GOT relative relocations on amd64
349 349 * we discard the addend. It was relevant
350 350 * to the reference - not to the data item
351 351 * being referenced (ie: that -4 thing).
352 352 */
353 353 raddend = 0;
354 354 osp = ofl->ofl_osgot;
355 355 roffset = ld_calc_got_offset(orsp, ofl);
356 356
357 357 } else if (orsp->rel_flags & FLG_REL_PLT) {
358 358 /*
359 359 * Note that relocations for PLT's actually
360 360 * cause a relocation againt the GOT.
361 361 */
362 362 osp = ofl->ofl_osplt;
363 363 roffset = (ofl->ofl_osgot->os_shdr->sh_addr) +
364 364 sdp->sd_aux->sa_PLTGOTndx * M_GOT_ENTSIZE;
365 365 raddend = 0;
366 366 if (plt_entry(ofl, sdp) == S_ERROR)
367 367 return (S_ERROR);
368 368
369 369 } else if (orsp->rel_flags & FLG_REL_BSS) {
370 370 /*
371 371 * This must be a R_AMD64_COPY. For these set the roffset to
372 372 * point to the new symbols location.
373 373 */
374 374 osp = ofl->ofl_isbss->is_osdesc;
375 375 roffset = value;
376 376
377 377 /*
378 378 * The raddend doesn't mean anything in a R_SPARC_COPY
379 379 * relocation. Null it out because it can confuse people.
380 380 */
381 381 raddend = 0;
382 382 } else {
383 383 osp = RELAUX_GET_OSDESC(orsp);
384 384
385 385 /*
386 386 * Calculate virtual offset of reference point; equals offset
387 387 * into section + vaddr of section for loadable sections, or
388 388 * offset plus section displacement for nonloadable sections.
389 389 */
390 390 roffset = orsp->rel_roffset +
391 391 (Off)_elf_getxoff(orsp->rel_isdesc->is_indata);
392 392 if (!(ofl->ofl_flags & FLG_OF_RELOBJ))
393 393 roffset += orsp->rel_isdesc->is_osdesc->
394 394 os_shdr->sh_addr;
395 395 }
396 396
397 397 if ((osp == 0) || ((relosp = osp->os_relosdesc) == 0))
398 398 relosp = ofl->ofl_osrel;
399 399
400 400 /*
401 401 * Assign the symbols index for the output relocation. If the
402 402 * relocation refers to a SECTION symbol then it's index is based upon
403 403 * the output sections symbols index. Otherwise the index can be
404 404 * derived from the symbols index itself.
405 405 */
406 406 if (orsp->rel_rtype == R_AMD64_RELATIVE)
407 407 ndx = STN_UNDEF;
408 408 else if ((orsp->rel_flags & FLG_REL_SCNNDX) ||
409 409 (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION)) {
410 410 if (sectmoved == 0) {
411 411 /*
412 412 * Check for a null input section. This can
413 413 * occur if this relocation references a symbol
414 414 * generated by sym_add_sym().
415 415 */
416 416 if (sdp->sd_isc && sdp->sd_isc->is_osdesc)
417 417 ndx = sdp->sd_isc->is_osdesc->os_identndx;
418 418 else
419 419 ndx = sdp->sd_shndx;
420 420 } else
421 421 ndx = ofl->ofl_parexpnndx;
422 422 } else
423 423 ndx = sdp->sd_symndx;
424 424
425 425 /*
426 426 * Add the symbols 'value' to the addend field.
427 427 */
428 428 if (orsp->rel_flags & FLG_REL_ADVAL)
429 429 raddend += value;
430 430
431 431 /*
432 432 * The addend field for R_AMD64_DTPMOD64 means nothing. The addend
433 433 * is propagated in the corresponding R_AMD64_DTPOFF64 relocation.
434 434 */
435 435 if (orsp->rel_rtype == R_AMD64_DTPMOD64)
436 436 raddend = 0;
437 437
438 438 relbits = (char *)relosp->os_outdata->d_buf;
439 439
440 440 rea.r_info = ELF_R_INFO(ndx, orsp->rel_rtype);
441 441 rea.r_offset = roffset;
442 442 rea.r_addend = raddend;
443 443 DBG_CALL(Dbg_reloc_out(ofl, ELF_DBG_LD, SHT_RELA, &rea, relosp->os_name,
444 444 ld_reloc_sym_name(orsp)));
445 445
446 446 /*
447 447 * Assert we haven't walked off the end of our relocation table.
448 448 */
449 449 assert(relosp->os_szoutrels <= relosp->os_shdr->sh_size);
450 450
451 451 (void) memcpy((relbits + relosp->os_szoutrels),
452 452 (char *)&rea, sizeof (Rela));
453 453 relosp->os_szoutrels += (Xword)sizeof (Rela);
454 454
455 455 /*
456 456 * Determine if this relocation is against a non-writable, allocatable
457 457 * section. If so we may need to provide a text relocation diagnostic.
458 458 * Note that relocations against the .plt (R_AMD64_JUMP_SLOT) actually
459 459 * result in modifications to the .got.
460 460 */
461 461 if (orsp->rel_rtype == R_AMD64_JUMP_SLOT)
462 462 osp = ofl->ofl_osgot;
463 463
464 464 ld_reloc_remain_entry(orsp, osp, ofl, remain_seen);
465 465 return (1);
466 466 }
467 467
468 468 /*
469 469 * amd64 Instructions for TLS processing
470 470 */
471 471 static uchar_t tlsinstr_gd_ie[] = {
472 472 /*
473 473 * 0x00 movq %fs:0, %rax
474 474 */
475 475 0x64, 0x48, 0x8b, 0x04, 0x25,
476 476 0x00, 0x00, 0x00, 0x00,
477 477 /*
478 478 * 0x09 addq x@gottpoff(%rip), %rax
479 479 */
480 480 0x48, 0x03, 0x05, 0x00, 0x00,
481 481 0x00, 0x00
482 482 };
483 483
484 484 static uchar_t tlsinstr_gd_le[] = {
485 485 /*
486 486 * 0x00 movq %fs:0, %rax
487 487 */
488 488 0x64, 0x48, 0x8b, 0x04, 0x25,
489 489 0x00, 0x00, 0x00, 0x00,
490 490 /*
491 491 * 0x09 leaq x@gottpoff(%rip), %rax
492 492 */
493 493 0x48, 0x8d, 0x80, 0x00, 0x00,
494 494 0x00, 0x00
495 495 };
496 496
497 497 static uchar_t tlsinstr_ld_le[] = {
498 498 /*
499 499 * .byte 0x66
500 500 */
501 501 0x66,
502 502 /*
503 503 * .byte 0x66
504 504 */
505 505 0x66,
506 506 /*
↓ open down ↓ |
506 lines elided |
↑ open up ↑ |
507 507 * .byte 0x66
508 508 */
509 509 0x66,
510 510 /*
511 511 * movq %fs:0, %rax
512 512 */
513 513 0x64, 0x48, 0x8b, 0x04, 0x25,
514 514 0x00, 0x00, 0x00, 0x00
515 515 };
516 516
517 +#define REX_B 0x1
518 +#define REX_X 0x2
519 +#define REX_R 0x4
520 +#define REX_W 0x8
521 +#define REX_PREFIX 0x40
522 +
523 +#define REX_RW (REX_PREFIX | REX_R | REX_W)
524 +#define REX_BW (REX_PREFIX | REX_B | REX_W)
525 +#define REX_BRW (REX_PREFIX | REX_B | REX_R | REX_W)
526 +
527 +#define REG_ESP 0x4
528 +
529 +#define INSN_ADDMR 0x03 /* addq mem,reg */
530 +#define INSN_ADDIR 0x81 /* addq imm,reg */
531 +#define INSN_MOVMR 0x8b /* movq mem,reg */
532 +#define INSN_MOVIR 0xc7 /* movq imm,reg */
533 +#define INSN_LEA 0x8d /* leaq mem,reg */
517 534
518 535 static Fixupret
519 536 tls_fixups(Ofl_desc *ofl, Rel_desc *arsp)
520 537 {
521 538 Sym_desc *sdp = arsp->rel_sym;
522 539 Word rtype = arsp->rel_rtype;
523 540 uchar_t *offset;
524 541
525 542 offset = (uchar_t *)((uintptr_t)arsp->rel_roffset +
526 543 (uintptr_t)_elf_getxoff(arsp->rel_isdesc->is_indata) +
527 544 (uintptr_t)RELAUX_GET_OSDESC(arsp)->os_outdata->d_buf);
528 545
546 + /*
547 + * Note that in certain of the original insn sequences below, the
548 + * instructions are not necessarily adjacent
549 + */
529 550 if (sdp->sd_ref == REF_DYN_NEED) {
530 551 /*
531 552 * IE reference model
532 553 */
533 554 switch (rtype) {
534 555 case R_AMD64_TLSGD:
535 556 /*
536 557 * GD -> IE
537 558 *
538 559 * Transition:
539 560 * 0x00 .byte 0x66
540 561 * 0x01 leaq x@tlsgd(%rip), %rdi
541 562 * 0x08 .word 0x6666
542 563 * 0x0a rex64
543 564 * 0x0b call __tls_get_addr@plt
544 565 * 0x10
545 566 * To:
546 567 * 0x00 movq %fs:0, %rax
547 568 * 0x09 addq x@gottpoff(%rip), %rax
548 569 * 0x10
549 570 */
550 571 DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH,
551 572 R_AMD64_GOTTPOFF, arsp, ld_reloc_sym_name));
552 573 arsp->rel_rtype = R_AMD64_GOTTPOFF;
553 574 arsp->rel_roffset += 8;
554 575 arsp->rel_raddend = (Sxword)-4;
555 576
556 577 /*
557 578 * Adjust 'offset' to beginning of instruction
558 579 * sequence.
559 580 */
560 581 offset -= 4;
561 582 (void) memcpy(offset, tlsinstr_gd_ie,
562 583 sizeof (tlsinstr_gd_ie));
563 584 return (FIX_RELOC);
564 585
565 586 case R_AMD64_PLT32:
566 587 /*
567 588 * Fixup done via the TLS_GD relocation.
568 589 */
569 590 DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH,
570 591 R_AMD64_NONE, arsp, ld_reloc_sym_name));
571 592 return (FIX_DONE);
572 593 }
573 594 }
574 595
575 596 /*
576 597 * LE reference model
577 598 */
578 599 switch (rtype) {
579 600 case R_AMD64_TLSGD:
580 601 /*
581 602 * GD -> LE
582 603 *
583 604 * Transition:
584 605 * 0x00 .byte 0x66
585 606 * 0x01 leaq x@tlsgd(%rip), %rdi
586 607 * 0x08 .word 0x6666
587 608 * 0x0a rex64
588 609 * 0x0b call __tls_get_addr@plt
589 610 * 0x10
590 611 * To:
591 612 * 0x00 movq %fs:0, %rax
592 613 * 0x09 leaq x@tpoff(%rax), %rax
593 614 * 0x10
594 615 */
595 616 DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH,
596 617 R_AMD64_TPOFF32, arsp, ld_reloc_sym_name));
597 618 arsp->rel_rtype = R_AMD64_TPOFF32;
↓ open down ↓ |
59 lines elided |
↑ open up ↑ |
598 619 arsp->rel_roffset += 8;
599 620 arsp->rel_raddend = 0;
600 621
601 622 /*
602 623 * Adjust 'offset' to beginning of instruction sequence.
603 624 */
604 625 offset -= 4;
605 626 (void) memcpy(offset, tlsinstr_gd_le, sizeof (tlsinstr_gd_le));
606 627 return (FIX_RELOC);
607 628
608 - case R_AMD64_GOTTPOFF:
629 + case R_AMD64_GOTTPOFF: {
609 630 /*
610 631 * IE -> LE
611 632 *
612 - * Transition:
613 - * 0x00 movq %fs:0, %rax
614 - * 0x09 addq x@gottopoff(%rip), %rax
615 - * 0x10
633 + * Transition 1:
634 + * movq %fs:0, %reg
635 + * addq x@gottpoff(%rip), %reg
616 636 * To:
617 - * 0x00 movq %fs:0, %rax
618 - * 0x09 leaq x@tpoff(%rax), %rax
619 - * 0x10
637 + * movq %fs:0, %reg
638 + * leaq x@tpoff(%reg), %reg
639 + *
640 + * Transition (as a special case):
641 + * movq %fs:0, %r12/%rsp
642 + * addq x@gottpoff(%rip), %r12/%rsp
643 + * To:
644 + * movq %fs:0, %r12/%rsp
645 + * addq x@tpoff(%rax), %r12/%rsp
646 + *
647 + * Transition 2:
648 + * movq x@gottpoff(%rip), %reg
649 + * movq %fs:(%reg), %reg
650 + * To:
651 + * movq x@tpoff(%reg), %reg
652 + * movq %fs:(%reg), %reg
620 653 */
654 + Conv_inv_buf_t inv_buf;
655 + uint8_t reg; /* Register */
656 +
657 + offset -= 3;
658 +
659 + reg = offset[2] >> 3; /* Encoded dest. reg. operand */
660 +
621 661 DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH,
622 662 R_AMD64_TPOFF32, arsp, ld_reloc_sym_name));
623 663 arsp->rel_rtype = R_AMD64_TPOFF32;
624 664 arsp->rel_raddend = 0;
625 665
626 666 /*
627 - * Adjust 'offset' to beginning of instruction sequence.
667 + * This is transition 2, and the special case of form 1 where
668 + * a normal transition would index %rsp or %r12 and need a SIB
669 + * byte in the leaq for which we lack space
628 670 */
629 - offset -= 12;
671 + if ((offset[1] == INSN_MOVMR) ||
672 + ((offset[1] == INSN_ADDMR) && (reg == REG_ESP))) {
673 + /*
674 + * If we needed an extra bit of MOD.reg to refer to
675 + * this register as the dest of the original movq we
676 + * need an extra bit of MOD.rm to refer to it in the
677 + * dest of the replacement movq or addq.
678 + */
679 + if (offset[0] == REX_RW)
680 + offset[0] = REX_BW;
630 681
631 - /*
632 - * Same code sequence used in the GD -> LE transition.
633 - */
634 - (void) memcpy(offset, tlsinstr_gd_le, sizeof (tlsinstr_gd_le));
635 - return (FIX_RELOC);
682 + offset[1] = (offset[1] == INSN_MOVMR) ?
683 + INSN_MOVIR : INSN_ADDIR;
684 + offset[2] = 0xc0 | reg;
685 +
686 + return (FIX_RELOC);
687 + } else if (offset[1] == INSN_ADDMR) {
688 + /*
689 + * If we needed an extra bit of MOD.reg to refer to
690 + * this register in the dest of the addq we need an
691 + * extra bit of both MOD.reg and MOD.rm to refer to it
692 + * in the source and dest of the leaq
693 + */
694 + if (offset[0] == REX_RW)
695 + offset[0] = REX_BRW;
696 +
697 + offset[1] = INSN_LEA;
698 + offset[2] = 0x80 | (reg << 3) | reg;
636 699
700 + return (FIX_RELOC);
701 + }
702 +
703 + ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_BADTLSINS),
704 + conv_reloc_amd64_type(arsp->rel_rtype, 0, &inv_buf),
705 + arsp->rel_isdesc->is_file->ifl_name,
706 + ld_reloc_sym_name(arsp),
707 + arsp->rel_isdesc->is_name,
708 + EC_OFF(arsp->rel_roffset));
709 + return (FIX_ERROR);
710 + }
637 711 case R_AMD64_TLSLD:
638 712 /*
639 713 * LD -> LE
640 714 *
641 715 * Transition
642 716 * 0x00 leaq x1@tlsgd(%rip), %rdi
643 717 * 0x07 call __tls_get_addr@plt
644 718 * 0x0c
645 719 * To:
646 720 * 0x00 .byte 0x66
647 721 * 0x01 .byte 0x66
648 722 * 0x02 .byte 0x66
649 723 * 0x03 movq %fs:0, %rax
650 724 */
651 725 DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH,
652 726 R_AMD64_NONE, arsp, ld_reloc_sym_name));
653 727 offset -= 3;
654 728 (void) memcpy(offset, tlsinstr_ld_le, sizeof (tlsinstr_ld_le));
655 729 return (FIX_DONE);
656 730
657 731 case R_AMD64_DTPOFF32:
658 732 /*
659 733 * LD->LE
660 734 *
661 735 * Transition:
662 736 * 0x00 leaq x1@dtpoff(%rax), %rcx
663 737 * To:
664 738 * 0x00 leaq x1@tpoff(%rax), %rcx
665 739 */
666 740 DBG_CALL(Dbg_reloc_transition(ofl->ofl_lml, M_MACH,
667 741 R_AMD64_TPOFF32, arsp, ld_reloc_sym_name));
668 742 arsp->rel_rtype = R_AMD64_TPOFF32;
669 743 arsp->rel_raddend = 0;
670 744 return (FIX_RELOC);
671 745 }
672 746
673 747 return (FIX_RELOC);
674 748 }
675 749
676 750 static uintptr_t
677 751 ld_do_activerelocs(Ofl_desc *ofl)
678 752 {
679 753 Rel_desc *arsp;
680 754 Rel_cachebuf *rcbp;
681 755 Aliste idx;
682 756 uintptr_t return_code = 1;
683 757 ofl_flag_t flags = ofl->ofl_flags;
684 758
685 759 if (aplist_nitems(ofl->ofl_actrels.rc_list) != 0)
686 760 DBG_CALL(Dbg_reloc_doact_title(ofl->ofl_lml));
687 761
688 762 /*
689 763 * Process active relocations.
690 764 */
691 765 REL_CACHE_TRAVERSE(&ofl->ofl_actrels, idx, rcbp, arsp) {
692 766 uchar_t *addr;
693 767 Xword value;
694 768 Sym_desc *sdp;
695 769 const char *ifl_name;
696 770 Xword refaddr;
697 771 int moved = 0;
698 772 Gotref gref;
699 773 Os_desc *osp;
700 774
701 775 /*
702 776 * If the section this relocation is against has been discarded
703 777 * (-zignore), then discard (skip) the relocation itself.
704 778 */
705 779 if ((arsp->rel_isdesc->is_flags & FLG_IS_DISCARD) &&
706 780 ((arsp->rel_flags & (FLG_REL_GOT | FLG_REL_BSS |
707 781 FLG_REL_PLT | FLG_REL_NOINFO)) == 0)) {
708 782 DBG_CALL(Dbg_reloc_discard(ofl->ofl_lml, M_MACH, arsp));
709 783 continue;
710 784 }
711 785
712 786 /*
713 787 * We determine what the 'got reference' model (if required)
714 788 * is at this point. This needs to be done before tls_fixup()
715 789 * since it may 'transition' our instructions.
716 790 *
717 791 * The got table entries have already been assigned,
718 792 * and we bind to those initial entries.
719 793 */
720 794 if (arsp->rel_flags & FLG_REL_DTLS)
721 795 gref = GOT_REF_TLSGD;
722 796 else if (arsp->rel_flags & FLG_REL_MTLS)
723 797 gref = GOT_REF_TLSLD;
724 798 else if (arsp->rel_flags & FLG_REL_STLS)
725 799 gref = GOT_REF_TLSIE;
726 800 else
727 801 gref = GOT_REF_GENERIC;
728 802
729 803 /*
730 804 * Perform any required TLS fixups.
731 805 */
732 806 if (arsp->rel_flags & FLG_REL_TLSFIX) {
733 807 Fixupret ret;
734 808
735 809 if ((ret = tls_fixups(ofl, arsp)) == FIX_ERROR)
736 810 return (S_ERROR);
737 811 if (ret == FIX_DONE)
738 812 continue;
739 813 }
740 814
741 815 /*
742 816 * If this is a relocation against a move table, or
743 817 * expanded move table, adjust the relocation entries.
744 818 */
745 819 if (RELAUX_GET_MOVE(arsp))
746 820 ld_adj_movereloc(ofl, arsp);
747 821
748 822 sdp = arsp->rel_sym;
749 823 refaddr = arsp->rel_roffset +
750 824 (Off)_elf_getxoff(arsp->rel_isdesc->is_indata);
751 825
752 826 if ((arsp->rel_flags & FLG_REL_CLVAL) ||
753 827 (arsp->rel_flags & FLG_REL_GOTCL))
754 828 value = 0;
755 829 else if (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION) {
756 830 Sym_desc *sym;
757 831
758 832 /*
759 833 * The value for a symbol pointing to a SECTION
760 834 * is based off of that sections position.
761 835 */
762 836 if ((sdp->sd_isc->is_flags & FLG_IS_RELUPD) &&
763 837 /* LINTED */
764 838 (sym = ld_am_I_partial(arsp, arsp->rel_raddend))) {
765 839 /*
766 840 * The symbol was moved, so adjust the value
767 841 * relative to the new section.
768 842 */
769 843 value = sym->sd_sym->st_value;
770 844 moved = 1;
771 845
772 846 /*
773 847 * The original raddend covers the displacement
774 848 * from the section start to the desired
775 849 * address. The value computed above gets us
776 850 * from the section start to the start of the
777 851 * symbol range. Adjust the old raddend to
778 852 * remove the offset from section start to
779 853 * symbol start, leaving the displacement
780 854 * within the range of the symbol.
781 855 */
782 856 arsp->rel_raddend -= sym->sd_osym->st_value;
783 857 } else {
784 858 value = _elf_getxoff(sdp->sd_isc->is_indata);
785 859 if (sdp->sd_isc->is_shdr->sh_flags & SHF_ALLOC)
786 860 value += sdp->sd_isc->is_osdesc->
787 861 os_shdr->sh_addr;
788 862 }
789 863 if (sdp->sd_isc->is_shdr->sh_flags & SHF_TLS)
790 864 value -= ofl->ofl_tlsphdr->p_vaddr;
791 865
792 866 } else if (IS_SIZE(arsp->rel_rtype)) {
793 867 /*
794 868 * Size relocations require the symbols size.
795 869 */
796 870 value = sdp->sd_sym->st_size;
797 871
798 872 } else if ((sdp->sd_flags & FLG_SY_CAP) &&
799 873 sdp->sd_aux && sdp->sd_aux->sa_PLTndx) {
800 874 /*
801 875 * If relocation is against a capabilities symbol, we
802 876 * need to jump to an associated PLT, so that at runtime
803 877 * ld.so.1 is involved to determine the best binding
804 878 * choice. Otherwise, the value is the symbols value.
805 879 */
806 880 value = ld_calc_plt_addr(sdp, ofl);
807 881 } else
808 882 value = sdp->sd_sym->st_value;
809 883
810 884 /*
811 885 * Relocation against the GLOBAL_OFFSET_TABLE.
812 886 */
813 887 if ((arsp->rel_flags & FLG_REL_GOT) &&
814 888 !ld_reloc_set_aux_osdesc(ofl, arsp, ofl->ofl_osgot))
815 889 return (S_ERROR);
816 890 osp = RELAUX_GET_OSDESC(arsp);
817 891
818 892 /*
819 893 * If loadable and not producing a relocatable object add the
820 894 * sections virtual address to the reference address.
821 895 */
822 896 if ((arsp->rel_flags & FLG_REL_LOAD) &&
823 897 ((flags & FLG_OF_RELOBJ) == 0))
824 898 refaddr += arsp->rel_isdesc->is_osdesc->
825 899 os_shdr->sh_addr;
826 900
827 901 /*
828 902 * If this entry has a PLT assigned to it, its value is actually
829 903 * the address of the PLT (and not the address of the function).
830 904 */
831 905 if (IS_PLT(arsp->rel_rtype)) {
832 906 if (sdp->sd_aux && sdp->sd_aux->sa_PLTndx)
833 907 value = ld_calc_plt_addr(sdp, ofl);
834 908 }
835 909
836 910 /*
837 911 * Add relocations addend to value. Add extra
838 912 * relocation addend if needed.
839 913 *
840 914 * Note: For GOT relative relocations on amd64 we discard the
841 915 * addend. It was relevant to the reference - not to the
842 916 * data item being referenced (ie: that -4 thing).
843 917 */
844 918 if ((arsp->rel_flags & FLG_REL_GOT) == 0)
845 919 value += arsp->rel_raddend;
846 920
847 921 /*
848 922 * Determine whether the value needs further adjustment. Filter
849 923 * through the attributes of the relocation to determine what
850 924 * adjustment is required. Note, many of the following cases
851 925 * are only applicable when a .got is present. As a .got is
852 926 * not generated when a relocatable object is being built,
853 927 * any adjustments that require a .got need to be skipped.
854 928 */
855 929 if ((arsp->rel_flags & FLG_REL_GOT) &&
856 930 ((flags & FLG_OF_RELOBJ) == 0)) {
857 931 Xword R1addr;
858 932 uintptr_t R2addr;
859 933 Word gotndx;
860 934 Gotndx *gnp;
861 935
862 936 /*
863 937 * Perform relocation against GOT table. Since this
864 938 * doesn't fit exactly into a relocation we place the
865 939 * appropriate byte in the GOT directly
866 940 *
867 941 * Calculate offset into GOT at which to apply
868 942 * the relocation.
869 943 */
870 944 gnp = ld_find_got_ndx(sdp->sd_GOTndxs, gref, ofl, arsp);
871 945 assert(gnp);
872 946
873 947 if (arsp->rel_rtype == R_AMD64_DTPOFF64)
874 948 gotndx = gnp->gn_gotndx + 1;
875 949 else
876 950 gotndx = gnp->gn_gotndx;
877 951
878 952 R1addr = (Xword)(gotndx * M_GOT_ENTSIZE);
879 953
880 954 /*
881 955 * Add the GOTs data's offset.
882 956 */
883 957 R2addr = R1addr + (uintptr_t)osp->os_outdata->d_buf;
884 958
885 959 DBG_CALL(Dbg_reloc_doact(ofl->ofl_lml, ELF_DBG_LD_ACT,
886 960 M_MACH, SHT_RELA, arsp, R1addr, value,
887 961 ld_reloc_sym_name));
888 962
889 963 /*
890 964 * And do it.
891 965 */
892 966 if (ofl->ofl_flags1 & FLG_OF1_ENCDIFF)
893 967 *(Xword *)R2addr = ld_bswap_Xword(value);
894 968 else
895 969 *(Xword *)R2addr = value;
896 970 continue;
897 971
898 972 } else if (IS_GOT_BASED(arsp->rel_rtype) &&
899 973 ((flags & FLG_OF_RELOBJ) == 0)) {
900 974 value -= ofl->ofl_osgot->os_shdr->sh_addr;
901 975
902 976 } else if (IS_GOTPCREL(arsp->rel_rtype) &&
903 977 ((flags & FLG_OF_RELOBJ) == 0)) {
904 978 Gotndx *gnp;
905 979
906 980 /*
907 981 * Calculation:
908 982 * G + GOT + A - P
909 983 */
910 984 gnp = ld_find_got_ndx(sdp->sd_GOTndxs, gref, ofl, arsp);
911 985 assert(gnp);
912 986 value = (Xword)(ofl->ofl_osgot->os_shdr-> sh_addr) +
913 987 ((Xword)gnp->gn_gotndx * M_GOT_ENTSIZE) +
914 988 arsp->rel_raddend - refaddr;
915 989
916 990 } else if (IS_GOT_PC(arsp->rel_rtype) &&
917 991 ((flags & FLG_OF_RELOBJ) == 0)) {
918 992 value = (Xword)(ofl->ofl_osgot->os_shdr->
919 993 sh_addr) - refaddr + arsp->rel_raddend;
920 994
921 995 } else if ((IS_PC_RELATIVE(arsp->rel_rtype)) &&
922 996 (((flags & FLG_OF_RELOBJ) == 0) ||
923 997 (osp == sdp->sd_isc->is_osdesc))) {
924 998 value -= refaddr;
925 999
926 1000 } else if (IS_TLS_INS(arsp->rel_rtype) &&
927 1001 IS_GOT_RELATIVE(arsp->rel_rtype) &&
928 1002 ((flags & FLG_OF_RELOBJ) == 0)) {
929 1003 Gotndx *gnp;
930 1004
931 1005 gnp = ld_find_got_ndx(sdp->sd_GOTndxs, gref, ofl, arsp);
932 1006 assert(gnp);
933 1007 value = (Xword)gnp->gn_gotndx * M_GOT_ENTSIZE;
934 1008
935 1009 } else if (IS_GOT_RELATIVE(arsp->rel_rtype) &&
936 1010 ((flags & FLG_OF_RELOBJ) == 0)) {
937 1011 Gotndx *gnp;
938 1012
939 1013 gnp = ld_find_got_ndx(sdp->sd_GOTndxs, gref, ofl, arsp);
940 1014 assert(gnp);
941 1015 value = (Xword)gnp->gn_gotndx * M_GOT_ENTSIZE;
942 1016
943 1017 } else if ((arsp->rel_flags & FLG_REL_STLS) &&
944 1018 ((flags & FLG_OF_RELOBJ) == 0)) {
945 1019 Xword tlsstatsize;
946 1020
947 1021 /*
948 1022 * This is the LE TLS reference model. Static
949 1023 * offset is hard-coded.
950 1024 */
951 1025 tlsstatsize = S_ROUND(ofl->ofl_tlsphdr->p_memsz,
952 1026 M_TLSSTATALIGN);
953 1027 value = tlsstatsize - value;
954 1028
955 1029 /*
956 1030 * Since this code is fixed up, it assumes a negative
957 1031 * offset that can be added to the thread pointer.
958 1032 */
959 1033 if (arsp->rel_rtype == R_AMD64_TPOFF32)
960 1034 value = -value;
961 1035 }
962 1036
963 1037 if (arsp->rel_isdesc->is_file)
964 1038 ifl_name = arsp->rel_isdesc->is_file->ifl_name;
965 1039 else
966 1040 ifl_name = MSG_INTL(MSG_STR_NULL);
967 1041
968 1042 /*
969 1043 * Make sure we have data to relocate. Compiler and assembler
970 1044 * developers have been known to generate relocations against
971 1045 * invalid sections (normally .bss), so for their benefit give
972 1046 * them sufficient information to help analyze the problem.
973 1047 * End users should never see this.
974 1048 */
975 1049 if (arsp->rel_isdesc->is_indata->d_buf == 0) {
976 1050 Conv_inv_buf_t inv_buf;
977 1051
978 1052 ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_REL_EMPTYSEC),
979 1053 conv_reloc_amd64_type(arsp->rel_rtype, 0, &inv_buf),
980 1054 ifl_name, ld_reloc_sym_name(arsp),
981 1055 EC_WORD(arsp->rel_isdesc->is_scnndx),
982 1056 arsp->rel_isdesc->is_name);
983 1057 return (S_ERROR);
984 1058 }
985 1059
986 1060 /*
987 1061 * Get the address of the data item we need to modify.
988 1062 */
989 1063 addr = (uchar_t *)((uintptr_t)arsp->rel_roffset +
990 1064 (uintptr_t)_elf_getxoff(arsp->rel_isdesc->is_indata));
991 1065
992 1066 DBG_CALL(Dbg_reloc_doact(ofl->ofl_lml, ELF_DBG_LD_ACT,
993 1067 M_MACH, SHT_RELA, arsp, EC_NATPTR(addr), value,
994 1068 ld_reloc_sym_name));
995 1069 addr += (uintptr_t)osp->os_outdata->d_buf;
996 1070
997 1071 if ((((uintptr_t)addr - (uintptr_t)ofl->ofl_nehdr) >
998 1072 ofl->ofl_size) || (arsp->rel_roffset >
999 1073 osp->os_shdr->sh_size)) {
1000 1074 int class;
1001 1075 Conv_inv_buf_t inv_buf;
1002 1076
1003 1077 if (((uintptr_t)addr - (uintptr_t)ofl->ofl_nehdr) >
1004 1078 ofl->ofl_size)
1005 1079 class = ERR_FATAL;
1006 1080 else
1007 1081 class = ERR_WARNING;
1008 1082
1009 1083 ld_eprintf(ofl, class, MSG_INTL(MSG_REL_INVALOFFSET),
1010 1084 conv_reloc_amd64_type(arsp->rel_rtype, 0, &inv_buf),
1011 1085 ifl_name, EC_WORD(arsp->rel_isdesc->is_scnndx),
1012 1086 arsp->rel_isdesc->is_name, ld_reloc_sym_name(arsp),
1013 1087 EC_ADDR((uintptr_t)addr -
1014 1088 (uintptr_t)ofl->ofl_nehdr));
1015 1089
1016 1090 if (class == ERR_FATAL) {
1017 1091 return_code = S_ERROR;
1018 1092 continue;
1019 1093 }
1020 1094 }
1021 1095
1022 1096 /*
1023 1097 * The relocation is additive. Ignore the previous symbol
1024 1098 * value if this local partial symbol is expanded.
1025 1099 */
1026 1100 if (moved)
1027 1101 value -= *addr;
1028 1102
1029 1103 /*
1030 1104 * If '-z noreloc' is specified - skip the do_reloc_ld stage.
1031 1105 */
1032 1106 if (OFL_DO_RELOC(ofl)) {
1033 1107 /*
1034 1108 * If this is a PROGBITS section and the running linker
1035 1109 * has a different byte order than the target host,
1036 1110 * tell do_reloc_ld() to swap bytes.
1037 1111 */
1038 1112 if (do_reloc_ld(arsp, addr, &value, ld_reloc_sym_name,
1039 1113 ifl_name, OFL_SWAP_RELOC_DATA(ofl, arsp),
1040 1114 ofl->ofl_lml) == 0) {
1041 1115 ofl->ofl_flags |= FLG_OF_FATAL;
1042 1116 return_code = S_ERROR;
1043 1117 }
1044 1118 }
1045 1119 }
1046 1120 return (return_code);
1047 1121 }
1048 1122
1049 1123 static uintptr_t
1050 1124 ld_add_outrel(Word flags, Rel_desc *rsp, Ofl_desc *ofl)
1051 1125 {
1052 1126 Rel_desc *orsp;
1053 1127 Sym_desc *sdp = rsp->rel_sym;
1054 1128
1055 1129 /*
1056 1130 * Static executables *do not* want any relocations against them.
1057 1131 * Since our engine still creates relocations against a WEAK UNDEFINED
1058 1132 * symbol in a static executable, it's best to disable them here
1059 1133 * instead of through out the relocation code.
1060 1134 */
1061 1135 if (OFL_IS_STATIC_EXEC(ofl))
1062 1136 return (1);
1063 1137
1064 1138 /*
1065 1139 * If we are adding a output relocation against a section
1066 1140 * symbol (non-RELATIVE) then mark that section. These sections
1067 1141 * will be added to the .dynsym symbol table.
1068 1142 */
1069 1143 if (sdp && (rsp->rel_rtype != M_R_RELATIVE) &&
1070 1144 ((flags & FLG_REL_SCNNDX) ||
1071 1145 (ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION))) {
1072 1146
1073 1147 /*
1074 1148 * If this is a COMMON symbol - no output section
1075 1149 * exists yet - (it's created as part of sym_validate()).
1076 1150 * So - we mark here that when it's created it should
1077 1151 * be tagged with the FLG_OS_OUTREL flag.
1078 1152 */
1079 1153 if ((sdp->sd_flags & FLG_SY_SPECSEC) &&
1080 1154 (sdp->sd_sym->st_shndx == SHN_COMMON)) {
1081 1155 if (ELF_ST_TYPE(sdp->sd_sym->st_info) != STT_TLS)
1082 1156 ofl->ofl_flags1 |= FLG_OF1_BSSOREL;
1083 1157 else
1084 1158 ofl->ofl_flags1 |= FLG_OF1_TLSOREL;
1085 1159 } else {
1086 1160 Os_desc *osp;
1087 1161 Is_desc *isp = sdp->sd_isc;
1088 1162
1089 1163 if (isp && ((osp = isp->is_osdesc) != NULL) &&
1090 1164 ((osp->os_flags & FLG_OS_OUTREL) == 0)) {
1091 1165 ofl->ofl_dynshdrcnt++;
1092 1166 osp->os_flags |= FLG_OS_OUTREL;
1093 1167 }
1094 1168 }
1095 1169 }
1096 1170
1097 1171 /* Enter it into the output relocation cache */
1098 1172 if ((orsp = ld_reloc_enter(ofl, &ofl->ofl_outrels, rsp, flags)) == NULL)
1099 1173 return (S_ERROR);
1100 1174
1101 1175 if (flags & FLG_REL_GOT)
1102 1176 ofl->ofl_relocgotsz += (Xword)sizeof (Rela);
1103 1177 else if (flags & FLG_REL_PLT)
1104 1178 ofl->ofl_relocpltsz += (Xword)sizeof (Rela);
1105 1179 else if (flags & FLG_REL_BSS)
1106 1180 ofl->ofl_relocbsssz += (Xword)sizeof (Rela);
1107 1181 else if (flags & FLG_REL_NOINFO)
1108 1182 ofl->ofl_relocrelsz += (Xword)sizeof (Rela);
1109 1183 else
1110 1184 RELAUX_GET_OSDESC(orsp)->os_szoutrels += (Xword)sizeof (Rela);
1111 1185
1112 1186 if (orsp->rel_rtype == M_R_RELATIVE)
1113 1187 ofl->ofl_relocrelcnt++;
1114 1188
1115 1189 /*
1116 1190 * We don't perform sorting on PLT relocations because
1117 1191 * they have already been assigned a PLT index and if we
1118 1192 * were to sort them we would have to re-assign the plt indexes.
1119 1193 */
1120 1194 if (!(flags & FLG_REL_PLT))
1121 1195 ofl->ofl_reloccnt++;
1122 1196
1123 1197 /*
1124 1198 * Insure a GLOBAL_OFFSET_TABLE is generated if required.
1125 1199 */
1126 1200 if (IS_GOT_REQUIRED(orsp->rel_rtype))
1127 1201 ofl->ofl_flags |= FLG_OF_BLDGOT;
1128 1202
1129 1203 /*
1130 1204 * Identify and possibly warn of a displacement relocation.
1131 1205 */
1132 1206 if (orsp->rel_flags & FLG_REL_DISP) {
1133 1207 ofl->ofl_dtflags_1 |= DF_1_DISPRELPND;
1134 1208
1135 1209 if (ofl->ofl_flags & FLG_OF_VERBOSE)
1136 1210 ld_disp_errmsg(MSG_INTL(MSG_REL_DISPREL4), orsp, ofl);
1137 1211 }
1138 1212 DBG_CALL(Dbg_reloc_ors_entry(ofl->ofl_lml, ELF_DBG_LD, SHT_RELA,
1139 1213 M_MACH, orsp));
1140 1214 return (1);
1141 1215 }
1142 1216
1143 1217 /*
1144 1218 * process relocation for a LOCAL symbol
1145 1219 */
1146 1220 static uintptr_t
1147 1221 ld_reloc_local(Rel_desc * rsp, Ofl_desc * ofl)
1148 1222 {
1149 1223 ofl_flag_t flags = ofl->ofl_flags;
1150 1224 Sym_desc *sdp = rsp->rel_sym;
1151 1225 Word shndx = sdp->sd_sym->st_shndx;
1152 1226 Word ortype = rsp->rel_rtype;
1153 1227
1154 1228 /*
1155 1229 * if ((shared object) and (not pc relative relocation) and
1156 1230 * (not against ABS symbol))
1157 1231 * then
1158 1232 * build R_AMD64_RELATIVE
1159 1233 * fi
1160 1234 */
1161 1235 if ((flags & FLG_OF_SHAROBJ) && (rsp->rel_flags & FLG_REL_LOAD) &&
1162 1236 !(IS_PC_RELATIVE(rsp->rel_rtype)) && !(IS_SIZE(rsp->rel_rtype)) &&
1163 1237 !(IS_GOT_BASED(rsp->rel_rtype)) &&
1164 1238 !(rsp->rel_isdesc != NULL &&
1165 1239 (rsp->rel_isdesc->is_shdr->sh_type == SHT_SUNW_dof)) &&
1166 1240 (((sdp->sd_flags & FLG_SY_SPECSEC) == 0) ||
1167 1241 (shndx != SHN_ABS) || (sdp->sd_aux && sdp->sd_aux->sa_symspec))) {
1168 1242
1169 1243 /*
1170 1244 * R_AMD64_RELATIVE updates a 64bit address, if this
1171 1245 * relocation isn't a 64bit binding then we can not
1172 1246 * simplify it to a RELATIVE relocation.
1173 1247 */
1174 1248 if (reloc_table[ortype].re_fsize != sizeof (Addr)) {
1175 1249 return (ld_add_outrel(0, rsp, ofl));
1176 1250 }
1177 1251
1178 1252 rsp->rel_rtype = R_AMD64_RELATIVE;
1179 1253 if (ld_add_outrel(FLG_REL_ADVAL, rsp, ofl) == S_ERROR)
1180 1254 return (S_ERROR);
1181 1255 rsp->rel_rtype = ortype;
1182 1256 return (1);
1183 1257 }
1184 1258
1185 1259 /*
1186 1260 * If the relocation is against a 'non-allocatable' section
1187 1261 * and we can not resolve it now - then give a warning
1188 1262 * message.
1189 1263 *
1190 1264 * We can not resolve the symbol if either:
1191 1265 * a) it's undefined
1192 1266 * b) it's defined in a shared library and a
1193 1267 * COPY relocation hasn't moved it to the executable
1194 1268 *
1195 1269 * Note: because we process all of the relocations against the
1196 1270 * text segment before any others - we know whether
1197 1271 * or not a copy relocation will be generated before
1198 1272 * we get here (see reloc_init()->reloc_segments()).
1199 1273 */
1200 1274 if (!(rsp->rel_flags & FLG_REL_LOAD) &&
1201 1275 ((shndx == SHN_UNDEF) ||
1202 1276 ((sdp->sd_ref == REF_DYN_NEED) &&
1203 1277 ((sdp->sd_flags & FLG_SY_MVTOCOMM) == 0)))) {
1204 1278 Conv_inv_buf_t inv_buf;
1205 1279 Os_desc *osp = RELAUX_GET_OSDESC(rsp);
1206 1280
1207 1281 /*
1208 1282 * If the relocation is against a SHT_SUNW_ANNOTATE
1209 1283 * section - then silently ignore that the relocation
1210 1284 * can not be resolved.
1211 1285 */
1212 1286 if (osp && (osp->os_shdr->sh_type == SHT_SUNW_ANNOTATE))
1213 1287 return (0);
1214 1288 ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_REL_EXTERNSYM),
1215 1289 conv_reloc_amd64_type(rsp->rel_rtype, 0, &inv_buf),
1216 1290 rsp->rel_isdesc->is_file->ifl_name,
1217 1291 ld_reloc_sym_name(rsp), osp->os_name);
1218 1292 return (1);
1219 1293 }
1220 1294
1221 1295 /*
1222 1296 * Perform relocation.
1223 1297 */
1224 1298 return (ld_add_actrel(NULL, rsp, ofl));
1225 1299 }
1226 1300
1227 1301
1228 1302 static uintptr_t
1229 1303 ld_reloc_TLS(Boolean local, Rel_desc * rsp, Ofl_desc * ofl)
1230 1304 {
1231 1305 Word rtype = rsp->rel_rtype;
1232 1306 Sym_desc *sdp = rsp->rel_sym;
1233 1307 ofl_flag_t flags = ofl->ofl_flags;
1234 1308 Gotndx *gnp;
1235 1309
1236 1310 /*
1237 1311 * If we're building an executable - use either the IE or LE access
1238 1312 * model. If we're building a shared object process any IE model.
1239 1313 */
1240 1314 if ((flags & FLG_OF_EXEC) || (IS_TLS_IE(rtype))) {
1241 1315 /*
1242 1316 * Set the DF_STATIC_TLS flag.
1243 1317 */
1244 1318 ofl->ofl_dtflags |= DF_STATIC_TLS;
1245 1319
1246 1320 if (!local || ((flags & FLG_OF_EXEC) == 0)) {
1247 1321 /*
1248 1322 * Assign a GOT entry for static TLS references.
1249 1323 */
1250 1324 if ((gnp = ld_find_got_ndx(sdp->sd_GOTndxs,
1251 1325 GOT_REF_TLSIE, ofl, rsp)) == NULL) {
1252 1326
1253 1327 if (ld_assign_got_TLS(local, rsp, ofl, sdp,
1254 1328 gnp, GOT_REF_TLSIE, FLG_REL_STLS,
1255 1329 rtype, R_AMD64_TPOFF64, 0) == S_ERROR)
1256 1330 return (S_ERROR);
1257 1331 }
1258 1332
1259 1333 /*
1260 1334 * IE access model.
1261 1335 */
1262 1336 if (IS_TLS_IE(rtype))
1263 1337 return (ld_add_actrel(FLG_REL_STLS, rsp, ofl));
1264 1338
1265 1339 /*
1266 1340 * Fixups are required for other executable models.
1267 1341 */
1268 1342 return (ld_add_actrel((FLG_REL_TLSFIX | FLG_REL_STLS),
1269 1343 rsp, ofl));
1270 1344 }
1271 1345
1272 1346 /*
1273 1347 * LE access model.
1274 1348 */
1275 1349 if (IS_TLS_LE(rtype))
1276 1350 return (ld_add_actrel(FLG_REL_STLS, rsp, ofl));
1277 1351
1278 1352 return (ld_add_actrel((FLG_REL_TLSFIX | FLG_REL_STLS),
1279 1353 rsp, ofl));
1280 1354 }
1281 1355
1282 1356 /*
1283 1357 * Building a shared object.
1284 1358 *
1285 1359 * Assign a GOT entry for a dynamic TLS reference.
1286 1360 */
1287 1361 if (IS_TLS_LD(rtype) && ((gnp = ld_find_got_ndx(sdp->sd_GOTndxs,
1288 1362 GOT_REF_TLSLD, ofl, rsp)) == NULL)) {
1289 1363
1290 1364 if (ld_assign_got_TLS(local, rsp, ofl, sdp, gnp, GOT_REF_TLSLD,
1291 1365 FLG_REL_MTLS, rtype, R_AMD64_DTPMOD64, NULL) == S_ERROR)
1292 1366 return (S_ERROR);
1293 1367
1294 1368 } else if (IS_TLS_GD(rtype) &&
1295 1369 ((gnp = ld_find_got_ndx(sdp->sd_GOTndxs, GOT_REF_TLSGD,
1296 1370 ofl, rsp)) == NULL)) {
1297 1371
1298 1372 if (ld_assign_got_TLS(local, rsp, ofl, sdp, gnp, GOT_REF_TLSGD,
1299 1373 FLG_REL_DTLS, rtype, R_AMD64_DTPMOD64,
1300 1374 R_AMD64_DTPOFF64) == S_ERROR)
1301 1375 return (S_ERROR);
1302 1376 }
1303 1377
1304 1378 if (IS_TLS_LD(rtype))
1305 1379 return (ld_add_actrel(FLG_REL_MTLS, rsp, ofl));
1306 1380
1307 1381 return (ld_add_actrel(FLG_REL_DTLS, rsp, ofl));
1308 1382 }
1309 1383
1310 1384 /* ARGSUSED5 */
1311 1385 static uintptr_t
1312 1386 ld_assign_got_ndx(Alist **alpp, Gotndx *pgnp, Gotref gref, Ofl_desc *ofl,
1313 1387 Rel_desc *rsp, Sym_desc *sdp)
1314 1388 {
1315 1389 Xword raddend;
1316 1390 Gotndx gn, *gnp;
1317 1391 Aliste idx;
1318 1392 uint_t gotents;
1319 1393
1320 1394 raddend = rsp->rel_raddend;
1321 1395 if (pgnp && (pgnp->gn_addend == raddend) && (pgnp->gn_gotref == gref))
1322 1396 return (1);
1323 1397
1324 1398 if ((gref == GOT_REF_TLSGD) || (gref == GOT_REF_TLSLD))
1325 1399 gotents = 2;
1326 1400 else
1327 1401 gotents = 1;
1328 1402
1329 1403 gn.gn_addend = raddend;
1330 1404 gn.gn_gotndx = ofl->ofl_gotcnt;
1331 1405 gn.gn_gotref = gref;
1332 1406
1333 1407 ofl->ofl_gotcnt += gotents;
1334 1408
1335 1409 if (gref == GOT_REF_TLSLD) {
1336 1410 if (ofl->ofl_tlsldgotndx == NULL) {
1337 1411 if ((gnp = libld_malloc(sizeof (Gotndx))) == NULL)
1338 1412 return (S_ERROR);
1339 1413 (void) memcpy(gnp, &gn, sizeof (Gotndx));
1340 1414 ofl->ofl_tlsldgotndx = gnp;
1341 1415 }
1342 1416 return (1);
1343 1417 }
1344 1418
1345 1419 idx = 0;
1346 1420 for (ALIST_TRAVERSE(*alpp, idx, gnp)) {
1347 1421 if (gnp->gn_addend > raddend)
1348 1422 break;
1349 1423 }
1350 1424
1351 1425 /*
1352 1426 * GOT indexes are maintained on an Alist, where there is typically
1353 1427 * only one index. The usage of this list is to scan the list to find
1354 1428 * an index, and then apply that index immediately to a relocation.
1355 1429 * Thus there are no external references to these GOT index structures
1356 1430 * that can be compromised by the Alist being reallocated.
1357 1431 */
1358 1432 if (alist_insert(alpp, &gn, sizeof (Gotndx),
1359 1433 AL_CNT_SDP_GOT, idx) == NULL)
1360 1434 return (S_ERROR);
1361 1435
1362 1436 return (1);
1363 1437 }
1364 1438
1365 1439 static void
1366 1440 ld_assign_plt_ndx(Sym_desc * sdp, Ofl_desc *ofl)
1367 1441 {
1368 1442 sdp->sd_aux->sa_PLTndx = 1 + ofl->ofl_pltcnt++;
1369 1443 sdp->sd_aux->sa_PLTGOTndx = ofl->ofl_gotcnt++;
1370 1444 ofl->ofl_flags |= FLG_OF_BLDGOT;
1371 1445 }
1372 1446
1373 1447 static uchar_t plt0_template[M_PLT_ENTSIZE] = {
1374 1448 /* 0x00 PUSHQ GOT+8(%rip) */ 0xff, 0x35, 0x00, 0x00, 0x00, 0x00,
1375 1449 /* 0x06 JMP *GOT+16(%rip) */ 0xff, 0x25, 0x00, 0x00, 0x00, 0x00,
1376 1450 /* 0x0c NOP */ 0x90,
1377 1451 /* 0x0d NOP */ 0x90,
1378 1452 /* 0x0e NOP */ 0x90,
1379 1453 /* 0x0f NOP */ 0x90
1380 1454 };
1381 1455
1382 1456 /*
1383 1457 * Initializes .got[0] with the _DYNAMIC symbol value.
1384 1458 */
1385 1459 static uintptr_t
1386 1460 ld_fillin_gotplt(Ofl_desc *ofl)
1387 1461 {
1388 1462 int bswap = (ofl->ofl_flags1 & FLG_OF1_ENCDIFF) != 0;
1389 1463
1390 1464 if (ofl->ofl_osgot) {
1391 1465 Sym_desc *sdp;
1392 1466
1393 1467 if ((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_DYNAMIC_U),
1394 1468 SYM_NOHASH, NULL, ofl)) != NULL) {
1395 1469 uchar_t *genptr;
1396 1470
1397 1471 genptr = ((uchar_t *)ofl->ofl_osgot->os_outdata->d_buf +
1398 1472 (M_GOT_XDYNAMIC * M_GOT_ENTSIZE));
1399 1473 /* LINTED */
1400 1474 *(Xword *)genptr = sdp->sd_sym->st_value;
1401 1475 if (bswap)
1402 1476 /* LINTED */
1403 1477 *(Xword *)genptr =
1404 1478 /* LINTED */
1405 1479 ld_bswap_Xword(*(Xword *)genptr);
1406 1480 }
1407 1481 }
1408 1482
1409 1483 /*
1410 1484 * Fill in the reserved slot in the procedure linkage table the first
1411 1485 * entry is:
1412 1486 * 0x00 PUSHQ GOT+8(%rip) # GOT[1]
1413 1487 * 0x06 JMP *GOT+16(%rip) # GOT[2]
1414 1488 * 0x0c NOP
1415 1489 * 0x0d NOP
1416 1490 * 0x0e NOP
1417 1491 * 0x0f NOP
1418 1492 */
1419 1493 if ((ofl->ofl_flags & FLG_OF_DYNAMIC) && ofl->ofl_osplt) {
1420 1494 uchar_t *pltent;
1421 1495 Xword val1;
1422 1496
1423 1497 pltent = (uchar_t *)ofl->ofl_osplt->os_outdata->d_buf;
1424 1498 bcopy(plt0_template, pltent, sizeof (plt0_template));
1425 1499
1426 1500 /*
1427 1501 * If '-z noreloc' is specified - skip the do_reloc_ld
1428 1502 * stage.
1429 1503 */
1430 1504 if (!OFL_DO_RELOC(ofl))
1431 1505 return (1);
1432 1506
1433 1507 /*
1434 1508 * filin:
1435 1509 * PUSHQ GOT + 8(%rip)
1436 1510 *
1437 1511 * Note: 0x06 below represents the offset to the
1438 1512 * next instruction - which is what %rip will
1439 1513 * be pointing at.
1440 1514 */
1441 1515 val1 = (ofl->ofl_osgot->os_shdr->sh_addr) +
1442 1516 (M_GOT_XLINKMAP * M_GOT_ENTSIZE) -
1443 1517 ofl->ofl_osplt->os_shdr->sh_addr - 0x06;
1444 1518
1445 1519 if (do_reloc_ld(&rdesc_r_amd64_gotpcrel, &pltent[0x02],
1446 1520 &val1, syn_rdesc_sym_name, MSG_ORIG(MSG_SPECFIL_PLTENT),
1447 1521 bswap, ofl->ofl_lml) == 0) {
1448 1522 ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_PLT_PLT0FAIL));
1449 1523 return (S_ERROR);
1450 1524 }
1451 1525
1452 1526 /*
1453 1527 * filin:
1454 1528 * JMP *GOT+16(%rip)
1455 1529 */
1456 1530 val1 = (ofl->ofl_osgot->os_shdr->sh_addr) +
1457 1531 (M_GOT_XRTLD * M_GOT_ENTSIZE) -
1458 1532 ofl->ofl_osplt->os_shdr->sh_addr - 0x0c;
1459 1533
1460 1534 if (do_reloc_ld(&rdesc_r_amd64_gotpcrel, &pltent[0x08],
1461 1535 &val1, syn_rdesc_sym_name, MSG_ORIG(MSG_SPECFIL_PLTENT),
1462 1536 bswap, ofl->ofl_lml) == 0) {
1463 1537 ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_PLT_PLT0FAIL));
1464 1538 return (S_ERROR);
1465 1539 }
1466 1540 }
1467 1541
1468 1542 return (1);
1469 1543 }
1470 1544
1471 1545
1472 1546
1473 1547 /*
1474 1548 * Template for generating "void (*)(void)" function
1475 1549 */
1476 1550 static const uchar_t nullfunc_tmpl[] = { /* amd64 */
1477 1551 /* 0x00 */ 0x55, /* pushq %rbp */
1478 1552 /* 0x01 */ 0x48, 0x8b, 0xec, /* movq %rsp,%rbp */
1479 1553 /* 0x04 */ 0x48, 0x8b, 0xe5, /* movq %rbp,%rsp */
1480 1554 /* 0x07 */ 0x5d, /* popq %rbp */
1481 1555 /* 0x08 */ 0xc3 /* ret */
1482 1556 };
1483 1557
1484 1558
1485 1559 /*
1486 1560 * Function used to provide fill padding in SHF_EXECINSTR sections
1487 1561 *
1488 1562 * entry:
1489 1563 *
1490 1564 * base - base address of section being filled
1491 1565 * offset - starting offset for fill within memory referenced by base
1492 1566 * cnt - # bytes to be filled
1493 1567 *
1494 1568 * exit:
1495 1569 * The fill has been completed.
1496 1570 */
1497 1571 static void
1498 1572 execfill(void *base, off_t off, size_t cnt)
1499 1573 {
1500 1574 /*
1501 1575 * 0x90 is an X86 NOP instruction in both 32 and 64-bit worlds.
1502 1576 * There are no alignment constraints.
1503 1577 */
1504 1578 (void) memset(off + (char *)base, 0x90, cnt);
1505 1579 }
1506 1580
1507 1581
1508 1582 /*
1509 1583 * Return the ld_targ definition for this target.
1510 1584 */
1511 1585 const Target *
1512 1586 ld_targ_init_x86(void)
1513 1587 {
1514 1588 static const Target _ld_targ = {
1515 1589 { /* Target_mach */
1516 1590 M_MACH, /* m_mach */
1517 1591 M_MACHPLUS, /* m_machplus */
1518 1592 M_FLAGSPLUS, /* m_flagsplus */
1519 1593 M_CLASS, /* m_class */
1520 1594 M_DATA, /* m_data */
1521 1595
1522 1596 M_SEGM_ALIGN, /* m_segm_align */
1523 1597 M_SEGM_ORIGIN, /* m_segm_origin */
1524 1598 M_SEGM_AORIGIN, /* m_segm_aorigin */
1525 1599 M_DATASEG_PERM, /* m_dataseg_perm */
1526 1600 M_STACK_PERM, /* m_stack_perm */
1527 1601 M_WORD_ALIGN, /* m_word_align */
1528 1602 MSG_ORIG(MSG_PTH_RTLD_AMD64), /* m_def_interp */
1529 1603
1530 1604 /* Relocation type codes */
1531 1605 M_R_ARRAYADDR, /* m_r_arrayaddr */
1532 1606 M_R_COPY, /* m_r_copy */
1533 1607 M_R_GLOB_DAT, /* m_r_glob_dat */
1534 1608 M_R_JMP_SLOT, /* m_r_jmp_slot */
1535 1609 M_R_NUM, /* m_r_num */
1536 1610 M_R_NONE, /* m_r_none */
1537 1611 M_R_RELATIVE, /* m_r_relative */
1538 1612 M_R_REGISTER, /* m_r_register */
1539 1613
1540 1614 /* Relocation related constants */
1541 1615 M_REL_DT_COUNT, /* m_rel_dt_count */
1542 1616 M_REL_DT_ENT, /* m_rel_dt_ent */
1543 1617 M_REL_DT_SIZE, /* m_rel_dt_size */
1544 1618 M_REL_DT_TYPE, /* m_rel_dt_type */
1545 1619 M_REL_SHT_TYPE, /* m_rel_sht_type */
1546 1620
1547 1621 /* GOT related constants */
1548 1622 M_GOT_ENTSIZE, /* m_got_entsize */
1549 1623 M_GOT_XNumber, /* m_got_xnumber */
1550 1624
1551 1625 /* PLT related constants */
1552 1626 M_PLT_ALIGN, /* m_plt_align */
1553 1627 M_PLT_ENTSIZE, /* m_plt_entsize */
1554 1628 M_PLT_RESERVSZ, /* m_plt_reservsz */
1555 1629 M_PLT_SHF_FLAGS, /* m_plt_shf_flags */
1556 1630
1557 1631 /* Section type of .eh_frame/.eh_frame_hdr sections */
1558 1632 SHT_AMD64_UNWIND, /* m_sht_unwind */
1559 1633
1560 1634 M_DT_REGISTER, /* m_dt_register */
1561 1635 },
1562 1636 { /* Target_machid */
1563 1637 M_ID_ARRAY, /* id_array */
1564 1638 M_ID_BSS, /* id_bss */
1565 1639 M_ID_CAP, /* id_cap */
1566 1640 M_ID_CAPINFO, /* id_capinfo */
1567 1641 M_ID_CAPCHAIN, /* id_capchain */
1568 1642 M_ID_DATA, /* id_data */
1569 1643 M_ID_DYNAMIC, /* id_dynamic */
1570 1644 M_ID_DYNSORT, /* id_dynsort */
1571 1645 M_ID_DYNSTR, /* id_dynstr */
1572 1646 M_ID_DYNSYM, /* id_dynsym */
1573 1647 M_ID_DYNSYM_NDX, /* id_dynsym_ndx */
1574 1648 M_ID_GOT, /* id_got */
1575 1649 M_ID_UNKNOWN, /* id_gotdata (unused) */
1576 1650 M_ID_HASH, /* id_hash */
1577 1651 M_ID_INTERP, /* id_interp */
1578 1652 M_ID_LBSS, /* id_lbss */
1579 1653 M_ID_LDYNSYM, /* id_ldynsym */
1580 1654 M_ID_NOTE, /* id_note */
1581 1655 M_ID_NULL, /* id_null */
1582 1656 M_ID_PLT, /* id_plt */
1583 1657 M_ID_REL, /* id_rel */
1584 1658 M_ID_STRTAB, /* id_strtab */
1585 1659 M_ID_SYMINFO, /* id_syminfo */
1586 1660 M_ID_SYMTAB, /* id_symtab */
1587 1661 M_ID_SYMTAB_NDX, /* id_symtab_ndx */
1588 1662 M_ID_TEXT, /* id_text */
1589 1663 M_ID_TLS, /* id_tls */
1590 1664 M_ID_TLSBSS, /* id_tlsbss */
1591 1665 M_ID_UNKNOWN, /* id_unknown */
1592 1666 M_ID_UNWIND, /* id_unwind */
1593 1667 M_ID_UNWINDHDR, /* id_unwindhdr */
1594 1668 M_ID_USER, /* id_user */
1595 1669 M_ID_VERSION, /* id_version */
1596 1670 },
1597 1671 { /* Target_nullfunc */
1598 1672 nullfunc_tmpl, /* nf_template */
1599 1673 sizeof (nullfunc_tmpl), /* nf_size */
1600 1674 },
1601 1675 { /* Target_fillfunc */
1602 1676 execfill /* ff_execfill */
1603 1677 },
1604 1678 { /* Target_machrel */
1605 1679 reloc_table,
1606 1680
1607 1681 ld_init_rel, /* mr_init_rel */
1608 1682 ld_mach_eflags, /* mr_mach_eflags */
1609 1683 ld_mach_make_dynamic, /* mr_mach_make_dynamic */
1610 1684 ld_mach_update_odynamic, /* mr_mach_update_odynamic */
1611 1685 ld_calc_plt_addr, /* mr_calc_plt_addr */
1612 1686 ld_perform_outreloc, /* mr_perform_outreloc */
1613 1687 ld_do_activerelocs, /* mr_do_activerelocs */
1614 1688 ld_add_outrel, /* mr_add_outrel */
1615 1689 NULL, /* mr_reloc_register */
1616 1690 ld_reloc_local, /* mr_reloc_local */
1617 1691 NULL, /* mr_reloc_GOTOP */
1618 1692 ld_reloc_TLS, /* mr_reloc_TLS */
1619 1693 NULL, /* mr_assign_got */
1620 1694 ld_find_got_ndx, /* mr_find_got_ndx */
1621 1695 ld_calc_got_offset, /* mr_calc_got_offset */
1622 1696 ld_assign_got_ndx, /* mr_assign_got_ndx */
1623 1697 ld_assign_plt_ndx, /* mr_assign_plt_ndx */
1624 1698 NULL, /* mr_allocate_got */
1625 1699 ld_fillin_gotplt, /* mr_fillin_gotplt */
1626 1700 },
1627 1701 { /* Target_machsym */
1628 1702 NULL, /* ms_reg_check */
1629 1703 NULL, /* ms_mach_sym_typecheck */
1630 1704 NULL, /* ms_is_regsym */
1631 1705 NULL, /* ms_reg_find */
1632 1706 NULL /* ms_reg_enter */
1633 1707 }
1634 1708 };
1635 1709
1636 1710 return (&_ld_targ);
1637 1711 }
↓ open down ↓ |
991 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX