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