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