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.
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.
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]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #define ELF_TARGET_ALL
32 #include <sys/types.h>
33 #include <sys/sysmacros.h>
49 #include <dt_provider.h>
50 #include <dt_program.h>
51 #include <dt_string.h>
54 #define ESHDR_SHSTRTAB 1
56 #define ESHDR_STRTAB 3
57 #define ESHDR_SYMTAB 4
61 #define PWRITE_SCN(index, data) \
62 (lseek64(fd, (off64_t)elf_file.shdr[(index)].sh_offset, SEEK_SET) != \
63 (off64_t)elf_file.shdr[(index)].sh_offset || \
64 dt_write(dtp, fd, (data), elf_file.shdr[(index)].sh_size) != \
65 elf_file.shdr[(index)].sh_size)
67 static const char DTRACE_SHSTRTAB32
[] = "\0"
69 ".SUNW_dof\0" /* 11 */
72 ".rel.SUNW_dof"; /* 37 */
74 static const char DTRACE_SHSTRTAB64
[] = "\0"
76 ".SUNW_dof\0" /* 11 */
79 ".rela.SUNW_dof"; /* 37 */
81 static const char DOFSTR
[] = "__SUNW_dof";
82 static const char DOFLAZYSTR
[] = "___SUNW_dof";
84 typedef struct dt_link_pair
{
85 struct dt_link_pair
*dlp_next
; /* next pair in linked list */
86 void *dlp_str
; /* buffer for string table */
87 void *dlp_sym
; /* buffer for symbol table */
90 typedef struct dof_elf32
{
91 uint32_t de_nrel
; /* relocation count */
92 Elf32_Rel
*de_rel
; /* array of relocations for x86 */
93 uint32_t de_nsym
; /* symbol count */
94 Elf32_Sym
*de_sym
; /* array of symbols */
95 uint32_t de_strlen
; /* size of of string table */
96 char *de_strtab
; /* string table */
97 uint32_t de_global
; /* index of the first global symbol */
101 prepare_elf32(dtrace_hdl_t
*dtp
, const dof_hdr_t
*dof
, dof_elf32_t
*dep
)
104 dof_relohdr_t
*dofrh
;
105 dof_relodesc_t
*dofr
;
115 dofs
= (dof_sec_t
*)((char *)dof
+ dof
->dofh_secoff
);
118 * First compute the size of the string table and the number of
119 * relocations present in the DOF.
121 for (i
= 0; i
< dof
->dofh_secnum
; i
++) {
122 if (dofs
[i
].dofs_type
!= DOF_SECT_URELHDR
)
126 dofrh
= (dof_relohdr_t
*)((char *)dof
+ dofs
[i
].dofs_offset
);
128 s
= &dofs
[dofrh
->dofr_strtab
];
129 strtab
= (char *)dof
+ s
->dofs_offset
;
130 assert(strtab
[0] == '\0');
131 strtabsz
+= s
->dofs_size
- 1;
133 s
= &dofs
[dofrh
->dofr_relsec
];
135 dofr
= (dof_relodesc_t
*)((char *)dof
+ s
->dofs_offset
);
136 count
+= s
->dofs_size
/ s
->dofs_entsize
;
139 dep
->de_strlen
= strtabsz
;
140 dep
->de_nrel
= count
;
141 dep
->de_nsym
= count
+ 1; /* the first symbol is always null */
143 if (dtp
->dt_lazyload
) {
144 dep
->de_strlen
+= sizeof (DOFLAZYSTR
);
147 dep
->de_strlen
+= sizeof (DOFSTR
);
151 if ((dep
->de_rel
= calloc(dep
->de_nrel
,
152 sizeof (dep
->de_rel
[0]))) == NULL
) {
153 return (dt_set_errno(dtp
, EDT_NOMEM
));
156 if ((dep
->de_sym
= calloc(dep
->de_nsym
, sizeof (Elf32_Sym
))) == NULL
) {
158 return (dt_set_errno(dtp
, EDT_NOMEM
));
161 if ((dep
->de_strtab
= calloc(dep
->de_strlen
, 1)) == NULL
) {
164 return (dt_set_errno(dtp
, EDT_NOMEM
));
169 dep
->de_strtab
[0] = '\0';
175 * The first symbol table entry must be zeroed and is always ignored.
177 bzero(sym
, sizeof (Elf32_Sym
));
181 * Take a second pass through the DOF sections filling in the
182 * memory we allocated.
184 for (i
= 0; i
< dof
->dofh_secnum
; i
++) {
185 if (dofs
[i
].dofs_type
!= DOF_SECT_URELHDR
)
189 dofrh
= (dof_relohdr_t
*)((char *)dof
+ dofs
[i
].dofs_offset
);
191 s
= &dofs
[dofrh
->dofr_strtab
];
192 strtab
= (char *)dof
+ s
->dofs_offset
;
193 bcopy(strtab
+ 1, dep
->de_strtab
+ strtabsz
, s
->dofs_size
);
195 strtabsz
+= s
->dofs_size
- 1;
197 s
= &dofs
[dofrh
->dofr_relsec
];
199 dofr
= (dof_relodesc_t
*)((char *)dof
+ s
->dofs_offset
);
200 nrel
= s
->dofs_size
/ s
->dofs_entsize
;
202 s
= &dofs
[dofrh
->dofr_tgtsec
];
204 for (j
= 0; j
< nrel
; j
++) {
205 #if defined(__i386) || defined(__amd64)
206 rel
->r_offset
= s
->dofs_offset
+
208 rel
->r_info
= ELF32_R_INFO(count
+ dep
->de_global
,
210 #elif defined(__sparc)
212 * Add 4 bytes to hit the low half of this 64-bit
213 * big-endian address.
215 rel
->r_offset
= s
->dofs_offset
+
216 dofr
[j
].dofr_offset
+ 4;
217 rel
->r_info
= ELF32_R_INFO(count
+ dep
->de_global
,
223 sym
->st_name
= base
+ dofr
[j
].dofr_name
- 1;
226 sym
->st_info
= ELF32_ST_INFO(STB_GLOBAL
, STT_FUNC
);
228 sym
->st_shndx
= SHN_UNDEF
;
237 * Add a symbol for the DOF itself. We use a different symbol for
238 * lazily and actively loaded DOF to make them easy to distinguish.
240 sym
->st_name
= strtabsz
;
242 sym
->st_size
= dof
->dofh_filesz
;
243 sym
->st_info
= ELF32_ST_INFO(STB_GLOBAL
, STT_OBJECT
);
245 sym
->st_shndx
= ESHDR_DOF
;
248 if (dtp
->dt_lazyload
) {
249 bcopy(DOFLAZYSTR
, dep
->de_strtab
+ strtabsz
,
250 sizeof (DOFLAZYSTR
));
251 strtabsz
+= sizeof (DOFLAZYSTR
);
253 bcopy(DOFSTR
, dep
->de_strtab
+ strtabsz
, sizeof (DOFSTR
));
254 strtabsz
+= sizeof (DOFSTR
);
257 assert(count
== dep
->de_nrel
);
258 assert(strtabsz
== dep
->de_strlen
);
264 typedef struct dof_elf64
{
277 prepare_elf64(dtrace_hdl_t
*dtp
, const dof_hdr_t
*dof
, dof_elf64_t
*dep
)
280 dof_relohdr_t
*dofrh
;
281 dof_relodesc_t
*dofr
;
291 dofs
= (dof_sec_t
*)((char *)dof
+ dof
->dofh_secoff
);
294 * First compute the size of the string table and the number of
295 * relocations present in the DOF.
297 for (i
= 0; i
< dof
->dofh_secnum
; i
++) {
298 if (dofs
[i
].dofs_type
!= DOF_SECT_URELHDR
)
302 dofrh
= (dof_relohdr_t
*)((char *)dof
+ dofs
[i
].dofs_offset
);
304 s
= &dofs
[dofrh
->dofr_strtab
];
305 strtab
= (char *)dof
+ s
->dofs_offset
;
306 assert(strtab
[0] == '\0');
307 strtabsz
+= s
->dofs_size
- 1;
309 s
= &dofs
[dofrh
->dofr_relsec
];
311 dofr
= (dof_relodesc_t
*)((char *)dof
+ s
->dofs_offset
);
312 count
+= s
->dofs_size
/ s
->dofs_entsize
;
315 dep
->de_strlen
= strtabsz
;
316 dep
->de_nrel
= count
;
317 dep
->de_nsym
= count
+ 1; /* the first symbol is always null */
319 if (dtp
->dt_lazyload
) {
320 dep
->de_strlen
+= sizeof (DOFLAZYSTR
);
323 dep
->de_strlen
+= sizeof (DOFSTR
);
327 if ((dep
->de_rel
= calloc(dep
->de_nrel
,
328 sizeof (dep
->de_rel
[0]))) == NULL
) {
329 return (dt_set_errno(dtp
, EDT_NOMEM
));
332 if ((dep
->de_sym
= calloc(dep
->de_nsym
, sizeof (Elf64_Sym
))) == NULL
) {
334 return (dt_set_errno(dtp
, EDT_NOMEM
));
337 if ((dep
->de_strtab
= calloc(dep
->de_strlen
, 1)) == NULL
) {
340 return (dt_set_errno(dtp
, EDT_NOMEM
));
345 dep
->de_strtab
[0] = '\0';
351 * The first symbol table entry must be zeroed and is always ignored.
353 bzero(sym
, sizeof (Elf64_Sym
));
357 * Take a second pass through the DOF sections filling in the
358 * memory we allocated.
360 for (i
= 0; i
< dof
->dofh_secnum
; i
++) {
361 if (dofs
[i
].dofs_type
!= DOF_SECT_URELHDR
)
365 dofrh
= (dof_relohdr_t
*)((char *)dof
+ dofs
[i
].dofs_offset
);
367 s
= &dofs
[dofrh
->dofr_strtab
];
368 strtab
= (char *)dof
+ s
->dofs_offset
;
369 bcopy(strtab
+ 1, dep
->de_strtab
+ strtabsz
, s
->dofs_size
);
371 strtabsz
+= s
->dofs_size
- 1;
373 s
= &dofs
[dofrh
->dofr_relsec
];
375 dofr
= (dof_relodesc_t
*)((char *)dof
+ s
->dofs_offset
);
376 nrel
= s
->dofs_size
/ s
->dofs_entsize
;
378 s
= &dofs
[dofrh
->dofr_tgtsec
];
380 for (j
= 0; j
< nrel
; j
++) {
381 #if defined(__i386) || defined(__amd64)
382 rel
->r_offset
= s
->dofs_offset
+
384 rel
->r_info
= ELF64_R_INFO(count
+ dep
->de_global
,
386 #elif defined(__sparc)
387 rel
->r_offset
= s
->dofs_offset
+
389 rel
->r_info
= ELF64_R_INFO(count
+ dep
->de_global
,
395 sym
->st_name
= base
+ dofr
[j
].dofr_name
- 1;
398 sym
->st_info
= GELF_ST_INFO(STB_GLOBAL
, STT_FUNC
);
400 sym
->st_shndx
= SHN_UNDEF
;
409 * Add a symbol for the DOF itself. We use a different symbol for
410 * lazily and actively loaded DOF to make them easy to distinguish.
412 sym
->st_name
= strtabsz
;
414 sym
->st_size
= dof
->dofh_filesz
;
415 sym
->st_info
= GELF_ST_INFO(STB_GLOBAL
, STT_OBJECT
);
417 sym
->st_shndx
= ESHDR_DOF
;
420 if (dtp
->dt_lazyload
) {
421 bcopy(DOFLAZYSTR
, dep
->de_strtab
+ strtabsz
,
422 sizeof (DOFLAZYSTR
));
423 strtabsz
+= sizeof (DOFLAZYSTR
);
425 bcopy(DOFSTR
, dep
->de_strtab
+ strtabsz
, sizeof (DOFSTR
));
426 strtabsz
+= sizeof (DOFSTR
);
429 assert(count
== dep
->de_nrel
);
430 assert(strtabsz
== dep
->de_strlen
);
436 * Write out an ELF32 file prologue consisting of a header, section headers,
437 * and a section header string table. The DOF data will follow this prologue
438 * and complete the contents of the given ELF file.
441 dump_elf32(dtrace_hdl_t
*dtp
, const dof_hdr_t
*dof
, int fd
)
445 Elf32_Shdr shdr
[ESHDR_NUM
];
454 if (prepare_elf32(dtp
, dof
, &de
) != 0)
455 return (-1); /* errno is set for us */
458 * If there are no relocations, we only need enough sections for
459 * the shstrtab and the DOF.
461 nshdr
= de
.de_nrel
== 0 ? ESHDR_SYMTAB
+ 1 : ESHDR_NUM
;
463 bzero(&elf_file
, sizeof (elf_file
));
465 elf_file
.ehdr
.e_ident
[EI_MAG0
] = ELFMAG0
;
466 elf_file
.ehdr
.e_ident
[EI_MAG1
] = ELFMAG1
;
467 elf_file
.ehdr
.e_ident
[EI_MAG2
] = ELFMAG2
;
468 elf_file
.ehdr
.e_ident
[EI_MAG3
] = ELFMAG3
;
469 elf_file
.ehdr
.e_ident
[EI_VERSION
] = EV_CURRENT
;
470 elf_file
.ehdr
.e_ident
[EI_CLASS
] = ELFCLASS32
;
471 #if defined(_BIG_ENDIAN)
472 elf_file
.ehdr
.e_ident
[EI_DATA
] = ELFDATA2MSB
;
473 #elif defined(_LITTLE_ENDIAN)
474 elf_file
.ehdr
.e_ident
[EI_DATA
] = ELFDATA2LSB
;
476 elf_file
.ehdr
.e_type
= ET_REL
;
478 elf_file
.ehdr
.e_machine
= EM_SPARC
;
479 #elif defined(__i386) || defined(__amd64)
480 elf_file
.ehdr
.e_machine
= EM_386
;
482 elf_file
.ehdr
.e_version
= EV_CURRENT
;
483 elf_file
.ehdr
.e_shoff
= sizeof (Elf32_Ehdr
);
484 elf_file
.ehdr
.e_ehsize
= sizeof (Elf32_Ehdr
);
485 elf_file
.ehdr
.e_phentsize
= sizeof (Elf32_Phdr
);
486 elf_file
.ehdr
.e_shentsize
= sizeof (Elf32_Shdr
);
487 elf_file
.ehdr
.e_shnum
= nshdr
;
488 elf_file
.ehdr
.e_shstrndx
= ESHDR_SHSTRTAB
;
489 off
= sizeof (elf_file
) + nshdr
* sizeof (Elf32_Shdr
);
491 shp
= &elf_file
.shdr
[ESHDR_SHSTRTAB
];
492 shp
->sh_name
= 1; /* DTRACE_SHSTRTAB32[1] = ".shstrtab" */
493 shp
->sh_type
= SHT_STRTAB
;
494 shp
->sh_offset
= off
;
495 shp
->sh_size
= sizeof (DTRACE_SHSTRTAB32
);
496 shp
->sh_addralign
= sizeof (char);
497 off
= P2ROUNDUP(shp
->sh_offset
+ shp
->sh_size
, 8);
499 shp
= &elf_file
.shdr
[ESHDR_DOF
];
500 shp
->sh_name
= 11; /* DTRACE_SHSTRTAB32[11] = ".SUNW_dof" */
501 shp
->sh_flags
= SHF_ALLOC
;
502 shp
->sh_type
= SHT_SUNW_dof
;
503 shp
->sh_offset
= off
;
504 shp
->sh_size
= dof
->dofh_filesz
;
505 shp
->sh_addralign
= 8;
506 off
= shp
->sh_offset
+ shp
->sh_size
;
508 shp
= &elf_file
.shdr
[ESHDR_STRTAB
];
509 shp
->sh_name
= 21; /* DTRACE_SHSTRTAB32[21] = ".strtab" */
510 shp
->sh_flags
= SHF_ALLOC
;
511 shp
->sh_type
= SHT_STRTAB
;
512 shp
->sh_offset
= off
;
513 shp
->sh_size
= de
.de_strlen
;
514 shp
->sh_addralign
= sizeof (char);
515 off
= P2ROUNDUP(shp
->sh_offset
+ shp
->sh_size
, 4);
517 shp
= &elf_file
.shdr
[ESHDR_SYMTAB
];
518 shp
->sh_name
= 29; /* DTRACE_SHSTRTAB32[29] = ".symtab" */
519 shp
->sh_flags
= SHF_ALLOC
;
520 shp
->sh_type
= SHT_SYMTAB
;
521 shp
->sh_entsize
= sizeof (Elf32_Sym
);
522 shp
->sh_link
= ESHDR_STRTAB
;
523 shp
->sh_offset
= off
;
524 shp
->sh_info
= de
.de_global
;
525 shp
->sh_size
= de
.de_nsym
* sizeof (Elf32_Sym
);
526 shp
->sh_addralign
= 4;
527 off
= P2ROUNDUP(shp
->sh_offset
+ shp
->sh_size
, 4);
529 if (de
.de_nrel
== 0) {
530 if (dt_write(dtp
, fd
, &elf_file
,
531 sizeof (elf_file
)) != sizeof (elf_file
) ||
532 PWRITE_SCN(ESHDR_SHSTRTAB
, DTRACE_SHSTRTAB32
) ||
533 PWRITE_SCN(ESHDR_STRTAB
, de
.de_strtab
) ||
534 PWRITE_SCN(ESHDR_SYMTAB
, de
.de_sym
) ||
535 PWRITE_SCN(ESHDR_DOF
, dof
)) {
536 ret
= dt_set_errno(dtp
, errno
);
539 shp
= &elf_file
.shdr
[ESHDR_REL
];
540 shp
->sh_name
= 37; /* DTRACE_SHSTRTAB32[37] = ".rel.SUNW_dof" */
541 shp
->sh_flags
= SHF_ALLOC
;
542 shp
->sh_type
= SHT_REL
;
543 shp
->sh_entsize
= sizeof (de
.de_rel
[0]);
544 shp
->sh_link
= ESHDR_SYMTAB
;
545 shp
->sh_info
= ESHDR_DOF
;
546 shp
->sh_offset
= off
;
547 shp
->sh_size
= de
.de_nrel
* sizeof (de
.de_rel
[0]);
548 shp
->sh_addralign
= 4;
550 if (dt_write(dtp
, fd
, &elf_file
,
551 sizeof (elf_file
)) != sizeof (elf_file
) ||
552 PWRITE_SCN(ESHDR_SHSTRTAB
, DTRACE_SHSTRTAB32
) ||
553 PWRITE_SCN(ESHDR_STRTAB
, de
.de_strtab
) ||
554 PWRITE_SCN(ESHDR_SYMTAB
, de
.de_sym
) ||
555 PWRITE_SCN(ESHDR_REL
, de
.de_rel
) ||
556 PWRITE_SCN(ESHDR_DOF
, dof
)) {
557 ret
= dt_set_errno(dtp
, errno
);
569 * Write out an ELF64 file prologue consisting of a header, section headers,
570 * and a section header string table. The DOF data will follow this prologue
571 * and complete the contents of the given ELF file.
574 dump_elf64(dtrace_hdl_t
*dtp
, const dof_hdr_t
*dof
, int fd
)
578 Elf64_Shdr shdr
[ESHDR_NUM
];
587 if (prepare_elf64(dtp
, dof
, &de
) != 0)
588 return (-1); /* errno is set for us */
591 * If there are no relocations, we only need enough sections for
592 * the shstrtab and the DOF.
594 nshdr
= de
.de_nrel
== 0 ? ESHDR_SYMTAB
+ 1 : ESHDR_NUM
;
596 bzero(&elf_file
, sizeof (elf_file
));
598 elf_file
.ehdr
.e_ident
[EI_MAG0
] = ELFMAG0
;
599 elf_file
.ehdr
.e_ident
[EI_MAG1
] = ELFMAG1
;
600 elf_file
.ehdr
.e_ident
[EI_MAG2
] = ELFMAG2
;
601 elf_file
.ehdr
.e_ident
[EI_MAG3
] = ELFMAG3
;
602 elf_file
.ehdr
.e_ident
[EI_VERSION
] = EV_CURRENT
;
603 elf_file
.ehdr
.e_ident
[EI_CLASS
] = ELFCLASS64
;
604 #if defined(_BIG_ENDIAN)
605 elf_file
.ehdr
.e_ident
[EI_DATA
] = ELFDATA2MSB
;
606 #elif defined(_LITTLE_ENDIAN)
607 elf_file
.ehdr
.e_ident
[EI_DATA
] = ELFDATA2LSB
;
609 elf_file
.ehdr
.e_type
= ET_REL
;
611 elf_file
.ehdr
.e_machine
= EM_SPARCV9
;
612 #elif defined(__i386) || defined(__amd64)
613 elf_file
.ehdr
.e_machine
= EM_AMD64
;
615 elf_file
.ehdr
.e_version
= EV_CURRENT
;
616 elf_file
.ehdr
.e_shoff
= sizeof (Elf64_Ehdr
);
617 elf_file
.ehdr
.e_ehsize
= sizeof (Elf64_Ehdr
);
618 elf_file
.ehdr
.e_phentsize
= sizeof (Elf64_Phdr
);
619 elf_file
.ehdr
.e_shentsize
= sizeof (Elf64_Shdr
);
620 elf_file
.ehdr
.e_shnum
= nshdr
;
621 elf_file
.ehdr
.e_shstrndx
= ESHDR_SHSTRTAB
;
622 off
= sizeof (elf_file
) + nshdr
* sizeof (Elf64_Shdr
);
624 shp
= &elf_file
.shdr
[ESHDR_SHSTRTAB
];
625 shp
->sh_name
= 1; /* DTRACE_SHSTRTAB64[1] = ".shstrtab" */
626 shp
->sh_type
= SHT_STRTAB
;
627 shp
->sh_offset
= off
;
628 shp
->sh_size
= sizeof (DTRACE_SHSTRTAB64
);
629 shp
->sh_addralign
= sizeof (char);
630 off
= P2ROUNDUP(shp
->sh_offset
+ shp
->sh_size
, 8);
632 shp
= &elf_file
.shdr
[ESHDR_DOF
];
633 shp
->sh_name
= 11; /* DTRACE_SHSTRTAB64[11] = ".SUNW_dof" */
634 shp
->sh_flags
= SHF_ALLOC
;
635 shp
->sh_type
= SHT_SUNW_dof
;
636 shp
->sh_offset
= off
;
637 shp
->sh_size
= dof
->dofh_filesz
;
638 shp
->sh_addralign
= 8;
639 off
= shp
->sh_offset
+ shp
->sh_size
;
641 shp
= &elf_file
.shdr
[ESHDR_STRTAB
];
642 shp
->sh_name
= 21; /* DTRACE_SHSTRTAB64[21] = ".strtab" */
643 shp
->sh_flags
= SHF_ALLOC
;
644 shp
->sh_type
= SHT_STRTAB
;
645 shp
->sh_offset
= off
;
646 shp
->sh_size
= de
.de_strlen
;
647 shp
->sh_addralign
= sizeof (char);
648 off
= P2ROUNDUP(shp
->sh_offset
+ shp
->sh_size
, 8);
650 shp
= &elf_file
.shdr
[ESHDR_SYMTAB
];
651 shp
->sh_name
= 29; /* DTRACE_SHSTRTAB64[29] = ".symtab" */
652 shp
->sh_flags
= SHF_ALLOC
;
653 shp
->sh_type
= SHT_SYMTAB
;
654 shp
->sh_entsize
= sizeof (Elf64_Sym
);
655 shp
->sh_link
= ESHDR_STRTAB
;
656 shp
->sh_offset
= off
;
657 shp
->sh_info
= de
.de_global
;
658 shp
->sh_size
= de
.de_nsym
* sizeof (Elf64_Sym
);
659 shp
->sh_addralign
= 8;
660 off
= P2ROUNDUP(shp
->sh_offset
+ shp
->sh_size
, 8);
662 if (de
.de_nrel
== 0) {
663 if (dt_write(dtp
, fd
, &elf_file
,
664 sizeof (elf_file
)) != sizeof (elf_file
) ||
665 PWRITE_SCN(ESHDR_SHSTRTAB
, DTRACE_SHSTRTAB64
) ||
666 PWRITE_SCN(ESHDR_STRTAB
, de
.de_strtab
) ||
667 PWRITE_SCN(ESHDR_SYMTAB
, de
.de_sym
) ||
668 PWRITE_SCN(ESHDR_DOF
, dof
)) {
669 ret
= dt_set_errno(dtp
, errno
);
672 shp
= &elf_file
.shdr
[ESHDR_REL
];
673 shp
->sh_name
= 37; /* DTRACE_SHSTRTAB64[37] = ".rel.SUNW_dof" */
674 shp
->sh_flags
= SHF_ALLOC
;
675 shp
->sh_type
= SHT_RELA
;
676 shp
->sh_entsize
= sizeof (de
.de_rel
[0]);
677 shp
->sh_link
= ESHDR_SYMTAB
;
678 shp
->sh_info
= ESHDR_DOF
;
679 shp
->sh_offset
= off
;
680 shp
->sh_size
= de
.de_nrel
* sizeof (de
.de_rel
[0]);
681 shp
->sh_addralign
= 8;
683 if (dt_write(dtp
, fd
, &elf_file
,
684 sizeof (elf_file
)) != sizeof (elf_file
) ||
685 PWRITE_SCN(ESHDR_SHSTRTAB
, DTRACE_SHSTRTAB64
) ||
686 PWRITE_SCN(ESHDR_STRTAB
, de
.de_strtab
) ||
687 PWRITE_SCN(ESHDR_SYMTAB
, de
.de_sym
) ||
688 PWRITE_SCN(ESHDR_REL
, de
.de_rel
) ||
689 PWRITE_SCN(ESHDR_DOF
, dof
)) {
690 ret
= dt_set_errno(dtp
, errno
);
702 dt_symtab_lookup(Elf_Data
*data_sym
, int nsym
, uintptr_t addr
, uint_t shn
,
708 for (i
= 0; i
< nsym
&& gelf_getsym(data_sym
, i
, sym
) != NULL
; i
++) {
709 if (GELF_ST_TYPE(sym
->st_info
) == STT_FUNC
&&
710 shn
== sym
->st_shndx
&&
711 sym
->st_value
<= addr
&&
712 addr
< sym
->st_value
+ sym
->st_size
) {
713 if (GELF_ST_BIND(sym
->st_info
) == STB_GLOBAL
)
728 #define DT_OP_RET 0x81c7e008
729 #define DT_OP_NOP 0x01000000
730 #define DT_OP_CALL 0x40000000
731 #define DT_OP_CLR_O0 0x90102000
733 #define DT_IS_MOV_O7(inst) (((inst) & 0xffffe000) == 0x9e100000)
734 #define DT_IS_RESTORE(inst) (((inst) & 0xc1f80000) == 0x81e80000)
735 #define DT_IS_RETL(inst) (((inst) & 0xfff83fff) == 0x81c02008)
737 #define DT_RS2(inst) ((inst) & 0x1f)
738 #define DT_MAKE_RETL(reg) (0x81c02008 | ((reg) << 14))
742 dt_modtext(dtrace_hdl_t
*dtp
, char *p
, int isenabled
, GElf_Rela
*rela
,
747 if ((rela
->r_offset
& (sizeof (uint32_t) - 1)) != 0)
751 ip
= (uint32_t *)(p
+ rela
->r_offset
);
754 * We only know about some specific relocation types.
756 if (GELF_R_TYPE(rela
->r_info
) != R_SPARC_WDISP30
&&
757 GELF_R_TYPE(rela
->r_info
) != R_SPARC_WPLT30
)
761 * We may have already processed this object file in an earlier linker
762 * invocation. Check to see if the present instruction sequence matches
763 * the one we would install below.
766 if (ip
[0] == DT_OP_NOP
) {
767 (*off
) += sizeof (ip
[0]);
771 if (DT_IS_RESTORE(ip
[1])) {
772 if (ip
[0] == DT_OP_RET
) {
773 (*off
) += sizeof (ip
[0]);
776 } else if (DT_IS_MOV_O7(ip
[1])) {
777 if (DT_IS_RETL(ip
[0]))
780 if (ip
[0] == DT_OP_NOP
) {
781 (*off
) += sizeof (ip
[0]);
788 * We only expect call instructions with a displacement of 0.
790 if (ip
[0] != DT_OP_CALL
) {
791 dt_dprintf("found %x instead of a call instruction at %llx\n",
792 ip
[0], (u_longlong_t
)rela
->r_offset
);
798 * It would necessarily indicate incorrect usage if an is-
799 * enabled probe were tail-called so flag that as an error.
800 * It's also potentially (very) tricky to handle gracefully,
801 * but could be done if this were a desired use scenario.
803 if (DT_IS_RESTORE(ip
[1]) || DT_IS_MOV_O7(ip
[1])) {
804 dt_dprintf("tail call to is-enabled probe at %llx\n",
805 (u_longlong_t
)rela
->r_offset
);
811 * On SPARC, we take advantage of the fact that the first
812 * argument shares the same register as for the return value.
813 * The macro handles the work of zeroing that register so we
814 * don't need to do anything special here. We instrument the
815 * instruction in the delay slot as we'll need to modify the
816 * return register after that instruction has been emulated.
819 (*off
) += sizeof (ip
[0]);
822 * If the call is followed by a restore, it's a tail call so
823 * change the call to a ret. If the call if followed by a mov
824 * of a register into %o7, it's a tail call in leaf context
825 * so change the call to a retl-like instruction that returns
826 * to that register value + 8 (rather than the typical %o7 +
827 * 8); the delay slot instruction is left, but should have no
828 * effect. Otherwise we change the call to be a nop. We
829 * identify the subsequent instruction as the probe point in
830 * all but the leaf tail-call case to ensure that arguments to
831 * the probe are complete and consistent. An astute, though
832 * largely hypothetical, observer would note that there is the
833 * possibility of a false-positive probe firing if the function
834 * contained a branch to the instruction in the delay slot of
835 * the call. Fixing this would require significant in-kernel
836 * modifications, and isn't worth doing until we see it in the
839 if (DT_IS_RESTORE(ip
[1])) {
841 (*off
) += sizeof (ip
[0]);
842 } else if (DT_IS_MOV_O7(ip
[1])) {
843 ip
[0] = DT_MAKE_RETL(DT_RS2(ip
[1]));
846 (*off
) += sizeof (ip
[0]);
853 #elif defined(__i386) || defined(__amd64)
855 #define DT_OP_NOP 0x90
856 #define DT_OP_RET 0xc3
857 #define DT_OP_CALL 0xe8
858 #define DT_OP_JMP32 0xe9
859 #define DT_OP_REX_RAX 0x48
860 #define DT_OP_XOR_EAX_0 0x33
861 #define DT_OP_XOR_EAX_1 0xc0
864 dt_modtext(dtrace_hdl_t
*dtp
, char *p
, int isenabled
, GElf_Rela
*rela
,
867 uint8_t *ip
= (uint8_t *)(p
+ rela
->r_offset
- 1);
871 * On x86, the first byte of the instruction is the call opcode and
872 * the next four bytes are the 32-bit address; the relocation is for
873 * the address operand. We back up the offset to the first byte of
874 * the instruction. For is-enabled probes, we later advance the offset
875 * so that it hits the first nop in the instruction sequence.
880 * We only know about some specific relocation types. Luckily
881 * these types have the same values on both 32-bit and 64-bit
884 if (GELF_R_TYPE(rela
->r_info
) != R_386_PC32
&&
885 GELF_R_TYPE(rela
->r_info
) != R_386_PLT32
)
889 * We may have already processed this object file in an earlier linker
890 * invocation. Check to see if the present instruction sequence matches
891 * the one we would install. For is-enabled probes, we advance the
892 * offset to the first nop instruction in the sequence to match the
893 * text modification code below.
896 if ((ip
[0] == DT_OP_NOP
|| ip
[0] == DT_OP_RET
) &&
897 ip
[1] == DT_OP_NOP
&& ip
[2] == DT_OP_NOP
&&
898 ip
[3] == DT_OP_NOP
&& ip
[4] == DT_OP_NOP
)
900 } else if (dtp
->dt_oflags
& DTRACE_O_LP64
) {
901 if (ip
[0] == DT_OP_REX_RAX
&&
902 ip
[1] == DT_OP_XOR_EAX_0
&& ip
[2] == DT_OP_XOR_EAX_1
&&
903 (ip
[3] == DT_OP_NOP
|| ip
[3] == DT_OP_RET
) &&
904 ip
[4] == DT_OP_NOP
) {
909 if (ip
[0] == DT_OP_XOR_EAX_0
&& ip
[1] == DT_OP_XOR_EAX_1
&&
910 (ip
[2] == DT_OP_NOP
|| ip
[2] == DT_OP_RET
) &&
911 ip
[3] == DT_OP_NOP
&& ip
[4] == DT_OP_NOP
) {
918 * We expect either a call instrution with a 32-bit displacement or a
919 * jmp instruction with a 32-bit displacement acting as a tail-call.
921 if (ip
[0] != DT_OP_CALL
&& ip
[0] != DT_OP_JMP32
) {
922 dt_dprintf("found %x instead of a call or jmp instruction at "
923 "%llx\n", ip
[0], (u_longlong_t
)rela
->r_offset
);
927 ret
= (ip
[0] == DT_OP_JMP32
) ? DT_OP_RET
: DT_OP_NOP
;
930 * Establish the instruction sequence -- all nops for probes, and an
931 * instruction to clear the return value register (%eax/%rax) followed
932 * by nops for is-enabled probes. For is-enabled probes, we advance
933 * the offset to the first nop. This isn't stricly necessary but makes
934 * for more readable disassembly when the probe is enabled.
942 } else if (dtp
->dt_oflags
& DTRACE_O_LP64
) {
943 ip
[0] = DT_OP_REX_RAX
;
944 ip
[1] = DT_OP_XOR_EAX_0
;
945 ip
[2] = DT_OP_XOR_EAX_1
;
950 ip
[0] = DT_OP_XOR_EAX_0
;
951 ip
[1] = DT_OP_XOR_EAX_1
;
967 dt_link_error(dtrace_hdl_t
*dtp
, Elf
*elf
, int fd
, dt_link_pair_t
*bufs
,
968 const char *format
, ...)
971 dt_link_pair_t
*pair
;
973 va_start(ap
, format
);
974 dt_set_errmsg(dtp
, NULL
, NULL
, NULL
, 0, format
, ap
);
983 while ((pair
= bufs
) != NULL
) {
984 bufs
= pair
->dlp_next
;
985 dt_free(dtp
, pair
->dlp_str
);
986 dt_free(dtp
, pair
->dlp_sym
);
990 return (dt_set_errno(dtp
, EDT_COMPILER
));
994 process_obj(dtrace_hdl_t
*dtp
, const char *obj
, int *eprobesp
)
996 static const char dt_prefix
[] = "__dtrace";
997 static const char dt_enabled
[] = "enabled";
998 static const char dt_symprefix
[] = "$dtrace";
999 static const char dt_symfmt
[] = "%s%d.%s";
1000 int fd
, i
, ndx
, eprobe
, mod
= 0;
1003 Elf_Scn
*scn_rel
, *scn_sym
, *scn_str
, *scn_tgt
;
1004 Elf_Data
*data_rel
, *data_sym
, *data_str
, *data_tgt
;
1005 GElf_Shdr shdr_rel
, shdr_sym
, shdr_str
, shdr_tgt
;
1006 GElf_Sym rsym
, fsym
, dsym
;
1009 char pname
[DTRACE_PROVNAMELEN
];
1012 uint32_t off
, eclass
, emachine1
, emachine2
;
1013 size_t symsize
, nsym
, isym
, istr
, len
;
1015 dt_link_pair_t
*pair
, *bufs
= NULL
;
1016 dt_strtab_t
*strtab
;
1018 if ((fd
= open64(obj
, O_RDWR
)) == -1) {
1019 return (dt_link_error(dtp
, elf
, fd
, bufs
,
1020 "failed to open %s: %s", obj
, strerror(errno
)));
1023 if ((elf
= elf_begin(fd
, ELF_C_RDWR
, NULL
)) == NULL
) {
1024 return (dt_link_error(dtp
, elf
, fd
, bufs
,
1025 "failed to process %s: %s", obj
, elf_errmsg(elf_errno())));
1028 switch (elf_kind(elf
)) {
1032 return (dt_link_error(dtp
, elf
, fd
, bufs
, "archives are not "
1033 "permitted; use the contents of the archive instead: %s",
1036 return (dt_link_error(dtp
, elf
, fd
, bufs
,
1037 "invalid file type: %s", obj
));
1040 if (gelf_getehdr(elf
, &ehdr
) == NULL
) {
1041 return (dt_link_error(dtp
, elf
, fd
, bufs
, "corrupt file: %s",
1045 if (dtp
->dt_oflags
& DTRACE_O_LP64
) {
1046 eclass
= ELFCLASS64
;
1047 #if defined(__sparc)
1048 emachine1
= emachine2
= EM_SPARCV9
;
1049 #elif defined(__i386) || defined(__amd64)
1050 emachine1
= emachine2
= EM_AMD64
;
1052 symsize
= sizeof (Elf64_Sym
);
1054 eclass
= ELFCLASS32
;
1055 #if defined(__sparc)
1056 emachine1
= EM_SPARC
;
1057 emachine2
= EM_SPARC32PLUS
;
1058 #elif defined(__i386) || defined(__amd64)
1059 emachine1
= emachine2
= EM_386
;
1061 symsize
= sizeof (Elf32_Sym
);
1064 if (ehdr
.e_ident
[EI_CLASS
] != eclass
) {
1065 return (dt_link_error(dtp
, elf
, fd
, bufs
,
1066 "incorrect ELF class for object file: %s", obj
));
1069 if (ehdr
.e_machine
!= emachine1
&& ehdr
.e_machine
!= emachine2
) {
1070 return (dt_link_error(dtp
, elf
, fd
, bufs
,
1071 "incorrect ELF machine type for object file: %s", obj
));
1075 * We use this token as a relatively unique handle for this file on the
1076 * system in order to disambiguate potential conflicts between files of
1077 * the same name which contain identially named local symbols.
1079 if ((objkey
= ftok(obj
, 0)) == (key_t
)-1) {
1080 return (dt_link_error(dtp
, elf
, fd
, bufs
,
1081 "failed to generate unique key for object file: %s", obj
));
1085 while ((scn_rel
= elf_nextscn(elf
, scn_rel
)) != NULL
) {
1086 if (gelf_getshdr(scn_rel
, &shdr_rel
) == NULL
)
1090 * Skip any non-relocation sections.
1092 if (shdr_rel
.sh_type
!= SHT_RELA
&& shdr_rel
.sh_type
!= SHT_REL
)
1095 if ((data_rel
= elf_getdata(scn_rel
, NULL
)) == NULL
)
1099 * Grab the section, section header and section data for the
1100 * symbol table that this relocation section references.
1102 if ((scn_sym
= elf_getscn(elf
, shdr_rel
.sh_link
)) == NULL
||
1103 gelf_getshdr(scn_sym
, &shdr_sym
) == NULL
||
1104 (data_sym
= elf_getdata(scn_sym
, NULL
)) == NULL
)
1108 * Ditto for that symbol table's string table.
1110 if ((scn_str
= elf_getscn(elf
, shdr_sym
.sh_link
)) == NULL
||
1111 gelf_getshdr(scn_str
, &shdr_str
) == NULL
||
1112 (data_str
= elf_getdata(scn_str
, NULL
)) == NULL
)
1116 * Grab the section, section header and section data for the
1117 * target section for the relocations. For the relocations
1118 * we're looking for -- this will typically be the text of the
1121 if ((scn_tgt
= elf_getscn(elf
, shdr_rel
.sh_info
)) == NULL
||
1122 gelf_getshdr(scn_tgt
, &shdr_tgt
) == NULL
||
1123 (data_tgt
= elf_getdata(scn_tgt
, NULL
)) == NULL
)
1127 * We're looking for relocations to symbols matching this form:
1129 * __dtrace[enabled]_<prov>___<probe>
1131 * For the generated object, we need to record the location
1132 * identified by the relocation, and create a new relocation
1133 * in the generated object that will be resolved at link time
1134 * to the location of the function in which the probe is
1135 * embedded. In the target object, we change the matched symbol
1136 * so that it will be ignored at link time, and we modify the
1137 * target (text) section to replace the call instruction with
1140 * If the function containing the probe is locally scoped
1141 * (static), we create an alias used by the relocation in the
1142 * generated object. The alias, a new symbol, will be global
1143 * (so that the relocation from the generated object can be
1144 * resolved), and hidden (so that it is converted to a local
1145 * symbol at link time). Such aliases have this form:
1147 * $dtrace<key>.<function>
1149 * We take a first pass through all the relocations to
1150 * populate our string table and count the number of extra
1151 * symbols we'll require.
1153 strtab
= dt_strtab_create(1);
1155 isym
= data_sym
->d_size
/ symsize
;
1156 istr
= data_str
->d_size
;
1158 for (i
= 0; i
< shdr_rel
.sh_size
/ shdr_rel
.sh_entsize
; i
++) {
1160 if (shdr_rel
.sh_type
== SHT_RELA
) {
1161 if (gelf_getrela(data_rel
, i
, &rela
) == NULL
)
1165 if (gelf_getrel(data_rel
, i
, &rel
) == NULL
)
1167 rela
.r_offset
= rel
.r_offset
;
1168 rela
.r_info
= rel
.r_info
;
1172 if (gelf_getsym(data_sym
, GELF_R_SYM(rela
.r_info
),
1174 dt_strtab_destroy(strtab
);
1178 s
= (char *)data_str
->d_buf
+ rsym
.st_name
;
1180 if (strncmp(s
, dt_prefix
, sizeof (dt_prefix
) - 1) != 0)
1183 if (dt_symtab_lookup(data_sym
, isym
, rela
.r_offset
,
1184 shdr_rel
.sh_info
, &fsym
) != 0) {
1185 dt_strtab_destroy(strtab
);
1189 if (GELF_ST_BIND(fsym
.st_info
) != STB_LOCAL
)
1192 if (fsym
.st_name
> data_str
->d_size
) {
1193 dt_strtab_destroy(strtab
);
1197 s
= (char *)data_str
->d_buf
+ fsym
.st_name
;
1200 * If this symbol isn't of type function, we've really
1201 * driven off the rails or the object file is corrupt.
1203 if (GELF_ST_TYPE(fsym
.st_info
) != STT_FUNC
) {
1204 dt_strtab_destroy(strtab
);
1205 return (dt_link_error(dtp
, elf
, fd
, bufs
,
1206 "expected %s to be of type function", s
));
1209 len
= snprintf(NULL
, 0, dt_symfmt
, dt_symprefix
,
1211 if ((p
= dt_alloc(dtp
, len
)) == NULL
) {
1212 dt_strtab_destroy(strtab
);
1215 (void) snprintf(p
, len
, dt_symfmt
, dt_symprefix
,
1218 if (dt_strtab_index(strtab
, p
) == -1) {
1220 (void) dt_strtab_insert(strtab
, p
);
1227 * If needed, allocate the additional space for the symbol
1228 * table and string table copying the old data into the new
1229 * buffers, and marking the buffers as dirty. We inject those
1230 * newly allocated buffers into the libelf data structures, but
1231 * are still responsible for freeing them once we're done with
1236 * The first byte of the string table is reserved for
1239 len
= dt_strtab_size(strtab
) - 1;
1242 assert(dt_strtab_index(strtab
, "") == 0);
1244 dt_strtab_destroy(strtab
);
1246 if ((pair
= dt_alloc(dtp
, sizeof (*pair
))) == NULL
)
1249 if ((pair
->dlp_str
= dt_alloc(dtp
, data_str
->d_size
+
1255 if ((pair
->dlp_sym
= dt_alloc(dtp
, data_sym
->d_size
+
1256 nsym
* symsize
)) == NULL
) {
1257 dt_free(dtp
, pair
->dlp_str
);
1262 pair
->dlp_next
= bufs
;
1265 bcopy(data_str
->d_buf
, pair
->dlp_str
, data_str
->d_size
);
1266 data_str
->d_buf
= pair
->dlp_str
;
1267 data_str
->d_size
+= len
;
1268 (void) elf_flagdata(data_str
, ELF_C_SET
, ELF_F_DIRTY
);
1270 shdr_str
.sh_size
+= len
;
1271 (void) gelf_update_shdr(scn_str
, &shdr_str
);
1273 bcopy(data_sym
->d_buf
, pair
->dlp_sym
, data_sym
->d_size
);
1274 data_sym
->d_buf
= pair
->dlp_sym
;
1275 data_sym
->d_size
+= nsym
* symsize
;
1276 (void) elf_flagdata(data_sym
, ELF_C_SET
, ELF_F_DIRTY
);
1278 shdr_sym
.sh_size
+= nsym
* symsize
;
1279 (void) gelf_update_shdr(scn_sym
, &shdr_sym
);
1283 dt_strtab_destroy(strtab
);
1287 * Now that the tables have been allocated, perform the
1288 * modifications described above.
1290 for (i
= 0; i
< shdr_rel
.sh_size
/ shdr_rel
.sh_entsize
; i
++) {
1292 if (shdr_rel
.sh_type
== SHT_RELA
) {
1293 if (gelf_getrela(data_rel
, i
, &rela
) == NULL
)
1297 if (gelf_getrel(data_rel
, i
, &rel
) == NULL
)
1299 rela
.r_offset
= rel
.r_offset
;
1300 rela
.r_info
= rel
.r_info
;
1304 ndx
= GELF_R_SYM(rela
.r_info
);
1306 if (gelf_getsym(data_sym
, ndx
, &rsym
) == NULL
||
1307 rsym
.st_name
> data_str
->d_size
)
1310 s
= (char *)data_str
->d_buf
+ rsym
.st_name
;
1312 if (strncmp(s
, dt_prefix
, sizeof (dt_prefix
) - 1) != 0)
1315 s
+= sizeof (dt_prefix
) - 1;
1318 * Check to see if this is an 'is-enabled' check as
1319 * opposed to a normal probe.
1321 if (strncmp(s
, dt_enabled
,
1322 sizeof (dt_enabled
) - 1) == 0) {
1323 s
+= sizeof (dt_enabled
) - 1;
1326 dt_dprintf("is-enabled probe\n");
1329 dt_dprintf("normal probe\n");
1335 if ((p
= strstr(s
, "___")) == NULL
||
1336 p
- s
>= sizeof (pname
))
1339 bcopy(s
, pname
, p
- s
);
1340 pname
[p
- s
] = '\0';
1342 p
= strhyphenate(p
+ 3); /* strlen("___") */
1344 if (dt_symtab_lookup(data_sym
, isym
, rela
.r_offset
,
1345 shdr_rel
.sh_info
, &fsym
) != 0)
1348 if (fsym
.st_name
> data_str
->d_size
)
1351 assert(GELF_ST_TYPE(fsym
.st_info
) == STT_FUNC
);
1354 * If a NULL relocation name is passed to
1355 * dt_probe_define(), the function name is used for the
1356 * relocation. The relocation needs to use a mangled
1357 * name if the symbol is locally scoped; the function
1358 * name may need to change if we've found the global
1359 * alias for the locally scoped symbol (we prefer
1360 * global symbols to locals in dt_symtab_lookup()).
1362 s
= (char *)data_str
->d_buf
+ fsym
.st_name
;
1365 if (GELF_ST_BIND(fsym
.st_info
) == STB_LOCAL
) {
1367 dsym
.st_name
= istr
;
1368 dsym
.st_info
= GELF_ST_INFO(STB_GLOBAL
,
1371 ELF64_ST_VISIBILITY(STV_ELIMINATE
);
1372 (void) gelf_update_sym(data_sym
, isym
, &dsym
);
1374 r
= (char *)data_str
->d_buf
+ istr
;
1375 istr
+= 1 + sprintf(r
, dt_symfmt
,
1376 dt_symprefix
, objkey
, s
);
1378 assert(isym
<= nsym
);
1380 } else if (strncmp(s
, dt_symprefix
,
1381 strlen(dt_symprefix
)) == 0) {
1383 if ((s
= strchr(s
, '.')) == NULL
)
1388 if ((pvp
= dt_provider_lookup(dtp
, pname
)) == NULL
) {
1389 return (dt_link_error(dtp
, elf
, fd
, bufs
,
1390 "no such provider %s", pname
));
1393 if ((prp
= dt_probe_lookup(pvp
, p
)) == NULL
) {
1394 return (dt_link_error(dtp
, elf
, fd
, bufs
,
1395 "no such probe %s", p
));
1398 assert(fsym
.st_value
<= rela
.r_offset
);
1400 off
= rela
.r_offset
- fsym
.st_value
;
1401 if (dt_modtext(dtp
, data_tgt
->d_buf
, eprobe
,
1402 &rela
, &off
) != 0) {
1406 if (dt_probe_define(pvp
, prp
, s
, r
, off
, eprobe
) != 0) {
1407 return (dt_link_error(dtp
, elf
, fd
, bufs
,
1408 "failed to allocate space for probe"));
1412 (void) elf_flagdata(data_tgt
, ELF_C_SET
, ELF_F_DIRTY
);
1415 * This symbol may already have been marked to
1416 * be ignored by another relocation referencing
1417 * the same symbol or if this object file has
1418 * already been processed by an earlier link
1421 if (rsym
.st_shndx
!= SHN_SUNW_IGNORE
) {
1422 rsym
.st_shndx
= SHN_SUNW_IGNORE
;
1423 (void) gelf_update_sym(data_sym
, ndx
, &rsym
);
1428 if (mod
&& elf_update(elf
, ELF_C_WRITE
) == -1)
1431 (void) elf_end(elf
);
1434 while ((pair
= bufs
) != NULL
) {
1435 bufs
= pair
->dlp_next
;
1436 dt_free(dtp
, pair
->dlp_str
);
1437 dt_free(dtp
, pair
->dlp_sym
);
1444 return (dt_link_error(dtp
, elf
, fd
, bufs
,
1445 "an error was encountered while processing %s", obj
));
1449 dtrace_program_link(dtrace_hdl_t
*dtp
, dtrace_prog_t
*pgp
, uint_t dflags
,
1450 const char *file
, int objc
, char *const objv
[])
1452 char drti
[PATH_MAX
];
1454 int fd
, status
, i
, cur
;
1457 int eprobes
= 0, ret
= 0;
1460 * A NULL program indicates a special use in which we just link
1461 * together a bunch of object files specified in objv and then
1462 * unlink(2) those object files.
1465 const char *fmt
= "%s -o %s -r";
1467 len
= snprintf(&tmp
, 1, fmt
, dtp
->dt_ld_path
, file
) + 1;
1469 for (i
= 0; i
< objc
; i
++)
1470 len
+= strlen(objv
[i
]) + 1;
1474 cur
= snprintf(cmd
, len
, fmt
, dtp
->dt_ld_path
, file
);
1476 for (i
= 0; i
< objc
; i
++)
1477 cur
+= snprintf(cmd
+ cur
, len
- cur
, " %s", objv
[i
]);
1479 if ((status
= system(cmd
)) == -1) {
1480 return (dt_link_error(dtp
, NULL
, -1, NULL
,
1481 "failed to run %s: %s", dtp
->dt_ld_path
,
1485 if (WIFSIGNALED(status
)) {
1486 return (dt_link_error(dtp
, NULL
, -1, NULL
,
1487 "failed to link %s: %s failed due to signal %d",
1488 file
, dtp
->dt_ld_path
, WTERMSIG(status
)));
1491 if (WEXITSTATUS(status
) != 0) {
1492 return (dt_link_error(dtp
, NULL
, -1, NULL
,
1493 "failed to link %s: %s exited with status %d\n",
1494 file
, dtp
->dt_ld_path
, WEXITSTATUS(status
)));
1497 for (i
= 0; i
< objc
; i
++) {
1498 if (strcmp(objv
[i
], file
) != 0)
1499 (void) unlink(objv
[i
]);
1505 for (i
= 0; i
< objc
; i
++) {
1506 if (process_obj(dtp
, objv
[i
], &eprobes
) != 0)
1507 return (-1); /* errno is set for us */
1511 * If there are is-enabled probes then we need to force use of DOF
1514 if (eprobes
&& pgp
->dp_dofversion
< DOF_VERSION_2
)
1515 pgp
->dp_dofversion
= DOF_VERSION_2
;
1517 if ((dof
= dtrace_dof_create(dtp
, pgp
, dflags
)) == NULL
)
1518 return (-1); /* errno is set for us */
1521 * Create a temporary file and then unlink it if we're going to
1522 * combine it with drti.o later. We can still refer to it in child
1523 * processes as /dev/fd/<fd>.
1525 if ((fd
= open64(file
, O_RDWR
| O_CREAT
| O_TRUNC
, 0666)) == -1) {
1526 return (dt_link_error(dtp
, NULL
, -1, NULL
,
1527 "failed to open %s: %s", file
, strerror(errno
)));
1531 * If -xlinktype=DOF has been selected, just write out the DOF.
1532 * Otherwise proceed to the default of generating and linking ELF.
1534 switch (dtp
->dt_linktype
) {
1536 if (dt_write(dtp
, fd
, dof
, dof
->dofh_filesz
) < dof
->dofh_filesz
)
1539 if (close(fd
) != 0 && ret
== 0)
1543 return (dt_link_error(dtp
, NULL
, -1, NULL
,
1544 "failed to write %s: %s", file
, strerror(ret
)));
1550 break; /* fall through to the rest of dtrace_program_link() */
1553 return (dt_link_error(dtp
, NULL
, -1, NULL
,
1554 "invalid link type %u\n", dtp
->dt_linktype
));
1558 if (!dtp
->dt_lazyload
)
1559 (void) unlink(file
);
1561 if (dtp
->dt_oflags
& DTRACE_O_LP64
)
1562 status
= dump_elf64(dtp
, dof
, fd
);
1564 status
= dump_elf32(dtp
, dof
, fd
);
1566 if (status
!= 0 || lseek(fd
, 0, SEEK_SET
) != 0) {
1567 return (dt_link_error(dtp
, NULL
, -1, NULL
,
1568 "failed to write %s: %s", file
, strerror(errno
)));
1571 if (!dtp
->dt_lazyload
) {
1572 const char *fmt
= "%s -o %s -r -Blocal -Breduce /dev/fd/%d %s";
1574 if (dtp
->dt_oflags
& DTRACE_O_LP64
) {
1575 (void) snprintf(drti
, sizeof (drti
),
1576 "%s/64/drti.o", _dtrace_libdir
);
1578 (void) snprintf(drti
, sizeof (drti
),
1579 "%s/drti.o", _dtrace_libdir
);
1582 len
= snprintf(&tmp
, 1, fmt
, dtp
->dt_ld_path
, file
, fd
,
1587 (void) snprintf(cmd
, len
, fmt
, dtp
->dt_ld_path
, file
, fd
, drti
);
1589 if ((status
= system(cmd
)) == -1) {
1590 ret
= dt_link_error(dtp
, NULL
, -1, NULL
,
1591 "failed to run %s: %s", dtp
->dt_ld_path
,
1596 (void) close(fd
); /* release temporary file */
1598 if (WIFSIGNALED(status
)) {
1599 ret
= dt_link_error(dtp
, NULL
, -1, NULL
,
1600 "failed to link %s: %s failed due to signal %d",
1601 file
, dtp
->dt_ld_path
, WTERMSIG(status
));
1605 if (WEXITSTATUS(status
) != 0) {
1606 ret
= dt_link_error(dtp
, NULL
, -1, NULL
,
1607 "failed to link %s: %s exited with status %d\n",
1608 file
, dtp
->dt_ld_path
, WEXITSTATUS(status
));
1616 dtrace_dof_destroy(dtp
, dof
);