xref: /freebsd-src/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c (revision 0e15d9fbeba47c947f62d8252ef673a306f7c2fb)
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 #if defined(_CALL_ELF) && _CALL_ELF == 2
650 	elf_file.ehdr.e_flags = 2;
651 #endif
652 	elf_file.ehdr.e_machine = EM_PPC64;
653 #elif defined(__i386) || defined(__amd64)
654 	elf_file.ehdr.e_machine = EM_AMD64;
655 #elif defined(__aarch64__)
656 	elf_file.ehdr.e_machine = EM_AARCH64;
657 #endif
658 	elf_file.ehdr.e_version = EV_CURRENT;
659 	elf_file.ehdr.e_shoff = sizeof (Elf64_Ehdr);
660 	elf_file.ehdr.e_ehsize = sizeof (Elf64_Ehdr);
661 	elf_file.ehdr.e_phentsize = sizeof (Elf64_Phdr);
662 	elf_file.ehdr.e_shentsize = sizeof (Elf64_Shdr);
663 	elf_file.ehdr.e_shnum = nshdr;
664 	elf_file.ehdr.e_shstrndx = ESHDR_SHSTRTAB;
665 	off = sizeof (elf_file) + nshdr * sizeof (Elf64_Shdr);
666 
667 	shp = &elf_file.shdr[ESHDR_SHSTRTAB];
668 	shp->sh_name = 1; /* DTRACE_SHSTRTAB64[1] = ".shstrtab" */
669 	shp->sh_type = SHT_STRTAB;
670 	shp->sh_offset = off;
671 	shp->sh_size = sizeof (DTRACE_SHSTRTAB64);
672 	shp->sh_addralign = sizeof (char);
673 	off = roundup2(shp->sh_offset + shp->sh_size, 8);
674 
675 	shp = &elf_file.shdr[ESHDR_DOF];
676 	shp->sh_name = 11; /* DTRACE_SHSTRTAB64[11] = ".SUNW_dof" */
677 	shp->sh_flags = SHF_ALLOC;
678 	shp->sh_type = SHT_SUNW_dof;
679 	shp->sh_offset = off;
680 	shp->sh_size = dof->dofh_filesz;
681 	shp->sh_addralign = 8;
682 	off = shp->sh_offset + shp->sh_size;
683 
684 	shp = &elf_file.shdr[ESHDR_STRTAB];
685 	shp->sh_name = 21; /* DTRACE_SHSTRTAB64[21] = ".strtab" */
686 	shp->sh_flags = SHF_ALLOC;
687 	shp->sh_type = SHT_STRTAB;
688 	shp->sh_offset = off;
689 	shp->sh_size = de.de_strlen;
690 	shp->sh_addralign = sizeof (char);
691 	off = roundup2(shp->sh_offset + shp->sh_size, 8);
692 
693 	shp = &elf_file.shdr[ESHDR_SYMTAB];
694 	shp->sh_name = 29; /* DTRACE_SHSTRTAB64[29] = ".symtab" */
695 	shp->sh_flags = SHF_ALLOC;
696 	shp->sh_type = SHT_SYMTAB;
697 	shp->sh_entsize = sizeof (Elf64_Sym);
698 	shp->sh_link = ESHDR_STRTAB;
699 	shp->sh_offset = off;
700 	shp->sh_info = de.de_global;
701 	shp->sh_size = de.de_nsym * sizeof (Elf64_Sym);
702 	shp->sh_addralign = 8;
703 	off = roundup2(shp->sh_offset + shp->sh_size, 8);
704 
705 	if (de.de_nrel == 0) {
706 		if (dt_write(dtp, fd, &elf_file,
707 		    sizeof (elf_file)) != sizeof (elf_file) ||
708 		    PWRITE_SCN(ESHDR_SHSTRTAB, DTRACE_SHSTRTAB64) ||
709 		    PWRITE_SCN(ESHDR_STRTAB, de.de_strtab) ||
710 		    PWRITE_SCN(ESHDR_SYMTAB, de.de_sym) ||
711 		    PWRITE_SCN(ESHDR_DOF, dof)) {
712 			ret = dt_set_errno(dtp, errno);
713 		}
714 	} else {
715 		shp = &elf_file.shdr[ESHDR_REL];
716 		shp->sh_name = 37; /* DTRACE_SHSTRTAB64[37] = ".rel.SUNW_dof" */
717 		shp->sh_flags = SHF_ALLOC;
718 		shp->sh_type = SHT_RELA;
719 		shp->sh_entsize = sizeof (de.de_rel[0]);
720 		shp->sh_link = ESHDR_SYMTAB;
721 		shp->sh_info = ESHDR_DOF;
722 		shp->sh_offset = off;
723 		shp->sh_size = de.de_nrel * sizeof (de.de_rel[0]);
724 		shp->sh_addralign = 8;
725 
726 		if (dt_write(dtp, fd, &elf_file,
727 		    sizeof (elf_file)) != sizeof (elf_file) ||
728 		    PWRITE_SCN(ESHDR_SHSTRTAB, DTRACE_SHSTRTAB64) ||
729 		    PWRITE_SCN(ESHDR_STRTAB, de.de_strtab) ||
730 		    PWRITE_SCN(ESHDR_SYMTAB, de.de_sym) ||
731 		    PWRITE_SCN(ESHDR_REL, de.de_rel) ||
732 		    PWRITE_SCN(ESHDR_DOF, dof)) {
733 			ret = dt_set_errno(dtp, errno);
734 		}
735 	}
736 
737 	free(de.de_strtab);
738 	free(de.de_sym);
739 	free(de.de_rel);
740 
741 	return (ret);
742 }
743 
744 static int
745 dt_symtab_lookup(Elf_Data *data_sym, int start, int end, uintptr_t addr,
746     uint_t shn, GElf_Sym *sym, int uses_funcdesc, Elf *elf)
747 {
748 	Elf64_Addr symval;
749 	Elf_Scn *opd_scn;
750 	Elf_Data *opd_desc;
751 	int i;
752 
753 	for (i = start; i < end && gelf_getsym(data_sym, i, sym) != NULL; i++) {
754 		if (GELF_ST_TYPE(sym->st_info) == STT_FUNC) {
755 			symval = sym->st_value;
756 			if (uses_funcdesc) {
757 				opd_scn = elf_getscn(elf, sym->st_shndx);
758 				opd_desc = elf_rawdata(opd_scn, NULL);
759 				symval =
760 				    *(uint64_t*)((char *)opd_desc->d_buf + symval);
761 			}
762 			if ((uses_funcdesc || shn == sym->st_shndx) &&
763 			    symval <= addr && addr < symval + sym->st_size)
764 				return (0);
765 		}
766 	}
767 
768 	return (-1);
769 }
770 
771 #if defined(__aarch64__)
772 #define	DT_OP_NOP		0xd503201f
773 #define	DT_OP_RET		0xd65f03c0
774 #define	DT_OP_CALL26		0x94000000
775 #define	DT_OP_JUMP26		0x14000000
776 
777 static int
778 dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
779     uint32_t *off)
780 {
781 	uint32_t *ip;
782 
783 	/*
784 	 * Ensure that the offset is aligned on an instruction boundary.
785 	 */
786 	if ((rela->r_offset & (sizeof (uint32_t) - 1)) != 0)
787 		return (-1);
788 
789 	/*
790 	 * We only know about some specific relocation types.
791 	 * We also recognize relocation type NONE, since that gets used for
792 	 * relocations of USDT probes, and we might be re-processing a file.
793 	 */
794 	if (GELF_R_TYPE(rela->r_info) != R_AARCH64_CALL26 &&
795 	    GELF_R_TYPE(rela->r_info) != R_AARCH64_JUMP26 &&
796 	    GELF_R_TYPE(rela->r_info) != R_AARCH64_NONE)
797 		return (-1);
798 
799 	ip = (uint32_t *)(p + rela->r_offset);
800 
801 	/*
802 	 * We may have already processed this object file in an earlier linker
803 	 * invocation. Check to see if the present instruction sequence matches
804 	 * the one we would install below.
805 	 */
806 	if (ip[0] == DT_OP_NOP || ip[0] == DT_OP_RET)
807 		return (0);
808 
809 	/*
810 	 * We only expect call instructions with a displacement of 0, or a jump
811 	 * instruction acting as a tail call.
812 	 */
813 	if (ip[0] != DT_OP_CALL26 && ip[0] != DT_OP_JUMP26) {
814 		dt_dprintf("found %x instead of a call or jmp instruction at "
815 		    "%llx\n", ip[0], (u_longlong_t)rela->r_offset);
816 		return (-1);
817 	}
818 
819 	/*
820 	 * On arm64, we do not have to differentiate between regular probes and
821 	 * is-enabled probes.  Both cases are encoded as a regular branch for
822 	 * non-tail call locations, and a jump for tail call locations.  Calls
823 	 * are to be converted into a no-op whereas jumps should become a
824 	 * return.
825 	 */
826 	if (ip[0] == DT_OP_CALL26)
827 		ip[0] = DT_OP_NOP;
828 	else
829 		ip[0] = DT_OP_RET;
830 
831 	return (0);
832 }
833 #elif defined(__arm__)
834 /* XXX */
835 static int
836 dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
837     uint32_t *off)
838 {
839 	printf("%s:%s(%d): arm not implemented\n", __FUNCTION__, __FILE__,
840 	    __LINE__);
841 	return (-1);
842 }
843 #elif defined(__mips__)
844 /* XXX */
845 static int
846 dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
847     uint32_t *off)
848 {
849 	printf("%s:%s(%d): MIPS not implemented\n", __FUNCTION__, __FILE__,
850 	    __LINE__);
851 	return (-1);
852 }
853 #elif defined(__powerpc__)
854 /* The sentinel is 'xor r3,r3,r3'. */
855 #define DT_OP_XOR_R3	0x7c631a78
856 
857 #define DT_OP_NOP		0x60000000
858 #define DT_OP_BLR		0x4e800020
859 
860 /* This captures all forms of branching to address. */
861 #define DT_IS_BRANCH(inst)	((inst & 0xfc000000) == 0x48000000)
862 #define DT_IS_BL(inst)	(DT_IS_BRANCH(inst) && (inst & 0x01))
863 
864 /* XXX */
865 static int
866 dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
867     uint32_t *off)
868 {
869 	uint32_t *ip;
870 
871 	if ((rela->r_offset & (sizeof (uint32_t) - 1)) != 0)
872 		return (-1);
873 
874 	/*LINTED*/
875 	ip = (uint32_t *)(p + rela->r_offset);
876 
877 	/*
878 	 * We only know about some specific relocation types.
879 	 */
880 	if (GELF_R_TYPE(rela->r_info) != R_PPC_REL24 &&
881 	    GELF_R_TYPE(rela->r_info) != R_PPC_PLTREL24)
882 		return (-1);
883 
884 	/*
885 	 * We may have already processed this object file in an earlier linker
886 	 * invocation. Check to see if the present instruction sequence matches
887 	 * the one we would install below.
888 	 */
889 	if (isenabled) {
890 		if (ip[0] == DT_OP_XOR_R3) {
891 			(*off) += sizeof (ip[0]);
892 			return (0);
893 		}
894 	} else {
895 		if (ip[0] == DT_OP_NOP) {
896 			(*off) += sizeof (ip[0]);
897 			return (0);
898 		}
899 	}
900 
901 	/*
902 	 * We only expect branch to address instructions.
903 	 */
904 	if (!DT_IS_BRANCH(ip[0])) {
905 		dt_dprintf("found %x instead of a branch instruction at %llx\n",
906 		    ip[0], (u_longlong_t)rela->r_offset);
907 		return (-1);
908 	}
909 
910 	if (isenabled) {
911 		/*
912 		 * It would necessarily indicate incorrect usage if an is-
913 		 * enabled probe were tail-called so flag that as an error.
914 		 * It's also potentially (very) tricky to handle gracefully,
915 		 * but could be done if this were a desired use scenario.
916 		 */
917 		if (!DT_IS_BL(ip[0])) {
918 			dt_dprintf("tail call to is-enabled probe at %llx\n",
919 			    (u_longlong_t)rela->r_offset);
920 			return (-1);
921 		}
922 
923 		ip[0] = DT_OP_XOR_R3;
924 		(*off) += sizeof (ip[0]);
925 	} else {
926 		if (DT_IS_BL(ip[0]))
927 			ip[0] = DT_OP_NOP;
928 		else
929 			ip[0] = DT_OP_BLR;
930 	}
931 
932 	return (0);
933 }
934 #elif defined(__riscv)
935 /* XXX */
936 static int
937 dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
938     uint32_t *off)
939 {
940 	printf("%s:%s(%d): RISC-V implementation required\n", __FUNCTION__,
941 	    __FILE__, __LINE__);
942 	return (-1);
943 }
944 
945 #elif defined(__i386) || defined(__amd64)
946 
947 #define	DT_OP_NOP		0x90
948 #define	DT_OP_RET		0xc3
949 #define	DT_OP_CALL		0xe8
950 #define	DT_OP_JMP32		0xe9
951 #define	DT_OP_REX_RAX		0x48
952 #define	DT_OP_XOR_EAX_0		0x33
953 #define	DT_OP_XOR_EAX_1		0xc0
954 
955 static int
956 dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
957     uint32_t *off)
958 {
959 	uint8_t *ip = (uint8_t *)(p + rela->r_offset - 1);
960 	uint8_t ret;
961 
962 	/*
963 	 * On x86, the first byte of the instruction is the call opcode and
964 	 * the next four bytes are the 32-bit address; the relocation is for
965 	 * the address operand. We back up the offset to the first byte of
966 	 * the instruction. For is-enabled probes, we later advance the offset
967 	 * so that it hits the first nop in the instruction sequence.
968 	 */
969 	(*off) -= 1;
970 
971 	/*
972 	 * We only know about some specific relocation types. Luckily
973 	 * these types have the same values on both 32-bit and 64-bit
974 	 * x86 architectures.
975 	 */
976 	if (GELF_R_TYPE(rela->r_info) != R_386_PC32 &&
977 	    GELF_R_TYPE(rela->r_info) != R_386_PLT32)
978 		return (-1);
979 
980 	/*
981 	 * We may have already processed this object file in an earlier linker
982 	 * invocation. Check to see if the present instruction sequence matches
983 	 * the one we would install. For is-enabled probes, we advance the
984 	 * offset to the first nop instruction in the sequence to match the
985 	 * text modification code below.
986 	 */
987 	if (!isenabled) {
988 		if ((ip[0] == DT_OP_NOP || ip[0] == DT_OP_RET) &&
989 		    ip[1] == DT_OP_NOP && ip[2] == DT_OP_NOP &&
990 		    ip[3] == DT_OP_NOP && ip[4] == DT_OP_NOP)
991 			return (0);
992 	} else if (dtp->dt_oflags & DTRACE_O_LP64) {
993 		if (ip[0] == DT_OP_REX_RAX &&
994 		    ip[1] == DT_OP_XOR_EAX_0 && ip[2] == DT_OP_XOR_EAX_1 &&
995 		    (ip[3] == DT_OP_NOP || ip[3] == DT_OP_RET) &&
996 		    ip[4] == DT_OP_NOP) {
997 			(*off) += 3;
998 			return (0);
999 		}
1000 	} else {
1001 		if (ip[0] == DT_OP_XOR_EAX_0 && ip[1] == DT_OP_XOR_EAX_1 &&
1002 		    (ip[2] == DT_OP_NOP || ip[2] == DT_OP_RET) &&
1003 		    ip[3] == DT_OP_NOP && ip[4] == DT_OP_NOP) {
1004 			(*off) += 2;
1005 			return (0);
1006 		}
1007 	}
1008 
1009 	/*
1010 	 * We expect either a call instrution with a 32-bit displacement or a
1011 	 * jmp instruction with a 32-bit displacement acting as a tail-call.
1012 	 */
1013 	if (ip[0] != DT_OP_CALL && ip[0] != DT_OP_JMP32) {
1014 		dt_dprintf("found %x instead of a call or jmp instruction at "
1015 		    "%llx\n", ip[0], (u_longlong_t)rela->r_offset);
1016 		return (-1);
1017 	}
1018 
1019 	ret = (ip[0] == DT_OP_JMP32) ? DT_OP_RET : DT_OP_NOP;
1020 
1021 	/*
1022 	 * Establish the instruction sequence -- all nops for probes, and an
1023 	 * instruction to clear the return value register (%eax/%rax) followed
1024 	 * by nops for is-enabled probes. For is-enabled probes, we advance
1025 	 * the offset to the first nop. This isn't stricly necessary but makes
1026 	 * for more readable disassembly when the probe is enabled.
1027 	 */
1028 	if (!isenabled) {
1029 		ip[0] = ret;
1030 		ip[1] = DT_OP_NOP;
1031 		ip[2] = DT_OP_NOP;
1032 		ip[3] = DT_OP_NOP;
1033 		ip[4] = DT_OP_NOP;
1034 	} else if (dtp->dt_oflags & DTRACE_O_LP64) {
1035 		ip[0] = DT_OP_REX_RAX;
1036 		ip[1] = DT_OP_XOR_EAX_0;
1037 		ip[2] = DT_OP_XOR_EAX_1;
1038 		ip[3] = ret;
1039 		ip[4] = DT_OP_NOP;
1040 		(*off) += 3;
1041 	} else {
1042 		ip[0] = DT_OP_XOR_EAX_0;
1043 		ip[1] = DT_OP_XOR_EAX_1;
1044 		ip[2] = ret;
1045 		ip[3] = DT_OP_NOP;
1046 		ip[4] = DT_OP_NOP;
1047 		(*off) += 2;
1048 	}
1049 
1050 	return (0);
1051 }
1052 
1053 #else
1054 #error unknown ISA
1055 #endif
1056 
1057 /*PRINTFLIKE5*/
1058 static int
1059 dt_link_error(dtrace_hdl_t *dtp, Elf *elf, int fd, dt_link_pair_t *bufs,
1060     const char *format, ...)
1061 {
1062 	va_list ap;
1063 	dt_link_pair_t *pair;
1064 
1065 	va_start(ap, format);
1066 	dt_set_errmsg(dtp, NULL, NULL, NULL, 0, format, ap);
1067 	va_end(ap);
1068 
1069 	if (elf != NULL)
1070 		(void) elf_end(elf);
1071 
1072 	if (fd >= 0)
1073 		(void) close(fd);
1074 
1075 	while ((pair = bufs) != NULL) {
1076 		bufs = pair->dlp_next;
1077 		dt_free(dtp, pair->dlp_str);
1078 		dt_free(dtp, pair->dlp_sym);
1079 		dt_free(dtp, pair);
1080 	}
1081 
1082 	return (dt_set_errno(dtp, EDT_COMPILER));
1083 }
1084 
1085 /*
1086  * Provide a unique identifier used when adding global symbols to an object.
1087  * This is the FNV-1a hash of an absolute path for the file.
1088  */
1089 static unsigned int
1090 hash_obj(const char *obj, int fd)
1091 {
1092 	char path[PATH_MAX];
1093 	unsigned int h;
1094 
1095 	if (realpath(obj, path) == NULL)
1096 		return (-1);
1097 
1098 	for (h = 2166136261u, obj = &path[0]; *obj != '\0'; obj++)
1099 		h = (h ^ *obj) * 16777619;
1100 	h &= 0x7fffffff;
1101 	return (h);
1102 }
1103 
1104 static int
1105 process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
1106 {
1107 	static const char dt_prefix[] = "__dtrace";
1108 	static const char dt_enabled[] = "enabled";
1109 	static const char dt_symprefix[] = "$dtrace";
1110 	static const char dt_symfmt[] = "%s%u.%s";
1111 	static const char dt_weaksymfmt[] = "%s.%s";
1112 	char probename[DTRACE_NAMELEN];
1113 	int fd, i, ndx, eprobe, uses_funcdesc = 0, mod = 0;
1114 	Elf *elf = NULL;
1115 	GElf_Ehdr ehdr;
1116 	Elf_Scn *scn_rel, *scn_sym, *scn_str, *scn_tgt;
1117 	Elf_Data *data_rel, *data_sym, *data_str, *data_tgt;
1118 	GElf_Shdr shdr_rel, shdr_sym, shdr_str, shdr_tgt;
1119 	GElf_Sym rsym, fsym, dsym;
1120 	GElf_Rela rela;
1121 	char *s, *p, *r;
1122 	char pname[DTRACE_PROVNAMELEN];
1123 	dt_provider_t *pvp;
1124 	dt_probe_t *prp;
1125 	uint32_t off, eclass, emachine1, emachine2;
1126 	size_t symsize, osym, nsym, isym, istr, len;
1127 	unsigned int objkey;
1128 	dt_link_pair_t *pair, *bufs = NULL;
1129 	dt_strtab_t *strtab;
1130 	void *tmp;
1131 
1132 	if ((fd = open64(obj, O_RDWR)) == -1) {
1133 		return (dt_link_error(dtp, elf, fd, bufs,
1134 		    "failed to open %s: %s", obj, strerror(errno)));
1135 	}
1136 
1137 	if ((elf = elf_begin(fd, ELF_C_RDWR, NULL)) == NULL) {
1138 		return (dt_link_error(dtp, elf, fd, bufs,
1139 		    "failed to process %s: %s", obj, elf_errmsg(elf_errno())));
1140 	}
1141 
1142 	switch (elf_kind(elf)) {
1143 	case ELF_K_ELF:
1144 		break;
1145 	case ELF_K_AR:
1146 		return (dt_link_error(dtp, elf, fd, bufs, "archives are not "
1147 		    "permitted; use the contents of the archive instead: %s",
1148 		    obj));
1149 	default:
1150 		return (dt_link_error(dtp, elf, fd, bufs,
1151 		    "invalid file type: %s", obj));
1152 	}
1153 
1154 	if (gelf_getehdr(elf, &ehdr) == NULL) {
1155 		return (dt_link_error(dtp, elf, fd, bufs, "corrupt file: %s",
1156 		    obj));
1157 	}
1158 
1159 	if (dtp->dt_oflags & DTRACE_O_LP64) {
1160 		eclass = ELFCLASS64;
1161 #if defined(__mips__)
1162 		emachine1 = emachine2 = EM_MIPS;
1163 #elif defined(__powerpc__)
1164 		emachine1 = emachine2 = EM_PPC64;
1165 #if !defined(_CALL_ELF) || _CALL_ELF == 1
1166 		uses_funcdesc = 1;
1167 #endif
1168 #elif defined(__i386) || defined(__amd64)
1169 		emachine1 = emachine2 = EM_AMD64;
1170 #elif defined(__aarch64__)
1171 		emachine1 = emachine2 = EM_AARCH64;
1172 #endif
1173 		symsize = sizeof (Elf64_Sym);
1174 	} else {
1175 		eclass = ELFCLASS32;
1176 #if defined(__arm__)
1177 		emachine1 = emachine2 = EM_ARM;
1178 #elif defined(__mips__)
1179 		emachine1 = emachine2 = EM_MIPS;
1180 #elif defined(__powerpc__)
1181 		emachine1 = emachine2 = EM_PPC;
1182 #elif defined(__i386) || defined(__amd64)
1183 		emachine1 = emachine2 = EM_386;
1184 #endif
1185 		symsize = sizeof (Elf32_Sym);
1186 	}
1187 
1188 	if (ehdr.e_ident[EI_CLASS] != eclass) {
1189 		return (dt_link_error(dtp, elf, fd, bufs,
1190 		    "incorrect ELF class for object file: %s", obj));
1191 	}
1192 
1193 	if (ehdr.e_machine != emachine1 && ehdr.e_machine != emachine2) {
1194 		return (dt_link_error(dtp, elf, fd, bufs,
1195 		    "incorrect ELF machine type for object file: %s", obj));
1196 	}
1197 
1198 	/*
1199 	 * We use this token as a relatively unique handle for this file on the
1200 	 * system in order to disambiguate potential conflicts between files of
1201 	 * the same name which contain identially named local symbols.
1202 	 */
1203 	if ((objkey = hash_obj(obj, fd)) == (unsigned int)-1)
1204 		return (dt_link_error(dtp, elf, fd, bufs,
1205 		    "failed to generate unique key for object file: %s", obj));
1206 
1207 	scn_rel = NULL;
1208 	while ((scn_rel = elf_nextscn(elf, scn_rel)) != NULL) {
1209 		if (gelf_getshdr(scn_rel, &shdr_rel) == NULL)
1210 			goto err;
1211 
1212 		/*
1213 		 * Skip any non-relocation sections.
1214 		 */
1215 		if (shdr_rel.sh_type != SHT_RELA && shdr_rel.sh_type != SHT_REL)
1216 			continue;
1217 
1218 		if ((data_rel = elf_getdata(scn_rel, NULL)) == NULL)
1219 			goto err;
1220 
1221 		/*
1222 		 * Grab the section, section header and section data for the
1223 		 * symbol table that this relocation section references.
1224 		 */
1225 		if ((scn_sym = elf_getscn(elf, shdr_rel.sh_link)) == NULL ||
1226 		    gelf_getshdr(scn_sym, &shdr_sym) == NULL ||
1227 		    (data_sym = elf_getdata(scn_sym, NULL)) == NULL)
1228 			goto err;
1229 
1230 		/*
1231 		 * Ditto for that symbol table's string table.
1232 		 */
1233 		if ((scn_str = elf_getscn(elf, shdr_sym.sh_link)) == NULL ||
1234 		    gelf_getshdr(scn_str, &shdr_str) == NULL ||
1235 		    (data_str = elf_getdata(scn_str, NULL)) == NULL)
1236 			goto err;
1237 
1238 		/*
1239 		 * Grab the section, section header and section data for the
1240 		 * target section for the relocations. For the relocations
1241 		 * we're looking for -- this will typically be the text of the
1242 		 * object file.
1243 		 */
1244 		if ((scn_tgt = elf_getscn(elf, shdr_rel.sh_info)) == NULL ||
1245 		    gelf_getshdr(scn_tgt, &shdr_tgt) == NULL ||
1246 		    (data_tgt = elf_getdata(scn_tgt, NULL)) == NULL)
1247 			goto err;
1248 
1249 		/*
1250 		 * We're looking for relocations to symbols matching this form:
1251 		 *
1252 		 *   __dtrace[enabled]_<prov>___<probe>
1253 		 *
1254 		 * For the generated object, we need to record the location
1255 		 * identified by the relocation, and create a new relocation
1256 		 * in the generated object that will be resolved at link time
1257 		 * to the location of the function in which the probe is
1258 		 * embedded. In the target object, we change the matched symbol
1259 		 * so that it will be ignored at link time, and we modify the
1260 		 * target (text) section to replace the call instruction with
1261 		 * one or more nops.
1262 		 *
1263 		 * To avoid runtime overhead, the relocations added to the
1264 		 * generated object should be resolved at static link time. We
1265 		 * therefore create aliases for the functions that contain
1266 		 * probes. An alias is global (so that the relocation from the
1267 		 * generated object can be resolved), and hidden (so that its
1268 		 * address is known at static link time). Such aliases have this
1269 		 * form:
1270 		 *
1271 		 *   $dtrace<key>.<function>
1272 		 *
1273 		 * We take a first pass through all the relocations to
1274 		 * populate our string table and count the number of extra
1275 		 * symbols we'll require.
1276 		 */
1277 		strtab = dt_strtab_create(1);
1278 		nsym = 0;
1279 		isym = data_sym->d_size / symsize;
1280 		istr = data_str->d_size;
1281 
1282 		for (i = 0; i < shdr_rel.sh_size / shdr_rel.sh_entsize; i++) {
1283 
1284 			if (shdr_rel.sh_type == SHT_RELA) {
1285 				if (gelf_getrela(data_rel, i, &rela) == NULL)
1286 					continue;
1287 			} else {
1288 				GElf_Rel rel;
1289 				if (gelf_getrel(data_rel, i, &rel) == NULL)
1290 					continue;
1291 				rela.r_offset = rel.r_offset;
1292 				rela.r_info = rel.r_info;
1293 				rela.r_addend = 0;
1294 			}
1295 
1296 			if (gelf_getsym(data_sym, GELF_R_SYM(rela.r_info),
1297 			    &rsym) == NULL) {
1298 				dt_strtab_destroy(strtab);
1299 				goto err;
1300 			}
1301 
1302 			s = (char *)data_str->d_buf + rsym.st_name;
1303 
1304 			if (strncmp(s, dt_prefix, sizeof (dt_prefix) - 1) != 0)
1305 				continue;
1306 
1307 			if (dt_symtab_lookup(data_sym, 0, isym, rela.r_offset,
1308 			    shdr_rel.sh_info, &fsym, uses_funcdesc,
1309 			    elf) != 0) {
1310 				dt_strtab_destroy(strtab);
1311 				goto err;
1312 			}
1313 
1314 			if (fsym.st_name > data_str->d_size) {
1315 				dt_strtab_destroy(strtab);
1316 				goto err;
1317 			}
1318 
1319 			s = (char *)data_str->d_buf + fsym.st_name;
1320 
1321 			/*
1322 			 * If this symbol isn't of type function, we've really
1323 			 * driven off the rails or the object file is corrupt.
1324 			 */
1325 			if (GELF_ST_TYPE(fsym.st_info) != STT_FUNC) {
1326 				dt_strtab_destroy(strtab);
1327 				return (dt_link_error(dtp, elf, fd, bufs,
1328 				    "expected %s to be of type function", s));
1329 			}
1330 
1331 			/*
1332 			 * Aliases of weak symbols don't get a uniquifier.
1333 			 */
1334 			if (GELF_ST_BIND(fsym.st_info) == STB_WEAK)
1335 				len = snprintf(NULL, 0, dt_weaksymfmt,
1336 				    dt_symprefix, s) + 1;
1337 			else
1338 				len = snprintf(NULL, 0, dt_symfmt, dt_symprefix,
1339 				    objkey, s) + 1;
1340 			if ((p = dt_alloc(dtp, len)) == NULL) {
1341 				dt_strtab_destroy(strtab);
1342 				goto err;
1343 			}
1344 			(void) snprintf(p, len, dt_symfmt, dt_symprefix,
1345 			    objkey, s);
1346 
1347 			if (dt_strtab_index(strtab, p) == -1) {
1348 				nsym++;
1349 				(void) dt_strtab_insert(strtab, p);
1350 			}
1351 
1352 			dt_free(dtp, p);
1353 		}
1354 
1355 		/*
1356 		 * If any probes were found, allocate the additional space for
1357 		 * the symbol table and string table, copying the old data into
1358 		 * the new buffers, and marking the buffers as dirty. We inject
1359 		 * those newly allocated buffers into the libelf data
1360 		 * structures, but are still responsible for freeing them once
1361 		 * we're done with the elf handle.
1362 		 */
1363 		if (nsym > 0) {
1364 			/*
1365 			 * The first byte of the string table is reserved for
1366 			 * the \0 entry.
1367 			 */
1368 			len = dt_strtab_size(strtab) - 1;
1369 
1370 			assert(len > 0);
1371 			assert(dt_strtab_index(strtab, "") == 0);
1372 
1373 			dt_strtab_destroy(strtab);
1374 
1375 			if ((pair = dt_alloc(dtp, sizeof (*pair))) == NULL)
1376 				goto err;
1377 
1378 			if ((pair->dlp_str = dt_alloc(dtp, data_str->d_size +
1379 			    len)) == NULL) {
1380 				dt_free(dtp, pair);
1381 				goto err;
1382 			}
1383 
1384 			if ((pair->dlp_sym = dt_alloc(dtp, data_sym->d_size +
1385 			    nsym * symsize)) == NULL) {
1386 				dt_free(dtp, pair->dlp_str);
1387 				dt_free(dtp, pair);
1388 				goto err;
1389 			}
1390 
1391 			pair->dlp_next = bufs;
1392 			bufs = pair;
1393 
1394 			bcopy(data_str->d_buf, pair->dlp_str, data_str->d_size);
1395 			tmp = data_str->d_buf;
1396 			data_str->d_buf = pair->dlp_str;
1397 			pair->dlp_str = tmp;
1398 			data_str->d_size += len;
1399 			(void) elf_flagdata(data_str, ELF_C_SET, ELF_F_DIRTY);
1400 
1401 			shdr_str.sh_size += len;
1402 			(void) gelf_update_shdr(scn_str, &shdr_str);
1403 
1404 			bcopy(data_sym->d_buf, pair->dlp_sym, data_sym->d_size);
1405 			tmp = data_sym->d_buf;
1406 			data_sym->d_buf = pair->dlp_sym;
1407 			pair->dlp_sym = tmp;
1408 			data_sym->d_size += nsym * symsize;
1409 			(void) elf_flagdata(data_sym, ELF_C_SET, ELF_F_DIRTY);
1410 
1411 			shdr_sym.sh_size += nsym * symsize;
1412 			(void) gelf_update_shdr(scn_sym, &shdr_sym);
1413 
1414 			osym = isym;
1415 			nsym += isym;
1416 		} else {
1417 			dt_strtab_destroy(strtab);
1418 			continue;
1419 		}
1420 
1421 		/*
1422 		 * Now that the tables have been allocated, perform the
1423 		 * modifications described above.
1424 		 */
1425 		for (i = 0; i < shdr_rel.sh_size / shdr_rel.sh_entsize; i++) {
1426 
1427 			if (shdr_rel.sh_type == SHT_RELA) {
1428 				if (gelf_getrela(data_rel, i, &rela) == NULL)
1429 					continue;
1430 			} else {
1431 				GElf_Rel rel;
1432 				if (gelf_getrel(data_rel, i, &rel) == NULL)
1433 					continue;
1434 				rela.r_offset = rel.r_offset;
1435 				rela.r_info = rel.r_info;
1436 				rela.r_addend = 0;
1437 			}
1438 
1439 			ndx = GELF_R_SYM(rela.r_info);
1440 
1441 			if (gelf_getsym(data_sym, ndx, &rsym) == NULL ||
1442 			    rsym.st_name > data_str->d_size)
1443 				goto err;
1444 
1445 			s = (char *)data_str->d_buf + rsym.st_name;
1446 
1447 			if (strncmp(s, dt_prefix, sizeof (dt_prefix) - 1) != 0)
1448 				continue;
1449 
1450 			s += sizeof (dt_prefix) - 1;
1451 
1452 			/*
1453 			 * Check to see if this is an 'is-enabled' check as
1454 			 * opposed to a normal probe.
1455 			 */
1456 			if (strncmp(s, dt_enabled,
1457 			    sizeof (dt_enabled) - 1) == 0) {
1458 				s += sizeof (dt_enabled) - 1;
1459 				eprobe = 1;
1460 				*eprobesp = 1;
1461 				dt_dprintf("is-enabled probe\n");
1462 			} else {
1463 				eprobe = 0;
1464 				dt_dprintf("normal probe\n");
1465 			}
1466 
1467 			if (*s++ != '_')
1468 				goto err;
1469 
1470 			if ((p = strstr(s, "___")) == NULL ||
1471 			    p - s >= sizeof (pname))
1472 				goto err;
1473 
1474 			bcopy(s, pname, p - s);
1475 			pname[p - s] = '\0';
1476 
1477 			if (dt_symtab_lookup(data_sym, osym, isym,
1478 			    rela.r_offset, shdr_rel.sh_info, &fsym,
1479 			    uses_funcdesc, elf) == 0) {
1480 				if (fsym.st_name > data_str->d_size)
1481 					goto err;
1482 
1483 				r = s = (char *) data_str->d_buf + fsym.st_name;
1484 				assert(strstr(s, dt_symprefix) == s);
1485 				s = strchr(s, '.') + 1;
1486 			} else if (dt_symtab_lookup(data_sym, 0, osym,
1487 			    rela.r_offset, shdr_rel.sh_info, &fsym,
1488 			    uses_funcdesc, elf) == 0) {
1489 				u_int bind;
1490 
1491 				bind = GELF_ST_BIND(fsym.st_info) == STB_WEAK ?
1492 				    STB_WEAK : STB_GLOBAL;
1493 
1494 				/*
1495 				 * Emit an alias for the symbol. It needs to be
1496 				 * non-preemptible so that .SUNW_dof relocations
1497 				 * may be resolved at static link time. Aliases
1498 				 * of weak symbols are given a non-unique name
1499 				 * so that they may be merged by the linker.
1500 				 */
1501 				dsym = fsym;
1502 				dsym.st_name = istr;
1503 				dsym.st_info = GELF_ST_INFO(bind, STT_FUNC);
1504 				dsym.st_other = GELF_ST_VISIBILITY(STV_HIDDEN);
1505 				(void) gelf_update_sym(data_sym, isym, &dsym);
1506 				r = (char *) data_str->d_buf + istr;
1507 				s = (char *) data_str->d_buf + fsym.st_name;
1508 				if (bind == STB_WEAK)
1509 					istr += sprintf(r, dt_weaksymfmt,
1510 					    dt_symprefix, s);
1511 				else
1512 					istr += sprintf(r, dt_symfmt,
1513 					    dt_symprefix, objkey, s);
1514 				istr++;
1515 				isym++;
1516 				assert(isym <= nsym);
1517 			} else
1518 				goto err;
1519 
1520 			if ((pvp = dt_provider_lookup(dtp, pname)) == NULL) {
1521 				return (dt_link_error(dtp, elf, fd, bufs,
1522 				    "no such provider %s", pname));
1523 			}
1524 
1525 			if (strlcpy(probename, p + 3, sizeof (probename)) >=
1526 			    sizeof (probename))
1527 				return (dt_link_error(dtp, elf, fd, bufs,
1528 				    "invalid probe name %s", probename));
1529 			(void) strhyphenate(probename);
1530 			if ((prp = dt_probe_lookup(pvp, probename)) == NULL)
1531 				return (dt_link_error(dtp, elf, fd, bufs,
1532 				    "no such probe %s", probename));
1533 
1534 			assert(fsym.st_value <= rela.r_offset);
1535 
1536 			off = rela.r_offset - fsym.st_value;
1537 			if (dt_modtext(dtp, data_tgt->d_buf, eprobe,
1538 			    &rela, &off) != 0)
1539 				goto err;
1540 
1541 			if (dt_probe_define(pvp, prp, s, r, off, eprobe) != 0) {
1542 				return (dt_link_error(dtp, elf, fd, bufs,
1543 				    "failed to allocate space for probe"));
1544 			}
1545 
1546 			/*
1547 			 * Our linker doesn't understand the SUNW_IGNORE ndx and
1548 			 * will try to use this relocation when we build the
1549 			 * final executable. Since we are done processing this
1550 			 * relocation, mark it as inexistant and let libelf
1551 			 * remove it from the file.
1552 			 * If this wasn't done, we would have garbage added to
1553 			 * the executable file as the symbol is going to be
1554 			 * change from UND to ABS.
1555 			 */
1556 			if (shdr_rel.sh_type == SHT_RELA) {
1557 				rela.r_offset = 0;
1558 				rela.r_info  = 0;
1559 				rela.r_addend = 0;
1560 				(void) gelf_update_rela(data_rel, i, &rela);
1561 			} else {
1562 				GElf_Rel rel;
1563 				rel.r_offset = 0;
1564 				rel.r_info = 0;
1565 				(void) gelf_update_rel(data_rel, i, &rel);
1566 			}
1567 
1568 			mod = 1;
1569 			(void) elf_flagdata(data_tgt, ELF_C_SET, ELF_F_DIRTY);
1570 
1571 			/*
1572 			 * This symbol may already have been marked to
1573 			 * be ignored by another relocation referencing
1574 			 * the same symbol or if this object file has
1575 			 * already been processed by an earlier link
1576 			 * invocation.
1577 			 */
1578 			if (rsym.st_shndx != SHN_ABS) {
1579 				rsym.st_shndx = SHN_ABS;
1580 				(void) gelf_update_sym(data_sym, ndx, &rsym);
1581 			}
1582 		}
1583 	}
1584 
1585 	if (mod && elf_update(elf, ELF_C_WRITE) == -1)
1586 		goto err;
1587 
1588 	(void) elf_end(elf);
1589 	(void) close(fd);
1590 
1591 	while ((pair = bufs) != NULL) {
1592 		bufs = pair->dlp_next;
1593 		dt_free(dtp, pair->dlp_str);
1594 		dt_free(dtp, pair->dlp_sym);
1595 		dt_free(dtp, pair);
1596 	}
1597 
1598 	return (0);
1599 
1600 err:
1601 	return (dt_link_error(dtp, elf, fd, bufs,
1602 	    "an error was encountered while processing %s", obj));
1603 }
1604 
1605 int
1606 dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
1607     const char *file, int objc, char *const objv[])
1608 {
1609 	char tfile[PATH_MAX];
1610 	char drti[PATH_MAX];
1611 	dof_hdr_t *dof;
1612 	int fd, status, i, cur;
1613 	char *cmd, tmp;
1614 	size_t len;
1615 	int eprobes = 0, ret = 0;
1616 
1617 	if (access(file, R_OK) == 0) {
1618 		fprintf(stderr, "dtrace: target object (%s) already exists. "
1619 		    "Please remove the target\ndtrace: object and rebuild all "
1620 		    "the source objects if you wish to run the DTrace\n"
1621 		    "dtrace: linking process again\n", file);
1622 		/*
1623 		 * Several build infrastructures run DTrace twice (e.g.
1624 		 * postgres) and we don't want the build to fail. Return
1625 		 * 0 here since this isn't really a fatal error.
1626 		 */
1627 		return (0);
1628 	}
1629 
1630 	/*
1631 	 * A NULL program indicates a special use in which we just link
1632 	 * together a bunch of object files specified in objv and then
1633 	 * unlink(2) those object files.
1634 	 */
1635 	if (pgp == NULL) {
1636 		const char *fmt = "%s -o %s -r";
1637 
1638 		len = snprintf(&tmp, 1, fmt, dtp->dt_ld_path, file) + 1;
1639 
1640 		for (i = 0; i < objc; i++)
1641 			len += strlen(objv[i]) + 1;
1642 
1643 		cmd = alloca(len);
1644 
1645 		cur = snprintf(cmd, len, fmt, dtp->dt_ld_path, file);
1646 
1647 		for (i = 0; i < objc; i++)
1648 			cur += snprintf(cmd + cur, len - cur, " %s", objv[i]);
1649 
1650 		if ((status = system(cmd)) == -1) {
1651 			return (dt_link_error(dtp, NULL, -1, NULL,
1652 			    "failed to run %s: %s", dtp->dt_ld_path,
1653 			    strerror(errno)));
1654 		}
1655 
1656 		if (WIFSIGNALED(status)) {
1657 			return (dt_link_error(dtp, NULL, -1, NULL,
1658 			    "failed to link %s: %s failed due to signal %d",
1659 			    file, dtp->dt_ld_path, WTERMSIG(status)));
1660 		}
1661 
1662 		if (WEXITSTATUS(status) != 0) {
1663 			return (dt_link_error(dtp, NULL, -1, NULL,
1664 			    "failed to link %s: %s exited with status %d\n",
1665 			    file, dtp->dt_ld_path, WEXITSTATUS(status)));
1666 		}
1667 
1668 		for (i = 0; i < objc; i++) {
1669 			if (strcmp(objv[i], file) != 0)
1670 				(void) unlink(objv[i]);
1671 		}
1672 
1673 		return (0);
1674 	}
1675 
1676 	for (i = 0; i < objc; i++) {
1677 		if (process_obj(dtp, objv[i], &eprobes) != 0)
1678 			return (-1); /* errno is set for us */
1679 	}
1680 
1681 	/*
1682 	 * If there are is-enabled probes then we need to force use of DOF
1683 	 * version 2.
1684 	 */
1685 	if (eprobes && pgp->dp_dofversion < DOF_VERSION_2)
1686 		pgp->dp_dofversion = DOF_VERSION_2;
1687 
1688 	if ((dof = dtrace_dof_create(dtp, pgp, dflags)) == NULL)
1689 		return (-1); /* errno is set for us */
1690 
1691 	snprintf(tfile, sizeof(tfile), "%s.XXXXXX", file);
1692 	if ((fd = mkostemp(tfile, O_CLOEXEC)) == -1)
1693 		return (dt_link_error(dtp, NULL, -1, NULL,
1694 		    "failed to create temporary file %s: %s",
1695 		    tfile, strerror(errno)));
1696 
1697 	/*
1698 	 * If -xlinktype=DOF has been selected, just write out the DOF.
1699 	 * Otherwise proceed to the default of generating and linking ELF.
1700 	 */
1701 	switch (dtp->dt_linktype) {
1702 	case DT_LTYP_DOF:
1703 		if (dt_write(dtp, fd, dof, dof->dofh_filesz) < dof->dofh_filesz)
1704 			ret = errno;
1705 
1706 		if (close(fd) != 0 && ret == 0)
1707 			ret = errno;
1708 
1709 		if (ret != 0) {
1710 			return (dt_link_error(dtp, NULL, -1, NULL,
1711 			    "failed to write %s: %s", file, strerror(ret)));
1712 		}
1713 
1714 		return (0);
1715 
1716 	case DT_LTYP_ELF:
1717 		break; /* fall through to the rest of dtrace_program_link() */
1718 
1719 	default:
1720 		return (dt_link_error(dtp, NULL, -1, NULL,
1721 		    "invalid link type %u\n", dtp->dt_linktype));
1722 	}
1723 
1724 
1725 	if (dtp->dt_oflags & DTRACE_O_LP64)
1726 		status = dump_elf64(dtp, dof, fd);
1727 	else
1728 		status = dump_elf32(dtp, dof, fd);
1729 
1730 	if (status != 0)
1731 		return (dt_link_error(dtp, NULL, -1, NULL,
1732 		    "failed to write %s: %s", tfile,
1733 		    strerror(dtrace_errno(dtp))));
1734 
1735 	if (!dtp->dt_lazyload) {
1736 		const char *fmt = "%s -o %s -r %s %s";
1737 		dt_dirpath_t *dp = dt_list_next(&dtp->dt_lib_path);
1738 
1739 		(void) snprintf(drti, sizeof (drti), "%s/drti.o", dp->dir_path);
1740 
1741 		len = snprintf(&tmp, 1, fmt, dtp->dt_ld_path, file, tfile,
1742 		    drti) + 1;
1743 
1744 		cmd = alloca(len);
1745 
1746 		(void) snprintf(cmd, len, fmt, dtp->dt_ld_path, file, tfile,
1747 		    drti);
1748 		if ((status = system(cmd)) == -1) {
1749 			ret = dt_link_error(dtp, NULL, fd, NULL,
1750 			    "failed to run %s: %s", dtp->dt_ld_path,
1751 			    strerror(errno));
1752 			goto done;
1753 		}
1754 
1755 		if (WIFSIGNALED(status)) {
1756 			ret = dt_link_error(dtp, NULL, fd, NULL,
1757 			    "failed to link %s: %s failed due to signal %d",
1758 			    file, dtp->dt_ld_path, WTERMSIG(status));
1759 			goto done;
1760 		}
1761 
1762 		if (WEXITSTATUS(status) != 0) {
1763 			ret = dt_link_error(dtp, NULL, fd, NULL,
1764 			    "failed to link %s: %s exited with status %d\n",
1765 			    file, dtp->dt_ld_path, WEXITSTATUS(status));
1766 			goto done;
1767 		}
1768 		(void) close(fd); /* release temporary file */
1769 
1770 		/*
1771 		 * Now that we've linked drti.o, reduce the global __SUNW_dof
1772 		 * symbol to a local symbol. This is needed to so that multiple
1773 		 * generated object files (for different providers, for
1774 		 * instance) can be linked together. This is accomplished using
1775 		 * the -Blocal flag with Sun's linker, but GNU ld doesn't appear
1776 		 * to have an equivalent option.
1777 		 */
1778 		asprintf(&cmd, "%s --localize-hidden %s", dtp->dt_objcopy_path,
1779 		    file);
1780 		if ((status = system(cmd)) == -1) {
1781 			ret = dt_link_error(dtp, NULL, -1, NULL,
1782 			    "failed to run %s: %s", dtp->dt_objcopy_path,
1783 			    strerror(errno));
1784 			free(cmd);
1785 			goto done;
1786 		}
1787 		free(cmd);
1788 
1789 		if (WIFSIGNALED(status)) {
1790 			ret = dt_link_error(dtp, NULL, -1, NULL,
1791 			    "failed to link %s: %s failed due to signal %d",
1792 			    file, dtp->dt_objcopy_path, WTERMSIG(status));
1793 			goto done;
1794 		}
1795 
1796 		if (WEXITSTATUS(status) != 0) {
1797 			ret = dt_link_error(dtp, NULL, -1, NULL,
1798 			    "failed to link %s: %s exited with status %d\n",
1799 			    file, dtp->dt_objcopy_path, WEXITSTATUS(status));
1800 			goto done;
1801 		}
1802 	} else {
1803 		if (rename(tfile, file) != 0) {
1804 			ret = dt_link_error(dtp, NULL, fd, NULL,
1805 			    "failed to rename %s to %s: %s", tfile, file,
1806 			    strerror(errno));
1807 			goto done;
1808 		}
1809 		(void) close(fd);
1810 	}
1811 
1812 done:
1813 	dtrace_dof_destroy(dtp, dof);
1814 
1815 	if (!dtp->dt_lazyload)
1816 		(void) unlink(tfile);
1817 	return (ret);
1818 }
1819