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