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