1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #define ELF_TARGET_ALL
30 #include <elf.h>
31
32 #include <sys/types.h>
33 #ifdef illumos
34 #include <sys/sysmacros.h>
35 #else
36 #define P2ROUNDUP(x, align) (-(-(x) & -(align)))
37 #endif
38
39 #include <unistd.h>
40 #include <strings.h>
41 #ifdef illumos
42 #include <alloca.h>
43 #endif
44 #include <limits.h>
45 #include <stddef.h>
46 #include <stdlib.h>
47 #include <stdio.h>
48 #include <fcntl.h>
49 #include <errno.h>
50 #ifdef illumos
51 #include <wait.h>
52 #else
53 #include <sys/wait.h>
54 #include <libelf.h>
55 #include <gelf.h>
56 #include <sys/mman.h>
57 #endif
58 #include <assert.h>
59 #include <sys/ipc.h>
60
61 #include <dt_impl.h>
62 #include <dt_provider.h>
63 #include <dt_program.h>
64 #include <dt_string.h>
65
66 #define ESHDR_NULL 0
67 #define ESHDR_SHSTRTAB 1
68 #define ESHDR_DOF 2
69 #define ESHDR_STRTAB 3
70 #define ESHDR_SYMTAB 4
71 #define ESHDR_REL 5
72 #define ESHDR_NUM 6
73
74 #define PWRITE_SCN(index, data) \
75 (lseek64(fd, (off64_t)elf_file.shdr[(index)].sh_offset, SEEK_SET) != \
76 (off64_t)elf_file.shdr[(index)].sh_offset || \
77 dt_write(dtp, fd, (data), elf_file.shdr[(index)].sh_size) != \
78 elf_file.shdr[(index)].sh_size)
79
80 static const char DTRACE_SHSTRTAB32[] = "\0"
81 ".shstrtab\0" /* 1 */
82 ".SUNW_dof\0" /* 11 */
83 ".strtab\0" /* 21 */
84 ".symtab\0" /* 29 */
85 #ifdef __sparc
86 ".rela.SUNW_dof"; /* 37 */
87 #else
88 ".rel.SUNW_dof"; /* 37 */
89 #endif
90
91 static const char DTRACE_SHSTRTAB64[] = "\0"
92 ".shstrtab\0" /* 1 */
93 ".SUNW_dof\0" /* 11 */
94 ".strtab\0" /* 21 */
95 ".symtab\0" /* 29 */
96 ".rela.SUNW_dof"; /* 37 */
97
98 static const char DOFSTR[] = "__SUNW_dof";
99 static const char DOFLAZYSTR[] = "___SUNW_dof";
100
101 typedef struct dt_link_pair {
102 struct dt_link_pair *dlp_next; /* next pair in linked list */
103 void *dlp_str; /* buffer for string table */
104 void *dlp_sym; /* buffer for symbol table */
105 } dt_link_pair_t;
106
107 typedef struct dof_elf32 {
108 uint32_t de_nrel; /* relocation count */
109 #ifdef __sparc
110 Elf32_Rela *de_rel; /* array of relocations for sparc */
111 #else
112 Elf32_Rel *de_rel; /* array of relocations for x86 */
113 #endif
114 uint32_t de_nsym; /* symbol count */
115 Elf32_Sym *de_sym; /* array of symbols */
116 uint32_t de_strlen; /* size of of string table */
117 char *de_strtab; /* string table */
118 uint32_t de_global; /* index of the first global symbol */
119 } dof_elf32_t;
120
121 static int
prepare_elf32(dtrace_hdl_t * dtp,const dof_hdr_t * dof,dof_elf32_t * dep)122 prepare_elf32(dtrace_hdl_t *dtp, const dof_hdr_t *dof, dof_elf32_t *dep)
123 {
124 dof_sec_t *dofs, *s;
125 dof_relohdr_t *dofrh;
126 dof_relodesc_t *dofr;
127 char *strtab;
128 int i, j, nrel;
129 size_t strtabsz = 1;
130 uint32_t count = 0;
131 size_t base;
132 Elf32_Sym *sym;
133 #ifdef __sparc
134 Elf32_Rela *rel;
135 #else
136 Elf32_Rel *rel;
137 #endif
138
139 /*LINTED*/
140 dofs = (dof_sec_t *)((char *)dof + dof->dofh_secoff);
141
142 /*
143 * First compute the size of the string table and the number of
144 * relocations present in the DOF.
145 */
146 for (i = 0; i < dof->dofh_secnum; i++) {
147 if (dofs[i].dofs_type != DOF_SECT_URELHDR)
148 continue;
149
150 /*LINTED*/
151 dofrh = (dof_relohdr_t *)((char *)dof + dofs[i].dofs_offset);
152
153 s = &dofs[dofrh->dofr_strtab];
154 strtab = (char *)dof + s->dofs_offset;
155 assert(strtab[0] == '\0');
156 strtabsz += s->dofs_size - 1;
157
158 s = &dofs[dofrh->dofr_relsec];
159 /*LINTED*/
160 dofr = (dof_relodesc_t *)((char *)dof + s->dofs_offset);
161 count += s->dofs_size / s->dofs_entsize;
162 }
163
164 dep->de_strlen = strtabsz;
165 dep->de_nrel = count;
166 dep->de_nsym = count + 1; /* the first symbol is always null */
167
168 if (dtp->dt_lazyload) {
169 dep->de_strlen += sizeof (DOFLAZYSTR);
170 dep->de_nsym++;
171 } else {
172 dep->de_strlen += sizeof (DOFSTR);
173 dep->de_nsym++;
174 }
175
176 if ((dep->de_rel = calloc(dep->de_nrel,
177 sizeof (dep->de_rel[0]))) == NULL) {
178 return (dt_set_errno(dtp, EDT_NOMEM));
179 }
180
181 if ((dep->de_sym = calloc(dep->de_nsym, sizeof (Elf32_Sym))) == NULL) {
182 free(dep->de_rel);
183 return (dt_set_errno(dtp, EDT_NOMEM));
184 }
185
186 if ((dep->de_strtab = calloc(dep->de_strlen, 1)) == NULL) {
187 free(dep->de_rel);
188 free(dep->de_sym);
189 return (dt_set_errno(dtp, EDT_NOMEM));
190 }
191
192 count = 0;
193 strtabsz = 1;
194 dep->de_strtab[0] = '\0';
195 rel = dep->de_rel;
196 sym = dep->de_sym;
197 dep->de_global = 1;
198
199 /*
200 * The first symbol table entry must be zeroed and is always ignored.
201 */
202 bzero(sym, sizeof (Elf32_Sym));
203 sym++;
204
205 /*
206 * Take a second pass through the DOF sections filling in the
207 * memory we allocated.
208 */
209 for (i = 0; i < dof->dofh_secnum; i++) {
210 if (dofs[i].dofs_type != DOF_SECT_URELHDR)
211 continue;
212
213 /*LINTED*/
214 dofrh = (dof_relohdr_t *)((char *)dof + dofs[i].dofs_offset);
215
216 s = &dofs[dofrh->dofr_strtab];
217 strtab = (char *)dof + s->dofs_offset;
218 bcopy(strtab + 1, dep->de_strtab + strtabsz, s->dofs_size);
219 base = strtabsz;
220 strtabsz += s->dofs_size - 1;
221
222 s = &dofs[dofrh->dofr_relsec];
223 /*LINTED*/
224 dofr = (dof_relodesc_t *)((char *)dof + s->dofs_offset);
225 nrel = s->dofs_size / s->dofs_entsize;
226
227 s = &dofs[dofrh->dofr_tgtsec];
228
229 for (j = 0; j < nrel; j++) {
230 #if defined(__aarch64__)
231 /* XXX */
232 printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
233 #elif defined(__arm__)
234 /* XXX */
235 printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
236 #elif defined(__i386) || defined(__amd64)
237 rel->r_offset = s->dofs_offset +
238 dofr[j].dofr_offset;
239 rel->r_info = ELF32_R_INFO(count + dep->de_global,
240 R_386_32);
241 #elif defined(__mips__)
242 /* XXX */
243 printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
244 #elif defined(__powerpc__)
245 /*
246 * Add 4 bytes to hit the low half of this 64-bit
247 * big-endian address.
248 */
249 rel->r_offset = s->dofs_offset +
250 dofr[j].dofr_offset + 4;
251 rel->r_info = ELF32_R_INFO(count + dep->de_global,
252 R_PPC_REL32);
253 #elif defined(__sparc)
254 /*
255 * Add 4 bytes to hit the low half of this 64-bit
256 * big-endian address.
257 */
258 rel->r_offset = s->dofs_offset +
259 dofr[j].dofr_offset + 4;
260 rel->r_info = ELF32_R_INFO(count + dep->de_global,
261 R_SPARC_32);
262 #else
263 #error unknown ISA
264 #endif
265
266 sym->st_name = base + dofr[j].dofr_name - 1;
267 sym->st_value = 0;
268 sym->st_size = 0;
269 sym->st_info = ELF32_ST_INFO(STB_GLOBAL, STT_FUNC);
270 sym->st_other = 0;
271 sym->st_shndx = SHN_UNDEF;
272
273 rel++;
274 sym++;
275 count++;
276 }
277 }
278
279 /*
280 * Add a symbol for the DOF itself. We use a different symbol for
281 * lazily and actively loaded DOF to make them easy to distinguish.
282 */
283 sym->st_name = strtabsz;
284 sym->st_value = 0;
285 sym->st_size = dof->dofh_filesz;
286 sym->st_info = ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT);
287 #ifdef illumos
288 sym->st_other = 0;
289 #else
290 sym->st_other = ELF32_ST_VISIBILITY(STV_HIDDEN);
291 #endif
292 sym->st_shndx = ESHDR_DOF;
293 sym++;
294
295 if (dtp->dt_lazyload) {
296 bcopy(DOFLAZYSTR, dep->de_strtab + strtabsz,
297 sizeof (DOFLAZYSTR));
298 strtabsz += sizeof (DOFLAZYSTR);
299 } else {
300 bcopy(DOFSTR, dep->de_strtab + strtabsz, sizeof (DOFSTR));
301 strtabsz += sizeof (DOFSTR);
302 }
303
304 assert(count == dep->de_nrel);
305 assert(strtabsz == dep->de_strlen);
306
307 return (0);
308 }
309
310
311 typedef struct dof_elf64 {
312 uint32_t de_nrel;
313 Elf64_Rela *de_rel;
314 uint32_t de_nsym;
315 Elf64_Sym *de_sym;
316
317 uint32_t de_strlen;
318 char *de_strtab;
319
320 uint32_t de_global;
321 } dof_elf64_t;
322
323 static int
prepare_elf64(dtrace_hdl_t * dtp,const dof_hdr_t * dof,dof_elf64_t * dep)324 prepare_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, dof_elf64_t *dep)
325 {
326 dof_sec_t *dofs, *s;
327 dof_relohdr_t *dofrh;
328 dof_relodesc_t *dofr;
329 char *strtab;
330 int i, j, nrel;
331 size_t strtabsz = 1;
332 #ifdef illumos
333 uint32_t count = 0;
334 #else
335 uint64_t count = 0;
336 #endif
337 size_t base;
338 Elf64_Sym *sym;
339 Elf64_Rela *rel;
340
341 /*LINTED*/
342 dofs = (dof_sec_t *)((char *)dof + dof->dofh_secoff);
343
344 /*
345 * First compute the size of the string table and the number of
346 * relocations present in the DOF.
347 */
348 for (i = 0; i < dof->dofh_secnum; i++) {
349 if (dofs[i].dofs_type != DOF_SECT_URELHDR)
350 continue;
351
352 /*LINTED*/
353 dofrh = (dof_relohdr_t *)((char *)dof + dofs[i].dofs_offset);
354
355 s = &dofs[dofrh->dofr_strtab];
356 strtab = (char *)dof + s->dofs_offset;
357 assert(strtab[0] == '\0');
358 strtabsz += s->dofs_size - 1;
359
360 s = &dofs[dofrh->dofr_relsec];
361 /*LINTED*/
362 dofr = (dof_relodesc_t *)((char *)dof + s->dofs_offset);
363 count += s->dofs_size / s->dofs_entsize;
364 }
365
366 dep->de_strlen = strtabsz;
367 dep->de_nrel = count;
368 dep->de_nsym = count + 1; /* the first symbol is always null */
369
370 if (dtp->dt_lazyload) {
371 dep->de_strlen += sizeof (DOFLAZYSTR);
372 dep->de_nsym++;
373 } else {
374 dep->de_strlen += sizeof (DOFSTR);
375 dep->de_nsym++;
376 }
377
378 if ((dep->de_rel = calloc(dep->de_nrel,
379 sizeof (dep->de_rel[0]))) == NULL) {
380 return (dt_set_errno(dtp, EDT_NOMEM));
381 }
382
383 if ((dep->de_sym = calloc(dep->de_nsym, sizeof (Elf64_Sym))) == NULL) {
384 free(dep->de_rel);
385 return (dt_set_errno(dtp, EDT_NOMEM));
386 }
387
388 if ((dep->de_strtab = calloc(dep->de_strlen, 1)) == NULL) {
389 free(dep->de_rel);
390 free(dep->de_sym);
391 return (dt_set_errno(dtp, EDT_NOMEM));
392 }
393
394 count = 0;
395 strtabsz = 1;
396 dep->de_strtab[0] = '\0';
397 rel = dep->de_rel;
398 sym = dep->de_sym;
399 dep->de_global = 1;
400
401 /*
402 * The first symbol table entry must be zeroed and is always ignored.
403 */
404 bzero(sym, sizeof (Elf64_Sym));
405 sym++;
406
407 /*
408 * Take a second pass through the DOF sections filling in the
409 * memory we allocated.
410 */
411 for (i = 0; i < dof->dofh_secnum; i++) {
412 if (dofs[i].dofs_type != DOF_SECT_URELHDR)
413 continue;
414
415 /*LINTED*/
416 dofrh = (dof_relohdr_t *)((char *)dof + dofs[i].dofs_offset);
417
418 s = &dofs[dofrh->dofr_strtab];
419 strtab = (char *)dof + s->dofs_offset;
420 bcopy(strtab + 1, dep->de_strtab + strtabsz, s->dofs_size);
421 base = strtabsz;
422 strtabsz += s->dofs_size - 1;
423
424 s = &dofs[dofrh->dofr_relsec];
425 /*LINTED*/
426 dofr = (dof_relodesc_t *)((char *)dof + s->dofs_offset);
427 nrel = s->dofs_size / s->dofs_entsize;
428
429 s = &dofs[dofrh->dofr_tgtsec];
430
431 for (j = 0; j < nrel; j++) {
432 #if defined(__aarch64__)
433 /* XXX */
434 #elif defined(__arm__)
435 /* XXX */
436 #elif defined(__mips__)
437 /* XXX */
438 #elif defined(__powerpc__)
439 rel->r_offset = s->dofs_offset +
440 dofr[j].dofr_offset;
441 rel->r_info = ELF64_R_INFO(count + dep->de_global,
442 R_PPC64_REL64);
443 #elif defined(__i386) || defined(__amd64)
444 rel->r_offset = s->dofs_offset +
445 dofr[j].dofr_offset;
446 #ifdef illumos
447 rel->r_info = ELF64_R_INFO(count + dep->de_global,
448 R_AMD64_64);
449 #else
450 rel->r_info = ELF64_R_INFO(count + dep->de_global,
451 R_X86_64_RELATIVE);
452 #endif
453 #elif defined(__sparc)
454 rel->r_offset = s->dofs_offset +
455 dofr[j].dofr_offset;
456 rel->r_info = ELF64_R_INFO(count + dep->de_global,
457 R_SPARC_64);
458 #else
459 #error unknown ISA
460 #endif
461
462 sym->st_name = base + dofr[j].dofr_name - 1;
463 sym->st_value = 0;
464 sym->st_size = 0;
465 sym->st_info = GELF_ST_INFO(STB_GLOBAL, STT_FUNC);
466 sym->st_other = 0;
467 sym->st_shndx = SHN_UNDEF;
468
469 rel++;
470 sym++;
471 count++;
472 }
473 }
474
475 /*
476 * Add a symbol for the DOF itself. We use a different symbol for
477 * lazily and actively loaded DOF to make them easy to distinguish.
478 */
479 sym->st_name = strtabsz;
480 sym->st_value = 0;
481 sym->st_size = dof->dofh_filesz;
482 sym->st_info = GELF_ST_INFO(STB_GLOBAL, STT_OBJECT);
483 #ifdef illumos
484 sym->st_other = 0;
485 #else
486 sym->st_other = ELF64_ST_VISIBILITY(STV_HIDDEN);
487 #endif
488 sym->st_shndx = ESHDR_DOF;
489 sym++;
490
491 if (dtp->dt_lazyload) {
492 bcopy(DOFLAZYSTR, dep->de_strtab + strtabsz,
493 sizeof (DOFLAZYSTR));
494 strtabsz += sizeof (DOFLAZYSTR);
495 } else {
496 bcopy(DOFSTR, dep->de_strtab + strtabsz, sizeof (DOFSTR));
497 strtabsz += sizeof (DOFSTR);
498 }
499
500 assert(count == dep->de_nrel);
501 assert(strtabsz == dep->de_strlen);
502
503 return (0);
504 }
505
506 /*
507 * Write out an ELF32 file prologue consisting of a header, section headers,
508 * and a section header string table. The DOF data will follow this prologue
509 * and complete the contents of the given ELF file.
510 */
511 static int
dump_elf32(dtrace_hdl_t * dtp,const dof_hdr_t * dof,int fd)512 dump_elf32(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd)
513 {
514 struct {
515 Elf32_Ehdr ehdr;
516 Elf32_Shdr shdr[ESHDR_NUM];
517 } elf_file;
518
519 Elf32_Shdr *shp;
520 Elf32_Off off;
521 dof_elf32_t de;
522 int ret = 0;
523 uint_t nshdr;
524
525 if (prepare_elf32(dtp, dof, &de) != 0)
526 return (-1); /* errno is set for us */
527
528 /*
529 * If there are no relocations, we only need enough sections for
530 * the shstrtab and the DOF.
531 */
532 nshdr = de.de_nrel == 0 ? ESHDR_SYMTAB + 1 : ESHDR_NUM;
533
534 bzero(&elf_file, sizeof (elf_file));
535
536 elf_file.ehdr.e_ident[EI_MAG0] = ELFMAG0;
537 elf_file.ehdr.e_ident[EI_MAG1] = ELFMAG1;
538 elf_file.ehdr.e_ident[EI_MAG2] = ELFMAG2;
539 elf_file.ehdr.e_ident[EI_MAG3] = ELFMAG3;
540 elf_file.ehdr.e_ident[EI_VERSION] = EV_CURRENT;
541 elf_file.ehdr.e_ident[EI_CLASS] = ELFCLASS32;
542 #if BYTE_ORDER == _BIG_ENDIAN
543 elf_file.ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
544 #else
545 elf_file.ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
546 #endif
547 #if defined(__FreeBSD__)
548 elf_file.ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
549 #endif
550 elf_file.ehdr.e_type = ET_REL;
551 #if defined(__arm__)
552 elf_file.ehdr.e_machine = EM_ARM;
553 #elif defined(__mips__)
554 elf_file.ehdr.e_machine = EM_MIPS;
555 #elif defined(__powerpc__)
556 elf_file.ehdr.e_machine = EM_PPC;
557 #elif defined(__sparc)
558 elf_file.ehdr.e_machine = EM_SPARC;
559 #elif defined(__i386) || defined(__amd64)
560 elf_file.ehdr.e_machine = EM_386;
561 #endif
562 elf_file.ehdr.e_version = EV_CURRENT;
563 elf_file.ehdr.e_shoff = sizeof (Elf32_Ehdr);
564 elf_file.ehdr.e_ehsize = sizeof (Elf32_Ehdr);
565 elf_file.ehdr.e_phentsize = sizeof (Elf32_Phdr);
566 elf_file.ehdr.e_shentsize = sizeof (Elf32_Shdr);
567 elf_file.ehdr.e_shnum = nshdr;
568 elf_file.ehdr.e_shstrndx = ESHDR_SHSTRTAB;
569 off = sizeof (elf_file) + nshdr * sizeof (Elf32_Shdr);
570
571 shp = &elf_file.shdr[ESHDR_SHSTRTAB];
572 shp->sh_name = 1; /* DTRACE_SHSTRTAB32[1] = ".shstrtab" */
573 shp->sh_type = SHT_STRTAB;
574 shp->sh_offset = off;
575 shp->sh_size = sizeof (DTRACE_SHSTRTAB32);
576 shp->sh_addralign = sizeof (char);
577 off = P2ROUNDUP(shp->sh_offset + shp->sh_size, 8);
578
579 shp = &elf_file.shdr[ESHDR_DOF];
580 shp->sh_name = 11; /* DTRACE_SHSTRTAB32[11] = ".SUNW_dof" */
581 shp->sh_flags = SHF_ALLOC;
582 shp->sh_type = SHT_SUNW_dof;
583 shp->sh_offset = off;
584 shp->sh_size = dof->dofh_filesz;
585 shp->sh_addralign = 8;
586 off = shp->sh_offset + shp->sh_size;
587
588 shp = &elf_file.shdr[ESHDR_STRTAB];
589 shp->sh_name = 21; /* DTRACE_SHSTRTAB32[21] = ".strtab" */
590 shp->sh_flags = SHF_ALLOC;
591 shp->sh_type = SHT_STRTAB;
592 shp->sh_offset = off;
593 shp->sh_size = de.de_strlen;
594 shp->sh_addralign = sizeof (char);
595 off = P2ROUNDUP(shp->sh_offset + shp->sh_size, 4);
596
597 shp = &elf_file.shdr[ESHDR_SYMTAB];
598 shp->sh_name = 29; /* DTRACE_SHSTRTAB32[29] = ".symtab" */
599 shp->sh_flags = SHF_ALLOC;
600 shp->sh_type = SHT_SYMTAB;
601 shp->sh_entsize = sizeof (Elf32_Sym);
602 shp->sh_link = ESHDR_STRTAB;
603 shp->sh_offset = off;
604 shp->sh_info = de.de_global;
605 shp->sh_size = de.de_nsym * sizeof (Elf32_Sym);
606 shp->sh_addralign = 4;
607 off = P2ROUNDUP(shp->sh_offset + shp->sh_size, 4);
608
609 if (de.de_nrel == 0) {
610 if (dt_write(dtp, fd, &elf_file,
611 sizeof (elf_file)) != sizeof (elf_file) ||
612 PWRITE_SCN(ESHDR_SHSTRTAB, DTRACE_SHSTRTAB32) ||
613 PWRITE_SCN(ESHDR_STRTAB, de.de_strtab) ||
614 PWRITE_SCN(ESHDR_SYMTAB, de.de_sym) ||
615 PWRITE_SCN(ESHDR_DOF, dof)) {
616 ret = dt_set_errno(dtp, errno);
617 }
618 } else {
619 shp = &elf_file.shdr[ESHDR_REL];
620 shp->sh_name = 37; /* DTRACE_SHSTRTAB32[37] = ".rel.SUNW_dof" */
621 shp->sh_flags = SHF_ALLOC;
622 #ifdef __sparc
623 shp->sh_type = SHT_RELA;
624 #else
625 shp->sh_type = SHT_REL;
626 #endif
627 shp->sh_entsize = sizeof (de.de_rel[0]);
628 shp->sh_link = ESHDR_SYMTAB;
629 shp->sh_info = ESHDR_DOF;
630 shp->sh_offset = off;
631 shp->sh_size = de.de_nrel * sizeof (de.de_rel[0]);
632 shp->sh_addralign = 4;
633
634 if (dt_write(dtp, fd, &elf_file,
635 sizeof (elf_file)) != sizeof (elf_file) ||
636 PWRITE_SCN(ESHDR_SHSTRTAB, DTRACE_SHSTRTAB32) ||
637 PWRITE_SCN(ESHDR_STRTAB, de.de_strtab) ||
638 PWRITE_SCN(ESHDR_SYMTAB, de.de_sym) ||
639 PWRITE_SCN(ESHDR_REL, de.de_rel) ||
640 PWRITE_SCN(ESHDR_DOF, dof)) {
641 ret = dt_set_errno(dtp, errno);
642 }
643 }
644
645 free(de.de_strtab);
646 free(de.de_sym);
647 free(de.de_rel);
648
649 return (ret);
650 }
651
652 /*
653 * Write out an ELF64 file prologue consisting of a header, section headers,
654 * and a section header string table. The DOF data will follow this prologue
655 * and complete the contents of the given ELF file.
656 */
657 static int
dump_elf64(dtrace_hdl_t * dtp,const dof_hdr_t * dof,int fd)658 dump_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd)
659 {
660 struct {
661 Elf64_Ehdr ehdr;
662 Elf64_Shdr shdr[ESHDR_NUM];
663 } elf_file;
664
665 Elf64_Shdr *shp;
666 Elf64_Off off;
667 dof_elf64_t de;
668 int ret = 0;
669 uint_t nshdr;
670
671 if (prepare_elf64(dtp, dof, &de) != 0)
672 return (-1); /* errno is set for us */
673
674 /*
675 * If there are no relocations, we only need enough sections for
676 * the shstrtab and the DOF.
677 */
678 nshdr = de.de_nrel == 0 ? ESHDR_SYMTAB + 1 : ESHDR_NUM;
679
680 bzero(&elf_file, sizeof (elf_file));
681
682 elf_file.ehdr.e_ident[EI_MAG0] = ELFMAG0;
683 elf_file.ehdr.e_ident[EI_MAG1] = ELFMAG1;
684 elf_file.ehdr.e_ident[EI_MAG2] = ELFMAG2;
685 elf_file.ehdr.e_ident[EI_MAG3] = ELFMAG3;
686 elf_file.ehdr.e_ident[EI_VERSION] = EV_CURRENT;
687 elf_file.ehdr.e_ident[EI_CLASS] = ELFCLASS64;
688 #if BYTE_ORDER == _BIG_ENDIAN
689 elf_file.ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
690 #else
691 elf_file.ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
692 #endif
693 #if defined(__FreeBSD__)
694 elf_file.ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
695 #endif
696 elf_file.ehdr.e_type = ET_REL;
697 #if defined(__arm__)
698 elf_file.ehdr.e_machine = EM_ARM;
699 #elif defined(__mips__)
700 elf_file.ehdr.e_machine = EM_MIPS;
701 #elif defined(__powerpc64__)
702 elf_file.ehdr.e_machine = EM_PPC64;
703 #elif defined(__sparc)
704 elf_file.ehdr.e_machine = EM_SPARCV9;
705 #elif defined(__i386) || defined(__amd64)
706 elf_file.ehdr.e_machine = EM_AMD64;
707 #endif
708 elf_file.ehdr.e_version = EV_CURRENT;
709 elf_file.ehdr.e_shoff = sizeof (Elf64_Ehdr);
710 elf_file.ehdr.e_ehsize = sizeof (Elf64_Ehdr);
711 elf_file.ehdr.e_phentsize = sizeof (Elf64_Phdr);
712 elf_file.ehdr.e_shentsize = sizeof (Elf64_Shdr);
713 elf_file.ehdr.e_shnum = nshdr;
714 elf_file.ehdr.e_shstrndx = ESHDR_SHSTRTAB;
715 off = sizeof (elf_file) + nshdr * sizeof (Elf64_Shdr);
716
717 shp = &elf_file.shdr[ESHDR_SHSTRTAB];
718 shp->sh_name = 1; /* DTRACE_SHSTRTAB64[1] = ".shstrtab" */
719 shp->sh_type = SHT_STRTAB;
720 shp->sh_offset = off;
721 shp->sh_size = sizeof (DTRACE_SHSTRTAB64);
722 shp->sh_addralign = sizeof (char);
723 off = P2ROUNDUP(shp->sh_offset + shp->sh_size, 8);
724
725 shp = &elf_file.shdr[ESHDR_DOF];
726 shp->sh_name = 11; /* DTRACE_SHSTRTAB64[11] = ".SUNW_dof" */
727 shp->sh_flags = SHF_ALLOC;
728 shp->sh_type = SHT_SUNW_dof;
729 shp->sh_offset = off;
730 shp->sh_size = dof->dofh_filesz;
731 shp->sh_addralign = 8;
732 off = shp->sh_offset + shp->sh_size;
733
734 shp = &elf_file.shdr[ESHDR_STRTAB];
735 shp->sh_name = 21; /* DTRACE_SHSTRTAB64[21] = ".strtab" */
736 shp->sh_flags = SHF_ALLOC;
737 shp->sh_type = SHT_STRTAB;
738 shp->sh_offset = off;
739 shp->sh_size = de.de_strlen;
740 shp->sh_addralign = sizeof (char);
741 off = P2ROUNDUP(shp->sh_offset + shp->sh_size, 8);
742
743 shp = &elf_file.shdr[ESHDR_SYMTAB];
744 shp->sh_name = 29; /* DTRACE_SHSTRTAB64[29] = ".symtab" */
745 shp->sh_flags = SHF_ALLOC;
746 shp->sh_type = SHT_SYMTAB;
747 shp->sh_entsize = sizeof (Elf64_Sym);
748 shp->sh_link = ESHDR_STRTAB;
749 shp->sh_offset = off;
750 shp->sh_info = de.de_global;
751 shp->sh_size = de.de_nsym * sizeof (Elf64_Sym);
752 shp->sh_addralign = 8;
753 off = P2ROUNDUP(shp->sh_offset + shp->sh_size, 8);
754
755 if (de.de_nrel == 0) {
756 if (dt_write(dtp, fd, &elf_file,
757 sizeof (elf_file)) != sizeof (elf_file) ||
758 PWRITE_SCN(ESHDR_SHSTRTAB, DTRACE_SHSTRTAB64) ||
759 PWRITE_SCN(ESHDR_STRTAB, de.de_strtab) ||
760 PWRITE_SCN(ESHDR_SYMTAB, de.de_sym) ||
761 PWRITE_SCN(ESHDR_DOF, dof)) {
762 ret = dt_set_errno(dtp, errno);
763 }
764 } else {
765 shp = &elf_file.shdr[ESHDR_REL];
766 shp->sh_name = 37; /* DTRACE_SHSTRTAB64[37] = ".rel.SUNW_dof" */
767 shp->sh_flags = SHF_ALLOC;
768 shp->sh_type = SHT_RELA;
769 shp->sh_entsize = sizeof (de.de_rel[0]);
770 shp->sh_link = ESHDR_SYMTAB;
771 shp->sh_info = ESHDR_DOF;
772 shp->sh_offset = off;
773 shp->sh_size = de.de_nrel * sizeof (de.de_rel[0]);
774 shp->sh_addralign = 8;
775
776 if (dt_write(dtp, fd, &elf_file,
777 sizeof (elf_file)) != sizeof (elf_file) ||
778 PWRITE_SCN(ESHDR_SHSTRTAB, DTRACE_SHSTRTAB64) ||
779 PWRITE_SCN(ESHDR_STRTAB, de.de_strtab) ||
780 PWRITE_SCN(ESHDR_SYMTAB, de.de_sym) ||
781 PWRITE_SCN(ESHDR_REL, de.de_rel) ||
782 PWRITE_SCN(ESHDR_DOF, dof)) {
783 ret = dt_set_errno(dtp, errno);
784 }
785 }
786
787 free(de.de_strtab);
788 free(de.de_sym);
789 free(de.de_rel);
790
791 return (ret);
792 }
793
794 static int
dt_symtab_lookup(Elf_Data * data_sym,int nsym,uintptr_t addr,uint_t shn,GElf_Sym * sym,int uses_funcdesc,Elf * elf)795 dt_symtab_lookup(Elf_Data *data_sym, int nsym, uintptr_t addr, uint_t shn,
796 GElf_Sym *sym, int uses_funcdesc, Elf *elf)
797 {
798 int i, ret = -1;
799 Elf64_Addr symval;
800 Elf_Scn *opd_scn;
801 Elf_Data *opd_desc;
802 GElf_Sym s;
803
804 for (i = 0; i < nsym && gelf_getsym(data_sym, i, sym) != NULL; i++) {
805 if (GELF_ST_TYPE(sym->st_info) == STT_FUNC) {
806 symval = sym->st_value;
807 if (uses_funcdesc) {
808 opd_scn = elf_getscn(elf, sym->st_shndx);
809 opd_desc = elf_rawdata(opd_scn, NULL);
810 symval =
811 *(uint64_t*)((char *)opd_desc->d_buf + symval);
812 }
813 if ((uses_funcdesc || shn == sym->st_shndx) &&
814 symval <= addr &&
815 addr < symval + sym->st_size) {
816 if (GELF_ST_BIND(sym->st_info) == STB_GLOBAL)
817 return (0);
818
819 ret = 0;
820 s = *sym;
821 }
822 }
823 }
824
825 if (ret == 0)
826 *sym = s;
827 return (ret);
828 }
829
830 #if defined(__aarch64__)
831 /* XXX */
832 static int
dt_modtext(dtrace_hdl_t * dtp,char * p,int isenabled,GElf_Rela * rela,uint32_t * off)833 dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
834 uint32_t *off)
835 {
836 printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
837 return (0);
838 }
839 #elif defined(__arm__)
840 /* XXX */
841 static int
dt_modtext(dtrace_hdl_t * dtp,char * p,int isenabled,GElf_Rela * rela,uint32_t * off)842 dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
843 uint32_t *off)
844 {
845 printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
846 return (0);
847 }
848 #elif defined(__mips__)
849 /* XXX */
850 static int
dt_modtext(dtrace_hdl_t * dtp,char * p,int isenabled,GElf_Rela * rela,uint32_t * off)851 dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
852 uint32_t *off)
853 {
854 printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
855 return (0);
856 }
857 #elif defined(__powerpc__)
858 /* The sentinel is 'xor r3,r3,r3'. */
859 #define DT_OP_XOR_R3 0x7c631a78
860
861 #define DT_OP_NOP 0x60000000
862 #define DT_OP_BLR 0x4e800020
863
864 /* This captures all forms of branching to address. */
865 #define DT_IS_BRANCH(inst) ((inst & 0xfc000000) == 0x48000000)
866 #define DT_IS_BL(inst) (DT_IS_BRANCH(inst) && (inst & 0x01))
867
868 /* XXX */
869 static int
dt_modtext(dtrace_hdl_t * dtp,char * p,int isenabled,GElf_Rela * rela,uint32_t * off)870 dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
871 uint32_t *off)
872 {
873 uint32_t *ip;
874
875 if ((rela->r_offset & (sizeof (uint32_t) - 1)) != 0)
876 return (-1);
877
878 /*LINTED*/
879 ip = (uint32_t *)(p + rela->r_offset);
880
881 /*
882 * We only know about some specific relocation types.
883 */
884 if (GELF_R_TYPE(rela->r_info) != R_PPC_REL24 &&
885 GELF_R_TYPE(rela->r_info) != R_PPC_PLTREL24)
886 return (-1);
887
888 /*
889 * We may have already processed this object file in an earlier linker
890 * invocation. Check to see if the present instruction sequence matches
891 * the one we would install below.
892 */
893 if (isenabled) {
894 if (ip[0] == DT_OP_XOR_R3) {
895 (*off) += sizeof (ip[0]);
896 return (0);
897 }
898 } else {
899 if (ip[0] == DT_OP_NOP) {
900 (*off) += sizeof (ip[0]);
901 return (0);
902 }
903 }
904
905 /*
906 * We only expect branch to address instructions.
907 */
908 if (!DT_IS_BRANCH(ip[0])) {
909 dt_dprintf("found %x instead of a branch instruction at %llx\n",
910 ip[0], (u_longlong_t)rela->r_offset);
911 return (-1);
912 }
913
914 if (isenabled) {
915 /*
916 * It would necessarily indicate incorrect usage if an is-
917 * enabled probe were tail-called so flag that as an error.
918 * It's also potentially (very) tricky to handle gracefully,
919 * but could be done if this were a desired use scenario.
920 */
921 if (!DT_IS_BL(ip[0])) {
922 dt_dprintf("tail call to is-enabled probe at %llx\n",
923 (u_longlong_t)rela->r_offset);
924 return (-1);
925 }
926
927 ip[0] = DT_OP_XOR_R3;
928 (*off) += sizeof (ip[0]);
929 } else {
930 if (DT_IS_BL(ip[0]))
931 ip[0] = DT_OP_NOP;
932 else
933 ip[0] = DT_OP_BLR;
934 }
935
936 return (0);
937 }
938
939 #elif defined(__sparc)
940
941 #define DT_OP_RET 0x81c7e008
942 #define DT_OP_NOP 0x01000000
943 #define DT_OP_CALL 0x40000000
944 #define DT_OP_CLR_O0 0x90102000
945
946 #define DT_IS_MOV_O7(inst) (((inst) & 0xffffe000) == 0x9e100000)
947 #define DT_IS_RESTORE(inst) (((inst) & 0xc1f80000) == 0x81e80000)
948 #define DT_IS_RETL(inst) (((inst) & 0xfff83fff) == 0x81c02008)
949
950 #define DT_RS2(inst) ((inst) & 0x1f)
951 #define DT_MAKE_RETL(reg) (0x81c02008 | ((reg) << 14))
952
953 /*ARGSUSED*/
954 static int
dt_modtext(dtrace_hdl_t * dtp,char * p,int isenabled,GElf_Rela * rela,uint32_t * off)955 dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
956 uint32_t *off)
957 {
958 uint32_t *ip;
959
960 if ((rela->r_offset & (sizeof (uint32_t) - 1)) != 0)
961 return (-1);
962
963 /*LINTED*/
964 ip = (uint32_t *)(p + rela->r_offset);
965
966 /*
967 * We only know about some specific relocation types.
968 */
969 if (GELF_R_TYPE(rela->r_info) != R_SPARC_WDISP30 &&
970 GELF_R_TYPE(rela->r_info) != R_SPARC_WPLT30)
971 return (-1);
972
973 /*
974 * We may have already processed this object file in an earlier linker
975 * invocation. Check to see if the present instruction sequence matches
976 * the one we would install below.
977 */
978 if (isenabled) {
979 if (ip[0] == DT_OP_NOP) {
980 (*off) += sizeof (ip[0]);
981 return (0);
982 }
983 } else {
984 if (DT_IS_RESTORE(ip[1])) {
985 if (ip[0] == DT_OP_RET) {
986 (*off) += sizeof (ip[0]);
987 return (0);
988 }
989 } else if (DT_IS_MOV_O7(ip[1])) {
990 if (DT_IS_RETL(ip[0]))
991 return (0);
992 } else {
993 if (ip[0] == DT_OP_NOP) {
994 (*off) += sizeof (ip[0]);
995 return (0);
996 }
997 }
998 }
999
1000 /*
1001 * We only expect call instructions with a displacement of 0.
1002 */
1003 if (ip[0] != DT_OP_CALL) {
1004 dt_dprintf("found %x instead of a call instruction at %llx\n",
1005 ip[0], (u_longlong_t)rela->r_offset);
1006 return (-1);
1007 }
1008
1009 if (isenabled) {
1010 /*
1011 * It would necessarily indicate incorrect usage if an is-
1012 * enabled probe were tail-called so flag that as an error.
1013 * It's also potentially (very) tricky to handle gracefully,
1014 * but could be done if this were a desired use scenario.
1015 */
1016 if (DT_IS_RESTORE(ip[1]) || DT_IS_MOV_O7(ip[1])) {
1017 dt_dprintf("tail call to is-enabled probe at %llx\n",
1018 (u_longlong_t)rela->r_offset);
1019 return (-1);
1020 }
1021
1022
1023 /*
1024 * On SPARC, we take advantage of the fact that the first
1025 * argument shares the same register as for the return value.
1026 * The macro handles the work of zeroing that register so we
1027 * don't need to do anything special here. We instrument the
1028 * instruction in the delay slot as we'll need to modify the
1029 * return register after that instruction has been emulated.
1030 */
1031 ip[0] = DT_OP_NOP;
1032 (*off) += sizeof (ip[0]);
1033 } else {
1034 /*
1035 * If the call is followed by a restore, it's a tail call so
1036 * change the call to a ret. If the call if followed by a mov
1037 * of a register into %o7, it's a tail call in leaf context
1038 * so change the call to a retl-like instruction that returns
1039 * to that register value + 8 (rather than the typical %o7 +
1040 * 8); the delay slot instruction is left, but should have no
1041 * effect. Otherwise we change the call to be a nop. We
1042 * identify the subsequent instruction as the probe point in
1043 * all but the leaf tail-call case to ensure that arguments to
1044 * the probe are complete and consistent. An astute, though
1045 * largely hypothetical, observer would note that there is the
1046 * possibility of a false-positive probe firing if the function
1047 * contained a branch to the instruction in the delay slot of
1048 * the call. Fixing this would require significant in-kernel
1049 * modifications, and isn't worth doing until we see it in the
1050 * wild.
1051 */
1052 if (DT_IS_RESTORE(ip[1])) {
1053 ip[0] = DT_OP_RET;
1054 (*off) += sizeof (ip[0]);
1055 } else if (DT_IS_MOV_O7(ip[1])) {
1056 ip[0] = DT_MAKE_RETL(DT_RS2(ip[1]));
1057 } else {
1058 ip[0] = DT_OP_NOP;
1059 (*off) += sizeof (ip[0]);
1060 }
1061 }
1062
1063 return (0);
1064 }
1065
1066 #elif defined(__i386) || defined(__amd64)
1067
1068 #define DT_OP_NOP 0x90
1069 #define DT_OP_RET 0xc3
1070 #define DT_OP_CALL 0xe8
1071 #define DT_OP_JMP32 0xe9
1072 #define DT_OP_REX_RAX 0x48
1073 #define DT_OP_XOR_EAX_0 0x33
1074 #define DT_OP_XOR_EAX_1 0xc0
1075
1076 static int
dt_modtext(dtrace_hdl_t * dtp,char * p,int isenabled,GElf_Rela * rela,uint32_t * off)1077 dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
1078 uint32_t *off)
1079 {
1080 uint8_t *ip = (uint8_t *)(p + rela->r_offset - 1);
1081 uint8_t ret;
1082
1083 /*
1084 * On x86, the first byte of the instruction is the call opcode and
1085 * the next four bytes are the 32-bit address; the relocation is for
1086 * the address operand. We back up the offset to the first byte of
1087 * the instruction. For is-enabled probes, we later advance the offset
1088 * so that it hits the first nop in the instruction sequence.
1089 */
1090 (*off) -= 1;
1091
1092 /*
1093 * We only know about some specific relocation types. Luckily
1094 * these types have the same values on both 32-bit and 64-bit
1095 * x86 architectures.
1096 */
1097 if (GELF_R_TYPE(rela->r_info) != R_386_PC32 &&
1098 GELF_R_TYPE(rela->r_info) != R_386_PLT32)
1099 return (-1);
1100
1101 /*
1102 * We may have already processed this object file in an earlier linker
1103 * invocation. Check to see if the present instruction sequence matches
1104 * the one we would install. For is-enabled probes, we advance the
1105 * offset to the first nop instruction in the sequence to match the
1106 * text modification code below.
1107 */
1108 if (!isenabled) {
1109 if ((ip[0] == DT_OP_NOP || ip[0] == DT_OP_RET) &&
1110 ip[1] == DT_OP_NOP && ip[2] == DT_OP_NOP &&
1111 ip[3] == DT_OP_NOP && ip[4] == DT_OP_NOP)
1112 return (0);
1113 } else if (dtp->dt_oflags & DTRACE_O_LP64) {
1114 if (ip[0] == DT_OP_REX_RAX &&
1115 ip[1] == DT_OP_XOR_EAX_0 && ip[2] == DT_OP_XOR_EAX_1 &&
1116 (ip[3] == DT_OP_NOP || ip[3] == DT_OP_RET) &&
1117 ip[4] == DT_OP_NOP) {
1118 (*off) += 3;
1119 return (0);
1120 }
1121 } else {
1122 if (ip[0] == DT_OP_XOR_EAX_0 && ip[1] == DT_OP_XOR_EAX_1 &&
1123 (ip[2] == DT_OP_NOP || ip[2] == DT_OP_RET) &&
1124 ip[3] == DT_OP_NOP && ip[4] == DT_OP_NOP) {
1125 (*off) += 2;
1126 return (0);
1127 }
1128 }
1129
1130 /*
1131 * We expect either a call instrution with a 32-bit displacement or a
1132 * jmp instruction with a 32-bit displacement acting as a tail-call.
1133 */
1134 if (ip[0] != DT_OP_CALL && ip[0] != DT_OP_JMP32) {
1135 dt_dprintf("found %x instead of a call or jmp instruction at "
1136 "%llx\n", ip[0], (u_longlong_t)rela->r_offset);
1137 return (-1);
1138 }
1139
1140 ret = (ip[0] == DT_OP_JMP32) ? DT_OP_RET : DT_OP_NOP;
1141
1142 /*
1143 * Establish the instruction sequence -- all nops for probes, and an
1144 * instruction to clear the return value register (%eax/%rax) followed
1145 * by nops for is-enabled probes. For is-enabled probes, we advance
1146 * the offset to the first nop. This isn't stricly necessary but makes
1147 * for more readable disassembly when the probe is enabled.
1148 */
1149 if (!isenabled) {
1150 ip[0] = ret;
1151 ip[1] = DT_OP_NOP;
1152 ip[2] = DT_OP_NOP;
1153 ip[3] = DT_OP_NOP;
1154 ip[4] = DT_OP_NOP;
1155 } else if (dtp->dt_oflags & DTRACE_O_LP64) {
1156 ip[0] = DT_OP_REX_RAX;
1157 ip[1] = DT_OP_XOR_EAX_0;
1158 ip[2] = DT_OP_XOR_EAX_1;
1159 ip[3] = ret;
1160 ip[4] = DT_OP_NOP;
1161 (*off) += 3;
1162 } else {
1163 ip[0] = DT_OP_XOR_EAX_0;
1164 ip[1] = DT_OP_XOR_EAX_1;
1165 ip[2] = ret;
1166 ip[3] = DT_OP_NOP;
1167 ip[4] = DT_OP_NOP;
1168 (*off) += 2;
1169 }
1170
1171 return (0);
1172 }
1173
1174 #else
1175 #error unknown ISA
1176 #endif
1177
1178 /*PRINTFLIKE5*/
1179 static int
dt_link_error(dtrace_hdl_t * dtp,Elf * elf,int fd,dt_link_pair_t * bufs,const char * format,...)1180 dt_link_error(dtrace_hdl_t *dtp, Elf *elf, int fd, dt_link_pair_t *bufs,
1181 const char *format, ...)
1182 {
1183 va_list ap;
1184 dt_link_pair_t *pair;
1185
1186 va_start(ap, format);
1187 dt_set_errmsg(dtp, NULL, NULL, NULL, 0, format, ap);
1188 va_end(ap);
1189
1190 if (elf != NULL)
1191 (void) elf_end(elf);
1192
1193 if (fd >= 0)
1194 (void) close(fd);
1195
1196 while ((pair = bufs) != NULL) {
1197 bufs = pair->dlp_next;
1198 dt_free(dtp, pair->dlp_str);
1199 dt_free(dtp, pair->dlp_sym);
1200 dt_free(dtp, pair);
1201 }
1202
1203 return (dt_set_errno(dtp, EDT_COMPILER));
1204 }
1205
1206 static int
process_obj(dtrace_hdl_t * dtp,const char * obj,int * eprobesp)1207 process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
1208 {
1209 static const char dt_prefix[] = "__dtrace";
1210 static const char dt_enabled[] = "enabled";
1211 static const char dt_symprefix[] = "$dtrace";
1212 static const char dt_symfmt[] = "%s%ld.%s";
1213 int fd, i, ndx, eprobe, mod = 0;
1214 Elf *elf = NULL;
1215 GElf_Ehdr ehdr;
1216 Elf_Scn *scn_rel, *scn_sym, *scn_str, *scn_tgt;
1217 Elf_Data *data_rel, *data_sym, *data_str, *data_tgt;
1218 GElf_Shdr shdr_rel, shdr_sym, shdr_str, shdr_tgt;
1219 GElf_Sym rsym, fsym, dsym;
1220 GElf_Rela rela;
1221 char *s, *p, *r;
1222 char pname[DTRACE_PROVNAMELEN];
1223 dt_provider_t *pvp;
1224 dt_probe_t *prp;
1225 uint32_t off, eclass, emachine1, emachine2;
1226 size_t symsize, nsym, isym, istr, len;
1227 key_t objkey;
1228 dt_link_pair_t *pair, *bufs = NULL;
1229 dt_strtab_t *strtab;
1230
1231 if ((fd = open64(obj, O_RDWR)) == -1) {
1232 return (dt_link_error(dtp, elf, fd, bufs,
1233 "failed to open %s: %s", obj, strerror(errno)));
1234 }
1235
1236 if ((elf = elf_begin(fd, ELF_C_RDWR, NULL)) == NULL) {
1237 return (dt_link_error(dtp, elf, fd, bufs,
1238 "failed to process %s: %s", obj, elf_errmsg(elf_errno())));
1239 }
1240
1241 switch (elf_kind(elf)) {
1242 case ELF_K_ELF:
1243 break;
1244 case ELF_K_AR:
1245 return (dt_link_error(dtp, elf, fd, bufs, "archives are not "
1246 "permitted; use the contents of the archive instead: %s",
1247 obj));
1248 default:
1249 return (dt_link_error(dtp, elf, fd, bufs,
1250 "invalid file type: %s", obj));
1251 }
1252
1253 if (gelf_getehdr(elf, &ehdr) == NULL) {
1254 return (dt_link_error(dtp, elf, fd, bufs, "corrupt file: %s",
1255 obj));
1256 }
1257
1258 if (dtp->dt_oflags & DTRACE_O_LP64) {
1259 eclass = ELFCLASS64;
1260 #if defined(__mips__)
1261 emachine1 = emachine2 = EM_MIPS;
1262 #elif defined(__powerpc__)
1263 emachine1 = emachine2 = EM_PPC64;
1264 #elif defined(__sparc)
1265 emachine1 = emachine2 = EM_SPARCV9;
1266 #elif defined(__i386) || defined(__amd64)
1267 emachine1 = emachine2 = EM_AMD64;
1268 #endif
1269 symsize = sizeof (Elf64_Sym);
1270 } else {
1271 eclass = ELFCLASS32;
1272 #if defined(__arm__)
1273 emachine1 = emachine2 = EM_ARM;
1274 #elif defined(__mips__)
1275 emachine1 = emachine2 = EM_MIPS;
1276 #elif defined(__powerpc__)
1277 emachine1 = emachine2 = EM_PPC;
1278 #elif defined(__sparc)
1279 emachine1 = EM_SPARC;
1280 emachine2 = EM_SPARC32PLUS;
1281 #elif defined(__i386) || defined(__amd64)
1282 emachine1 = emachine2 = EM_386;
1283 #endif
1284 symsize = sizeof (Elf32_Sym);
1285 }
1286
1287 if (ehdr.e_ident[EI_CLASS] != eclass) {
1288 return (dt_link_error(dtp, elf, fd, bufs,
1289 "incorrect ELF class for object file: %s", obj));
1290 }
1291
1292 if (ehdr.e_machine != emachine1 && ehdr.e_machine != emachine2) {
1293 return (dt_link_error(dtp, elf, fd, bufs,
1294 "incorrect ELF machine type for object file: %s", obj));
1295 }
1296
1297 /*
1298 * We use this token as a relatively unique handle for this file on the
1299 * system in order to disambiguate potential conflicts between files of
1300 * the same name which contain identially named local symbols.
1301 */
1302 if ((objkey = ftok(obj, 0)) == (key_t)-1) {
1303 return (dt_link_error(dtp, elf, fd, bufs,
1304 "failed to generate unique key for object file: %s", obj));
1305 }
1306
1307 scn_rel = NULL;
1308 while ((scn_rel = elf_nextscn(elf, scn_rel)) != NULL) {
1309 if (gelf_getshdr(scn_rel, &shdr_rel) == NULL)
1310 goto err;
1311
1312 /*
1313 * Skip any non-relocation sections.
1314 */
1315 if (shdr_rel.sh_type != SHT_RELA && shdr_rel.sh_type != SHT_REL)
1316 continue;
1317
1318 if ((data_rel = elf_getdata(scn_rel, NULL)) == NULL)
1319 goto err;
1320
1321 /*
1322 * Grab the section, section header and section data for the
1323 * symbol table that this relocation section references.
1324 */
1325 if ((scn_sym = elf_getscn(elf, shdr_rel.sh_link)) == NULL ||
1326 gelf_getshdr(scn_sym, &shdr_sym) == NULL ||
1327 (data_sym = elf_getdata(scn_sym, NULL)) == NULL)
1328 goto err;
1329
1330 /*
1331 * Ditto for that symbol table's string table.
1332 */
1333 if ((scn_str = elf_getscn(elf, shdr_sym.sh_link)) == NULL ||
1334 gelf_getshdr(scn_str, &shdr_str) == NULL ||
1335 (data_str = elf_getdata(scn_str, NULL)) == NULL)
1336 goto err;
1337
1338 /*
1339 * Grab the section, section header and section data for the
1340 * target section for the relocations. For the relocations
1341 * we're looking for -- this will typically be the text of the
1342 * object file.
1343 */
1344 if ((scn_tgt = elf_getscn(elf, shdr_rel.sh_info)) == NULL ||
1345 gelf_getshdr(scn_tgt, &shdr_tgt) == NULL ||
1346 (data_tgt = elf_getdata(scn_tgt, NULL)) == NULL)
1347 goto err;
1348
1349 /*
1350 * We're looking for relocations to symbols matching this form:
1351 *
1352 * __dtrace[enabled]_<prov>___<probe>
1353 *
1354 * For the generated object, we need to record the location
1355 * identified by the relocation, and create a new relocation
1356 * in the generated object that will be resolved at link time
1357 * to the location of the function in which the probe is
1358 * embedded. In the target object, we change the matched symbol
1359 * so that it will be ignored at link time, and we modify the
1360 * target (text) section to replace the call instruction with
1361 * one or more nops.
1362 *
1363 * If the function containing the probe is locally scoped
1364 * (static), we create an alias used by the relocation in the
1365 * generated object. The alias, a new symbol, will be global
1366 * (so that the relocation from the generated object can be
1367 * resolved), and hidden (so that it is converted to a local
1368 * symbol at link time). Such aliases have this form:
1369 *
1370 * $dtrace<key>.<function>
1371 *
1372 * We take a first pass through all the relocations to
1373 * populate our string table and count the number of extra
1374 * symbols we'll require.
1375 */
1376 strtab = dt_strtab_create(1);
1377 nsym = 0;
1378 isym = data_sym->d_size / symsize;
1379 istr = data_str->d_size;
1380
1381 for (i = 0; i < shdr_rel.sh_size / shdr_rel.sh_entsize; i++) {
1382
1383 if (shdr_rel.sh_type == SHT_RELA) {
1384 if (gelf_getrela(data_rel, i, &rela) == NULL)
1385 continue;
1386 } else {
1387 GElf_Rel rel;
1388 if (gelf_getrel(data_rel, i, &rel) == NULL)
1389 continue;
1390 rela.r_offset = rel.r_offset;
1391 rela.r_info = rel.r_info;
1392 rela.r_addend = 0;
1393 }
1394
1395 if (gelf_getsym(data_sym, GELF_R_SYM(rela.r_info),
1396 &rsym) == NULL) {
1397 dt_strtab_destroy(strtab);
1398 goto err;
1399 }
1400
1401 s = (char *)data_str->d_buf + rsym.st_name;
1402
1403 if (strncmp(s, dt_prefix, sizeof (dt_prefix) - 1) != 0)
1404 continue;
1405
1406 if (dt_symtab_lookup(data_sym, isym, rela.r_offset,
1407 shdr_rel.sh_info, &fsym,
1408 (emachine1 == EM_PPC64), elf) != 0) {
1409 dt_strtab_destroy(strtab);
1410 goto err;
1411 }
1412
1413 if (GELF_ST_BIND(fsym.st_info) != STB_LOCAL)
1414 continue;
1415
1416 if (fsym.st_name > data_str->d_size) {
1417 dt_strtab_destroy(strtab);
1418 goto err;
1419 }
1420
1421 s = (char *)data_str->d_buf + fsym.st_name;
1422
1423 /*
1424 * If this symbol isn't of type function, we've really
1425 * driven off the rails or the object file is corrupt.
1426 */
1427 if (GELF_ST_TYPE(fsym.st_info) != STT_FUNC) {
1428 dt_strtab_destroy(strtab);
1429 return (dt_link_error(dtp, elf, fd, bufs,
1430 "expected %s to be of type function", s));
1431 }
1432
1433 len = snprintf(NULL, 0, dt_symfmt, dt_symprefix,
1434 objkey, s) + 1;
1435 if ((p = dt_alloc(dtp, len)) == NULL) {
1436 dt_strtab_destroy(strtab);
1437 goto err;
1438 }
1439 (void) snprintf(p, len, dt_symfmt, dt_symprefix,
1440 objkey, s);
1441
1442 if (dt_strtab_index(strtab, p) == -1) {
1443 nsym++;
1444 (void) dt_strtab_insert(strtab, p);
1445 }
1446
1447 dt_free(dtp, p);
1448 }
1449
1450 /*
1451 * If needed, allocate the additional space for the symbol
1452 * table and string table copying the old data into the new
1453 * buffers, and marking the buffers as dirty. We inject those
1454 * newly allocated buffers into the libelf data structures, but
1455 * are still responsible for freeing them once we're done with
1456 * the elf handle.
1457 */
1458 if (nsym > 0) {
1459 /*
1460 * The first byte of the string table is reserved for
1461 * the \0 entry.
1462 */
1463 len = dt_strtab_size(strtab) - 1;
1464
1465 assert(len > 0);
1466 assert(dt_strtab_index(strtab, "") == 0);
1467
1468 dt_strtab_destroy(strtab);
1469
1470 if ((pair = dt_alloc(dtp, sizeof (*pair))) == NULL)
1471 goto err;
1472
1473 if ((pair->dlp_str = dt_alloc(dtp, data_str->d_size +
1474 len)) == NULL) {
1475 dt_free(dtp, pair);
1476 goto err;
1477 }
1478
1479 if ((pair->dlp_sym = dt_alloc(dtp, data_sym->d_size +
1480 nsym * symsize)) == NULL) {
1481 dt_free(dtp, pair->dlp_str);
1482 dt_free(dtp, pair);
1483 goto err;
1484 }
1485
1486 pair->dlp_next = bufs;
1487 bufs = pair;
1488
1489 bcopy(data_str->d_buf, pair->dlp_str, data_str->d_size);
1490 data_str->d_buf = pair->dlp_str;
1491 data_str->d_size += len;
1492 (void) elf_flagdata(data_str, ELF_C_SET, ELF_F_DIRTY);
1493
1494 shdr_str.sh_size += len;
1495 (void) gelf_update_shdr(scn_str, &shdr_str);
1496
1497 bcopy(data_sym->d_buf, pair->dlp_sym, data_sym->d_size);
1498 data_sym->d_buf = pair->dlp_sym;
1499 data_sym->d_size += nsym * symsize;
1500 (void) elf_flagdata(data_sym, ELF_C_SET, ELF_F_DIRTY);
1501
1502 shdr_sym.sh_size += nsym * symsize;
1503 (void) gelf_update_shdr(scn_sym, &shdr_sym);
1504
1505 nsym += isym;
1506 } else {
1507 dt_strtab_destroy(strtab);
1508 }
1509
1510 /*
1511 * Now that the tables have been allocated, perform the
1512 * modifications described above.
1513 */
1514 for (i = 0; i < shdr_rel.sh_size / shdr_rel.sh_entsize; i++) {
1515
1516 if (shdr_rel.sh_type == SHT_RELA) {
1517 if (gelf_getrela(data_rel, i, &rela) == NULL)
1518 continue;
1519 } else {
1520 GElf_Rel rel;
1521 if (gelf_getrel(data_rel, i, &rel) == NULL)
1522 continue;
1523 rela.r_offset = rel.r_offset;
1524 rela.r_info = rel.r_info;
1525 rela.r_addend = 0;
1526 }
1527
1528 ndx = GELF_R_SYM(rela.r_info);
1529
1530 if (gelf_getsym(data_sym, ndx, &rsym) == NULL ||
1531 rsym.st_name > data_str->d_size)
1532 goto err;
1533
1534 s = (char *)data_str->d_buf + rsym.st_name;
1535
1536 if (strncmp(s, dt_prefix, sizeof (dt_prefix) - 1) != 0)
1537 continue;
1538
1539 s += sizeof (dt_prefix) - 1;
1540
1541 /*
1542 * Check to see if this is an 'is-enabled' check as
1543 * opposed to a normal probe.
1544 */
1545 if (strncmp(s, dt_enabled,
1546 sizeof (dt_enabled) - 1) == 0) {
1547 s += sizeof (dt_enabled) - 1;
1548 eprobe = 1;
1549 *eprobesp = 1;
1550 dt_dprintf("is-enabled probe\n");
1551 } else {
1552 eprobe = 0;
1553 dt_dprintf("normal probe\n");
1554 }
1555
1556 if (*s++ != '_')
1557 goto err;
1558
1559 if ((p = strstr(s, "___")) == NULL ||
1560 p - s >= sizeof (pname))
1561 goto err;
1562
1563 bcopy(s, pname, p - s);
1564 pname[p - s] = '\0';
1565
1566 p = strhyphenate(p + 3); /* strlen("___") */
1567
1568 if (dt_symtab_lookup(data_sym, isym, rela.r_offset,
1569 shdr_rel.sh_info, &fsym,
1570 (emachine1 == EM_PPC64), elf) != 0)
1571 goto err;
1572
1573 if (fsym.st_name > data_str->d_size)
1574 goto err;
1575
1576 assert(GELF_ST_TYPE(fsym.st_info) == STT_FUNC);
1577
1578 /*
1579 * If a NULL relocation name is passed to
1580 * dt_probe_define(), the function name is used for the
1581 * relocation. The relocation needs to use a mangled
1582 * name if the symbol is locally scoped; the function
1583 * name may need to change if we've found the global
1584 * alias for the locally scoped symbol (we prefer
1585 * global symbols to locals in dt_symtab_lookup()).
1586 */
1587 s = (char *)data_str->d_buf + fsym.st_name;
1588 r = NULL;
1589
1590 if (GELF_ST_BIND(fsym.st_info) == STB_LOCAL) {
1591 dsym = fsym;
1592 dsym.st_name = istr;
1593 dsym.st_info = GELF_ST_INFO(STB_GLOBAL,
1594 STT_FUNC);
1595 dsym.st_other =
1596 ELF64_ST_VISIBILITY(STV_ELIMINATE);
1597 (void) gelf_update_sym(data_sym, isym, &dsym);
1598
1599 r = (char *)data_str->d_buf + istr;
1600 istr += 1 + sprintf(r, dt_symfmt,
1601 dt_symprefix, objkey, s);
1602 isym++;
1603 assert(isym <= nsym);
1604
1605 } else if (strncmp(s, dt_symprefix,
1606 strlen(dt_symprefix)) == 0) {
1607 r = s;
1608 if ((s = strchr(s, '.')) == NULL)
1609 goto err;
1610 s++;
1611 }
1612
1613 if ((pvp = dt_provider_lookup(dtp, pname)) == NULL) {
1614 return (dt_link_error(dtp, elf, fd, bufs,
1615 "no such provider %s", pname));
1616 }
1617
1618 if ((prp = dt_probe_lookup(pvp, p)) == NULL) {
1619 return (dt_link_error(dtp, elf, fd, bufs,
1620 "no such probe %s", p));
1621 }
1622
1623 assert(fsym.st_value <= rela.r_offset);
1624
1625 off = rela.r_offset - fsym.st_value;
1626 if (dt_modtext(dtp, data_tgt->d_buf, eprobe,
1627 &rela, &off) != 0)
1628 goto err;
1629
1630 if (dt_probe_define(pvp, prp, s, r, off, eprobe) != 0) {
1631 return (dt_link_error(dtp, elf, fd, bufs,
1632 "failed to allocate space for probe"));
1633 }
1634 #ifndef illumos
1635 /*
1636 * Our linker doesn't understand the SUNW_IGNORE ndx and
1637 * will try to use this relocation when we build the
1638 * final executable. Since we are done processing this
1639 * relocation, mark it as inexistant and let libelf
1640 * remove it from the file.
1641 * If this wasn't done, we would have garbage added to
1642 * the executable file as the symbol is going to be
1643 * change from UND to ABS.
1644 */
1645 if (shdr_rel.sh_type == SHT_RELA) {
1646 rela.r_offset = 0;
1647 rela.r_info = 0;
1648 rela.r_addend = 0;
1649 (void) gelf_update_rela(data_rel, i, &rela);
1650 } else {
1651 GElf_Rel rel;
1652 rel.r_offset = 0;
1653 rel.r_info = 0;
1654 (void) gelf_update_rel(data_rel, i, &rel);
1655 }
1656 #endif
1657
1658 mod = 1;
1659 (void) elf_flagdata(data_tgt, ELF_C_SET, ELF_F_DIRTY);
1660
1661 /*
1662 * This symbol may already have been marked to
1663 * be ignored by another relocation referencing
1664 * the same symbol or if this object file has
1665 * already been processed by an earlier link
1666 * invocation.
1667 */
1668 #ifndef illumos
1669 #define SHN_SUNW_IGNORE SHN_ABS
1670 #endif
1671 if (rsym.st_shndx != SHN_SUNW_IGNORE) {
1672 rsym.st_shndx = SHN_SUNW_IGNORE;
1673 (void) gelf_update_sym(data_sym, ndx, &rsym);
1674 }
1675 }
1676 }
1677
1678 if (mod && elf_update(elf, ELF_C_WRITE) == -1)
1679 goto err;
1680
1681 (void) elf_end(elf);
1682 (void) close(fd);
1683
1684 #ifndef illumos
1685 if (nsym > 0)
1686 #endif
1687 while ((pair = bufs) != NULL) {
1688 bufs = pair->dlp_next;
1689 dt_free(dtp, pair->dlp_str);
1690 dt_free(dtp, pair->dlp_sym);
1691 dt_free(dtp, pair);
1692 }
1693
1694 return (0);
1695
1696 err:
1697 return (dt_link_error(dtp, elf, fd, bufs,
1698 "an error was encountered while processing %s", obj));
1699 }
1700
1701 int
dtrace_program_link(dtrace_hdl_t * dtp,dtrace_prog_t * pgp,uint_t dflags,const char * file,int objc,char * const objv[])1702 dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
1703 const char *file, int objc, char *const objv[])
1704 {
1705 #ifndef illumos
1706 char tfile[PATH_MAX];
1707 #endif
1708 char drti[PATH_MAX];
1709 dof_hdr_t *dof;
1710 int fd, status, i, cur;
1711 char *cmd, tmp;
1712 size_t len;
1713 int eprobes = 0, ret = 0;
1714
1715 #ifndef illumos
1716 if (access(file, R_OK) == 0) {
1717 fprintf(stderr, "dtrace: target object (%s) already exists. "
1718 "Please remove the target\ndtrace: object and rebuild all "
1719 "the source objects if you wish to run the DTrace\n"
1720 "dtrace: linking process again\n", file);
1721 /*
1722 * Several build infrastructures run DTrace twice (e.g.
1723 * postgres) and we don't want the build to fail. Return
1724 * 0 here since this isn't really a fatal error.
1725 */
1726 return (0);
1727 }
1728 #endif
1729
1730 /*
1731 * A NULL program indicates a special use in which we just link
1732 * together a bunch of object files specified in objv and then
1733 * unlink(2) those object files.
1734 */
1735 if (pgp == NULL) {
1736 const char *fmt = "%s -o %s -r";
1737
1738 len = snprintf(&tmp, 1, fmt, dtp->dt_ld_path, file) + 1;
1739
1740 for (i = 0; i < objc; i++)
1741 len += strlen(objv[i]) + 1;
1742
1743 cmd = alloca(len);
1744
1745 cur = snprintf(cmd, len, fmt, dtp->dt_ld_path, file);
1746
1747 for (i = 0; i < objc; i++)
1748 cur += snprintf(cmd + cur, len - cur, " %s", objv[i]);
1749
1750 if ((status = system(cmd)) == -1) {
1751 return (dt_link_error(dtp, NULL, -1, NULL,
1752 "failed to run %s: %s", dtp->dt_ld_path,
1753 strerror(errno)));
1754 }
1755
1756 if (WIFSIGNALED(status)) {
1757 return (dt_link_error(dtp, NULL, -1, NULL,
1758 "failed to link %s: %s failed due to signal %d",
1759 file, dtp->dt_ld_path, WTERMSIG(status)));
1760 }
1761
1762 if (WEXITSTATUS(status) != 0) {
1763 return (dt_link_error(dtp, NULL, -1, NULL,
1764 "failed to link %s: %s exited with status %d\n",
1765 file, dtp->dt_ld_path, WEXITSTATUS(status)));
1766 }
1767
1768 for (i = 0; i < objc; i++) {
1769 if (strcmp(objv[i], file) != 0)
1770 (void) unlink(objv[i]);
1771 }
1772
1773 return (0);
1774 }
1775
1776 for (i = 0; i < objc; i++) {
1777 if (process_obj(dtp, objv[i], &eprobes) != 0)
1778 return (-1); /* errno is set for us */
1779 }
1780
1781 /*
1782 * If there are is-enabled probes then we need to force use of DOF
1783 * version 2.
1784 */
1785 if (eprobes && pgp->dp_dofversion < DOF_VERSION_2)
1786 pgp->dp_dofversion = DOF_VERSION_2;
1787
1788 if ((dof = dtrace_dof_create(dtp, pgp, dflags)) == NULL)
1789 return (-1); /* errno is set for us */
1790
1791 #ifdef illumos
1792 /*
1793 * Create a temporary file and then unlink it if we're going to
1794 * combine it with drti.o later. We can still refer to it in child
1795 * processes as /dev/fd/<fd>.
1796 */
1797 if ((fd = open64(file, O_RDWR | O_CREAT | O_TRUNC, 0666)) == -1) {
1798 return (dt_link_error(dtp, NULL, -1, NULL,
1799 "failed to open %s: %s", file, strerror(errno)));
1800 }
1801 #else
1802 snprintf(tfile, sizeof(tfile), "%s.XXXXXX", file);
1803 if ((fd = mkostemp(tfile, O_CLOEXEC)) == -1)
1804 return (dt_link_error(dtp, NULL, -1, NULL,
1805 "failed to create temporary file %s: %s",
1806 tfile, strerror(errno)));
1807 #endif
1808
1809 /*
1810 * If -xlinktype=DOF has been selected, just write out the DOF.
1811 * Otherwise proceed to the default of generating and linking ELF.
1812 */
1813 switch (dtp->dt_linktype) {
1814 case DT_LTYP_DOF:
1815 if (dt_write(dtp, fd, dof, dof->dofh_filesz) < dof->dofh_filesz)
1816 ret = errno;
1817
1818 if (close(fd) != 0 && ret == 0)
1819 ret = errno;
1820
1821 if (ret != 0) {
1822 return (dt_link_error(dtp, NULL, -1, NULL,
1823 "failed to write %s: %s", file, strerror(ret)));
1824 }
1825
1826 return (0);
1827
1828 case DT_LTYP_ELF:
1829 break; /* fall through to the rest of dtrace_program_link() */
1830
1831 default:
1832 return (dt_link_error(dtp, NULL, -1, NULL,
1833 "invalid link type %u\n", dtp->dt_linktype));
1834 }
1835
1836
1837 #ifdef illumos
1838 if (!dtp->dt_lazyload)
1839 (void) unlink(file);
1840 #endif
1841
1842 if (dtp->dt_oflags & DTRACE_O_LP64)
1843 status = dump_elf64(dtp, dof, fd);
1844 else
1845 status = dump_elf32(dtp, dof, fd);
1846
1847 #ifdef illumos
1848 if (status != 0 || lseek(fd, 0, SEEK_SET) != 0) {
1849 return (dt_link_error(dtp, NULL, -1, NULL,
1850 "failed to write %s: %s", file, strerror(errno)));
1851 }
1852 #else
1853 if (status != 0)
1854 return (dt_link_error(dtp, NULL, -1, NULL,
1855 "failed to write %s: %s", tfile,
1856 strerror(dtrace_errno(dtp))));
1857 #endif
1858
1859 if (!dtp->dt_lazyload) {
1860 #ifdef illumos
1861 const char *fmt = "%s -o %s -r -Blocal -Breduce /dev/fd/%d %s";
1862
1863 if (dtp->dt_oflags & DTRACE_O_LP64) {
1864 (void) snprintf(drti, sizeof (drti),
1865 "%s/64/drti.o", _dtrace_libdir);
1866 } else {
1867 (void) snprintf(drti, sizeof (drti),
1868 "%s/drti.o", _dtrace_libdir);
1869 }
1870
1871 len = snprintf(&tmp, 1, fmt, dtp->dt_ld_path, file, fd,
1872 drti) + 1;
1873
1874 cmd = alloca(len);
1875
1876 (void) snprintf(cmd, len, fmt, dtp->dt_ld_path, file, fd, drti);
1877 #else
1878 const char *fmt = "%s -o %s -r %s %s";
1879 dt_dirpath_t *dp = dt_list_next(&dtp->dt_lib_path);
1880
1881 (void) snprintf(drti, sizeof (drti), "%s/drti.o", dp->dir_path);
1882
1883 len = snprintf(&tmp, 1, fmt, dtp->dt_ld_path, file, tfile,
1884 drti) + 1;
1885
1886 cmd = alloca(len);
1887
1888 (void) snprintf(cmd, len, fmt, dtp->dt_ld_path, file, tfile,
1889 drti);
1890 #endif
1891 if ((status = system(cmd)) == -1) {
1892 ret = dt_link_error(dtp, NULL, fd, NULL,
1893 "failed to run %s: %s", dtp->dt_ld_path,
1894 strerror(errno));
1895 goto done;
1896 }
1897
1898 if (WIFSIGNALED(status)) {
1899 ret = dt_link_error(dtp, NULL, fd, NULL,
1900 "failed to link %s: %s failed due to signal %d",
1901 file, dtp->dt_ld_path, WTERMSIG(status));
1902 goto done;
1903 }
1904
1905 if (WEXITSTATUS(status) != 0) {
1906 ret = dt_link_error(dtp, NULL, fd, NULL,
1907 "failed to link %s: %s exited with status %d\n",
1908 file, dtp->dt_ld_path, WEXITSTATUS(status));
1909 goto done;
1910 }
1911 (void) close(fd); /* release temporary file */
1912
1913 #ifdef __FreeBSD__
1914 /*
1915 * Now that we've linked drti.o, reduce the global __SUNW_dof
1916 * symbol to a local symbol. This is needed to so that multiple
1917 * generated object files (for different providers, for
1918 * instance) can be linked together. This is accomplished using
1919 * the -Blocal flag with Sun's linker, but GNU ld doesn't appear
1920 * to have an equivalent option.
1921 */
1922 asprintf(&cmd, "%s --localize-hidden %s", dtp->dt_objcopy_path,
1923 file);
1924 if ((status = system(cmd)) == -1) {
1925 ret = dt_link_error(dtp, NULL, -1, NULL,
1926 "failed to run %s: %s", dtp->dt_objcopy_path,
1927 strerror(errno));
1928 free(cmd);
1929 goto done;
1930 }
1931 free(cmd);
1932
1933 if (WIFSIGNALED(status)) {
1934 ret = dt_link_error(dtp, NULL, -1, NULL,
1935 "failed to link %s: %s failed due to signal %d",
1936 file, dtp->dt_objcopy_path, WTERMSIG(status));
1937 goto done;
1938 }
1939
1940 if (WEXITSTATUS(status) != 0) {
1941 ret = dt_link_error(dtp, NULL, -1, NULL,
1942 "failed to link %s: %s exited with status %d\n",
1943 file, dtp->dt_objcopy_path, WEXITSTATUS(status));
1944 goto done;
1945 }
1946 #endif
1947 } else {
1948 #ifdef __FreeBSD__
1949 if (rename(tfile, file) != 0) {
1950 ret = dt_link_error(dtp, NULL, fd, NULL,
1951 "failed to rename %s to %s: %s", tfile, file,
1952 strerror(errno));
1953 goto done;
1954 }
1955 #endif
1956 (void) close(fd);
1957 }
1958
1959 done:
1960 dtrace_dof_destroy(dtp, dof);
1961
1962 #ifdef __FreeBSD__
1963 if (!dtp->dt_lazyload)
1964 (void) unlink(tfile);
1965 #endif
1966 return (ret);
1967 }
1968