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