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