]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.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 below.
872          */
873         if (isenabled) {
874                 if (ip[0] == DT_OP_NOP) {
875                         (*off) += sizeof (ip[0]);
876                         return (0);
877                 }
878         } else {
879                 if (DT_IS_RESTORE(ip[1])) {
880                         if (ip[0] == DT_OP_RET) {
881                                 (*off) += sizeof (ip[0]);
882                                 return (0);
883                         }
884                 } else if (DT_IS_MOV_O7(ip[1])) {
885                         if (DT_IS_RETL(ip[0]))
886                                 return (0);
887                 } else {
888                         if (ip[0] == DT_OP_NOP) {
889                                 (*off) += sizeof (ip[0]);
890                                 return (0);
891                         }
892                 }
893         }
894
895         /*
896          * We only expect call instructions with a displacement of 0.
897          */
898         if (ip[0] != DT_OP_CALL) {
899                 dt_dprintf("found %x instead of a call instruction at %llx\n",
900                     ip[0], (u_longlong_t)rela->r_offset);
901                 return (-1);
902         }
903
904         if (isenabled) {
905                 /*
906                  * It would necessarily indicate incorrect usage if an is-
907                  * enabled probe were tail-called so flag that as an error.
908                  * It's also potentially (very) tricky to handle gracefully,
909                  * but could be done if this were a desired use scenario.
910                  */
911                 if (DT_IS_RESTORE(ip[1]) || DT_IS_MOV_O7(ip[1])) {
912                         dt_dprintf("tail call to is-enabled probe at %llx\n",
913                             (u_longlong_t)rela->r_offset);
914                         return (-1);
915                 }
916
917
918                 /*
919                  * On SPARC, we take advantage of the fact that the first
920                  * argument shares the same register as for the return value.
921                  * The macro handles the work of zeroing that register so we
922                  * don't need to do anything special here. We instrument the
923                  * instruction in the delay slot as we'll need to modify the
924                  * return register after that instruction has been emulated.
925                  */
926                 ip[0] = DT_OP_NOP;
927                 (*off) += sizeof (ip[0]);
928         } else {
929                 /*
930                  * If the call is followed by a restore, it's a tail call so
931                  * change the call to a ret. If the call if followed by a mov
932                  * of a register into %o7, it's a tail call in leaf context
933                  * so change the call to a retl-like instruction that returns
934                  * to that register value + 8 (rather than the typical %o7 +
935                  * 8); the delay slot instruction is left, but should have no
936                  * effect. Otherwise we change the call to be a nop. We
937                  * identify the subsequent instruction as the probe point in
938                  * all but the leaf tail-call case to ensure that arguments to
939                  * the probe are complete and consistent. An astute, though
940                  * largely hypothetical, observer would note that there is the
941                  * possibility of a false-positive probe firing if the function
942                  * contained a branch to the instruction in the delay slot of
943                  * the call. Fixing this would require significant in-kernel
944                  * modifications, and isn't worth doing until we see it in the
945                  * wild.
946                  */
947                 if (DT_IS_RESTORE(ip[1])) {
948                         ip[0] = DT_OP_RET;
949                         (*off) += sizeof (ip[0]);
950                 } else if (DT_IS_MOV_O7(ip[1])) {
951                         ip[0] = DT_MAKE_RETL(DT_RS2(ip[1]));
952                 } else {
953                         ip[0] = DT_OP_NOP;
954                         (*off) += sizeof (ip[0]);
955                 }
956         }
957
958         return (0);
959 }
960
961 #elif defined(__i386) || defined(__amd64)
962
963 #define DT_OP_NOP               0x90
964 #define DT_OP_RET               0xc3
965 #define DT_OP_CALL              0xe8
966 #define DT_OP_JMP32             0xe9
967 #define DT_OP_REX_RAX           0x48
968 #define DT_OP_XOR_EAX_0         0x33
969 #define DT_OP_XOR_EAX_1         0xc0
970
971 static int
972 dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
973     uint32_t *off)
974 {
975         uint8_t *ip = (uint8_t *)(p + rela->r_offset - 1);
976         uint8_t ret;
977
978         /*
979          * On x86, the first byte of the instruction is the call opcode and
980          * the next four bytes are the 32-bit address; the relocation is for
981          * the address operand. We back up the offset to the first byte of
982          * the instruction. For is-enabled probes, we later advance the offset
983          * so that it hits the first nop in the instruction sequence.
984          */
985         (*off) -= 1;
986
987         /*
988          * We only know about some specific relocation types. Luckily
989          * these types have the same values on both 32-bit and 64-bit
990          * x86 architectures.
991          */
992         if (GELF_R_TYPE(rela->r_info) != R_386_PC32 &&
993             GELF_R_TYPE(rela->r_info) != R_386_PLT32)
994                 return (-1);
995
996         /*
997          * We may have already processed this object file in an earlier linker
998          * invocation. Check to see if the present instruction sequence matches
999          * the one we would install. For is-enabled probes, we advance the
1000          * offset to the first nop instruction in the sequence to match the
1001          * text modification code below.
1002          */
1003         if (!isenabled) {
1004                 if ((ip[0] == DT_OP_NOP || ip[0] == DT_OP_RET) &&
1005                     ip[1] == DT_OP_NOP && ip[2] == DT_OP_NOP &&
1006                     ip[3] == DT_OP_NOP && ip[4] == DT_OP_NOP)
1007                         return (0);
1008         } else if (dtp->dt_oflags & DTRACE_O_LP64) {
1009                 if (ip[0] == DT_OP_REX_RAX &&
1010                     ip[1] == DT_OP_XOR_EAX_0 && ip[2] == DT_OP_XOR_EAX_1 &&
1011                     (ip[3] == DT_OP_NOP || ip[3] == DT_OP_RET) &&
1012                     ip[4] == DT_OP_NOP) {
1013                         (*off) += 3;
1014                         return (0);
1015                 }
1016         } else {
1017                 if (ip[0] == DT_OP_XOR_EAX_0 && ip[1] == DT_OP_XOR_EAX_1 &&
1018                     (ip[2] == DT_OP_NOP || ip[2] == DT_OP_RET) &&
1019                     ip[3] == DT_OP_NOP && ip[4] == DT_OP_NOP) {
1020                         (*off) += 2;
1021                         return (0);
1022                 }
1023         }
1024
1025         /*
1026          * We expect either a call instrution with a 32-bit displacement or a
1027          * jmp instruction with a 32-bit displacement acting as a tail-call.
1028          */
1029         if (ip[0] != DT_OP_CALL && ip[0] != DT_OP_JMP32) {
1030                 dt_dprintf("found %x instead of a call or jmp instruction at "
1031                     "%llx\n", ip[0], (u_longlong_t)rela->r_offset);
1032                 return (-1);
1033         }
1034
1035         ret = (ip[0] == DT_OP_JMP32) ? DT_OP_RET : DT_OP_NOP;
1036
1037         /*
1038          * Establish the instruction sequence -- all nops for probes, and an
1039          * instruction to clear the return value register (%eax/%rax) followed
1040          * by nops for is-enabled probes. For is-enabled probes, we advance
1041          * the offset to the first nop. This isn't stricly necessary but makes
1042          * for more readable disassembly when the probe is enabled.
1043          */
1044         if (!isenabled) {
1045                 ip[0] = ret;
1046                 ip[1] = DT_OP_NOP;
1047                 ip[2] = DT_OP_NOP;
1048                 ip[3] = DT_OP_NOP;
1049                 ip[4] = DT_OP_NOP;
1050         } else if (dtp->dt_oflags & DTRACE_O_LP64) {
1051                 ip[0] = DT_OP_REX_RAX;
1052                 ip[1] = DT_OP_XOR_EAX_0;
1053                 ip[2] = DT_OP_XOR_EAX_1;
1054                 ip[3] = ret;
1055                 ip[4] = DT_OP_NOP;
1056                 (*off) += 3;
1057         } else {
1058                 ip[0] = DT_OP_XOR_EAX_0;
1059                 ip[1] = DT_OP_XOR_EAX_1;
1060                 ip[2] = ret;
1061                 ip[3] = DT_OP_NOP;
1062                 ip[4] = DT_OP_NOP;
1063                 (*off) += 2;
1064         }
1065
1066         return (0);
1067 }
1068
1069 #else
1070 #error unknown ISA
1071 #endif
1072
1073 /*PRINTFLIKE5*/
1074 static int
1075 dt_link_error(dtrace_hdl_t *dtp, Elf *elf, int fd, dt_link_pair_t *bufs,
1076     const char *format, ...)
1077 {
1078         va_list ap;
1079         dt_link_pair_t *pair;
1080
1081         va_start(ap, format);
1082         dt_set_errmsg(dtp, NULL, NULL, NULL, 0, format, ap);
1083         va_end(ap);
1084
1085         if (elf != NULL)
1086                 (void) elf_end(elf);
1087
1088         if (fd >= 0)
1089                 (void) close(fd);
1090
1091         while ((pair = bufs) != NULL) {
1092                 bufs = pair->dlp_next;
1093                 dt_free(dtp, pair->dlp_str);
1094                 dt_free(dtp, pair->dlp_sym);
1095                 dt_free(dtp, pair);
1096         }
1097
1098         return (dt_set_errno(dtp, EDT_COMPILER));
1099 }
1100
1101 static int
1102 process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
1103 {
1104         static const char dt_prefix[] = "__dtrace";
1105         static const char dt_enabled[] = "enabled";
1106         static const char dt_symprefix[] = "$dtrace";
1107         static const char dt_symfmt[] = "%s%d.%s";
1108         int fd, i, ndx, eprobe, mod = 0;
1109         Elf *elf = NULL;
1110         GElf_Ehdr ehdr;
1111         Elf_Scn *scn_rel, *scn_sym, *scn_str, *scn_tgt;
1112         Elf_Data *data_rel, *data_sym, *data_str, *data_tgt;
1113         GElf_Shdr shdr_rel, shdr_sym, shdr_str, shdr_tgt;
1114         GElf_Sym rsym, fsym, dsym;
1115         GElf_Rela rela;
1116         char *s, *p, *r;
1117         char pname[DTRACE_PROVNAMELEN];
1118         dt_provider_t *pvp;
1119         dt_probe_t *prp;
1120         uint32_t off, eclass, emachine1, emachine2;
1121         size_t symsize, nsym, isym, istr, len;
1122         key_t objkey;
1123         dt_link_pair_t *pair, *bufs = NULL;
1124         dt_strtab_t *strtab;
1125
1126         if ((fd = open64(obj, O_RDWR)) == -1) {
1127                 return (dt_link_error(dtp, elf, fd, bufs,
1128                     "failed to open %s: %s", obj, strerror(errno)));
1129         }
1130
1131         if ((elf = elf_begin(fd, ELF_C_RDWR, NULL)) == NULL) {
1132                 return (dt_link_error(dtp, elf, fd, bufs,
1133                     "failed to process %s: %s", obj, elf_errmsg(elf_errno())));
1134         }
1135
1136         switch (elf_kind(elf)) {
1137         case ELF_K_ELF:
1138                 break;
1139         case ELF_K_AR:
1140                 return (dt_link_error(dtp, elf, fd, bufs, "archives are not "
1141                     "permitted; use the contents of the archive instead: %s",
1142                     obj));
1143         default:
1144                 return (dt_link_error(dtp, elf, fd, bufs,
1145                     "invalid file type: %s", obj));
1146         }
1147
1148         if (gelf_getehdr(elf, &ehdr) == NULL) {
1149                 return (dt_link_error(dtp, elf, fd, bufs, "corrupt file: %s",
1150                     obj));
1151         }
1152
1153         if (dtp->dt_oflags & DTRACE_O_LP64) {
1154                 eclass = ELFCLASS64;
1155 #if defined(__ia64__)
1156                 emachine1 = emachine2 = EM_IA_64;
1157 #elif defined(__mips__)
1158                 emachine1 = emachine2 = EM_MIPS;
1159 #elif defined(__powerpc__)
1160                 emachine1 = emachine2 = EM_PPC64;
1161 #elif defined(__sparc)
1162                 emachine1 = emachine2 = EM_SPARCV9;
1163 #elif defined(__i386) || defined(__amd64)
1164                 emachine1 = emachine2 = EM_AMD64;
1165 #endif
1166                 symsize = sizeof (Elf64_Sym);
1167         } else {
1168                 eclass = ELFCLASS32;
1169 #if defined(__arm__)
1170                 emachine1 = emachine2 = EM_ARM;
1171 #elif defined(__mips__)
1172                 emachine1 = emachine2 = EM_MIPS;
1173 #elif defined(__powerpc__)
1174                 emachine1 = emachine2 = EM_PPC;
1175 #elif defined(__sparc)
1176                 emachine1 = EM_SPARC;
1177                 emachine2 = EM_SPARC32PLUS;
1178 #elif defined(__i386) || defined(__amd64) || defined(__ia64__)
1179                 emachine1 = emachine2 = EM_386;
1180 #endif
1181                 symsize = sizeof (Elf32_Sym);
1182         }
1183
1184         if (ehdr.e_ident[EI_CLASS] != eclass) {
1185                 return (dt_link_error(dtp, elf, fd, bufs,
1186                     "incorrect ELF class for object file: %s", obj));
1187         }
1188
1189         if (ehdr.e_machine != emachine1 && ehdr.e_machine != emachine2) {
1190                 return (dt_link_error(dtp, elf, fd, bufs,
1191                     "incorrect ELF machine type for object file: %s", obj));
1192         }
1193
1194         /*
1195          * We use this token as a relatively unique handle for this file on the
1196          * system in order to disambiguate potential conflicts between files of
1197          * the same name which contain identially named local symbols.
1198          */
1199         if ((objkey = ftok(obj, 0)) == (key_t)-1) {
1200                 return (dt_link_error(dtp, elf, fd, bufs,
1201                     "failed to generate unique key for object file: %s", obj));
1202         }
1203
1204         scn_rel = NULL;
1205         while ((scn_rel = elf_nextscn(elf, scn_rel)) != NULL) {
1206                 if (gelf_getshdr(scn_rel, &shdr_rel) == NULL)
1207                         goto err;
1208
1209                 /*
1210                  * Skip any non-relocation sections.
1211                  */
1212                 if (shdr_rel.sh_type != SHT_RELA && shdr_rel.sh_type != SHT_REL)
1213                         continue;
1214
1215                 if ((data_rel = elf_getdata(scn_rel, NULL)) == NULL)
1216                         goto err;
1217
1218                 /*
1219                  * Grab the section, section header and section data for the
1220                  * symbol table that this relocation section references.
1221                  */
1222                 if ((scn_sym = elf_getscn(elf, shdr_rel.sh_link)) == NULL ||
1223                     gelf_getshdr(scn_sym, &shdr_sym) == NULL ||
1224                     (data_sym = elf_getdata(scn_sym, NULL)) == NULL)
1225                         goto err;
1226
1227                 /*
1228                  * Ditto for that symbol table's string table.
1229                  */
1230                 if ((scn_str = elf_getscn(elf, shdr_sym.sh_link)) == NULL ||
1231                     gelf_getshdr(scn_str, &shdr_str) == NULL ||
1232                     (data_str = elf_getdata(scn_str, NULL)) == NULL)
1233                         goto err;
1234
1235                 /*
1236                  * Grab the section, section header and section data for the
1237                  * target section for the relocations. For the relocations
1238                  * we're looking for -- this will typically be the text of the
1239                  * object file.
1240                  */
1241                 if ((scn_tgt = elf_getscn(elf, shdr_rel.sh_info)) == NULL ||
1242                     gelf_getshdr(scn_tgt, &shdr_tgt) == NULL ||
1243                     (data_tgt = elf_getdata(scn_tgt, NULL)) == NULL)
1244                         goto err;
1245
1246                 /*
1247                  * We're looking for relocations to symbols matching this form:
1248                  *
1249                  *   __dtrace[enabled]_<prov>___<probe>
1250                  *
1251                  * For the generated object, we need to record the location
1252                  * identified by the relocation, and create a new relocation
1253                  * in the generated object that will be resolved at link time
1254                  * to the location of the function in which the probe is
1255                  * embedded. In the target object, we change the matched symbol
1256                  * so that it will be ignored at link time, and we modify the
1257                  * target (text) section to replace the call instruction with
1258                  * one or more nops.
1259                  *
1260                  * If the function containing the probe is locally scoped
1261                  * (static), we create an alias used by the relocation in the
1262                  * generated object. The alias, a new symbol, will be global
1263                  * (so that the relocation from the generated object can be
1264                  * resolved), and hidden (so that it is converted to a local
1265                  * symbol at link time). Such aliases have this form:
1266                  *
1267                  *   $dtrace<key>.<function>
1268                  *
1269                  * We take a first pass through all the relocations to
1270                  * populate our string table and count the number of extra
1271                  * symbols we'll require.
1272                  */
1273                 strtab = dt_strtab_create(1);
1274                 nsym = 0;
1275                 isym = data_sym->d_size / symsize;
1276                 istr = data_str->d_size;
1277
1278                 for (i = 0; i < shdr_rel.sh_size / shdr_rel.sh_entsize; i++) {
1279
1280                         if (shdr_rel.sh_type == SHT_RELA) {
1281                                 if (gelf_getrela(data_rel, i, &rela) == NULL)
1282                                         continue;
1283                         } else {
1284                                 GElf_Rel rel;
1285                                 if (gelf_getrel(data_rel, i, &rel) == NULL)
1286                                         continue;
1287                                 rela.r_offset = rel.r_offset;
1288                                 rela.r_info = rel.r_info;
1289                                 rela.r_addend = 0;
1290                         }
1291
1292                         if (gelf_getsym(data_sym, GELF_R_SYM(rela.r_info),
1293                             &rsym) == NULL) {
1294                                 dt_strtab_destroy(strtab);
1295                                 goto err;
1296                         }
1297
1298                         s = (char *)data_str->d_buf + rsym.st_name;
1299
1300                         if (strncmp(s, dt_prefix, sizeof (dt_prefix) - 1) != 0)
1301                                 continue;
1302
1303                         if (dt_symtab_lookup(data_sym, isym, rela.r_offset,
1304                             shdr_rel.sh_info, &fsym) != 0) {
1305                                 dt_strtab_destroy(strtab);
1306                                 goto err;
1307                         }
1308
1309                         if (GELF_ST_BIND(fsym.st_info) != STB_LOCAL)
1310                                 continue;
1311
1312                         if (fsym.st_name > data_str->d_size) {
1313                                 dt_strtab_destroy(strtab);
1314                                 goto err;
1315                         }
1316
1317                         s = (char *)data_str->d_buf + fsym.st_name;
1318
1319                         /*
1320                          * If this symbol isn't of type function, we've really
1321                          * driven off the rails or the object file is corrupt.
1322                          */
1323                         if (GELF_ST_TYPE(fsym.st_info) != STT_FUNC) {
1324                                 dt_strtab_destroy(strtab);
1325                                 return (dt_link_error(dtp, elf, fd, bufs,
1326                                     "expected %s to be of type function", s));
1327                         }
1328
1329                         len = snprintf(NULL, 0, dt_symfmt, dt_symprefix,
1330                             objkey, s) + 1;
1331                         if ((p = dt_alloc(dtp, len)) == NULL) {
1332                                 dt_strtab_destroy(strtab);
1333                                 goto err;
1334                         }
1335                         (void) snprintf(p, len, dt_symfmt, dt_symprefix,
1336                             objkey, s);
1337
1338                         if (dt_strtab_index(strtab, p) == -1) {
1339                                 nsym++;
1340                                 (void) dt_strtab_insert(strtab, p);
1341                         }
1342
1343                         dt_free(dtp, p);
1344                 }
1345
1346                 /*
1347                  * If needed, allocate the additional space for the symbol
1348                  * table and string table copying the old data into the new
1349                  * buffers, and marking the buffers as dirty. We inject those
1350                  * newly allocated buffers into the libelf data structures, but
1351                  * are still responsible for freeing them once we're done with
1352                  * the elf handle.
1353                  */
1354                 if (nsym > 0) {
1355                         /*
1356                          * The first byte of the string table is reserved for
1357                          * the \0 entry.
1358                          */
1359                         len = dt_strtab_size(strtab) - 1;
1360
1361                         assert(len > 0);
1362                         assert(dt_strtab_index(strtab, "") == 0);
1363
1364                         dt_strtab_destroy(strtab);
1365
1366                         if ((pair = dt_alloc(dtp, sizeof (*pair))) == NULL)
1367                                 goto err;
1368
1369                         if ((pair->dlp_str = dt_alloc(dtp, data_str->d_size +
1370                             len)) == NULL) {
1371                                 dt_free(dtp, pair);
1372                                 goto err;
1373                         }
1374
1375                         if ((pair->dlp_sym = dt_alloc(dtp, data_sym->d_size +
1376                             nsym * symsize)) == NULL) {
1377                                 dt_free(dtp, pair->dlp_str);
1378                                 dt_free(dtp, pair);
1379                                 goto err;
1380                         }
1381
1382                         pair->dlp_next = bufs;
1383                         bufs = pair;
1384
1385                         bcopy(data_str->d_buf, pair->dlp_str, data_str->d_size);
1386                         data_str->d_buf = pair->dlp_str;
1387                         data_str->d_size += len;
1388                         (void) elf_flagdata(data_str, ELF_C_SET, ELF_F_DIRTY);
1389
1390                         shdr_str.sh_size += len;
1391                         (void) gelf_update_shdr(scn_str, &shdr_str);
1392
1393                         bcopy(data_sym->d_buf, pair->dlp_sym, data_sym->d_size);
1394                         data_sym->d_buf = pair->dlp_sym;
1395                         data_sym->d_size += nsym * symsize;
1396                         (void) elf_flagdata(data_sym, ELF_C_SET, ELF_F_DIRTY);
1397
1398                         shdr_sym.sh_size += nsym * symsize;
1399                         (void) gelf_update_shdr(scn_sym, &shdr_sym);
1400
1401                         nsym += isym;
1402                 } else {
1403                         dt_strtab_destroy(strtab);
1404                 }
1405
1406                 /*
1407                  * Now that the tables have been allocated, perform the
1408                  * modifications described above.
1409                  */
1410                 for (i = 0; i < shdr_rel.sh_size / shdr_rel.sh_entsize; i++) {
1411
1412                         if (shdr_rel.sh_type == SHT_RELA) {
1413                                 if (gelf_getrela(data_rel, i, &rela) == NULL)
1414                                         continue;
1415                         } else {
1416                                 GElf_Rel rel;
1417                                 if (gelf_getrel(data_rel, i, &rel) == NULL)
1418                                         continue;
1419                                 rela.r_offset = rel.r_offset;
1420                                 rela.r_info = rel.r_info;
1421                                 rela.r_addend = 0;
1422                         }
1423
1424                         ndx = GELF_R_SYM(rela.r_info);
1425
1426                         if (gelf_getsym(data_sym, ndx, &rsym) == NULL ||
1427                             rsym.st_name > data_str->d_size)
1428                                 goto err;
1429
1430                         s = (char *)data_str->d_buf + rsym.st_name;
1431
1432                         if (strncmp(s, dt_prefix, sizeof (dt_prefix) - 1) != 0)
1433                                 continue;
1434
1435                         s += sizeof (dt_prefix) - 1;
1436
1437                         /*
1438                          * Check to see if this is an 'is-enabled' check as
1439                          * opposed to a normal probe.
1440                          */
1441                         if (strncmp(s, dt_enabled,
1442                             sizeof (dt_enabled) - 1) == 0) {
1443                                 s += sizeof (dt_enabled) - 1;
1444                                 eprobe = 1;
1445                                 *eprobesp = 1;
1446                                 dt_dprintf("is-enabled probe\n");
1447                         } else {
1448                                 eprobe = 0;
1449                                 dt_dprintf("normal probe\n");
1450                         }
1451
1452                         if (*s++ != '_')
1453                                 goto err;
1454
1455                         if ((p = strstr(s, "___")) == NULL ||
1456                             p - s >= sizeof (pname))
1457                                 goto err;
1458
1459                         bcopy(s, pname, p - s);
1460                         pname[p - s] = '\0';
1461
1462                         p = strhyphenate(p + 3); /* strlen("___") */
1463
1464                         if (dt_symtab_lookup(data_sym, isym, rela.r_offset,
1465                             shdr_rel.sh_info, &fsym) != 0)
1466                                 goto err;
1467
1468                         if (fsym.st_name > data_str->d_size)
1469                                 goto err;
1470
1471                         assert(GELF_ST_TYPE(fsym.st_info) == STT_FUNC);
1472
1473                         /*
1474                          * If a NULL relocation name is passed to
1475                          * dt_probe_define(), the function name is used for the
1476                          * relocation. The relocation needs to use a mangled
1477                          * name if the symbol is locally scoped; the function
1478                          * name may need to change if we've found the global
1479                          * alias for the locally scoped symbol (we prefer
1480                          * global symbols to locals in dt_symtab_lookup()).
1481                          */
1482                         s = (char *)data_str->d_buf + fsym.st_name;
1483                         r = NULL;
1484
1485                         if (GELF_ST_BIND(fsym.st_info) == STB_LOCAL) {
1486                                 dsym = fsym;
1487                                 dsym.st_name = istr;
1488                                 dsym.st_info = GELF_ST_INFO(STB_GLOBAL,
1489                                     STT_FUNC);
1490                                 dsym.st_other =
1491                                     ELF64_ST_VISIBILITY(STV_ELIMINATE);
1492                                 (void) gelf_update_sym(data_sym, isym, &dsym);
1493
1494                                 r = (char *)data_str->d_buf + istr;
1495                                 istr += 1 + sprintf(r, dt_symfmt,
1496                                     dt_symprefix, objkey, s);
1497                                 isym++;
1498                                 assert(isym <= nsym);
1499
1500                         } else if (strncmp(s, dt_symprefix,
1501                             strlen(dt_symprefix)) == 0) {
1502                                 r = s;
1503                                 if ((s = strchr(s, '.')) == NULL)
1504                                         goto err;
1505                                 s++;
1506                         }
1507
1508                         if ((pvp = dt_provider_lookup(dtp, pname)) == NULL) {
1509                                 return (dt_link_error(dtp, elf, fd, bufs,
1510                                     "no such provider %s", pname));
1511                         }
1512
1513                         if ((prp = dt_probe_lookup(pvp, p)) == NULL) {
1514                                 return (dt_link_error(dtp, elf, fd, bufs,
1515                                     "no such probe %s", p));
1516                         }
1517
1518                         assert(fsym.st_value <= rela.r_offset);
1519
1520                         off = rela.r_offset - fsym.st_value;
1521                         if (dt_modtext(dtp, data_tgt->d_buf, eprobe,
1522                             &rela, &off) != 0) {
1523                                 goto err;
1524                         }
1525
1526                         if (dt_probe_define(pvp, prp, s, r, off, eprobe) != 0) {
1527                                 return (dt_link_error(dtp, elf, fd, bufs,
1528                                     "failed to allocate space for probe"));
1529                         }
1530
1531                         mod = 1;
1532                         (void) elf_flagdata(data_tgt, ELF_C_SET, ELF_F_DIRTY);
1533
1534                         /*
1535                          * This symbol may already have been marked to
1536                          * be ignored by another relocation referencing
1537                          * the same symbol or if this object file has
1538                          * already been processed by an earlier link
1539                          * invocation.
1540                          */
1541 printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
1542 #ifdef DOODAD
1543                         if (rsym.st_shndx != SHN_SUNW_IGNORE) {
1544                                 rsym.st_shndx = SHN_SUNW_IGNORE;
1545                                 (void) gelf_update_sym(data_sym, ndx, &rsym);
1546                         }
1547 #endif
1548                 }
1549         }
1550
1551         if (mod && elf_update(elf, ELF_C_WRITE) == -1)
1552                 goto err;
1553
1554         (void) elf_end(elf);
1555         (void) close(fd);
1556
1557         while ((pair = bufs) != NULL) {
1558                 bufs = pair->dlp_next;
1559                 dt_free(dtp, pair->dlp_str);
1560                 dt_free(dtp, pair->dlp_sym);
1561                 dt_free(dtp, pair);
1562         }
1563
1564         return (0);
1565
1566 err:
1567         return (dt_link_error(dtp, elf, fd, bufs,
1568             "an error was encountered while processing %s", obj));
1569 }
1570
1571 int
1572 dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
1573     const char *file, int objc, char *const objv[])
1574 {
1575 #if !defined(sun)
1576         char tfile[PATH_MAX];
1577 #endif
1578         char drti[PATH_MAX];
1579         dof_hdr_t *dof;
1580         int fd, status, i, cur;
1581         char *cmd, tmp;
1582         size_t len;
1583         int eprobes = 0, ret = 0;
1584
1585 #if !defined(sun)
1586         /* XXX Should get a temp file name here. */
1587         snprintf(tfile, sizeof(tfile), "%s.tmp", file);
1588 #endif
1589
1590         /*
1591          * A NULL program indicates a special use in which we just link
1592          * together a bunch of object files specified in objv and then
1593          * unlink(2) those object files.
1594          */
1595         if (pgp == NULL) {
1596                 const char *fmt = "%s -o %s -r";
1597
1598                 len = snprintf(&tmp, 1, fmt, dtp->dt_ld_path, file) + 1;
1599
1600                 for (i = 0; i < objc; i++)
1601                         len += strlen(objv[i]) + 1;
1602
1603                 cmd = alloca(len);
1604
1605                 cur = snprintf(cmd, len, fmt, dtp->dt_ld_path, file);
1606
1607                 for (i = 0; i < objc; i++)
1608                         cur += snprintf(cmd + cur, len - cur, " %s", objv[i]);
1609
1610                 if ((status = system(cmd)) == -1) {
1611                         return (dt_link_error(dtp, NULL, -1, NULL,
1612                             "failed to run %s: %s", dtp->dt_ld_path,
1613                             strerror(errno)));
1614                 }
1615
1616                 if (WIFSIGNALED(status)) {
1617                         return (dt_link_error(dtp, NULL, -1, NULL,
1618                             "failed to link %s: %s failed due to signal %d",
1619                             file, dtp->dt_ld_path, WTERMSIG(status)));
1620                 }
1621
1622                 if (WEXITSTATUS(status) != 0) {
1623                         return (dt_link_error(dtp, NULL, -1, NULL,
1624                             "failed to link %s: %s exited with status %d\n",
1625                             file, dtp->dt_ld_path, WEXITSTATUS(status)));
1626                 }
1627
1628                 for (i = 0; i < objc; i++) {
1629                         if (strcmp(objv[i], file) != 0)
1630                                 (void) unlink(objv[i]);
1631                 }
1632
1633                 return (0);
1634         }
1635
1636         for (i = 0; i < objc; i++) {
1637                 if (process_obj(dtp, objv[i], &eprobes) != 0)
1638                         return (-1); /* errno is set for us */
1639         }
1640
1641         /*
1642          * If there are is-enabled probes then we need to force use of DOF
1643          * version 2.
1644          */
1645         if (eprobes && pgp->dp_dofversion < DOF_VERSION_2)
1646                 pgp->dp_dofversion = DOF_VERSION_2;
1647
1648         if ((dof = dtrace_dof_create(dtp, pgp, dflags)) == NULL)
1649                 return (-1); /* errno is set for us */
1650
1651 #if defined(sun)
1652         /*
1653          * Create a temporary file and then unlink it if we're going to
1654          * combine it with drti.o later.  We can still refer to it in child
1655          * processes as /dev/fd/<fd>.
1656          */
1657         if ((fd = open64(file, O_RDWR | O_CREAT | O_TRUNC, 0666)) == -1) {
1658                 return (dt_link_error(dtp, NULL, -1, NULL,
1659                     "failed to open %s: %s", file, strerror(errno)));
1660         }
1661 #else
1662         if ((fd = open(tfile, O_RDWR | O_CREAT | O_TRUNC, 0666)) == -1)
1663                 return (dt_link_error(dtp, NULL, -1, NULL,
1664                     "failed to open %s: %s", tfile, strerror(errno)));
1665 #endif
1666
1667         /*
1668          * If -xlinktype=DOF has been selected, just write out the DOF.
1669          * Otherwise proceed to the default of generating and linking ELF.
1670          */
1671         switch (dtp->dt_linktype) {
1672         case DT_LTYP_DOF:
1673                 if (dt_write(dtp, fd, dof, dof->dofh_filesz) < dof->dofh_filesz)
1674                         ret = errno;
1675
1676                 if (close(fd) != 0 && ret == 0)
1677                         ret = errno;
1678
1679                 if (ret != 0) {
1680                         return (dt_link_error(dtp, NULL, -1, NULL,
1681                             "failed to write %s: %s", file, strerror(ret)));
1682                 }
1683
1684                 return (0);
1685
1686         case DT_LTYP_ELF:
1687                 break; /* fall through to the rest of dtrace_program_link() */
1688
1689         default:
1690                 return (dt_link_error(dtp, NULL, -1, NULL,
1691                     "invalid link type %u\n", dtp->dt_linktype));
1692         }
1693
1694
1695 #if defined(sun)
1696         if (!dtp->dt_lazyload)
1697                 (void) unlink(file);
1698 #endif
1699
1700         if (dtp->dt_oflags & DTRACE_O_LP64)
1701                 status = dump_elf64(dtp, dof, fd);
1702         else
1703                 status = dump_elf32(dtp, dof, fd);
1704
1705         if (status != 0 || lseek(fd, 0, SEEK_SET) != 0) {
1706                 return (dt_link_error(dtp, NULL, -1, NULL,
1707                     "failed to write %s: %s", file, strerror(errno)));
1708         }
1709
1710         if (!dtp->dt_lazyload) {
1711 #if defined(sun)
1712                 const char *fmt = "%s -o %s -r -Blocal -Breduce /dev/fd/%d %s";
1713
1714                 if (dtp->dt_oflags & DTRACE_O_LP64) {
1715                         (void) snprintf(drti, sizeof (drti),
1716                             "%s/64/drti.o", _dtrace_libdir);
1717                 } else {
1718                         (void) snprintf(drti, sizeof (drti),
1719                             "%s/drti.o", _dtrace_libdir);
1720                 }
1721
1722                 len = snprintf(&tmp, 1, fmt, dtp->dt_ld_path, file, fd,
1723                     drti) + 1;
1724
1725                 cmd = alloca(len);
1726
1727                 (void) snprintf(cmd, len, fmt, dtp->dt_ld_path, file, fd, drti);
1728 #else
1729                 const char *fmt = "%s -o %s -r %s %s";
1730
1731 #if defined(__amd64__)
1732                 /*
1733                  * Arches which default to 64-bit need to explicitly use
1734                  * the 32-bit library path.
1735                  */
1736                 int use_32 = !(dtp->dt_oflags & DTRACE_O_LP64);
1737 #else
1738                 /*
1739                  * Arches which are 32-bit only just use the normal
1740                  * library path.
1741                  */
1742                 int use_32 = 0;
1743 #endif
1744
1745                 (void) snprintf(drti, sizeof (drti), "/usr/lib%s/dtrace/drti.o",
1746                     use_32 ? "32":"");
1747
1748                 len = snprintf(&tmp, 1, fmt, dtp->dt_ld_path, file, tfile,
1749                     drti) + 1;
1750
1751                 cmd = alloca(len);
1752
1753                 (void) snprintf(cmd, len, fmt, dtp->dt_ld_path, file, tfile, drti);
1754 #endif
1755
1756                 if ((status = system(cmd)) == -1) {
1757                         ret = dt_link_error(dtp, NULL, -1, NULL,
1758                             "failed to run %s: %s", dtp->dt_ld_path,
1759                             strerror(errno));
1760                         goto done;
1761                 }
1762
1763                 (void) close(fd); /* release temporary file */
1764
1765                 if (WIFSIGNALED(status)) {
1766                         ret = dt_link_error(dtp, NULL, -1, NULL,
1767                             "failed to link %s: %s failed due to signal %d",
1768                             file, dtp->dt_ld_path, WTERMSIG(status));
1769                         goto done;
1770                 }
1771
1772                 if (WEXITSTATUS(status) != 0) {
1773                         ret = dt_link_error(dtp, NULL, -1, NULL,
1774                             "failed to link %s: %s exited with status %d\n",
1775                             file, dtp->dt_ld_path, WEXITSTATUS(status));
1776                         goto done;
1777                 }
1778         } else {
1779                 (void) close(fd);
1780         }
1781
1782 done:
1783         dtrace_dof_destroy(dtp, dof);
1784
1785 #if !defined(sun)
1786         unlink(tfile);
1787 #endif
1788         return (ret);
1789 }