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.
25 * Copyright 2017-2018 Mark Johnston <markj@FreeBSD.org>
28 #include <sys/param.h>
47 #include <dt_provider.h>
48 #include <dt_program.h>
49 #include <dt_string.h>
52 #define ESHDR_SHSTRTAB 1
54 #define ESHDR_STRTAB 3
55 #define ESHDR_SYMTAB 4
59 #define PWRITE_SCN(index, data) \
60 (lseek64(fd, (off64_t)elf_file.shdr[(index)].sh_offset, SEEK_SET) != \
61 (off64_t)elf_file.shdr[(index)].sh_offset || \
62 dt_write(dtp, fd, (data), elf_file.shdr[(index)].sh_size) != \
63 elf_file.shdr[(index)].sh_size)
65 static const char DTRACE_SHSTRTAB32[] = "\0"
67 ".SUNW_dof\0" /* 11 */
70 ".rel.SUNW_dof"; /* 37 */
72 static const char DTRACE_SHSTRTAB64[] = "\0"
74 ".SUNW_dof\0" /* 11 */
77 ".rela.SUNW_dof"; /* 37 */
79 static const char DOFSTR[] = "__SUNW_dof";
80 static const char DOFLAZYSTR[] = "___SUNW_dof";
82 typedef struct dt_link_pair {
83 struct dt_link_pair *dlp_next; /* next pair in linked list */
84 void *dlp_str; /* buffer for string table */
85 void *dlp_sym; /* buffer for symbol table */
88 typedef struct dof_elf32 {
89 uint32_t de_nrel; /* relocation count */
90 Elf32_Rel *de_rel; /* array of relocations for x86 */
91 uint32_t de_nsym; /* symbol count */
92 Elf32_Sym *de_sym; /* array of symbols */
93 uint32_t de_strlen; /* size of of string table */
94 char *de_strtab; /* string table */
95 uint32_t de_global; /* index of the first global symbol */
99 prepare_elf32(dtrace_hdl_t *dtp, const dof_hdr_t *dof, dof_elf32_t *dep)
102 dof_relohdr_t *dofrh;
103 dof_relodesc_t *dofr;
113 dofs = (dof_sec_t *)((char *)dof + dof->dofh_secoff);
116 * First compute the size of the string table and the number of
117 * relocations present in the DOF.
119 for (i = 0; i < dof->dofh_secnum; i++) {
120 if (dofs[i].dofs_type != DOF_SECT_URELHDR)
124 dofrh = (dof_relohdr_t *)((char *)dof + dofs[i].dofs_offset);
126 s = &dofs[dofrh->dofr_strtab];
127 strtab = (char *)dof + s->dofs_offset;
128 assert(strtab[0] == '\0');
129 strtabsz += s->dofs_size - 1;
131 s = &dofs[dofrh->dofr_relsec];
133 dofr = (dof_relodesc_t *)((char *)dof + s->dofs_offset);
134 count += s->dofs_size / s->dofs_entsize;
137 dep->de_strlen = strtabsz;
138 dep->de_nrel = count;
139 dep->de_nsym = count + 1; /* the first symbol is always null */
141 if (dtp->dt_lazyload) {
142 dep->de_strlen += sizeof (DOFLAZYSTR);
145 dep->de_strlen += sizeof (DOFSTR);
149 if ((dep->de_rel = calloc(dep->de_nrel,
150 sizeof (dep->de_rel[0]))) == NULL) {
151 return (dt_set_errno(dtp, EDT_NOMEM));
154 if ((dep->de_sym = calloc(dep->de_nsym, sizeof (Elf32_Sym))) == NULL) {
156 return (dt_set_errno(dtp, EDT_NOMEM));
159 if ((dep->de_strtab = calloc(dep->de_strlen, 1)) == NULL) {
162 return (dt_set_errno(dtp, EDT_NOMEM));
167 dep->de_strtab[0] = '\0';
173 * The first symbol table entry must be zeroed and is always ignored.
175 bzero(sym, sizeof (Elf32_Sym));
179 * Take a second pass through the DOF sections filling in the
180 * memory we allocated.
182 for (i = 0; i < dof->dofh_secnum; i++) {
183 if (dofs[i].dofs_type != DOF_SECT_URELHDR)
187 dofrh = (dof_relohdr_t *)((char *)dof + dofs[i].dofs_offset);
189 s = &dofs[dofrh->dofr_strtab];
190 strtab = (char *)dof + s->dofs_offset;
191 bcopy(strtab + 1, dep->de_strtab + strtabsz, s->dofs_size);
193 strtabsz += s->dofs_size - 1;
195 s = &dofs[dofrh->dofr_relsec];
197 dofr = (dof_relodesc_t *)((char *)dof + s->dofs_offset);
198 nrel = s->dofs_size / s->dofs_entsize;
200 s = &dofs[dofrh->dofr_tgtsec];
202 for (j = 0; j < nrel; j++) {
203 #if defined(__aarch64__)
204 rel->r_offset = s->dofs_offset +
206 rel->r_info = ELF32_R_INFO(count + dep->de_global,
208 #elif defined(__arm__)
210 printf("%s:%s(%d): arm not implemented\n",
211 __FUNCTION__, __FILE__, __LINE__);
212 #elif defined(__i386) || defined(__amd64)
213 rel->r_offset = s->dofs_offset +
215 rel->r_info = ELF32_R_INFO(count + dep->de_global,
217 #elif defined(__mips__)
219 printf("%s:%s(%d): MIPS not implemented\n",
220 __FUNCTION__, __FILE__, __LINE__);
221 #elif defined(__powerpc__)
223 * Add 4 bytes to hit the low half of this 64-bit
224 * big-endian address.
226 rel->r_offset = s->dofs_offset +
227 dofr[j].dofr_offset + 4;
228 rel->r_info = ELF32_R_INFO(count + dep->de_global,
230 #elif defined(__riscv)
232 printf("%s:%s(%d): RISC-V not implemented\n",
233 __FUNCTION__, __FILE__, __LINE__);
238 sym->st_name = base + dofr[j].dofr_name - 1;
241 sym->st_info = ELF32_ST_INFO(STB_GLOBAL, STT_FUNC);
242 sym->st_other = ELF32_ST_VISIBILITY(STV_HIDDEN);
243 sym->st_shndx = SHN_UNDEF;
252 * Add a symbol for the DOF itself. We use a different symbol for
253 * lazily and actively loaded DOF to make them easy to distinguish.
255 sym->st_name = strtabsz;
257 sym->st_size = dof->dofh_filesz;
258 sym->st_info = ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT);
259 sym->st_other = ELF32_ST_VISIBILITY(STV_HIDDEN);
260 sym->st_shndx = ESHDR_DOF;
263 if (dtp->dt_lazyload) {
264 bcopy(DOFLAZYSTR, dep->de_strtab + strtabsz,
265 sizeof (DOFLAZYSTR));
266 strtabsz += sizeof (DOFLAZYSTR);
268 bcopy(DOFSTR, dep->de_strtab + strtabsz, sizeof (DOFSTR));
269 strtabsz += sizeof (DOFSTR);
272 assert(count == dep->de_nrel);
273 assert(strtabsz == dep->de_strlen);
279 typedef struct dof_elf64 {
292 prepare_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, dof_elf64_t *dep)
295 dof_relohdr_t *dofrh;
296 dof_relodesc_t *dofr;
306 dofs = (dof_sec_t *)((char *)dof + dof->dofh_secoff);
309 * First compute the size of the string table and the number of
310 * relocations present in the DOF.
312 for (i = 0; i < dof->dofh_secnum; i++) {
313 if (dofs[i].dofs_type != DOF_SECT_URELHDR)
317 dofrh = (dof_relohdr_t *)((char *)dof + dofs[i].dofs_offset);
319 s = &dofs[dofrh->dofr_strtab];
320 strtab = (char *)dof + s->dofs_offset;
321 assert(strtab[0] == '\0');
322 strtabsz += s->dofs_size - 1;
324 s = &dofs[dofrh->dofr_relsec];
326 dofr = (dof_relodesc_t *)((char *)dof + s->dofs_offset);
327 count += s->dofs_size / s->dofs_entsize;
330 dep->de_strlen = strtabsz;
331 dep->de_nrel = count;
332 dep->de_nsym = count + 1; /* the first symbol is always null */
334 if (dtp->dt_lazyload) {
335 dep->de_strlen += sizeof (DOFLAZYSTR);
338 dep->de_strlen += sizeof (DOFSTR);
342 if ((dep->de_rel = calloc(dep->de_nrel,
343 sizeof (dep->de_rel[0]))) == NULL) {
344 return (dt_set_errno(dtp, EDT_NOMEM));
347 if ((dep->de_sym = calloc(dep->de_nsym, sizeof (Elf64_Sym))) == NULL) {
349 return (dt_set_errno(dtp, EDT_NOMEM));
352 if ((dep->de_strtab = calloc(dep->de_strlen, 1)) == NULL) {
355 return (dt_set_errno(dtp, EDT_NOMEM));
360 dep->de_strtab[0] = '\0';
366 * The first symbol table entry must be zeroed and is always ignored.
368 bzero(sym, sizeof (Elf64_Sym));
372 * Take a second pass through the DOF sections filling in the
373 * memory we allocated.
375 for (i = 0; i < dof->dofh_secnum; i++) {
376 if (dofs[i].dofs_type != DOF_SECT_URELHDR)
380 dofrh = (dof_relohdr_t *)((char *)dof + dofs[i].dofs_offset);
382 s = &dofs[dofrh->dofr_strtab];
383 strtab = (char *)dof + s->dofs_offset;
384 bcopy(strtab + 1, dep->de_strtab + strtabsz, s->dofs_size);
386 strtabsz += s->dofs_size - 1;
388 s = &dofs[dofrh->dofr_relsec];
390 dofr = (dof_relodesc_t *)((char *)dof + s->dofs_offset);
391 nrel = s->dofs_size / s->dofs_entsize;
393 s = &dofs[dofrh->dofr_tgtsec];
395 for (j = 0; j < nrel; j++) {
396 #if defined(__aarch64__)
397 rel->r_offset = s->dofs_offset +
399 rel->r_info = ELF64_R_INFO(count + dep->de_global,
401 #elif defined(__arm__)
403 #elif defined(__mips__)
405 #elif defined(__powerpc__)
406 rel->r_offset = s->dofs_offset +
408 rel->r_info = ELF64_R_INFO(count + dep->de_global,
410 #elif defined(__riscv)
412 #elif defined(__i386) || defined(__amd64)
413 rel->r_offset = s->dofs_offset +
415 rel->r_info = ELF64_R_INFO(count + dep->de_global,
421 sym->st_name = base + dofr[j].dofr_name - 1;
424 sym->st_info = GELF_ST_INFO(STB_GLOBAL, STT_FUNC);
425 sym->st_other = ELF64_ST_VISIBILITY(STV_HIDDEN);
426 sym->st_shndx = SHN_UNDEF;
435 * Add a symbol for the DOF itself. We use a different symbol for
436 * lazily and actively loaded DOF to make them easy to distinguish.
438 sym->st_name = strtabsz;
440 sym->st_size = dof->dofh_filesz;
441 sym->st_info = GELF_ST_INFO(STB_GLOBAL, STT_OBJECT);
442 sym->st_other = ELF64_ST_VISIBILITY(STV_HIDDEN);
443 sym->st_shndx = ESHDR_DOF;
446 if (dtp->dt_lazyload) {
447 bcopy(DOFLAZYSTR, dep->de_strtab + strtabsz,
448 sizeof (DOFLAZYSTR));
449 strtabsz += sizeof (DOFLAZYSTR);
451 bcopy(DOFSTR, dep->de_strtab + strtabsz, sizeof (DOFSTR));
452 strtabsz += sizeof (DOFSTR);
455 assert(count == dep->de_nrel);
456 assert(strtabsz == dep->de_strlen);
462 * Write out an ELF32 file prologue consisting of a header, section headers,
463 * and a section header string table. The DOF data will follow this prologue
464 * and complete the contents of the given ELF file.
467 dump_elf32(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd)
471 Elf32_Shdr shdr[ESHDR_NUM];
480 if (prepare_elf32(dtp, dof, &de) != 0)
481 return (-1); /* errno is set for us */
484 * If there are no relocations, we only need enough sections for
485 * the shstrtab and the DOF.
487 nshdr = de.de_nrel == 0 ? ESHDR_SYMTAB + 1 : ESHDR_NUM;
489 bzero(&elf_file, sizeof (elf_file));
491 elf_file.ehdr.e_ident[EI_MAG0] = ELFMAG0;
492 elf_file.ehdr.e_ident[EI_MAG1] = ELFMAG1;
493 elf_file.ehdr.e_ident[EI_MAG2] = ELFMAG2;
494 elf_file.ehdr.e_ident[EI_MAG3] = ELFMAG3;
495 elf_file.ehdr.e_ident[EI_VERSION] = EV_CURRENT;
496 elf_file.ehdr.e_ident[EI_CLASS] = ELFCLASS32;
497 #if BYTE_ORDER == _BIG_ENDIAN
498 elf_file.ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
500 elf_file.ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
502 elf_file.ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
503 elf_file.ehdr.e_type = ET_REL;
505 elf_file.ehdr.e_machine = EM_ARM;
506 #elif defined(__mips__)
507 elf_file.ehdr.e_machine = EM_MIPS;
508 #elif defined(__powerpc__)
509 elf_file.ehdr.e_machine = EM_PPC;
510 #elif defined(__i386) || defined(__amd64)
511 elf_file.ehdr.e_machine = EM_386;
512 #elif defined(__aarch64__)
513 elf_file.ehdr.e_machine = EM_AARCH64;
515 elf_file.ehdr.e_version = EV_CURRENT;
516 elf_file.ehdr.e_shoff = sizeof (Elf32_Ehdr);
517 elf_file.ehdr.e_ehsize = sizeof (Elf32_Ehdr);
518 elf_file.ehdr.e_phentsize = sizeof (Elf32_Phdr);
519 elf_file.ehdr.e_shentsize = sizeof (Elf32_Shdr);
520 elf_file.ehdr.e_shnum = nshdr;
521 elf_file.ehdr.e_shstrndx = ESHDR_SHSTRTAB;
522 off = sizeof (elf_file) + nshdr * sizeof (Elf32_Shdr);
524 shp = &elf_file.shdr[ESHDR_SHSTRTAB];
525 shp->sh_name = 1; /* DTRACE_SHSTRTAB32[1] = ".shstrtab" */
526 shp->sh_type = SHT_STRTAB;
527 shp->sh_offset = off;
528 shp->sh_size = sizeof (DTRACE_SHSTRTAB32);
529 shp->sh_addralign = sizeof (char);
530 off = roundup2(shp->sh_offset + shp->sh_size, 8);
532 shp = &elf_file.shdr[ESHDR_DOF];
533 shp->sh_name = 11; /* DTRACE_SHSTRTAB32[11] = ".SUNW_dof" */
534 shp->sh_flags = SHF_ALLOC;
535 shp->sh_type = SHT_SUNW_dof;
536 shp->sh_offset = off;
537 shp->sh_size = dof->dofh_filesz;
538 shp->sh_addralign = 8;
539 off = shp->sh_offset + shp->sh_size;
541 shp = &elf_file.shdr[ESHDR_STRTAB];
542 shp->sh_name = 21; /* DTRACE_SHSTRTAB32[21] = ".strtab" */
543 shp->sh_flags = SHF_ALLOC;
544 shp->sh_type = SHT_STRTAB;
545 shp->sh_offset = off;
546 shp->sh_size = de.de_strlen;
547 shp->sh_addralign = sizeof (char);
548 off = roundup2(shp->sh_offset + shp->sh_size, 4);
550 shp = &elf_file.shdr[ESHDR_SYMTAB];
551 shp->sh_name = 29; /* DTRACE_SHSTRTAB32[29] = ".symtab" */
552 shp->sh_flags = SHF_ALLOC;
553 shp->sh_type = SHT_SYMTAB;
554 shp->sh_entsize = sizeof (Elf32_Sym);
555 shp->sh_link = ESHDR_STRTAB;
556 shp->sh_offset = off;
557 shp->sh_info = de.de_global;
558 shp->sh_size = de.de_nsym * sizeof (Elf32_Sym);
559 shp->sh_addralign = 4;
560 off = roundup2(shp->sh_offset + shp->sh_size, 4);
562 if (de.de_nrel == 0) {
563 if (dt_write(dtp, fd, &elf_file,
564 sizeof (elf_file)) != sizeof (elf_file) ||
565 PWRITE_SCN(ESHDR_SHSTRTAB, DTRACE_SHSTRTAB32) ||
566 PWRITE_SCN(ESHDR_STRTAB, de.de_strtab) ||
567 PWRITE_SCN(ESHDR_SYMTAB, de.de_sym) ||
568 PWRITE_SCN(ESHDR_DOF, dof)) {
569 ret = dt_set_errno(dtp, errno);
572 shp = &elf_file.shdr[ESHDR_REL];
573 shp->sh_name = 37; /* DTRACE_SHSTRTAB32[37] = ".rel.SUNW_dof" */
574 shp->sh_flags = SHF_ALLOC;
575 shp->sh_type = SHT_REL;
576 shp->sh_entsize = sizeof (de.de_rel[0]);
577 shp->sh_link = ESHDR_SYMTAB;
578 shp->sh_info = ESHDR_DOF;
579 shp->sh_offset = off;
580 shp->sh_size = de.de_nrel * sizeof (de.de_rel[0]);
581 shp->sh_addralign = 4;
583 if (dt_write(dtp, fd, &elf_file,
584 sizeof (elf_file)) != sizeof (elf_file) ||
585 PWRITE_SCN(ESHDR_SHSTRTAB, DTRACE_SHSTRTAB32) ||
586 PWRITE_SCN(ESHDR_STRTAB, de.de_strtab) ||
587 PWRITE_SCN(ESHDR_SYMTAB, de.de_sym) ||
588 PWRITE_SCN(ESHDR_REL, de.de_rel) ||
589 PWRITE_SCN(ESHDR_DOF, dof)) {
590 ret = dt_set_errno(dtp, errno);
602 * Write out an ELF64 file prologue consisting of a header, section headers,
603 * and a section header string table. The DOF data will follow this prologue
604 * and complete the contents of the given ELF file.
607 dump_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd)
611 Elf64_Shdr shdr[ESHDR_NUM];
620 if (prepare_elf64(dtp, dof, &de) != 0)
621 return (-1); /* errno is set for us */
624 * If there are no relocations, we only need enough sections for
625 * the shstrtab and the DOF.
627 nshdr = de.de_nrel == 0 ? ESHDR_SYMTAB + 1 : ESHDR_NUM;
629 bzero(&elf_file, sizeof (elf_file));
631 elf_file.ehdr.e_ident[EI_MAG0] = ELFMAG0;
632 elf_file.ehdr.e_ident[EI_MAG1] = ELFMAG1;
633 elf_file.ehdr.e_ident[EI_MAG2] = ELFMAG2;
634 elf_file.ehdr.e_ident[EI_MAG3] = ELFMAG3;
635 elf_file.ehdr.e_ident[EI_VERSION] = EV_CURRENT;
636 elf_file.ehdr.e_ident[EI_CLASS] = ELFCLASS64;
637 #if BYTE_ORDER == _BIG_ENDIAN
638 elf_file.ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
640 elf_file.ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
642 elf_file.ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
643 elf_file.ehdr.e_type = ET_REL;
645 elf_file.ehdr.e_machine = EM_ARM;
646 #elif defined(__mips__)
647 elf_file.ehdr.e_machine = EM_MIPS;
648 #elif defined(__powerpc64__)
649 elf_file.ehdr.e_machine = EM_PPC64;
650 #elif defined(__i386) || defined(__amd64)
651 elf_file.ehdr.e_machine = EM_AMD64;
652 #elif defined(__aarch64__)
653 elf_file.ehdr.e_machine = EM_AARCH64;
655 elf_file.ehdr.e_version = EV_CURRENT;
656 elf_file.ehdr.e_shoff = sizeof (Elf64_Ehdr);
657 elf_file.ehdr.e_ehsize = sizeof (Elf64_Ehdr);
658 elf_file.ehdr.e_phentsize = sizeof (Elf64_Phdr);
659 elf_file.ehdr.e_shentsize = sizeof (Elf64_Shdr);
660 elf_file.ehdr.e_shnum = nshdr;
661 elf_file.ehdr.e_shstrndx = ESHDR_SHSTRTAB;
662 off = sizeof (elf_file) + nshdr * sizeof (Elf64_Shdr);
664 shp = &elf_file.shdr[ESHDR_SHSTRTAB];
665 shp->sh_name = 1; /* DTRACE_SHSTRTAB64[1] = ".shstrtab" */
666 shp->sh_type = SHT_STRTAB;
667 shp->sh_offset = off;
668 shp->sh_size = sizeof (DTRACE_SHSTRTAB64);
669 shp->sh_addralign = sizeof (char);
670 off = roundup2(shp->sh_offset + shp->sh_size, 8);
672 shp = &elf_file.shdr[ESHDR_DOF];
673 shp->sh_name = 11; /* DTRACE_SHSTRTAB64[11] = ".SUNW_dof" */
674 shp->sh_flags = SHF_ALLOC;
675 shp->sh_type = SHT_SUNW_dof;
676 shp->sh_offset = off;
677 shp->sh_size = dof->dofh_filesz;
678 shp->sh_addralign = 8;
679 off = shp->sh_offset + shp->sh_size;
681 shp = &elf_file.shdr[ESHDR_STRTAB];
682 shp->sh_name = 21; /* DTRACE_SHSTRTAB64[21] = ".strtab" */
683 shp->sh_flags = SHF_ALLOC;
684 shp->sh_type = SHT_STRTAB;
685 shp->sh_offset = off;
686 shp->sh_size = de.de_strlen;
687 shp->sh_addralign = sizeof (char);
688 off = roundup2(shp->sh_offset + shp->sh_size, 8);
690 shp = &elf_file.shdr[ESHDR_SYMTAB];
691 shp->sh_name = 29; /* DTRACE_SHSTRTAB64[29] = ".symtab" */
692 shp->sh_flags = SHF_ALLOC;
693 shp->sh_type = SHT_SYMTAB;
694 shp->sh_entsize = sizeof (Elf64_Sym);
695 shp->sh_link = ESHDR_STRTAB;
696 shp->sh_offset = off;
697 shp->sh_info = de.de_global;
698 shp->sh_size = de.de_nsym * sizeof (Elf64_Sym);
699 shp->sh_addralign = 8;
700 off = roundup2(shp->sh_offset + shp->sh_size, 8);
702 if (de.de_nrel == 0) {
703 if (dt_write(dtp, fd, &elf_file,
704 sizeof (elf_file)) != sizeof (elf_file) ||
705 PWRITE_SCN(ESHDR_SHSTRTAB, DTRACE_SHSTRTAB64) ||
706 PWRITE_SCN(ESHDR_STRTAB, de.de_strtab) ||
707 PWRITE_SCN(ESHDR_SYMTAB, de.de_sym) ||
708 PWRITE_SCN(ESHDR_DOF, dof)) {
709 ret = dt_set_errno(dtp, errno);
712 shp = &elf_file.shdr[ESHDR_REL];
713 shp->sh_name = 37; /* DTRACE_SHSTRTAB64[37] = ".rel.SUNW_dof" */
714 shp->sh_flags = SHF_ALLOC;
715 shp->sh_type = SHT_RELA;
716 shp->sh_entsize = sizeof (de.de_rel[0]);
717 shp->sh_link = ESHDR_SYMTAB;
718 shp->sh_info = ESHDR_DOF;
719 shp->sh_offset = off;
720 shp->sh_size = de.de_nrel * sizeof (de.de_rel[0]);
721 shp->sh_addralign = 8;
723 if (dt_write(dtp, fd, &elf_file,
724 sizeof (elf_file)) != sizeof (elf_file) ||
725 PWRITE_SCN(ESHDR_SHSTRTAB, DTRACE_SHSTRTAB64) ||
726 PWRITE_SCN(ESHDR_STRTAB, de.de_strtab) ||
727 PWRITE_SCN(ESHDR_SYMTAB, de.de_sym) ||
728 PWRITE_SCN(ESHDR_REL, de.de_rel) ||
729 PWRITE_SCN(ESHDR_DOF, dof)) {
730 ret = dt_set_errno(dtp, errno);
742 dt_symtab_lookup(Elf_Data *data_sym, int start, int end, uintptr_t addr,
743 uint_t shn, GElf_Sym *sym, int uses_funcdesc, Elf *elf)
750 for (i = start; i < end && gelf_getsym(data_sym, i, sym) != NULL; i++) {
751 if (GELF_ST_TYPE(sym->st_info) == STT_FUNC) {
752 symval = sym->st_value;
754 opd_scn = elf_getscn(elf, sym->st_shndx);
755 opd_desc = elf_rawdata(opd_scn, NULL);
757 *(uint64_t*)((char *)opd_desc->d_buf + symval);
759 if ((uses_funcdesc || shn == sym->st_shndx) &&
760 symval <= addr && addr < symval + sym->st_size)
768 #if defined(__aarch64__)
769 #define DT_OP_NOP 0xd503201f
770 #define DT_OP_RET 0xd65f03c0
771 #define DT_OP_CALL26 0x94000000
772 #define DT_OP_JUMP26 0x14000000
775 dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
781 * Ensure that the offset is aligned on an instruction boundary.
783 if ((rela->r_offset & (sizeof (uint32_t) - 1)) != 0)
787 * We only know about some specific relocation types.
788 * We also recognize relocation type NONE, since that gets used for
789 * relocations of USDT probes, and we might be re-processing a file.
791 if (GELF_R_TYPE(rela->r_info) != R_AARCH64_CALL26 &&
792 GELF_R_TYPE(rela->r_info) != R_AARCH64_JUMP26 &&
793 GELF_R_TYPE(rela->r_info) != R_AARCH64_NONE)
796 ip = (uint32_t *)(p + rela->r_offset);
799 * We may have already processed this object file in an earlier linker
800 * invocation. Check to see if the present instruction sequence matches
801 * the one we would install below.
803 if (ip[0] == DT_OP_NOP || ip[0] == DT_OP_RET)
807 * We only expect call instructions with a displacement of 0, or a jump
808 * instruction acting as a tail call.
810 if (ip[0] != DT_OP_CALL26 && ip[0] != DT_OP_JUMP26) {
811 dt_dprintf("found %x instead of a call or jmp instruction at "
812 "%llx\n", ip[0], (u_longlong_t)rela->r_offset);
817 * On arm64, we do not have to differentiate between regular probes and
818 * is-enabled probes. Both cases are encoded as a regular branch for
819 * non-tail call locations, and a jump for tail call locations. Calls
820 * are to be converted into a no-op whereas jumps should become a
823 if (ip[0] == DT_OP_CALL26)
830 #elif defined(__arm__)
833 dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
836 printf("%s:%s(%d): arm not implemented\n", __FUNCTION__, __FILE__,
840 #elif defined(__mips__)
843 dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
846 printf("%s:%s(%d): MIPS not implemented\n", __FUNCTION__, __FILE__,
850 #elif defined(__powerpc__)
851 /* The sentinel is 'xor r3,r3,r3'. */
852 #define DT_OP_XOR_R3 0x7c631a78
854 #define DT_OP_NOP 0x60000000
855 #define DT_OP_BLR 0x4e800020
857 /* This captures all forms of branching to address. */
858 #define DT_IS_BRANCH(inst) ((inst & 0xfc000000) == 0x48000000)
859 #define DT_IS_BL(inst) (DT_IS_BRANCH(inst) && (inst & 0x01))
863 dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
868 if ((rela->r_offset & (sizeof (uint32_t) - 1)) != 0)
872 ip = (uint32_t *)(p + rela->r_offset);
875 * We only know about some specific relocation types.
877 if (GELF_R_TYPE(rela->r_info) != R_PPC_REL24 &&
878 GELF_R_TYPE(rela->r_info) != R_PPC_PLTREL24)
882 * We may have already processed this object file in an earlier linker
883 * invocation. Check to see if the present instruction sequence matches
884 * the one we would install below.
887 if (ip[0] == DT_OP_XOR_R3) {
888 (*off) += sizeof (ip[0]);
892 if (ip[0] == DT_OP_NOP) {
893 (*off) += sizeof (ip[0]);
899 * We only expect branch to address instructions.
901 if (!DT_IS_BRANCH(ip[0])) {
902 dt_dprintf("found %x instead of a branch instruction at %llx\n",
903 ip[0], (u_longlong_t)rela->r_offset);
909 * It would necessarily indicate incorrect usage if an is-
910 * enabled probe were tail-called so flag that as an error.
911 * It's also potentially (very) tricky to handle gracefully,
912 * but could be done if this were a desired use scenario.
914 if (!DT_IS_BL(ip[0])) {
915 dt_dprintf("tail call to is-enabled probe at %llx\n",
916 (u_longlong_t)rela->r_offset);
920 ip[0] = DT_OP_XOR_R3;
921 (*off) += sizeof (ip[0]);
931 #elif defined(__riscv)
934 dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
937 printf("%s:%s(%d): RISC-V implementation required\n", __FUNCTION__,
942 #elif defined(__i386) || defined(__amd64)
944 #define DT_OP_NOP 0x90
945 #define DT_OP_RET 0xc3
946 #define DT_OP_CALL 0xe8
947 #define DT_OP_JMP32 0xe9
948 #define DT_OP_REX_RAX 0x48
949 #define DT_OP_XOR_EAX_0 0x33
950 #define DT_OP_XOR_EAX_1 0xc0
953 dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
956 uint8_t *ip = (uint8_t *)(p + rela->r_offset - 1);
960 * On x86, the first byte of the instruction is the call opcode and
961 * the next four bytes are the 32-bit address; the relocation is for
962 * the address operand. We back up the offset to the first byte of
963 * the instruction. For is-enabled probes, we later advance the offset
964 * so that it hits the first nop in the instruction sequence.
969 * We only know about some specific relocation types. Luckily
970 * these types have the same values on both 32-bit and 64-bit
973 if (GELF_R_TYPE(rela->r_info) != R_386_PC32 &&
974 GELF_R_TYPE(rela->r_info) != R_386_PLT32)
978 * We may have already processed this object file in an earlier linker
979 * invocation. Check to see if the present instruction sequence matches
980 * the one we would install. For is-enabled probes, we advance the
981 * offset to the first nop instruction in the sequence to match the
982 * text modification code below.
985 if ((ip[0] == DT_OP_NOP || ip[0] == DT_OP_RET) &&
986 ip[1] == DT_OP_NOP && ip[2] == DT_OP_NOP &&
987 ip[3] == DT_OP_NOP && ip[4] == DT_OP_NOP)
989 } else if (dtp->dt_oflags & DTRACE_O_LP64) {
990 if (ip[0] == DT_OP_REX_RAX &&
991 ip[1] == DT_OP_XOR_EAX_0 && ip[2] == DT_OP_XOR_EAX_1 &&
992 (ip[3] == DT_OP_NOP || ip[3] == DT_OP_RET) &&
993 ip[4] == DT_OP_NOP) {
998 if (ip[0] == DT_OP_XOR_EAX_0 && ip[1] == DT_OP_XOR_EAX_1 &&
999 (ip[2] == DT_OP_NOP || ip[2] == DT_OP_RET) &&
1000 ip[3] == DT_OP_NOP && ip[4] == DT_OP_NOP) {
1007 * We expect either a call instrution with a 32-bit displacement or a
1008 * jmp instruction with a 32-bit displacement acting as a tail-call.
1010 if (ip[0] != DT_OP_CALL && ip[0] != DT_OP_JMP32) {
1011 dt_dprintf("found %x instead of a call or jmp instruction at "
1012 "%llx\n", ip[0], (u_longlong_t)rela->r_offset);
1016 ret = (ip[0] == DT_OP_JMP32) ? DT_OP_RET : DT_OP_NOP;
1019 * Establish the instruction sequence -- all nops for probes, and an
1020 * instruction to clear the return value register (%eax/%rax) followed
1021 * by nops for is-enabled probes. For is-enabled probes, we advance
1022 * the offset to the first nop. This isn't stricly necessary but makes
1023 * for more readable disassembly when the probe is enabled.
1031 } else if (dtp->dt_oflags & DTRACE_O_LP64) {
1032 ip[0] = DT_OP_REX_RAX;
1033 ip[1] = DT_OP_XOR_EAX_0;
1034 ip[2] = DT_OP_XOR_EAX_1;
1039 ip[0] = DT_OP_XOR_EAX_0;
1040 ip[1] = DT_OP_XOR_EAX_1;
1056 dt_link_error(dtrace_hdl_t *dtp, Elf *elf, int fd, dt_link_pair_t *bufs,
1057 const char *format, ...)
1060 dt_link_pair_t *pair;
1062 va_start(ap, format);
1063 dt_set_errmsg(dtp, NULL, NULL, NULL, 0, format, ap);
1067 (void) elf_end(elf);
1072 while ((pair = bufs) != NULL) {
1073 bufs = pair->dlp_next;
1074 dt_free(dtp, pair->dlp_str);
1075 dt_free(dtp, pair->dlp_sym);
1079 return (dt_set_errno(dtp, EDT_COMPILER));
1083 * Provide a unique identifier used when adding global symbols to an object.
1084 * This is the FNV-1a hash of an absolute path for the file.
1087 hash_obj(const char *obj, int fd)
1089 char path[PATH_MAX];
1092 if (realpath(obj, path) == NULL)
1095 for (h = 2166136261u, obj = &path[0]; *obj != '\0'; obj++)
1096 h = (h ^ *obj) * 16777619;
1102 process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
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%u.%s";
1108 static const char dt_weaksymfmt[] = "%s.%s";
1109 char probename[DTRACE_NAMELEN];
1110 int fd, i, ndx, eprobe, mod = 0;
1113 Elf_Scn *scn_rel, *scn_sym, *scn_str, *scn_tgt;
1114 Elf_Data *data_rel, *data_sym, *data_str, *data_tgt;
1115 GElf_Shdr shdr_rel, shdr_sym, shdr_str, shdr_tgt;
1116 GElf_Sym rsym, fsym, dsym;
1119 char pname[DTRACE_PROVNAMELEN];
1122 uint32_t off, eclass, emachine1, emachine2;
1123 size_t symsize, osym, nsym, isym, istr, len;
1124 unsigned int objkey;
1125 dt_link_pair_t *pair, *bufs = NULL;
1126 dt_strtab_t *strtab;
1129 if ((fd = open64(obj, O_RDWR)) == -1) {
1130 return (dt_link_error(dtp, elf, fd, bufs,
1131 "failed to open %s: %s", obj, strerror(errno)));
1134 if ((elf = elf_begin(fd, ELF_C_RDWR, NULL)) == NULL) {
1135 return (dt_link_error(dtp, elf, fd, bufs,
1136 "failed to process %s: %s", obj, elf_errmsg(elf_errno())));
1139 switch (elf_kind(elf)) {
1143 return (dt_link_error(dtp, elf, fd, bufs, "archives are not "
1144 "permitted; use the contents of the archive instead: %s",
1147 return (dt_link_error(dtp, elf, fd, bufs,
1148 "invalid file type: %s", obj));
1151 if (gelf_getehdr(elf, &ehdr) == NULL) {
1152 return (dt_link_error(dtp, elf, fd, bufs, "corrupt file: %s",
1156 if (dtp->dt_oflags & DTRACE_O_LP64) {
1157 eclass = ELFCLASS64;
1158 #if defined(__mips__)
1159 emachine1 = emachine2 = EM_MIPS;
1160 #elif defined(__powerpc__)
1161 emachine1 = emachine2 = EM_PPC64;
1162 #elif defined(__i386) || defined(__amd64)
1163 emachine1 = emachine2 = EM_AMD64;
1164 #elif defined(__aarch64__)
1165 emachine1 = emachine2 = EM_AARCH64;
1167 symsize = sizeof (Elf64_Sym);
1169 eclass = ELFCLASS32;
1170 #if defined(__arm__)
1171 emachine1 = emachine2 = EM_ARM;
1172 #elif defined(__mips__)
1173 emachine1 = emachine2 = EM_MIPS;
1174 #elif defined(__powerpc__)
1175 emachine1 = emachine2 = EM_PPC;
1176 #elif defined(__i386) || defined(__amd64)
1177 emachine1 = emachine2 = EM_386;
1179 symsize = sizeof (Elf32_Sym);
1182 if (ehdr.e_ident[EI_CLASS] != eclass) {
1183 return (dt_link_error(dtp, elf, fd, bufs,
1184 "incorrect ELF class for object file: %s", obj));
1187 if (ehdr.e_machine != emachine1 && ehdr.e_machine != emachine2) {
1188 return (dt_link_error(dtp, elf, fd, bufs,
1189 "incorrect ELF machine type for object file: %s", obj));
1193 * We use this token as a relatively unique handle for this file on the
1194 * system in order to disambiguate potential conflicts between files of
1195 * the same name which contain identially named local symbols.
1197 if ((objkey = hash_obj(obj, fd)) == (unsigned int)-1)
1198 return (dt_link_error(dtp, elf, fd, bufs,
1199 "failed to generate unique key for object file: %s", obj));
1202 while ((scn_rel = elf_nextscn(elf, scn_rel)) != NULL) {
1203 if (gelf_getshdr(scn_rel, &shdr_rel) == NULL)
1207 * Skip any non-relocation sections.
1209 if (shdr_rel.sh_type != SHT_RELA && shdr_rel.sh_type != SHT_REL)
1212 if ((data_rel = elf_getdata(scn_rel, NULL)) == NULL)
1216 * Grab the section, section header and section data for the
1217 * symbol table that this relocation section references.
1219 if ((scn_sym = elf_getscn(elf, shdr_rel.sh_link)) == NULL ||
1220 gelf_getshdr(scn_sym, &shdr_sym) == NULL ||
1221 (data_sym = elf_getdata(scn_sym, NULL)) == NULL)
1225 * Ditto for that symbol table's string table.
1227 if ((scn_str = elf_getscn(elf, shdr_sym.sh_link)) == NULL ||
1228 gelf_getshdr(scn_str, &shdr_str) == NULL ||
1229 (data_str = elf_getdata(scn_str, NULL)) == NULL)
1233 * Grab the section, section header and section data for the
1234 * target section for the relocations. For the relocations
1235 * we're looking for -- this will typically be the text of the
1238 if ((scn_tgt = elf_getscn(elf, shdr_rel.sh_info)) == NULL ||
1239 gelf_getshdr(scn_tgt, &shdr_tgt) == NULL ||
1240 (data_tgt = elf_getdata(scn_tgt, NULL)) == NULL)
1244 * We're looking for relocations to symbols matching this form:
1246 * __dtrace[enabled]_<prov>___<probe>
1248 * For the generated object, we need to record the location
1249 * identified by the relocation, and create a new relocation
1250 * in the generated object that will be resolved at link time
1251 * to the location of the function in which the probe is
1252 * embedded. In the target object, we change the matched symbol
1253 * so that it will be ignored at link time, and we modify the
1254 * target (text) section to replace the call instruction with
1257 * To avoid runtime overhead, the relocations added to the
1258 * generated object should be resolved at static link time. We
1259 * therefore create aliases for the functions that contain
1260 * probes. An alias is global (so that the relocation from the
1261 * generated object can be resolved), and hidden (so that its
1262 * address is known at static link time). Such aliases have this
1265 * $dtrace<key>.<function>
1267 * We take a first pass through all the relocations to
1268 * populate our string table and count the number of extra
1269 * symbols we'll require.
1271 strtab = dt_strtab_create(1);
1273 isym = data_sym->d_size / symsize;
1274 istr = data_str->d_size;
1276 for (i = 0; i < shdr_rel.sh_size / shdr_rel.sh_entsize; i++) {
1278 if (shdr_rel.sh_type == SHT_RELA) {
1279 if (gelf_getrela(data_rel, i, &rela) == NULL)
1283 if (gelf_getrel(data_rel, i, &rel) == NULL)
1285 rela.r_offset = rel.r_offset;
1286 rela.r_info = rel.r_info;
1290 if (gelf_getsym(data_sym, GELF_R_SYM(rela.r_info),
1292 dt_strtab_destroy(strtab);
1296 s = (char *)data_str->d_buf + rsym.st_name;
1298 if (strncmp(s, dt_prefix, sizeof (dt_prefix) - 1) != 0)
1301 if (dt_symtab_lookup(data_sym, 0, isym, rela.r_offset,
1302 shdr_rel.sh_info, &fsym, (emachine1 == EM_PPC64),
1304 dt_strtab_destroy(strtab);
1308 if (fsym.st_name > data_str->d_size) {
1309 dt_strtab_destroy(strtab);
1313 s = (char *)data_str->d_buf + fsym.st_name;
1316 * If this symbol isn't of type function, we've really
1317 * driven off the rails or the object file is corrupt.
1319 if (GELF_ST_TYPE(fsym.st_info) != STT_FUNC) {
1320 dt_strtab_destroy(strtab);
1321 return (dt_link_error(dtp, elf, fd, bufs,
1322 "expected %s to be of type function", s));
1326 * Aliases of weak symbols don't get a uniquifier.
1328 if (GELF_ST_BIND(fsym.st_info) == STB_WEAK)
1329 len = snprintf(NULL, 0, dt_weaksymfmt,
1330 dt_symprefix, s) + 1;
1332 len = snprintf(NULL, 0, dt_symfmt, dt_symprefix,
1334 if ((p = dt_alloc(dtp, len)) == NULL) {
1335 dt_strtab_destroy(strtab);
1338 (void) snprintf(p, len, dt_symfmt, dt_symprefix,
1341 if (dt_strtab_index(strtab, p) == -1) {
1343 (void) dt_strtab_insert(strtab, p);
1350 * If any probes were found, allocate the additional space for
1351 * the symbol table and string table, copying the old data into
1352 * the new buffers, and marking the buffers as dirty. We inject
1353 * those newly allocated buffers into the libelf data
1354 * structures, but are still responsible for freeing them once
1355 * we're done with the elf handle.
1359 * The first byte of the string table is reserved for
1362 len = dt_strtab_size(strtab) - 1;
1365 assert(dt_strtab_index(strtab, "") == 0);
1367 dt_strtab_destroy(strtab);
1369 if ((pair = dt_alloc(dtp, sizeof (*pair))) == NULL)
1372 if ((pair->dlp_str = dt_alloc(dtp, data_str->d_size +
1378 if ((pair->dlp_sym = dt_alloc(dtp, data_sym->d_size +
1379 nsym * symsize)) == NULL) {
1380 dt_free(dtp, pair->dlp_str);
1385 pair->dlp_next = bufs;
1388 bcopy(data_str->d_buf, pair->dlp_str, data_str->d_size);
1389 tmp = data_str->d_buf;
1390 data_str->d_buf = pair->dlp_str;
1391 pair->dlp_str = tmp;
1392 data_str->d_size += len;
1393 (void) elf_flagdata(data_str, ELF_C_SET, ELF_F_DIRTY);
1395 shdr_str.sh_size += len;
1396 (void) gelf_update_shdr(scn_str, &shdr_str);
1398 bcopy(data_sym->d_buf, pair->dlp_sym, data_sym->d_size);
1399 tmp = data_sym->d_buf;
1400 data_sym->d_buf = pair->dlp_sym;
1401 pair->dlp_sym = tmp;
1402 data_sym->d_size += nsym * symsize;
1403 (void) elf_flagdata(data_sym, ELF_C_SET, ELF_F_DIRTY);
1405 shdr_sym.sh_size += nsym * symsize;
1406 (void) gelf_update_shdr(scn_sym, &shdr_sym);
1411 dt_strtab_destroy(strtab);
1416 * Now that the tables have been allocated, perform the
1417 * modifications described above.
1419 for (i = 0; i < shdr_rel.sh_size / shdr_rel.sh_entsize; i++) {
1421 if (shdr_rel.sh_type == SHT_RELA) {
1422 if (gelf_getrela(data_rel, i, &rela) == NULL)
1426 if (gelf_getrel(data_rel, i, &rel) == NULL)
1428 rela.r_offset = rel.r_offset;
1429 rela.r_info = rel.r_info;
1433 ndx = GELF_R_SYM(rela.r_info);
1435 if (gelf_getsym(data_sym, ndx, &rsym) == NULL ||
1436 rsym.st_name > data_str->d_size)
1439 s = (char *)data_str->d_buf + rsym.st_name;
1441 if (strncmp(s, dt_prefix, sizeof (dt_prefix) - 1) != 0)
1444 s += sizeof (dt_prefix) - 1;
1447 * Check to see if this is an 'is-enabled' check as
1448 * opposed to a normal probe.
1450 if (strncmp(s, dt_enabled,
1451 sizeof (dt_enabled) - 1) == 0) {
1452 s += sizeof (dt_enabled) - 1;
1455 dt_dprintf("is-enabled probe\n");
1458 dt_dprintf("normal probe\n");
1464 if ((p = strstr(s, "___")) == NULL ||
1465 p - s >= sizeof (pname))
1468 bcopy(s, pname, p - s);
1469 pname[p - s] = '\0';
1471 if (dt_symtab_lookup(data_sym, osym, isym,
1472 rela.r_offset, shdr_rel.sh_info, &fsym,
1473 (emachine1 == EM_PPC64), elf) == 0) {
1474 if (fsym.st_name > data_str->d_size)
1477 r = s = (char *) data_str->d_buf + fsym.st_name;
1478 assert(strstr(s, dt_symprefix) == s);
1479 s = strchr(s, '.') + 1;
1480 } else if (dt_symtab_lookup(data_sym, 0, osym,
1481 rela.r_offset, shdr_rel.sh_info, &fsym,
1482 (emachine1 == EM_PPC64), elf) == 0) {
1485 bind = GELF_ST_BIND(fsym.st_info) == STB_WEAK ?
1486 STB_WEAK : STB_GLOBAL;
1489 * Emit an alias for the symbol. It needs to be
1490 * non-preemptible so that .SUNW_dof relocations
1491 * may be resolved at static link time. Aliases
1492 * of weak symbols are given a non-unique name
1493 * so that they may be merged by the linker.
1496 dsym.st_name = istr;
1497 dsym.st_info = GELF_ST_INFO(bind, STT_FUNC);
1498 dsym.st_other = GELF_ST_VISIBILITY(STV_HIDDEN);
1499 (void) gelf_update_sym(data_sym, isym, &dsym);
1500 r = (char *) data_str->d_buf + istr;
1501 s = (char *) data_str->d_buf + fsym.st_name;
1502 if (bind == STB_WEAK)
1503 istr += sprintf(r, dt_weaksymfmt,
1506 istr += sprintf(r, dt_symfmt,
1507 dt_symprefix, objkey, s);
1510 assert(isym <= nsym);
1514 if ((pvp = dt_provider_lookup(dtp, pname)) == NULL) {
1515 return (dt_link_error(dtp, elf, fd, bufs,
1516 "no such provider %s", pname));
1519 if (strlcpy(probename, p + 3, sizeof (probename)) >=
1521 return (dt_link_error(dtp, elf, fd, bufs,
1522 "invalid probe name %s", probename));
1523 (void) strhyphenate(probename);
1524 if ((prp = dt_probe_lookup(pvp, probename)) == NULL)
1525 return (dt_link_error(dtp, elf, fd, bufs,
1526 "no such probe %s", probename));
1528 assert(fsym.st_value <= rela.r_offset);
1530 off = rela.r_offset - fsym.st_value;
1531 if (dt_modtext(dtp, data_tgt->d_buf, eprobe,
1535 if (dt_probe_define(pvp, prp, s, r, off, eprobe) != 0) {
1536 return (dt_link_error(dtp, elf, fd, bufs,
1537 "failed to allocate space for probe"));
1541 * Our linker doesn't understand the SUNW_IGNORE ndx and
1542 * will try to use this relocation when we build the
1543 * final executable. Since we are done processing this
1544 * relocation, mark it as inexistant and let libelf
1545 * remove it from the file.
1546 * If this wasn't done, we would have garbage added to
1547 * the executable file as the symbol is going to be
1548 * change from UND to ABS.
1550 if (shdr_rel.sh_type == SHT_RELA) {
1554 (void) gelf_update_rela(data_rel, i, &rela);
1559 (void) gelf_update_rel(data_rel, i, &rel);
1563 (void) elf_flagdata(data_tgt, ELF_C_SET, ELF_F_DIRTY);
1566 * This symbol may already have been marked to
1567 * be ignored by another relocation referencing
1568 * the same symbol or if this object file has
1569 * already been processed by an earlier link
1572 if (rsym.st_shndx != SHN_ABS) {
1573 rsym.st_shndx = SHN_ABS;
1574 (void) gelf_update_sym(data_sym, ndx, &rsym);
1579 if (mod && elf_update(elf, ELF_C_WRITE) == -1)
1582 (void) elf_end(elf);
1585 while ((pair = bufs) != NULL) {
1586 bufs = pair->dlp_next;
1587 dt_free(dtp, pair->dlp_str);
1588 dt_free(dtp, pair->dlp_sym);
1595 return (dt_link_error(dtp, elf, fd, bufs,
1596 "an error was encountered while processing %s", obj));
1600 dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
1601 const char *file, int objc, char *const objv[])
1603 char tfile[PATH_MAX];
1604 char drti[PATH_MAX];
1606 int fd, status, i, cur;
1609 int eprobes = 0, ret = 0;
1611 if (access(file, R_OK) == 0) {
1612 fprintf(stderr, "dtrace: target object (%s) already exists. "
1613 "Please remove the target\ndtrace: object and rebuild all "
1614 "the source objects if you wish to run the DTrace\n"
1615 "dtrace: linking process again\n", file);
1617 * Several build infrastructures run DTrace twice (e.g.
1618 * postgres) and we don't want the build to fail. Return
1619 * 0 here since this isn't really a fatal error.
1625 * A NULL program indicates a special use in which we just link
1626 * together a bunch of object files specified in objv and then
1627 * unlink(2) those object files.
1630 const char *fmt = "%s -o %s -r";
1632 len = snprintf(&tmp, 1, fmt, dtp->dt_ld_path, file) + 1;
1634 for (i = 0; i < objc; i++)
1635 len += strlen(objv[i]) + 1;
1639 cur = snprintf(cmd, len, fmt, dtp->dt_ld_path, file);
1641 for (i = 0; i < objc; i++)
1642 cur += snprintf(cmd + cur, len - cur, " %s", objv[i]);
1644 if ((status = system(cmd)) == -1) {
1645 return (dt_link_error(dtp, NULL, -1, NULL,
1646 "failed to run %s: %s", dtp->dt_ld_path,
1650 if (WIFSIGNALED(status)) {
1651 return (dt_link_error(dtp, NULL, -1, NULL,
1652 "failed to link %s: %s failed due to signal %d",
1653 file, dtp->dt_ld_path, WTERMSIG(status)));
1656 if (WEXITSTATUS(status) != 0) {
1657 return (dt_link_error(dtp, NULL, -1, NULL,
1658 "failed to link %s: %s exited with status %d\n",
1659 file, dtp->dt_ld_path, WEXITSTATUS(status)));
1662 for (i = 0; i < objc; i++) {
1663 if (strcmp(objv[i], file) != 0)
1664 (void) unlink(objv[i]);
1670 for (i = 0; i < objc; i++) {
1671 if (process_obj(dtp, objv[i], &eprobes) != 0)
1672 return (-1); /* errno is set for us */
1676 * If there are is-enabled probes then we need to force use of DOF
1679 if (eprobes && pgp->dp_dofversion < DOF_VERSION_2)
1680 pgp->dp_dofversion = DOF_VERSION_2;
1682 if ((dof = dtrace_dof_create(dtp, pgp, dflags)) == NULL)
1683 return (-1); /* errno is set for us */
1685 snprintf(tfile, sizeof(tfile), "%s.XXXXXX", file);
1686 if ((fd = mkostemp(tfile, O_CLOEXEC)) == -1)
1687 return (dt_link_error(dtp, NULL, -1, NULL,
1688 "failed to create temporary file %s: %s",
1689 tfile, strerror(errno)));
1692 * If -xlinktype=DOF has been selected, just write out the DOF.
1693 * Otherwise proceed to the default of generating and linking ELF.
1695 switch (dtp->dt_linktype) {
1697 if (dt_write(dtp, fd, dof, dof->dofh_filesz) < dof->dofh_filesz)
1700 if (close(fd) != 0 && ret == 0)
1704 return (dt_link_error(dtp, NULL, -1, NULL,
1705 "failed to write %s: %s", file, strerror(ret)));
1711 break; /* fall through to the rest of dtrace_program_link() */
1714 return (dt_link_error(dtp, NULL, -1, NULL,
1715 "invalid link type %u\n", dtp->dt_linktype));
1719 if (dtp->dt_oflags & DTRACE_O_LP64)
1720 status = dump_elf64(dtp, dof, fd);
1722 status = dump_elf32(dtp, dof, fd);
1725 return (dt_link_error(dtp, NULL, -1, NULL,
1726 "failed to write %s: %s", tfile,
1727 strerror(dtrace_errno(dtp))));
1729 if (!dtp->dt_lazyload) {
1730 const char *fmt = "%s -o %s -r %s %s";
1731 dt_dirpath_t *dp = dt_list_next(&dtp->dt_lib_path);
1733 (void) snprintf(drti, sizeof (drti), "%s/drti.o", dp->dir_path);
1735 len = snprintf(&tmp, 1, fmt, dtp->dt_ld_path, file, tfile,
1740 (void) snprintf(cmd, len, fmt, dtp->dt_ld_path, file, tfile,
1742 if ((status = system(cmd)) == -1) {
1743 ret = dt_link_error(dtp, NULL, fd, NULL,
1744 "failed to run %s: %s", dtp->dt_ld_path,
1749 if (WIFSIGNALED(status)) {
1750 ret = dt_link_error(dtp, NULL, fd, NULL,
1751 "failed to link %s: %s failed due to signal %d",
1752 file, dtp->dt_ld_path, WTERMSIG(status));
1756 if (WEXITSTATUS(status) != 0) {
1757 ret = dt_link_error(dtp, NULL, fd, NULL,
1758 "failed to link %s: %s exited with status %d\n",
1759 file, dtp->dt_ld_path, WEXITSTATUS(status));
1762 (void) close(fd); /* release temporary file */
1765 * Now that we've linked drti.o, reduce the global __SUNW_dof
1766 * symbol to a local symbol. This is needed to so that multiple
1767 * generated object files (for different providers, for
1768 * instance) can be linked together. This is accomplished using
1769 * the -Blocal flag with Sun's linker, but GNU ld doesn't appear
1770 * to have an equivalent option.
1772 asprintf(&cmd, "%s --localize-hidden %s", dtp->dt_objcopy_path,
1774 if ((status = system(cmd)) == -1) {
1775 ret = dt_link_error(dtp, NULL, -1, NULL,
1776 "failed to run %s: %s", dtp->dt_objcopy_path,
1783 if (WIFSIGNALED(status)) {
1784 ret = dt_link_error(dtp, NULL, -1, NULL,
1785 "failed to link %s: %s failed due to signal %d",
1786 file, dtp->dt_objcopy_path, WTERMSIG(status));
1790 if (WEXITSTATUS(status) != 0) {
1791 ret = dt_link_error(dtp, NULL, -1, NULL,
1792 "failed to link %s: %s exited with status %d\n",
1793 file, dtp->dt_objcopy_path, WEXITSTATUS(status));
1797 if (rename(tfile, file) != 0) {
1798 ret = dt_link_error(dtp, NULL, fd, NULL,
1799 "failed to rename %s to %s: %s", tfile, file,
1807 dtrace_dof_destroy(dtp, dof);
1809 if (!dtp->dt_lazyload)
1810 (void) unlink(tfile);