import less(1)
[unleashed/tickless.git] / usr / src / lib / libdtrace / common / dt_link.c
blob0c7937460f5941e035217a039617862ce81609a6
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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
30 #include <elf.h>
32 #include <sys/types.h>
33 #include <sys/sysmacros.h>
35 #include <unistd.h>
36 #include <strings.h>
37 #include <alloca.h>
38 #include <limits.h>
39 #include <stddef.h>
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <fcntl.h>
43 #include <errno.h>
44 #include <wait.h>
45 #include <assert.h>
46 #include <sys/ipc.h>
48 #include <dt_impl.h>
49 #include <dt_provider.h>
50 #include <dt_program.h>
51 #include <dt_string.h>
53 #define ESHDR_NULL 0
54 #define ESHDR_SHSTRTAB 1
55 #define ESHDR_DOF 2
56 #define ESHDR_STRTAB 3
57 #define ESHDR_SYMTAB 4
58 #define ESHDR_REL 5
59 #define ESHDR_NUM 6
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"
68 ".shstrtab\0" /* 1 */
69 ".SUNW_dof\0" /* 11 */
70 ".strtab\0" /* 21 */
71 ".symtab\0" /* 29 */
72 ".rel.SUNW_dof"; /* 37 */
74 static const char DTRACE_SHSTRTAB64[] = "\0"
75 ".shstrtab\0" /* 1 */
76 ".SUNW_dof\0" /* 11 */
77 ".strtab\0" /* 21 */
78 ".symtab\0" /* 29 */
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 */
88 } dt_link_pair_t;
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 */
98 } dof_elf32_t;
100 static int
101 prepare_elf32(dtrace_hdl_t *dtp, const dof_hdr_t *dof, dof_elf32_t *dep)
103 dof_sec_t *dofs, *s;
104 dof_relohdr_t *dofrh;
105 dof_relodesc_t *dofr;
106 char *strtab;
107 int i, j, nrel;
108 size_t strtabsz = 1;
109 uint32_t count = 0;
110 size_t base;
111 Elf32_Sym *sym;
112 Elf32_Rel *rel;
114 /*LINTED*/
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)
123 continue;
125 /*LINTED*/
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];
134 /*LINTED*/
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);
145 dep->de_nsym++;
146 } else {
147 dep->de_strlen += sizeof (DOFSTR);
148 dep->de_nsym++;
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) {
157 free(dep->de_rel);
158 return (dt_set_errno(dtp, EDT_NOMEM));
161 if ((dep->de_strtab = calloc(dep->de_strlen, 1)) == NULL) {
162 free(dep->de_rel);
163 free(dep->de_sym);
164 return (dt_set_errno(dtp, EDT_NOMEM));
167 count = 0;
168 strtabsz = 1;
169 dep->de_strtab[0] = '\0';
170 rel = dep->de_rel;
171 sym = dep->de_sym;
172 dep->de_global = 1;
175 * The first symbol table entry must be zeroed and is always ignored.
177 bzero(sym, sizeof (Elf32_Sym));
178 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)
186 continue;
188 /*LINTED*/
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);
194 base = strtabsz;
195 strtabsz += s->dofs_size - 1;
197 s = &dofs[dofrh->dofr_relsec];
198 /*LINTED*/
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 +
207 dofr[j].dofr_offset;
208 rel->r_info = ELF32_R_INFO(count + dep->de_global,
209 R_386_32);
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,
218 R_SPARC_32);
219 #else
220 #error unknown ISA
221 #endif
223 sym->st_name = base + dofr[j].dofr_name - 1;
224 sym->st_value = 0;
225 sym->st_size = 0;
226 sym->st_info = ELF32_ST_INFO(STB_GLOBAL, STT_FUNC);
227 sym->st_other = 0;
228 sym->st_shndx = SHN_UNDEF;
230 rel++;
231 sym++;
232 count++;
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;
241 sym->st_value = 0;
242 sym->st_size = dof->dofh_filesz;
243 sym->st_info = ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT);
244 sym->st_other = 0;
245 sym->st_shndx = ESHDR_DOF;
246 sym++;
248 if (dtp->dt_lazyload) {
249 bcopy(DOFLAZYSTR, dep->de_strtab + strtabsz,
250 sizeof (DOFLAZYSTR));
251 strtabsz += sizeof (DOFLAZYSTR);
252 } else {
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);
260 return (0);
264 typedef struct dof_elf64 {
265 uint32_t de_nrel;
266 Elf64_Rela *de_rel;
267 uint32_t de_nsym;
268 Elf64_Sym *de_sym;
270 uint32_t de_strlen;
271 char *de_strtab;
273 uint32_t de_global;
274 } dof_elf64_t;
276 static int
277 prepare_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, dof_elf64_t *dep)
279 dof_sec_t *dofs, *s;
280 dof_relohdr_t *dofrh;
281 dof_relodesc_t *dofr;
282 char *strtab;
283 int i, j, nrel;
284 size_t strtabsz = 1;
285 uint32_t count = 0;
286 size_t base;
287 Elf64_Sym *sym;
288 Elf64_Rela *rel;
290 /*LINTED*/
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)
299 continue;
301 /*LINTED*/
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];
310 /*LINTED*/
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);
321 dep->de_nsym++;
322 } else {
323 dep->de_strlen += sizeof (DOFSTR);
324 dep->de_nsym++;
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) {
333 free(dep->de_rel);
334 return (dt_set_errno(dtp, EDT_NOMEM));
337 if ((dep->de_strtab = calloc(dep->de_strlen, 1)) == NULL) {
338 free(dep->de_rel);
339 free(dep->de_sym);
340 return (dt_set_errno(dtp, EDT_NOMEM));
343 count = 0;
344 strtabsz = 1;
345 dep->de_strtab[0] = '\0';
346 rel = dep->de_rel;
347 sym = dep->de_sym;
348 dep->de_global = 1;
351 * The first symbol table entry must be zeroed and is always ignored.
353 bzero(sym, sizeof (Elf64_Sym));
354 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)
362 continue;
364 /*LINTED*/
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);
370 base = strtabsz;
371 strtabsz += s->dofs_size - 1;
373 s = &dofs[dofrh->dofr_relsec];
374 /*LINTED*/
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 +
383 dofr[j].dofr_offset;
384 rel->r_info = ELF64_R_INFO(count + dep->de_global,
385 R_AMD64_64);
386 #elif defined(__sparc)
387 rel->r_offset = s->dofs_offset +
388 dofr[j].dofr_offset;
389 rel->r_info = ELF64_R_INFO(count + dep->de_global,
390 R_SPARC_64);
391 #else
392 #error unknown ISA
393 #endif
395 sym->st_name = base + dofr[j].dofr_name - 1;
396 sym->st_value = 0;
397 sym->st_size = 0;
398 sym->st_info = GELF_ST_INFO(STB_GLOBAL, STT_FUNC);
399 sym->st_other = 0;
400 sym->st_shndx = SHN_UNDEF;
402 rel++;
403 sym++;
404 count++;
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;
413 sym->st_value = 0;
414 sym->st_size = dof->dofh_filesz;
415 sym->st_info = GELF_ST_INFO(STB_GLOBAL, STT_OBJECT);
416 sym->st_other = 0;
417 sym->st_shndx = ESHDR_DOF;
418 sym++;
420 if (dtp->dt_lazyload) {
421 bcopy(DOFLAZYSTR, dep->de_strtab + strtabsz,
422 sizeof (DOFLAZYSTR));
423 strtabsz += sizeof (DOFLAZYSTR);
424 } else {
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);
432 return (0);
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.
440 static int
441 dump_elf32(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd)
443 struct {
444 Elf32_Ehdr ehdr;
445 Elf32_Shdr shdr[ESHDR_NUM];
446 } elf_file;
448 Elf32_Shdr *shp;
449 Elf32_Off off;
450 dof_elf32_t de;
451 int ret = 0;
452 uint_t nshdr;
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;
475 #endif
476 elf_file.ehdr.e_type = ET_REL;
477 #if defined(__sparc)
478 elf_file.ehdr.e_machine = EM_SPARC;
479 #elif defined(__i386) || defined(__amd64)
480 elf_file.ehdr.e_machine = EM_386;
481 #endif
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);
538 } else {
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);
561 free(de.de_strtab);
562 free(de.de_sym);
563 free(de.de_rel);
565 return (ret);
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.
573 static int
574 dump_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd)
576 struct {
577 Elf64_Ehdr ehdr;
578 Elf64_Shdr shdr[ESHDR_NUM];
579 } elf_file;
581 Elf64_Shdr *shp;
582 Elf64_Off off;
583 dof_elf64_t de;
584 int ret = 0;
585 uint_t nshdr;
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;
608 #endif
609 elf_file.ehdr.e_type = ET_REL;
610 #if defined(__sparc)
611 elf_file.ehdr.e_machine = EM_SPARCV9;
612 #elif defined(__i386) || defined(__amd64)
613 elf_file.ehdr.e_machine = EM_AMD64;
614 #endif
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);
671 } else {
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);
694 free(de.de_strtab);
695 free(de.de_sym);
696 free(de.de_rel);
698 return (ret);
701 static int
702 dt_symtab_lookup(Elf_Data *data_sym, int nsym, uintptr_t addr, uint_t shn,
703 GElf_Sym *sym)
705 int i, ret = -1;
706 GElf_Sym s;
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)
714 return (0);
716 ret = 0;
717 s = *sym;
721 if (ret == 0)
722 *sym = s;
723 return (ret);
726 #if defined(__sparc)
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))
740 /*ARGSUSED*/
741 static int
742 dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
743 uint32_t *off)
745 uint32_t *ip;
747 if ((rela->r_offset & (sizeof (uint32_t) - 1)) != 0)
748 return (-1);
750 /*LINTED*/
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)
758 return (-1);
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.
765 if (isenabled) {
766 if (ip[0] == DT_OP_NOP) {
767 (*off) += sizeof (ip[0]);
768 return (0);
770 } else {
771 if (DT_IS_RESTORE(ip[1])) {
772 if (ip[0] == DT_OP_RET) {
773 (*off) += sizeof (ip[0]);
774 return (0);
776 } else if (DT_IS_MOV_O7(ip[1])) {
777 if (DT_IS_RETL(ip[0]))
778 return (0);
779 } else {
780 if (ip[0] == DT_OP_NOP) {
781 (*off) += sizeof (ip[0]);
782 return (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);
793 return (-1);
796 if (isenabled) {
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);
806 return (-1);
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.
818 ip[0] = DT_OP_NOP;
819 (*off) += sizeof (ip[0]);
820 } else {
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
837 * wild.
839 if (DT_IS_RESTORE(ip[1])) {
840 ip[0] = DT_OP_RET;
841 (*off) += sizeof (ip[0]);
842 } else if (DT_IS_MOV_O7(ip[1])) {
843 ip[0] = DT_MAKE_RETL(DT_RS2(ip[1]));
844 } else {
845 ip[0] = DT_OP_NOP;
846 (*off) += sizeof (ip[0]);
850 return (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
863 static int
864 dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
865 uint32_t *off)
867 uint8_t *ip = (uint8_t *)(p + rela->r_offset - 1);
868 uint8_t ret;
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.
877 (*off) -= 1;
880 * We only know about some specific relocation types. Luckily
881 * these types have the same values on both 32-bit and 64-bit
882 * x86 architectures.
884 if (GELF_R_TYPE(rela->r_info) != R_386_PC32 &&
885 GELF_R_TYPE(rela->r_info) != R_386_PLT32)
886 return (-1);
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.
895 if (!isenabled) {
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)
899 return (0);
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) {
905 (*off) += 3;
906 return (0);
908 } else {
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) {
912 (*off) += 2;
913 return (0);
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);
924 return (-1);
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.
936 if (!isenabled) {
937 ip[0] = ret;
938 ip[1] = DT_OP_NOP;
939 ip[2] = DT_OP_NOP;
940 ip[3] = DT_OP_NOP;
941 ip[4] = DT_OP_NOP;
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;
946 ip[3] = ret;
947 ip[4] = DT_OP_NOP;
948 (*off) += 3;
949 } else {
950 ip[0] = DT_OP_XOR_EAX_0;
951 ip[1] = DT_OP_XOR_EAX_1;
952 ip[2] = ret;
953 ip[3] = DT_OP_NOP;
954 ip[4] = DT_OP_NOP;
955 (*off) += 2;
958 return (0);
961 #else
962 #error unknown ISA
963 #endif
965 /*PRINTFLIKE5*/
966 static int
967 dt_link_error(dtrace_hdl_t *dtp, Elf *elf, int fd, dt_link_pair_t *bufs,
968 const char *format, ...)
970 va_list ap;
971 dt_link_pair_t *pair;
973 va_start(ap, format);
974 dt_set_errmsg(dtp, NULL, NULL, NULL, 0, format, ap);
975 va_end(ap);
977 if (elf != NULL)
978 (void) elf_end(elf);
980 if (fd >= 0)
981 (void) close(fd);
983 while ((pair = bufs) != NULL) {
984 bufs = pair->dlp_next;
985 dt_free(dtp, pair->dlp_str);
986 dt_free(dtp, pair->dlp_sym);
987 dt_free(dtp, pair);
990 return (dt_set_errno(dtp, EDT_COMPILER));
993 static int
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;
1001 Elf *elf = NULL;
1002 GElf_Ehdr ehdr;
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;
1007 GElf_Rela rela;
1008 char *s, *p, *r;
1009 char pname[DTRACE_PROVNAMELEN];
1010 dt_provider_t *pvp;
1011 dt_probe_t *prp;
1012 uint32_t off, eclass, emachine1, emachine2;
1013 size_t symsize, nsym, isym, istr, len;
1014 key_t objkey;
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)) {
1029 case ELF_K_ELF:
1030 break;
1031 case ELF_K_AR:
1032 return (dt_link_error(dtp, elf, fd, bufs, "archives are not "
1033 "permitted; use the contents of the archive instead: %s",
1034 obj));
1035 default:
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",
1042 obj));
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;
1051 #endif
1052 symsize = sizeof (Elf64_Sym);
1053 } else {
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;
1060 #endif
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));
1084 scn_rel = NULL;
1085 while ((scn_rel = elf_nextscn(elf, scn_rel)) != NULL) {
1086 if (gelf_getshdr(scn_rel, &shdr_rel) == NULL)
1087 goto err;
1090 * Skip any non-relocation sections.
1092 if (shdr_rel.sh_type != SHT_RELA && shdr_rel.sh_type != SHT_REL)
1093 continue;
1095 if ((data_rel = elf_getdata(scn_rel, NULL)) == NULL)
1096 goto err;
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)
1105 goto err;
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)
1113 goto err;
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
1119 * object file.
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)
1124 goto err;
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
1138 * one or more nops.
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);
1154 nsym = 0;
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)
1162 continue;
1163 } else {
1164 GElf_Rel rel;
1165 if (gelf_getrel(data_rel, i, &rel) == NULL)
1166 continue;
1167 rela.r_offset = rel.r_offset;
1168 rela.r_info = rel.r_info;
1169 rela.r_addend = 0;
1172 if (gelf_getsym(data_sym, GELF_R_SYM(rela.r_info),
1173 &rsym) == NULL) {
1174 dt_strtab_destroy(strtab);
1175 goto err;
1178 s = (char *)data_str->d_buf + rsym.st_name;
1180 if (strncmp(s, dt_prefix, sizeof (dt_prefix) - 1) != 0)
1181 continue;
1183 if (dt_symtab_lookup(data_sym, isym, rela.r_offset,
1184 shdr_rel.sh_info, &fsym) != 0) {
1185 dt_strtab_destroy(strtab);
1186 goto err;
1189 if (GELF_ST_BIND(fsym.st_info) != STB_LOCAL)
1190 continue;
1192 if (fsym.st_name > data_str->d_size) {
1193 dt_strtab_destroy(strtab);
1194 goto err;
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,
1210 objkey, s) + 1;
1211 if ((p = dt_alloc(dtp, len)) == NULL) {
1212 dt_strtab_destroy(strtab);
1213 goto err;
1215 (void) snprintf(p, len, dt_symfmt, dt_symprefix,
1216 objkey, s);
1218 if (dt_strtab_index(strtab, p) == -1) {
1219 nsym++;
1220 (void) dt_strtab_insert(strtab, p);
1223 dt_free(dtp, 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
1232 * the elf handle.
1234 if (nsym > 0) {
1236 * The first byte of the string table is reserved for
1237 * the \0 entry.
1239 len = dt_strtab_size(strtab) - 1;
1241 assert(len > 0);
1242 assert(dt_strtab_index(strtab, "") == 0);
1244 dt_strtab_destroy(strtab);
1246 if ((pair = dt_alloc(dtp, sizeof (*pair))) == NULL)
1247 goto err;
1249 if ((pair->dlp_str = dt_alloc(dtp, data_str->d_size +
1250 len)) == NULL) {
1251 dt_free(dtp, pair);
1252 goto err;
1255 if ((pair->dlp_sym = dt_alloc(dtp, data_sym->d_size +
1256 nsym * symsize)) == NULL) {
1257 dt_free(dtp, pair->dlp_str);
1258 dt_free(dtp, pair);
1259 goto err;
1262 pair->dlp_next = bufs;
1263 bufs = pair;
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);
1281 nsym += isym;
1282 } else {
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)
1294 continue;
1295 } else {
1296 GElf_Rel rel;
1297 if (gelf_getrel(data_rel, i, &rel) == NULL)
1298 continue;
1299 rela.r_offset = rel.r_offset;
1300 rela.r_info = rel.r_info;
1301 rela.r_addend = 0;
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)
1308 goto err;
1310 s = (char *)data_str->d_buf + rsym.st_name;
1312 if (strncmp(s, dt_prefix, sizeof (dt_prefix) - 1) != 0)
1313 continue;
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;
1324 eprobe = 1;
1325 *eprobesp = 1;
1326 dt_dprintf("is-enabled probe\n");
1327 } else {
1328 eprobe = 0;
1329 dt_dprintf("normal probe\n");
1332 if (*s++ != '_')
1333 goto err;
1335 if ((p = strstr(s, "___")) == NULL ||
1336 p - s >= sizeof (pname))
1337 goto err;
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)
1346 goto err;
1348 if (fsym.st_name > data_str->d_size)
1349 goto err;
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;
1363 r = NULL;
1365 if (GELF_ST_BIND(fsym.st_info) == STB_LOCAL) {
1366 dsym = fsym;
1367 dsym.st_name = istr;
1368 dsym.st_info = GELF_ST_INFO(STB_GLOBAL,
1369 STT_FUNC);
1370 dsym.st_other =
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);
1377 isym++;
1378 assert(isym <= nsym);
1380 } else if (strncmp(s, dt_symprefix,
1381 strlen(dt_symprefix)) == 0) {
1382 r = s;
1383 if ((s = strchr(s, '.')) == NULL)
1384 goto err;
1385 s++;
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) {
1403 goto err;
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"));
1411 mod = 1;
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
1419 * invocation.
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)
1429 goto err;
1431 (void) elf_end(elf);
1432 (void) close(fd);
1434 while ((pair = bufs) != NULL) {
1435 bufs = pair->dlp_next;
1436 dt_free(dtp, pair->dlp_str);
1437 dt_free(dtp, pair->dlp_sym);
1438 dt_free(dtp, pair);
1441 return (0);
1443 err:
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];
1453 dof_hdr_t *dof;
1454 int fd, status, i, cur;
1455 char *cmd, tmp;
1456 size_t len;
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.
1464 if (pgp == NULL) {
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;
1472 cmd = alloca(len);
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,
1482 strerror(errno)));
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]);
1502 return (0);
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
1512 * version 2.
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) {
1535 case DT_LTYP_DOF:
1536 if (dt_write(dtp, fd, dof, dof->dofh_filesz) < dof->dofh_filesz)
1537 ret = errno;
1539 if (close(fd) != 0 && ret == 0)
1540 ret = errno;
1542 if (ret != 0) {
1543 return (dt_link_error(dtp, NULL, -1, NULL,
1544 "failed to write %s: %s", file, strerror(ret)));
1547 return (0);
1549 case DT_LTYP_ELF:
1550 break; /* fall through to the rest of dtrace_program_link() */
1552 default:
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);
1563 else
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);
1577 } else {
1578 (void) snprintf(drti, sizeof (drti),
1579 "%s/drti.o", _dtrace_libdir);
1582 len = snprintf(&tmp, 1, fmt, dtp->dt_ld_path, file, fd,
1583 drti) + 1;
1585 cmd = alloca(len);
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,
1592 strerror(errno));
1593 goto done;
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));
1602 goto done;
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));
1609 goto done;
1611 } else {
1612 (void) close(fd);
1615 done:
1616 dtrace_dof_destroy(dtp, dof);
1617 return (ret);