1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright 2017-2018 Mark Johnston <markj@FreeBSD.org>
26 */
27
28 #include <sys/param.h>
29 #include <sys/mman.h>
30 #include <sys/wait.h>
31
32 #include <assert.h>
33 #include <elf.h>
34 #include <sys/types.h>
35 #include <fcntl.h>
36 #include <gelf.h>
37 #include <limits.h>
38 #include <stddef.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <strings.h>
42 #include <errno.h>
43 #include <unistd.h>
44
45 #include <libelf.h>
46
47 #include <dt_impl.h>
48 #include <dt_provider.h>
49 #include <dt_program.h>
50 #include <dt_string.h>
51
52 #define ESHDR_NULL 0
53 #define ESHDR_SHSTRTAB 1
54 #define ESHDR_DOF 2
55 #define ESHDR_STRTAB 3
56 #define ESHDR_SYMTAB 4
57 #define ESHDR_REL 5
58 #define ESHDR_NUM 6
59
60 #define PWRITE_SCN(index, data) \
61 (lseek64(fd, (off64_t)elf_file.shdr[(index)].sh_offset, SEEK_SET) != \
62 (off64_t)elf_file.shdr[(index)].sh_offset || \
63 dt_write(dtp, fd, (data), elf_file.shdr[(index)].sh_size) != \
64 elf_file.shdr[(index)].sh_size)
65
66 static const char DTRACE_SHSTRTAB32[] = "\0"
67 ".shstrtab\0" /* 1 */
68 ".SUNW_dof\0" /* 11 */
69 ".strtab\0" /* 21 */
70 ".symtab\0" /* 29 */
71 ".rel.SUNW_dof"; /* 37 */
72
73 static const char DTRACE_SHSTRTAB64[] = "\0"
74 ".shstrtab\0" /* 1 */
75 ".SUNW_dof\0" /* 11 */
76 ".strtab\0" /* 21 */
77 ".symtab\0" /* 29 */
78 ".rela.SUNW_dof"; /* 37 */
79
80 static const char DOFSTR[] = "__SUNW_dof";
81 static const char DOFLAZYSTR[] = "___SUNW_dof";
82
83 typedef struct dt_link_pair {
84 struct dt_link_pair *dlp_next; /* next pair in linked list */
85 void *dlp_str; /* buffer for string table */
86 void *dlp_sym; /* buffer for symbol table */
87 } dt_link_pair_t;
88
89 typedef struct dof_elf32 {
90 uint32_t de_nrel; /* relocation count */
91 Elf32_Rel *de_rel; /* array of relocations for x86 */
92 uint32_t de_nsym; /* symbol count */
93 Elf32_Sym *de_sym; /* array of symbols */
94 uint32_t de_strlen; /* size of of string table */
95 char *de_strtab; /* string table */
96 uint32_t de_global; /* index of the first global symbol */
97 } dof_elf32_t;
98
99 static int
prepare_elf32(dtrace_hdl_t * dtp,const dof_hdr_t * dof,dof_elf32_t * dep)100 prepare_elf32(dtrace_hdl_t *dtp, const dof_hdr_t *dof, dof_elf32_t *dep)
101 {
102 dof_sec_t *dofs, *s;
103 dof_relohdr_t *dofrh;
104 dof_relodesc_t *dofr;
105 char *strtab;
106 int i, j, nrel;
107 size_t strtabsz = 1;
108 uint32_t count = 0;
109 size_t base;
110 Elf32_Sym *sym;
111 Elf32_Rel *rel;
112
113 /*LINTED*/
114 dofs = (dof_sec_t *)((char *)dof + dof->dofh_secoff);
115
116 /*
117 * First compute the size of the string table and the number of
118 * relocations present in the DOF.
119 */
120 for (i = 0; i < dof->dofh_secnum; i++) {
121 if (dofs[i].dofs_type != DOF_SECT_URELHDR)
122 continue;
123
124 /*LINTED*/
125 dofrh = (dof_relohdr_t *)((char *)dof + dofs[i].dofs_offset);
126
127 s = &dofs[dofrh->dofr_strtab];
128 strtab = (char *)dof + s->dofs_offset;
129 assert(strtab[0] == '\0');
130 strtabsz += s->dofs_size - 1;
131
132 s = &dofs[dofrh->dofr_relsec];
133 /*LINTED*/
134 dofr = (dof_relodesc_t *)((char *)dof + s->dofs_offset);
135 count += s->dofs_size / s->dofs_entsize;
136 }
137
138 dep->de_strlen = strtabsz;
139 dep->de_nrel = count;
140 dep->de_nsym = count + 1; /* the first symbol is always null */
141
142 if (dtp->dt_lazyload) {
143 dep->de_strlen += sizeof (DOFLAZYSTR);
144 dep->de_nsym++;
145 } else {
146 dep->de_strlen += sizeof (DOFSTR);
147 dep->de_nsym++;
148 }
149
150 if ((dep->de_rel = calloc(dep->de_nrel,
151 sizeof (dep->de_rel[0]))) == NULL) {
152 return (dt_set_errno(dtp, EDT_NOMEM));
153 }
154
155 if ((dep->de_sym = calloc(dep->de_nsym, sizeof (Elf32_Sym))) == NULL) {
156 free(dep->de_rel);
157 return (dt_set_errno(dtp, EDT_NOMEM));
158 }
159
160 if ((dep->de_strtab = calloc(dep->de_strlen, 1)) == NULL) {
161 free(dep->de_rel);
162 free(dep->de_sym);
163 return (dt_set_errno(dtp, EDT_NOMEM));
164 }
165
166 count = 0;
167 strtabsz = 1;
168 dep->de_strtab[0] = '\0';
169 rel = dep->de_rel;
170 sym = dep->de_sym;
171 dep->de_global = 1;
172
173 /*
174 * The first symbol table entry must be zeroed and is always ignored.
175 */
176 bzero(sym, sizeof (Elf32_Sym));
177 sym++;
178
179 /*
180 * Take a second pass through the DOF sections filling in the
181 * memory we allocated.
182 */
183 for (i = 0; i < dof->dofh_secnum; i++) {
184 if (dofs[i].dofs_type != DOF_SECT_URELHDR)
185 continue;
186
187 /*LINTED*/
188 dofrh = (dof_relohdr_t *)((char *)dof + dofs[i].dofs_offset);
189
190 s = &dofs[dofrh->dofr_strtab];
191 strtab = (char *)dof + s->dofs_offset;
192 bcopy(strtab + 1, dep->de_strtab + strtabsz, s->dofs_size);
193 base = strtabsz;
194 strtabsz += s->dofs_size - 1;
195
196 s = &dofs[dofrh->dofr_relsec];
197 /*LINTED*/
198 dofr = (dof_relodesc_t *)((char *)dof + s->dofs_offset);
199 nrel = s->dofs_size / s->dofs_entsize;
200
201 s = &dofs[dofrh->dofr_tgtsec];
202
203 for (j = 0; j < nrel; j++) {
204 #if defined(__aarch64__)
205 rel->r_offset = s->dofs_offset +
206 dofr[j].dofr_offset;
207 rel->r_info = ELF32_R_INFO(count + dep->de_global,
208 R_ARM_REL32);
209 #elif defined(__arm__)
210 /* XXX */
211 printf("%s:%s(%d): arm not implemented\n",
212 __FUNCTION__, __FILE__, __LINE__);
213 #elif defined(__i386) || defined(__amd64)
214 rel->r_offset = s->dofs_offset +
215 dofr[j].dofr_offset;
216 rel->r_info = ELF32_R_INFO(count + dep->de_global,
217 R_386_PC32);
218 #elif defined(__powerpc__)
219 /*
220 * Add 4 bytes to hit the low half of this 64-bit
221 * big-endian address.
222 */
223 rel->r_offset = s->dofs_offset +
224 dofr[j].dofr_offset + 4;
225 rel->r_info = ELF32_R_INFO(count + dep->de_global,
226 R_PPC_REL32);
227 #elif defined(__riscv)
228 rel->r_offset = s->dofs_offset + dofr[j].dofr_offset;
229 rel->r_info = ELF32_R_INFO(count + dep->de_global,
230 R_RISCV_32_PCREL);
231 #else
232 #error unknown ISA
233 #endif
234
235 sym->st_name = base + dofr[j].dofr_name - 1;
236 sym->st_value = 0;
237 sym->st_size = 0;
238 sym->st_info = ELF32_ST_INFO(STB_GLOBAL, STT_FUNC);
239 sym->st_other = ELF32_ST_VISIBILITY(STV_HIDDEN);
240 sym->st_shndx = SHN_UNDEF;
241
242 rel++;
243 sym++;
244 count++;
245 }
246 }
247
248 /*
249 * Add a symbol for the DOF itself. We use a different symbol for
250 * lazily and actively loaded DOF to make them easy to distinguish.
251 */
252 sym->st_name = strtabsz;
253 sym->st_value = 0;
254 sym->st_size = dof->dofh_filesz;
255 sym->st_info = ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT);
256 sym->st_other = ELF32_ST_VISIBILITY(STV_HIDDEN);
257 sym->st_shndx = ESHDR_DOF;
258 sym++;
259
260 if (dtp->dt_lazyload) {
261 bcopy(DOFLAZYSTR, dep->de_strtab + strtabsz,
262 sizeof (DOFLAZYSTR));
263 strtabsz += sizeof (DOFLAZYSTR);
264 } else {
265 bcopy(DOFSTR, dep->de_strtab + strtabsz, sizeof (DOFSTR));
266 strtabsz += sizeof (DOFSTR);
267 }
268
269 assert(count == dep->de_nrel);
270 assert(strtabsz == dep->de_strlen);
271
272 return (0);
273 }
274
275
276 typedef struct dof_elf64 {
277 uint32_t de_nrel;
278 Elf64_Rela *de_rel;
279 uint32_t de_nsym;
280 Elf64_Sym *de_sym;
281
282 uint32_t de_strlen;
283 char *de_strtab;
284
285 uint32_t de_global;
286 } dof_elf64_t;
287
288 static int
prepare_elf64(dtrace_hdl_t * dtp,const dof_hdr_t * dof,dof_elf64_t * dep)289 prepare_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, dof_elf64_t *dep)
290 {
291 dof_sec_t *dofs, *s;
292 dof_relohdr_t *dofrh;
293 dof_relodesc_t *dofr;
294 char *strtab;
295 int i, j, nrel;
296 size_t strtabsz = 1;
297 uint64_t count = 0;
298 size_t base;
299 Elf64_Sym *sym;
300 Elf64_Rela *rel;
301
302 /*LINTED*/
303 dofs = (dof_sec_t *)((char *)dof + dof->dofh_secoff);
304
305 /*
306 * First compute the size of the string table and the number of
307 * relocations present in the DOF.
308 */
309 for (i = 0; i < dof->dofh_secnum; i++) {
310 if (dofs[i].dofs_type != DOF_SECT_URELHDR)
311 continue;
312
313 /*LINTED*/
314 dofrh = (dof_relohdr_t *)((char *)dof + dofs[i].dofs_offset);
315
316 s = &dofs[dofrh->dofr_strtab];
317 strtab = (char *)dof + s->dofs_offset;
318 assert(strtab[0] == '\0');
319 strtabsz += s->dofs_size - 1;
320
321 s = &dofs[dofrh->dofr_relsec];
322 /*LINTED*/
323 dofr = (dof_relodesc_t *)((char *)dof + s->dofs_offset);
324 count += s->dofs_size / s->dofs_entsize;
325 }
326
327 dep->de_strlen = strtabsz;
328 dep->de_nrel = count;
329 dep->de_nsym = count + 1; /* the first symbol is always null */
330
331 if (dtp->dt_lazyload) {
332 dep->de_strlen += sizeof (DOFLAZYSTR);
333 dep->de_nsym++;
334 } else {
335 dep->de_strlen += sizeof (DOFSTR);
336 dep->de_nsym++;
337 }
338
339 if ((dep->de_rel = calloc(dep->de_nrel,
340 sizeof (dep->de_rel[0]))) == NULL) {
341 return (dt_set_errno(dtp, EDT_NOMEM));
342 }
343
344 if ((dep->de_sym = calloc(dep->de_nsym, sizeof (Elf64_Sym))) == NULL) {
345 free(dep->de_rel);
346 return (dt_set_errno(dtp, EDT_NOMEM));
347 }
348
349 if ((dep->de_strtab = calloc(dep->de_strlen, 1)) == NULL) {
350 free(dep->de_rel);
351 free(dep->de_sym);
352 return (dt_set_errno(dtp, EDT_NOMEM));
353 }
354
355 count = 0;
356 strtabsz = 1;
357 dep->de_strtab[0] = '\0';
358 rel = dep->de_rel;
359 sym = dep->de_sym;
360 dep->de_global = 1;
361
362 /*
363 * The first symbol table entry must be zeroed and is always ignored.
364 */
365 bzero(sym, sizeof (Elf64_Sym));
366 sym++;
367
368 /*
369 * Take a second pass through the DOF sections filling in the
370 * memory we allocated.
371 */
372 for (i = 0; i < dof->dofh_secnum; i++) {
373 if (dofs[i].dofs_type != DOF_SECT_URELHDR)
374 continue;
375
376 /*LINTED*/
377 dofrh = (dof_relohdr_t *)((char *)dof + dofs[i].dofs_offset);
378
379 s = &dofs[dofrh->dofr_strtab];
380 strtab = (char *)dof + s->dofs_offset;
381 bcopy(strtab + 1, dep->de_strtab + strtabsz, s->dofs_size);
382 base = strtabsz;
383 strtabsz += s->dofs_size - 1;
384
385 s = &dofs[dofrh->dofr_relsec];
386 /*LINTED*/
387 dofr = (dof_relodesc_t *)((char *)dof + s->dofs_offset);
388 nrel = s->dofs_size / s->dofs_entsize;
389
390 s = &dofs[dofrh->dofr_tgtsec];
391
392 for (j = 0; j < nrel; j++) {
393 #if defined(__aarch64__)
394 rel->r_offset = s->dofs_offset +
395 dofr[j].dofr_offset;
396 rel->r_info = ELF64_R_INFO(count + dep->de_global,
397 R_AARCH64_PREL64);
398 #elif defined(__arm__)
399 /* XXX */
400 #elif defined(__powerpc__)
401 rel->r_offset = s->dofs_offset +
402 dofr[j].dofr_offset;
403 rel->r_info = ELF64_R_INFO(count + dep->de_global,
404 R_PPC64_REL64);
405 #elif defined(__riscv)
406 rel->r_offset = s->dofs_offset + dofr[j].dofr_offset;
407 rel->r_info = ELF64_R_INFO(count + dep->de_global,
408 R_RISCV_32_PCREL);
409 #elif defined(__i386) || defined(__amd64)
410 rel->r_offset = s->dofs_offset +
411 dofr[j].dofr_offset;
412 rel->r_info = ELF64_R_INFO(count + dep->de_global,
413 R_X86_64_PC64);
414 #else
415 #error unknown ISA
416 #endif
417
418 sym->st_name = base + dofr[j].dofr_name - 1;
419 sym->st_value = 0;
420 sym->st_size = 0;
421 sym->st_info = GELF_ST_INFO(STB_GLOBAL, STT_FUNC);
422 sym->st_other = ELF64_ST_VISIBILITY(STV_HIDDEN);
423 sym->st_shndx = SHN_UNDEF;
424
425 rel++;
426 sym++;
427 count++;
428 }
429 }
430
431 /*
432 * Add a symbol for the DOF itself. We use a different symbol for
433 * lazily and actively loaded DOF to make them easy to distinguish.
434 */
435 sym->st_name = strtabsz;
436 sym->st_value = 0;
437 sym->st_size = dof->dofh_filesz;
438 sym->st_info = GELF_ST_INFO(STB_GLOBAL, STT_OBJECT);
439 sym->st_other = ELF64_ST_VISIBILITY(STV_HIDDEN);
440 sym->st_shndx = ESHDR_DOF;
441 sym++;
442
443 if (dtp->dt_lazyload) {
444 bcopy(DOFLAZYSTR, dep->de_strtab + strtabsz,
445 sizeof (DOFLAZYSTR));
446 strtabsz += sizeof (DOFLAZYSTR);
447 } else {
448 bcopy(DOFSTR, dep->de_strtab + strtabsz, sizeof (DOFSTR));
449 strtabsz += sizeof (DOFSTR);
450 }
451
452 assert(count == dep->de_nrel);
453 assert(strtabsz == dep->de_strlen);
454
455 return (0);
456 }
457
458 /*
459 * Write out an ELF32 file prologue consisting of a header, section headers,
460 * and a section header string table. The DOF data will follow this prologue
461 * and complete the contents of the given ELF file.
462 */
463 static int
dump_elf32(dtrace_hdl_t * dtp,const dof_hdr_t * dof,int fd)464 dump_elf32(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd)
465 {
466 struct {
467 Elf32_Ehdr ehdr;
468 Elf32_Shdr shdr[ESHDR_NUM];
469 } elf_file;
470
471 Elf32_Shdr *shp;
472 Elf32_Off off;
473 dof_elf32_t de;
474 int ret = 0;
475 uint_t nshdr;
476
477 if (prepare_elf32(dtp, dof, &de) != 0)
478 return (-1); /* errno is set for us */
479
480 /*
481 * If there are no relocations, we only need enough sections for
482 * the shstrtab and the DOF.
483 */
484 nshdr = de.de_nrel == 0 ? ESHDR_SYMTAB + 1 : ESHDR_NUM;
485
486 bzero(&elf_file, sizeof (elf_file));
487
488 elf_file.ehdr.e_ident[EI_MAG0] = ELFMAG0;
489 elf_file.ehdr.e_ident[EI_MAG1] = ELFMAG1;
490 elf_file.ehdr.e_ident[EI_MAG2] = ELFMAG2;
491 elf_file.ehdr.e_ident[EI_MAG3] = ELFMAG3;
492 elf_file.ehdr.e_ident[EI_VERSION] = EV_CURRENT;
493 elf_file.ehdr.e_ident[EI_CLASS] = ELFCLASS32;
494 #if BYTE_ORDER == _BIG_ENDIAN
495 elf_file.ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
496 #else
497 elf_file.ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
498 #endif
499 elf_file.ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
500 elf_file.ehdr.e_type = ET_REL;
501 #if defined(__arm__)
502 elf_file.ehdr.e_machine = EM_ARM;
503 #elif defined(__powerpc__)
504 elf_file.ehdr.e_machine = EM_PPC;
505 #elif defined(__i386) || defined(__amd64)
506 elf_file.ehdr.e_machine = EM_386;
507 #elif defined(__aarch64__)
508 elf_file.ehdr.e_machine = EM_AARCH64;
509 #elif defined(__riscv)
510 elf_file.ehdr.e_machine = EM_RISCV;
511
512 /* Set the ELF flags according to our current ABI */
513 #if defined(__riscv_compressed)
514 elf_file.ehdr.e_flags |= EF_RISCV_RVC;
515 #endif
516 #if defined(__riscv_float_abi_soft)
517 elf_file.ehdr.e_flags |= EF_RISCV_FLOAT_ABI_SOFT;
518 #endif
519 #if defined(__riscv_float_abi_single)
520 elf_file.ehdr.e_flags |= EF_RISCV_FLOAT_ABI_SINGLE;
521 #endif
522 #if defined(__riscv_float_abi_double)
523 elf_file.ehdr.e_flags |= EF_RISCV_FLOAT_ABI_DOUBLE;
524 #endif
525 #endif
526 elf_file.ehdr.e_version = EV_CURRENT;
527 elf_file.ehdr.e_shoff = sizeof (Elf32_Ehdr);
528 elf_file.ehdr.e_ehsize = sizeof (Elf32_Ehdr);
529 elf_file.ehdr.e_phentsize = sizeof (Elf32_Phdr);
530 elf_file.ehdr.e_shentsize = sizeof (Elf32_Shdr);
531 elf_file.ehdr.e_shnum = nshdr;
532 elf_file.ehdr.e_shstrndx = ESHDR_SHSTRTAB;
533 off = sizeof (elf_file) + nshdr * sizeof (Elf32_Shdr);
534
535 shp = &elf_file.shdr[ESHDR_SHSTRTAB];
536 shp->sh_name = 1; /* DTRACE_SHSTRTAB32[1] = ".shstrtab" */
537 shp->sh_type = SHT_STRTAB;
538 shp->sh_offset = off;
539 shp->sh_size = sizeof (DTRACE_SHSTRTAB32);
540 shp->sh_addralign = sizeof (char);
541 off = roundup2(shp->sh_offset + shp->sh_size, 8);
542
543 shp = &elf_file.shdr[ESHDR_DOF];
544 shp->sh_name = 11; /* DTRACE_SHSTRTAB32[11] = ".SUNW_dof" */
545 shp->sh_flags = SHF_ALLOC;
546 shp->sh_type = SHT_SUNW_dof;
547 shp->sh_offset = off;
548 shp->sh_size = dof->dofh_filesz;
549 shp->sh_addralign = 8;
550 off = shp->sh_offset + shp->sh_size;
551
552 shp = &elf_file.shdr[ESHDR_STRTAB];
553 shp->sh_name = 21; /* DTRACE_SHSTRTAB32[21] = ".strtab" */
554 shp->sh_flags = SHF_ALLOC;
555 shp->sh_type = SHT_STRTAB;
556 shp->sh_offset = off;
557 shp->sh_size = de.de_strlen;
558 shp->sh_addralign = sizeof (char);
559 off = roundup2(shp->sh_offset + shp->sh_size, 4);
560
561 shp = &elf_file.shdr[ESHDR_SYMTAB];
562 shp->sh_name = 29; /* DTRACE_SHSTRTAB32[29] = ".symtab" */
563 shp->sh_flags = SHF_ALLOC;
564 shp->sh_type = SHT_SYMTAB;
565 shp->sh_entsize = sizeof (Elf32_Sym);
566 shp->sh_link = ESHDR_STRTAB;
567 shp->sh_offset = off;
568 shp->sh_info = de.de_global;
569 shp->sh_size = de.de_nsym * sizeof (Elf32_Sym);
570 shp->sh_addralign = 4;
571 off = roundup2(shp->sh_offset + shp->sh_size, 4);
572
573 if (de.de_nrel == 0) {
574 if (dt_write(dtp, fd, &elf_file,
575 sizeof (elf_file)) != sizeof (elf_file) ||
576 PWRITE_SCN(ESHDR_SHSTRTAB, DTRACE_SHSTRTAB32) ||
577 PWRITE_SCN(ESHDR_STRTAB, de.de_strtab) ||
578 PWRITE_SCN(ESHDR_SYMTAB, de.de_sym) ||
579 PWRITE_SCN(ESHDR_DOF, dof)) {
580 ret = dt_set_errno(dtp, errno);
581 }
582 } else {
583 shp = &elf_file.shdr[ESHDR_REL];
584 shp->sh_name = 37; /* DTRACE_SHSTRTAB32[37] = ".rel.SUNW_dof" */
585 shp->sh_flags = 0;
586 shp->sh_type = SHT_REL;
587 shp->sh_entsize = sizeof (de.de_rel[0]);
588 shp->sh_link = ESHDR_SYMTAB;
589 shp->sh_info = ESHDR_DOF;
590 shp->sh_offset = off;
591 shp->sh_size = de.de_nrel * sizeof (de.de_rel[0]);
592 shp->sh_addralign = 4;
593
594 if (dt_write(dtp, fd, &elf_file,
595 sizeof (elf_file)) != sizeof (elf_file) ||
596 PWRITE_SCN(ESHDR_SHSTRTAB, DTRACE_SHSTRTAB32) ||
597 PWRITE_SCN(ESHDR_STRTAB, de.de_strtab) ||
598 PWRITE_SCN(ESHDR_SYMTAB, de.de_sym) ||
599 PWRITE_SCN(ESHDR_REL, de.de_rel) ||
600 PWRITE_SCN(ESHDR_DOF, dof)) {
601 ret = dt_set_errno(dtp, errno);
602 }
603 }
604
605 free(de.de_strtab);
606 free(de.de_sym);
607 free(de.de_rel);
608
609 return (ret);
610 }
611
612 /*
613 * Write out an ELF64 file prologue consisting of a header, section headers,
614 * and a section header string table. The DOF data will follow this prologue
615 * and complete the contents of the given ELF file.
616 */
617 static int
dump_elf64(dtrace_hdl_t * dtp,const dof_hdr_t * dof,int fd)618 dump_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd)
619 {
620 struct {
621 Elf64_Ehdr ehdr;
622 Elf64_Shdr shdr[ESHDR_NUM];
623 } elf_file;
624
625 Elf64_Shdr *shp;
626 Elf64_Off off;
627 dof_elf64_t de;
628 int ret = 0;
629 uint_t nshdr;
630
631 if (prepare_elf64(dtp, dof, &de) != 0)
632 return (-1); /* errno is set for us */
633
634 /*
635 * If there are no relocations, we only need enough sections for
636 * the shstrtab and the DOF.
637 */
638 nshdr = de.de_nrel == 0 ? ESHDR_SYMTAB + 1 : ESHDR_NUM;
639
640 bzero(&elf_file, sizeof (elf_file));
641
642 elf_file.ehdr.e_ident[EI_MAG0] = ELFMAG0;
643 elf_file.ehdr.e_ident[EI_MAG1] = ELFMAG1;
644 elf_file.ehdr.e_ident[EI_MAG2] = ELFMAG2;
645 elf_file.ehdr.e_ident[EI_MAG3] = ELFMAG3;
646 elf_file.ehdr.e_ident[EI_VERSION] = EV_CURRENT;
647 elf_file.ehdr.e_ident[EI_CLASS] = ELFCLASS64;
648 #if BYTE_ORDER == _BIG_ENDIAN
649 elf_file.ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
650 #else
651 elf_file.ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
652 #endif
653 elf_file.ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
654 elf_file.ehdr.e_type = ET_REL;
655 #if defined(__arm__)
656 elf_file.ehdr.e_machine = EM_ARM;
657 #elif defined(__powerpc64__)
658 #if defined(_CALL_ELF) && _CALL_ELF == 2
659 elf_file.ehdr.e_flags = 2;
660 #endif
661 elf_file.ehdr.e_machine = EM_PPC64;
662 #elif defined(__i386) || defined(__amd64)
663 elf_file.ehdr.e_machine = EM_AMD64;
664 #elif defined(__aarch64__)
665 elf_file.ehdr.e_machine = EM_AARCH64;
666 #elif defined(__riscv)
667 elf_file.ehdr.e_machine = EM_RISCV;
668
669 /* Set the ELF flags according to our current ABI */
670 #if defined(__riscv_compressed)
671 elf_file.ehdr.e_flags |= EF_RISCV_RVC;
672 #endif
673 #if defined(__riscv_float_abi_soft)
674 elf_file.ehdr.e_flags |= EF_RISCV_FLOAT_ABI_SOFT;
675 #endif
676 #if defined(__riscv_float_abi_single)
677 elf_file.ehdr.e_flags |= EF_RISCV_FLOAT_ABI_SINGLE;
678 #endif
679 #if defined(__riscv_float_abi_double)
680 elf_file.ehdr.e_flags |= EF_RISCV_FLOAT_ABI_DOUBLE;
681 #endif
682 #endif
683 elf_file.ehdr.e_version = EV_CURRENT;
684 elf_file.ehdr.e_shoff = sizeof (Elf64_Ehdr);
685 elf_file.ehdr.e_ehsize = sizeof (Elf64_Ehdr);
686 elf_file.ehdr.e_phentsize = sizeof (Elf64_Phdr);
687 elf_file.ehdr.e_shentsize = sizeof (Elf64_Shdr);
688 elf_file.ehdr.e_shnum = nshdr;
689 elf_file.ehdr.e_shstrndx = ESHDR_SHSTRTAB;
690 off = sizeof (elf_file) + nshdr * sizeof (Elf64_Shdr);
691
692 shp = &elf_file.shdr[ESHDR_SHSTRTAB];
693 shp->sh_name = 1; /* DTRACE_SHSTRTAB64[1] = ".shstrtab" */
694 shp->sh_type = SHT_STRTAB;
695 shp->sh_offset = off;
696 shp->sh_size = sizeof (DTRACE_SHSTRTAB64);
697 shp->sh_addralign = sizeof (char);
698 off = roundup2(shp->sh_offset + shp->sh_size, 8);
699
700 shp = &elf_file.shdr[ESHDR_DOF];
701 shp->sh_name = 11; /* DTRACE_SHSTRTAB64[11] = ".SUNW_dof" */
702 shp->sh_flags = SHF_ALLOC;
703 shp->sh_type = SHT_SUNW_dof;
704 shp->sh_offset = off;
705 shp->sh_size = dof->dofh_filesz;
706 shp->sh_addralign = 8;
707 off = shp->sh_offset + shp->sh_size;
708
709 shp = &elf_file.shdr[ESHDR_STRTAB];
710 shp->sh_name = 21; /* DTRACE_SHSTRTAB64[21] = ".strtab" */
711 shp->sh_flags = SHF_ALLOC;
712 shp->sh_type = SHT_STRTAB;
713 shp->sh_offset = off;
714 shp->sh_size = de.de_strlen;
715 shp->sh_addralign = sizeof (char);
716 off = roundup2(shp->sh_offset + shp->sh_size, 8);
717
718 shp = &elf_file.shdr[ESHDR_SYMTAB];
719 shp->sh_name = 29; /* DTRACE_SHSTRTAB64[29] = ".symtab" */
720 shp->sh_flags = SHF_ALLOC;
721 shp->sh_type = SHT_SYMTAB;
722 shp->sh_entsize = sizeof (Elf64_Sym);
723 shp->sh_link = ESHDR_STRTAB;
724 shp->sh_offset = off;
725 shp->sh_info = de.de_global;
726 shp->sh_size = de.de_nsym * sizeof (Elf64_Sym);
727 shp->sh_addralign = 8;
728 off = roundup2(shp->sh_offset + shp->sh_size, 8);
729
730 if (de.de_nrel == 0) {
731 if (dt_write(dtp, fd, &elf_file,
732 sizeof (elf_file)) != sizeof (elf_file) ||
733 PWRITE_SCN(ESHDR_SHSTRTAB, DTRACE_SHSTRTAB64) ||
734 PWRITE_SCN(ESHDR_STRTAB, de.de_strtab) ||
735 PWRITE_SCN(ESHDR_SYMTAB, de.de_sym) ||
736 PWRITE_SCN(ESHDR_DOF, dof)) {
737 ret = dt_set_errno(dtp, errno);
738 }
739 } else {
740 shp = &elf_file.shdr[ESHDR_REL];
741 shp->sh_name = 37; /* DTRACE_SHSTRTAB64[37] = ".rel.SUNW_dof" */
742 shp->sh_flags = 0;
743 shp->sh_type = SHT_RELA;
744 shp->sh_entsize = sizeof (de.de_rel[0]);
745 shp->sh_link = ESHDR_SYMTAB;
746 shp->sh_info = ESHDR_DOF;
747 shp->sh_offset = off;
748 shp->sh_size = de.de_nrel * sizeof (de.de_rel[0]);
749 shp->sh_addralign = 8;
750
751 if (dt_write(dtp, fd, &elf_file,
752 sizeof (elf_file)) != sizeof (elf_file) ||
753 PWRITE_SCN(ESHDR_SHSTRTAB, DTRACE_SHSTRTAB64) ||
754 PWRITE_SCN(ESHDR_STRTAB, de.de_strtab) ||
755 PWRITE_SCN(ESHDR_SYMTAB, de.de_sym) ||
756 PWRITE_SCN(ESHDR_REL, de.de_rel) ||
757 PWRITE_SCN(ESHDR_DOF, dof)) {
758 ret = dt_set_errno(dtp, errno);
759 }
760 }
761
762 free(de.de_strtab);
763 free(de.de_sym);
764 free(de.de_rel);
765
766 return (ret);
767 }
768
769 static int
dt_symtab_lookup(Elf_Data * data_sym,int start,int end,uintptr_t addr,uint_t shn,GElf_Sym * sym,int uses_funcdesc,Elf * elf)770 dt_symtab_lookup(Elf_Data *data_sym, int start, int end, uintptr_t addr,
771 uint_t shn, GElf_Sym *sym, int uses_funcdesc, Elf *elf)
772 {
773 Elf64_Addr symval;
774 Elf_Scn *opd_scn;
775 Elf_Data *opd_desc;
776 int i;
777
778 for (i = start; i < end && gelf_getsym(data_sym, i, sym) != NULL; i++) {
779 if (GELF_ST_TYPE(sym->st_info) == STT_FUNC) {
780 symval = sym->st_value;
781 if (uses_funcdesc) {
782 opd_scn = elf_getscn(elf, sym->st_shndx);
783 opd_desc = elf_rawdata(opd_scn, NULL);
784 symval =
785 *(uint64_t*)((char *)opd_desc->d_buf + symval);
786 }
787 if ((uses_funcdesc || shn == sym->st_shndx) &&
788 symval <= addr && addr < symval + sym->st_size)
789 return (0);
790 }
791 }
792
793 return (-1);
794 }
795
796 #if defined(__aarch64__)
797 #define DT_OP_NOP 0xd503201f
798 #define DT_OP_RET 0xd65f03c0
799 #define DT_OP_CALL26 0x94000000
800 #define DT_OP_JUMP26 0x14000000
801 #define DT_REL_NONE R_AARCH64_NONE
802
803 static int
dt_modtext(dtrace_hdl_t * dtp,char * p,int isenabled,GElf_Rela * rela,uint32_t * off)804 dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
805 uint32_t *off)
806 {
807 uint32_t *ip;
808
809 /*
810 * Ensure that the offset is aligned on an instruction boundary.
811 */
812 if ((rela->r_offset & (sizeof (uint32_t) - 1)) != 0)
813 return (-1);
814
815 /*
816 * We only know about some specific relocation types.
817 * We also recognize relocation type NONE, since that gets used for
818 * relocations of USDT probes, and we might be re-processing a file.
819 */
820 if (GELF_R_TYPE(rela->r_info) != R_AARCH64_CALL26 &&
821 GELF_R_TYPE(rela->r_info) != R_AARCH64_JUMP26 &&
822 GELF_R_TYPE(rela->r_info) != R_AARCH64_NONE)
823 return (-1);
824
825 ip = (uint32_t *)(p + rela->r_offset);
826
827 /*
828 * We may have already processed this object file in an earlier linker
829 * invocation. Check to see if the present instruction sequence matches
830 * the one we would install below.
831 */
832 if (ip[0] == DT_OP_NOP || ip[0] == DT_OP_RET)
833 return (0);
834
835 /*
836 * We only expect call instructions with a displacement of 0, or a jump
837 * instruction acting as a tail call.
838 */
839 if (ip[0] != DT_OP_CALL26 && ip[0] != DT_OP_JUMP26) {
840 dt_dprintf("found %x instead of a call or jmp instruction at "
841 "%llx\n", ip[0], (u_longlong_t)rela->r_offset);
842 return (-1);
843 }
844
845 /*
846 * On arm64, we do not have to differentiate between regular probes and
847 * is-enabled probes. Both cases are encoded as a regular branch for
848 * non-tail call locations, and a jump for tail call locations. Calls
849 * are to be converted into a no-op whereas jumps should become a
850 * return.
851 */
852 if (ip[0] == DT_OP_CALL26)
853 ip[0] = DT_OP_NOP;
854 else
855 ip[0] = DT_OP_RET;
856
857 return (0);
858 }
859 #elif defined(__arm__)
860 #define DT_REL_NONE R_ARM_NONE
861
862 static int
dt_modtext(dtrace_hdl_t * dtp,char * p,int isenabled,GElf_Rela * rela,uint32_t * off)863 dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
864 uint32_t *off)
865 {
866 printf("%s:%s(%d): arm not implemented\n", __FUNCTION__, __FILE__,
867 __LINE__);
868 return (-1);
869 }
870 #elif defined(__powerpc__)
871 /* The sentinel is 'xor r3,r3,r3'. */
872 #define DT_OP_XOR_R3 0x7c631a78
873
874 #define DT_OP_NOP 0x60000000
875 #define DT_OP_BLR 0x4e800020
876
877 /* This captures all forms of branching to address. */
878 #define DT_IS_BRANCH(inst) ((inst & 0xfc000000) == 0x48000000)
879 #define DT_IS_BL(inst) (DT_IS_BRANCH(inst) && (inst & 0x01))
880
881 #define DT_REL_NONE R_PPC_NONE
882
883 static int
dt_modtext(dtrace_hdl_t * dtp,char * p,int isenabled,GElf_Rela * rela,uint32_t * off)884 dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
885 uint32_t *off)
886 {
887 uint32_t *ip;
888
889 if ((rela->r_offset & (sizeof (uint32_t) - 1)) != 0)
890 return (-1);
891
892 /*LINTED*/
893 ip = (uint32_t *)(p + rela->r_offset);
894
895 /*
896 * We only know about some specific relocation types.
897 */
898 if (GELF_R_TYPE(rela->r_info) != R_PPC_REL24 &&
899 GELF_R_TYPE(rela->r_info) != R_PPC_PLTREL24 &&
900 GELF_R_TYPE(rela->r_info) != R_PPC_NONE)
901 return (-1);
902
903 /*
904 * We may have already processed this object file in an earlier linker
905 * invocation. Check to see if the present instruction sequence matches
906 * the one we would install below.
907 */
908 if (isenabled) {
909 if (ip[0] == DT_OP_XOR_R3) {
910 (*off) += sizeof (ip[0]);
911 return (0);
912 }
913 } else {
914 if (ip[0] == DT_OP_NOP) {
915 (*off) += sizeof (ip[0]);
916 return (0);
917 }
918 }
919
920 /*
921 * We only expect branch to address instructions.
922 */
923 if (!DT_IS_BRANCH(ip[0])) {
924 dt_dprintf("found %x instead of a branch instruction at %llx\n",
925 ip[0], (u_longlong_t)rela->r_offset);
926 return (-1);
927 }
928
929 if (isenabled) {
930 /*
931 * It would necessarily indicate incorrect usage if an is-
932 * enabled probe were tail-called so flag that as an error.
933 * It's also potentially (very) tricky to handle gracefully,
934 * but could be done if this were a desired use scenario.
935 */
936 if (!DT_IS_BL(ip[0])) {
937 dt_dprintf("tail call to is-enabled probe at %llx\n",
938 (u_longlong_t)rela->r_offset);
939 return (-1);
940 }
941
942 ip[0] = DT_OP_XOR_R3;
943 (*off) += sizeof (ip[0]);
944 } else {
945 if (DT_IS_BL(ip[0]))
946 ip[0] = DT_OP_NOP;
947 else
948 ip[0] = DT_OP_BLR;
949 }
950
951 return (0);
952 }
953 #elif defined(__riscv)
954 #define DT_OP_NOP 0x00000013 /* addi x0, x0, 0 */
955 #define DT_OP_RET 0x00008067 /* jalr x0, x1, 0 */
956 #define DT_OP_IS_AUIPC(op) (((op) & 0x7f) == 0x17)
957 #define DT_OP_IS_JALR(op) (((op) & 0x707f) == 0x67)
958 #define DT_OP_JALR_CALL 0x000080e7 /* jalr x1, x1, 0 */
959 #define DT_OP_JALR_TAIL 0x00030067 /* jalr x0, x6, 0 */
960 #define DT_REL_NONE R_RISCV_NONE
961
962 static int
dt_modtext(dtrace_hdl_t * dtp,char * p,int isenabled,GElf_Rela * rela,uint32_t * off)963 dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
964 uint32_t *off)
965 {
966 uint32_t *ip;
967
968 /*
969 * XXX: this implementation is untested, but should serve as a decent
970 * starting point.
971 */
972
973 /*
974 * Ensure that the offset is aligned on a compressed-instruction
975 * boundary.
976 */
977 if ((rela->r_offset & (sizeof (uint16_t) - 1)) != 0)
978 return (-1);
979
980 /*
981 * We only know about some specific relocation types.
982 * We also recognize relocation type NONE, since that gets used for
983 * relocations of USDT probes, and we might be re-processing a file.
984 */
985 if (GELF_R_TYPE(rela->r_info) != R_RISCV_CALL &&
986 GELF_R_TYPE(rela->r_info) != R_RISCV_CALL_PLT &&
987 GELF_R_TYPE(rela->r_info) != R_RISCV_NONE)
988 return (-1);
989
990 ip = (uint32_t *)(p + rela->r_offset);
991
992 /*
993 * We may have already processed this object file in an earlier linker
994 * invocation. Check to see if the present instruction sequence matches
995 * the one we would install below.
996 */
997 if (ip[0] == DT_OP_NOP && (ip[1] == DT_OP_NOP || ip[1] == DT_OP_RET))
998 return (0);
999
1000 /*
1001 * We expect a auipc+jalr pair, either from a call or a tail.
1002 * - call: auipc x1 0; jalr x1, x1, 0
1003 * - tail: auipc x6 0; jalr x0, x6, 0
1004 */
1005 if (!DT_OP_IS_AUIPC(ip[0]) || !DT_OP_IS_JALR(ip[1]))
1006 return (-1);
1007
1008 /*
1009 * On riscv, we do not have to differentiate between regular probes and
1010 * is-enabled probes. Calls are to be converted into a no-op whereas
1011 * tail calls should become a return.
1012 */
1013 if (ip[1] == DT_OP_JALR_CALL) {
1014 ip[0] = DT_OP_NOP;
1015 ip[1] = DT_OP_NOP;
1016 } else {
1017 ip[0] = DT_OP_NOP;
1018 ip[1] = DT_OP_RET;
1019 }
1020
1021 return (0);
1022 }
1023
1024 #elif defined(__i386) || defined(__amd64)
1025
1026 #define DT_OP_NOP 0x90
1027 #define DT_OP_RET 0xc3
1028 #define DT_OP_CALL 0xe8
1029 #define DT_OP_JMP32 0xe9
1030 #define DT_OP_REX_RAX 0x48
1031 #define DT_OP_XOR_EAX_0 0x33
1032 #define DT_OP_XOR_EAX_1 0xc0
1033
1034 #define DT_REL_NONE R_386_NONE
1035
1036 static int
dt_modtext(dtrace_hdl_t * dtp,char * p,int isenabled,GElf_Rela * rela,uint32_t * off)1037 dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
1038 uint32_t *off)
1039 {
1040 uint8_t *ip = (uint8_t *)(p + rela->r_offset - 1);
1041 uint8_t ret;
1042
1043 /*
1044 * On x86, the first byte of the instruction is the call opcode and
1045 * the next four bytes are the 32-bit address; the relocation is for
1046 * the address operand. We back up the offset to the first byte of
1047 * the instruction. For is-enabled probes, we later advance the offset
1048 * so that it hits the first nop in the instruction sequence.
1049 */
1050 (*off) -= 1;
1051
1052 /*
1053 * We only know about some specific relocation types. Luckily
1054 * these types have the same values on both 32-bit and 64-bit
1055 * x86 architectures.
1056 */
1057 if (GELF_R_TYPE(rela->r_info) != R_386_PC32 &&
1058 GELF_R_TYPE(rela->r_info) != R_386_PLT32 &&
1059 GELF_R_TYPE(rela->r_info) != R_386_NONE)
1060 return (-1);
1061
1062 /*
1063 * We may have already processed this object file in an earlier linker
1064 * invocation. Check to see if the present instruction sequence matches
1065 * the one we would install. For is-enabled probes, we advance the
1066 * offset to the first nop instruction in the sequence to match the
1067 * text modification code below.
1068 */
1069 if (!isenabled) {
1070 if ((ip[0] == DT_OP_NOP || ip[0] == DT_OP_RET) &&
1071 ip[1] == DT_OP_NOP && ip[2] == DT_OP_NOP &&
1072 ip[3] == DT_OP_NOP && ip[4] == DT_OP_NOP)
1073 return (0);
1074 } else if (dtp->dt_oflags & DTRACE_O_LP64) {
1075 if (ip[0] == DT_OP_REX_RAX &&
1076 ip[1] == DT_OP_XOR_EAX_0 && ip[2] == DT_OP_XOR_EAX_1 &&
1077 (ip[3] == DT_OP_NOP || ip[3] == DT_OP_RET) &&
1078 ip[4] == DT_OP_NOP) {
1079 (*off) += 3;
1080 return (0);
1081 }
1082 } else {
1083 if (ip[0] == DT_OP_XOR_EAX_0 && ip[1] == DT_OP_XOR_EAX_1 &&
1084 (ip[2] == DT_OP_NOP || ip[2] == DT_OP_RET) &&
1085 ip[3] == DT_OP_NOP && ip[4] == DT_OP_NOP) {
1086 (*off) += 2;
1087 return (0);
1088 }
1089 }
1090
1091 /*
1092 * We expect either a call instrution with a 32-bit displacement or a
1093 * jmp instruction with a 32-bit displacement acting as a tail-call.
1094 */
1095 if (ip[0] != DT_OP_CALL && ip[0] != DT_OP_JMP32) {
1096 dt_dprintf("found %x instead of a call or jmp instruction at "
1097 "%llx\n", ip[0], (u_longlong_t)rela->r_offset);
1098 return (-1);
1099 }
1100
1101 ret = (ip[0] == DT_OP_JMP32) ? DT_OP_RET : DT_OP_NOP;
1102
1103 /*
1104 * Establish the instruction sequence -- all nops for probes, and an
1105 * instruction to clear the return value register (%eax/%rax) followed
1106 * by nops for is-enabled probes. For is-enabled probes, we advance
1107 * the offset to the first nop. This isn't stricly necessary but makes
1108 * for more readable disassembly when the probe is enabled.
1109 */
1110 if (!isenabled) {
1111 ip[0] = ret;
1112 ip[1] = DT_OP_NOP;
1113 ip[2] = DT_OP_NOP;
1114 ip[3] = DT_OP_NOP;
1115 ip[4] = DT_OP_NOP;
1116 } else if (dtp->dt_oflags & DTRACE_O_LP64) {
1117 ip[0] = DT_OP_REX_RAX;
1118 ip[1] = DT_OP_XOR_EAX_0;
1119 ip[2] = DT_OP_XOR_EAX_1;
1120 ip[3] = ret;
1121 ip[4] = DT_OP_NOP;
1122 (*off) += 3;
1123 } else {
1124 ip[0] = DT_OP_XOR_EAX_0;
1125 ip[1] = DT_OP_XOR_EAX_1;
1126 ip[2] = ret;
1127 ip[3] = DT_OP_NOP;
1128 ip[4] = DT_OP_NOP;
1129 (*off) += 2;
1130 }
1131
1132 return (0);
1133 }
1134
1135 #else
1136 #error unknown ISA
1137 #endif
1138
1139 /*PRINTFLIKE5*/
1140 static int
dt_link_error(dtrace_hdl_t * dtp,Elf * elf,int fd,dt_link_pair_t * bufs,const char * format,...)1141 dt_link_error(dtrace_hdl_t *dtp, Elf *elf, int fd, dt_link_pair_t *bufs,
1142 const char *format, ...)
1143 {
1144 va_list ap;
1145 dt_link_pair_t *pair;
1146
1147 va_start(ap, format);
1148 dt_set_errmsg(dtp, NULL, NULL, NULL, 0, format, ap);
1149 va_end(ap);
1150
1151 if (elf != NULL)
1152 (void) elf_end(elf);
1153
1154 if (fd >= 0)
1155 (void) close(fd);
1156
1157 while ((pair = bufs) != NULL) {
1158 bufs = pair->dlp_next;
1159 dt_free(dtp, pair->dlp_str);
1160 dt_free(dtp, pair->dlp_sym);
1161 dt_free(dtp, pair);
1162 }
1163
1164 return (dt_set_errno(dtp, EDT_COMPILER));
1165 }
1166
1167 /*
1168 * Provide a unique identifier used when adding global symbols to an object.
1169 * This is the FNV-1a hash of an absolute path for the file.
1170 */
1171 static unsigned int
hash_obj(const char * obj,int fd)1172 hash_obj(const char *obj, int fd)
1173 {
1174 char path[PATH_MAX];
1175 unsigned int h;
1176
1177 if (realpath(obj, path) == NULL)
1178 return (-1);
1179
1180 for (h = 2166136261u, obj = &path[0]; *obj != '\0'; obj++)
1181 h = (h ^ *obj) * 16777619;
1182 h &= 0x7fffffff;
1183 return (h);
1184 }
1185
1186 static int
process_obj(dtrace_hdl_t * dtp,const char * obj,int * eprobesp)1187 process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
1188 {
1189 static const char dt_prefix[] = "__dtrace";
1190 static const char dt_enabled[] = "enabled";
1191 static const char dt_symprefix[] = "$dtrace";
1192 static const char dt_symfmt[] = "%s%u.%s";
1193 static const char dt_weaksymfmt[] = "%s.%s";
1194 char probename[DTRACE_NAMELEN];
1195 int fd, i, ndx, eprobe, uses_funcdesc = 0, mod = 0;
1196 Elf *elf = NULL;
1197 GElf_Ehdr ehdr;
1198 Elf_Scn *scn_rel, *scn_sym, *scn_str, *scn_tgt;
1199 Elf_Data *data_rel, *data_sym, *data_str, *data_tgt;
1200 GElf_Shdr shdr_rel, shdr_sym, shdr_str, shdr_tgt;
1201 GElf_Sym rsym, fsym, dsym;
1202 GElf_Rela rela;
1203 char *s, *p, *r;
1204 char pname[DTRACE_PROVNAMELEN];
1205 dt_provider_t *pvp;
1206 dt_probe_t *prp;
1207 uint32_t off, eclass, emachine1, emachine2;
1208 size_t symsize, osym, nsym, isym, istr, len;
1209 unsigned int objkey;
1210 dt_link_pair_t *pair, *bufs = NULL;
1211 dt_strtab_t *strtab;
1212 void *tmp;
1213
1214 if ((fd = open64(obj, O_RDWR)) == -1) {
1215 return (dt_link_error(dtp, elf, fd, bufs,
1216 "failed to open %s: %s", obj, strerror(errno)));
1217 }
1218
1219 if ((elf = elf_begin(fd, ELF_C_RDWR, NULL)) == NULL) {
1220 return (dt_link_error(dtp, elf, fd, bufs,
1221 "failed to process %s: %s", obj, elf_errmsg(elf_errno())));
1222 }
1223
1224 switch (elf_kind(elf)) {
1225 case ELF_K_ELF:
1226 break;
1227 case ELF_K_AR:
1228 return (dt_link_error(dtp, elf, fd, bufs, "archives are not "
1229 "permitted; use the contents of the archive instead: %s",
1230 obj));
1231 default:
1232 return (dt_link_error(dtp, elf, fd, bufs,
1233 "invalid file type: %s", obj));
1234 }
1235
1236 if (gelf_getehdr(elf, &ehdr) == NULL) {
1237 return (dt_link_error(dtp, elf, fd, bufs, "corrupt file: %s",
1238 obj));
1239 }
1240
1241 if (dtp->dt_oflags & DTRACE_O_LP64) {
1242 eclass = ELFCLASS64;
1243 #if defined(__powerpc__)
1244 emachine1 = emachine2 = EM_PPC64;
1245 #if !defined(_CALL_ELF) || _CALL_ELF == 1
1246 uses_funcdesc = 1;
1247 #endif
1248 #elif defined(__i386) || defined(__amd64)
1249 emachine1 = emachine2 = EM_AMD64;
1250 #elif defined(__aarch64__)
1251 emachine1 = emachine2 = EM_AARCH64;
1252 #elif defined(__riscv)
1253 emachine1 = emachine2 = EM_RISCV;
1254 #endif
1255 symsize = sizeof (Elf64_Sym);
1256 } else {
1257 eclass = ELFCLASS32;
1258 #if defined(__arm__)
1259 emachine1 = emachine2 = EM_ARM;
1260 #elif defined(__powerpc__)
1261 emachine1 = emachine2 = EM_PPC;
1262 #elif defined(__i386) || defined(__amd64)
1263 emachine1 = emachine2 = EM_386;
1264 #endif
1265 symsize = sizeof (Elf32_Sym);
1266 }
1267
1268 if (ehdr.e_ident[EI_CLASS] != eclass) {
1269 return (dt_link_error(dtp, elf, fd, bufs,
1270 "incorrect ELF class for object file: %s", obj));
1271 }
1272
1273 if (ehdr.e_machine != emachine1 && ehdr.e_machine != emachine2) {
1274 return (dt_link_error(dtp, elf, fd, bufs,
1275 "incorrect ELF machine type for object file: %s", obj));
1276 }
1277
1278 /*
1279 * We use this token as a relatively unique handle for this file on the
1280 * system in order to disambiguate potential conflicts between files of
1281 * the same name which contain identially named local symbols.
1282 */
1283 if ((objkey = hash_obj(obj, fd)) == (unsigned int)-1)
1284 return (dt_link_error(dtp, elf, fd, bufs,
1285 "failed to generate unique key for object file: %s", obj));
1286
1287 scn_rel = NULL;
1288 while ((scn_rel = elf_nextscn(elf, scn_rel)) != NULL) {
1289 if (gelf_getshdr(scn_rel, &shdr_rel) == NULL)
1290 goto err;
1291
1292 /*
1293 * Skip any non-relocation sections.
1294 */
1295 if (shdr_rel.sh_type != SHT_RELA && shdr_rel.sh_type != SHT_REL)
1296 continue;
1297
1298 if ((data_rel = elf_getdata(scn_rel, NULL)) == NULL)
1299 goto err;
1300
1301 /*
1302 * Grab the section, section header and section data for the
1303 * symbol table that this relocation section references.
1304 */
1305 if ((scn_sym = elf_getscn(elf, shdr_rel.sh_link)) == NULL ||
1306 gelf_getshdr(scn_sym, &shdr_sym) == NULL ||
1307 (data_sym = elf_getdata(scn_sym, NULL)) == NULL)
1308 goto err;
1309
1310 /*
1311 * Ditto for that symbol table's string table.
1312 */
1313 if ((scn_str = elf_getscn(elf, shdr_sym.sh_link)) == NULL ||
1314 gelf_getshdr(scn_str, &shdr_str) == NULL ||
1315 (data_str = elf_getdata(scn_str, NULL)) == NULL)
1316 goto err;
1317
1318 /*
1319 * Grab the section, section header and section data for the
1320 * target section for the relocations. For the relocations
1321 * we're looking for -- this will typically be the text of the
1322 * object file.
1323 */
1324 if ((scn_tgt = elf_getscn(elf, shdr_rel.sh_info)) == NULL ||
1325 gelf_getshdr(scn_tgt, &shdr_tgt) == NULL ||
1326 (data_tgt = elf_getdata(scn_tgt, NULL)) == NULL)
1327 goto err;
1328
1329 /*
1330 * We're looking for relocations to symbols matching this form:
1331 *
1332 * __dtrace[enabled]_<prov>___<probe>
1333 *
1334 * For the generated object, we need to record the location
1335 * identified by the relocation, and create a new relocation
1336 * in the generated object that will be resolved at link time
1337 * to the location of the function in which the probe is
1338 * embedded. In the target object, we change the matched symbol
1339 * so that it will be ignored at link time, and we modify the
1340 * target (text) section to replace the call instruction with
1341 * one or more nops.
1342 *
1343 * To avoid runtime overhead, the relocations added to the
1344 * generated object should be resolved at static link time. We
1345 * therefore create aliases for the functions that contain
1346 * probes. An alias is global (so that the relocation from the
1347 * generated object can be resolved), and hidden (so that its
1348 * address is known at static link time). Such aliases have this
1349 * form:
1350 *
1351 * $dtrace<key>.<function>
1352 *
1353 * We take a first pass through all the relocations to
1354 * populate our string table and count the number of extra
1355 * symbols we'll require.
1356 *
1357 * We also handle the case where the object has already been
1358 * processed, to support incremental rebuilds. Relocations
1359 * of interest are converted to type NONE, but all information
1360 * needed to reconstruct the output DOF is retained.
1361 */
1362 strtab = dt_strtab_create(1);
1363 nsym = 0;
1364 isym = data_sym->d_size / symsize;
1365 istr = data_str->d_size;
1366
1367 for (i = 0; i < shdr_rel.sh_size / shdr_rel.sh_entsize; i++) {
1368 if (shdr_rel.sh_type == SHT_RELA) {
1369 if (gelf_getrela(data_rel, i, &rela) == NULL)
1370 continue;
1371 } else {
1372 GElf_Rel rel;
1373 if (gelf_getrel(data_rel, i, &rel) == NULL)
1374 continue;
1375 rela.r_offset = rel.r_offset;
1376 rela.r_info = rel.r_info;
1377 rela.r_addend = 0;
1378 }
1379
1380 if (gelf_getsym(data_sym, GELF_R_SYM(rela.r_info),
1381 &rsym) == NULL) {
1382 dt_strtab_destroy(strtab);
1383 goto err;
1384 }
1385
1386 s = (char *)data_str->d_buf + rsym.st_name;
1387
1388 if (strncmp(s, dt_prefix, sizeof (dt_prefix) - 1) != 0)
1389 continue;
1390
1391 if (dt_symtab_lookup(data_sym, 0, isym, rela.r_offset,
1392 shdr_rel.sh_info, &fsym, uses_funcdesc,
1393 elf) != 0) {
1394 dt_strtab_destroy(strtab);
1395 goto err;
1396 }
1397
1398 if (fsym.st_name > data_str->d_size) {
1399 dt_strtab_destroy(strtab);
1400 goto err;
1401 }
1402
1403 s = (char *)data_str->d_buf + fsym.st_name;
1404
1405 /*
1406 * If this symbol isn't of type function, we've really
1407 * driven off the rails or the object file is corrupt.
1408 */
1409 if (GELF_ST_TYPE(fsym.st_info) != STT_FUNC) {
1410 dt_strtab_destroy(strtab);
1411 return (dt_link_error(dtp, elf, fd, bufs,
1412 "expected %s to be of type function", s));
1413 }
1414
1415 /*
1416 * Aliases of weak symbols don't get a uniquifier.
1417 */
1418 if (GELF_ST_BIND(fsym.st_info) == STB_WEAK) {
1419 len = snprintf(NULL, 0, dt_weaksymfmt,
1420 dt_symprefix, s) + 1;
1421 } else {
1422 len = snprintf(NULL, 0, dt_symfmt, dt_symprefix,
1423 objkey, s) + 1;
1424 }
1425 if ((p = dt_alloc(dtp, len)) == NULL) {
1426 dt_strtab_destroy(strtab);
1427 goto err;
1428 }
1429 if (GELF_ST_BIND(fsym.st_info) == STB_WEAK) {
1430 (void) snprintf(p, len, dt_weaksymfmt,
1431 dt_symprefix, s);
1432 } else {
1433 (void) snprintf(p, len, dt_symfmt, dt_symprefix,
1434 objkey, s);
1435 }
1436
1437 if (dt_strtab_index(strtab, p) == -1) {
1438 /*
1439 * Do not add new symbols if this object file
1440 * has already been processed.
1441 */
1442 if (GELF_R_TYPE(rela.r_info) != DT_REL_NONE)
1443 nsym++;
1444 (void) dt_strtab_insert(strtab, p);
1445 }
1446
1447 dt_free(dtp, p);
1448 }
1449
1450 /*
1451 * If any new probes were found, allocate the additional space
1452 * for the symbol table and string table, copying the old data
1453 * into the new buffers, and marking the buffers as dirty. We
1454 * inject those newly allocated buffers into the libelf data
1455 * structures, but are still responsible for freeing them once
1456 * we're done with the elf handle.
1457 */
1458 osym = isym;
1459 if (nsym > 0) {
1460 /*
1461 * The first byte of the string table is reserved for
1462 * the \0 entry.
1463 */
1464 len = dt_strtab_size(strtab) - 1;
1465
1466 assert(len > 0);
1467 assert(dt_strtab_index(strtab, "") == 0);
1468
1469 dt_strtab_destroy(strtab);
1470
1471 if ((pair = dt_alloc(dtp, sizeof (*pair))) == NULL)
1472 goto err;
1473
1474 if ((pair->dlp_str = dt_alloc(dtp, data_str->d_size +
1475 len)) == NULL) {
1476 dt_free(dtp, pair);
1477 goto err;
1478 }
1479
1480 if ((pair->dlp_sym = dt_alloc(dtp, data_sym->d_size +
1481 nsym * symsize)) == NULL) {
1482 dt_free(dtp, pair->dlp_str);
1483 dt_free(dtp, pair);
1484 goto err;
1485 }
1486
1487 pair->dlp_next = bufs;
1488 bufs = pair;
1489
1490 bcopy(data_str->d_buf, pair->dlp_str, data_str->d_size);
1491 tmp = data_str->d_buf;
1492 data_str->d_buf = pair->dlp_str;
1493 pair->dlp_str = tmp;
1494 data_str->d_size += len;
1495 (void) elf_flagdata(data_str, ELF_C_SET, ELF_F_DIRTY);
1496
1497 shdr_str.sh_size += len;
1498 (void) gelf_update_shdr(scn_str, &shdr_str);
1499
1500 bcopy(data_sym->d_buf, pair->dlp_sym, data_sym->d_size);
1501 tmp = data_sym->d_buf;
1502 data_sym->d_buf = pair->dlp_sym;
1503 pair->dlp_sym = tmp;
1504 data_sym->d_size += nsym * symsize;
1505 (void) elf_flagdata(data_sym, ELF_C_SET, ELF_F_DIRTY);
1506
1507 shdr_sym.sh_size += nsym * symsize;
1508 (void) gelf_update_shdr(scn_sym, &shdr_sym);
1509
1510 nsym += isym;
1511 } else if (dt_strtab_empty(strtab)) {
1512 dt_strtab_destroy(strtab);
1513 continue;
1514 }
1515
1516 /*
1517 * Now that the tables have been allocated, perform the
1518 * modifications described above.
1519 */
1520 for (i = 0; i < shdr_rel.sh_size / shdr_rel.sh_entsize; i++) {
1521 if (shdr_rel.sh_type == SHT_RELA) {
1522 if (gelf_getrela(data_rel, i, &rela) == NULL)
1523 continue;
1524 } else {
1525 GElf_Rel rel;
1526 if (gelf_getrel(data_rel, i, &rel) == NULL)
1527 continue;
1528 rela.r_offset = rel.r_offset;
1529 rela.r_info = rel.r_info;
1530 rela.r_addend = 0;
1531 }
1532
1533 ndx = GELF_R_SYM(rela.r_info);
1534
1535 if (gelf_getsym(data_sym, ndx, &rsym) == NULL ||
1536 rsym.st_name > data_str->d_size)
1537 goto err;
1538
1539 s = (char *)data_str->d_buf + rsym.st_name;
1540
1541 if (strncmp(s, dt_prefix, sizeof (dt_prefix) - 1) != 0)
1542 continue;
1543
1544 s += sizeof (dt_prefix) - 1;
1545
1546 /*
1547 * Check to see if this is an 'is-enabled' check as
1548 * opposed to a normal probe.
1549 */
1550 if (strncmp(s, dt_enabled,
1551 sizeof (dt_enabled) - 1) == 0) {
1552 s += sizeof (dt_enabled) - 1;
1553 eprobe = 1;
1554 *eprobesp = 1;
1555 dt_dprintf("is-enabled probe\n");
1556 } else {
1557 eprobe = 0;
1558 dt_dprintf("normal probe\n");
1559 }
1560
1561 if (*s++ != '_')
1562 goto err;
1563
1564 if ((p = strstr(s, "___")) == NULL ||
1565 p - s >= sizeof (pname))
1566 goto err;
1567
1568 bcopy(s, pname, p - s);
1569 pname[p - s] = '\0';
1570
1571 if (dt_symtab_lookup(data_sym, osym, isym,
1572 rela.r_offset, shdr_rel.sh_info, &fsym,
1573 uses_funcdesc, elf) == 0) {
1574 if (fsym.st_name > data_str->d_size)
1575 goto err;
1576
1577 r = s = (char *) data_str->d_buf + fsym.st_name;
1578 assert(strstr(s, dt_symprefix) == s);
1579 s = strchr(s, '.') + 1;
1580 } else if (dt_symtab_lookup(data_sym, 0, osym,
1581 rela.r_offset, shdr_rel.sh_info, &fsym,
1582 uses_funcdesc, elf) == 0) {
1583 u_int bind;
1584
1585 bind = GELF_ST_BIND(fsym.st_info) == STB_WEAK ?
1586 STB_WEAK : STB_GLOBAL;
1587 s = (char *) data_str->d_buf + fsym.st_name;
1588 if (GELF_R_TYPE(rela.r_info) != DT_REL_NONE) {
1589 /*
1590 * Emit an alias for the symbol. It
1591 * needs to be non-preemptible so that
1592 * .SUNW_dof relocations may be resolved
1593 * at static link time. Aliases of weak
1594 * symbols are given a non-unique name
1595 * so that they may be merged by the
1596 * linker.
1597 */
1598 dsym = fsym;
1599 dsym.st_name = istr;
1600 dsym.st_info = GELF_ST_INFO(bind,
1601 STT_FUNC);
1602 dsym.st_other =
1603 GELF_ST_VISIBILITY(STV_HIDDEN);
1604 (void) gelf_update_sym(data_sym, isym,
1605 &dsym);
1606 isym++;
1607 assert(isym <= nsym);
1608
1609 r = (char *) data_str->d_buf + istr;
1610 if (bind == STB_WEAK) {
1611 istr += sprintf(r,
1612 dt_weaksymfmt, dt_symprefix,
1613 s);
1614 } else {
1615 istr += sprintf(r, dt_symfmt,
1616 dt_symprefix, objkey, s);
1617 }
1618 istr++;
1619 } else {
1620 if (bind == STB_WEAK) {
1621 (void) asprintf(&r,
1622 dt_weaksymfmt, dt_symprefix,
1623 s);
1624 } else {
1625 (void) asprintf(&r, dt_symfmt,
1626 dt_symprefix, objkey, s);
1627 }
1628 }
1629 } else {
1630 goto err;
1631 }
1632
1633 if ((pvp = dt_provider_lookup(dtp, pname)) == NULL) {
1634 return (dt_link_error(dtp, elf, fd, bufs,
1635 "no such provider %s", pname));
1636 }
1637
1638 if (strlcpy(probename, p + 3, sizeof (probename)) >=
1639 sizeof (probename))
1640 return (dt_link_error(dtp, elf, fd, bufs,
1641 "invalid probe name %s", probename));
1642 (void) strhyphenate(probename);
1643 if ((prp = dt_probe_lookup(pvp, probename)) == NULL)
1644 return (dt_link_error(dtp, elf, fd, bufs,
1645 "no such probe %s", probename));
1646
1647 assert(fsym.st_value <= rela.r_offset);
1648
1649 off = rela.r_offset - fsym.st_value;
1650 if (dt_modtext(dtp, data_tgt->d_buf, eprobe,
1651 &rela, &off) != 0)
1652 goto err;
1653
1654 if (dt_probe_define(pvp, prp, s, r, off, eprobe) != 0) {
1655 return (dt_link_error(dtp, elf, fd, bufs,
1656 "failed to allocate space for probe"));
1657 }
1658
1659 /*
1660 * We are done with this relocation, but it must be
1661 * preserved in order to support incremental rebuilds.
1662 */
1663 if (shdr_rel.sh_type == SHT_RELA) {
1664 rela.r_info = GELF_R_INFO(
1665 GELF_R_SYM(rela.r_info), DT_REL_NONE);
1666 (void) gelf_update_rela(data_rel, i, &rela);
1667 } else {
1668 GElf_Rel rel;
1669 rel.r_offset = rela.r_offset;
1670 rel.r_info = GELF_R_INFO(
1671 GELF_R_SYM(rela.r_info), DT_REL_NONE);
1672 (void) gelf_update_rel(data_rel, i, &rel);
1673 }
1674
1675 mod = 1;
1676 (void) elf_flagdata(data_tgt, ELF_C_SET, ELF_F_DIRTY);
1677
1678 /*
1679 * This symbol may already have been marked to
1680 * be ignored by another relocation referencing
1681 * the same symbol or if this object file has
1682 * already been processed by an earlier link
1683 * invocation.
1684 */
1685 if (rsym.st_shndx != SHN_ABS) {
1686 rsym.st_info = GELF_ST_INFO(STB_WEAK, STT_FUNC);
1687 rsym.st_shndx = SHN_ABS;
1688 (void) gelf_update_sym(data_sym, ndx, &rsym);
1689 }
1690 }
1691 }
1692
1693 if (mod && elf_update(elf, ELF_C_WRITE) == -1)
1694 goto err;
1695
1696 (void) elf_end(elf);
1697 (void) close(fd);
1698
1699 while ((pair = bufs) != NULL) {
1700 bufs = pair->dlp_next;
1701 dt_free(dtp, pair->dlp_str);
1702 dt_free(dtp, pair->dlp_sym);
1703 dt_free(dtp, pair);
1704 }
1705
1706 return (0);
1707
1708 err:
1709 return (dt_link_error(dtp, elf, fd, bufs,
1710 "an error was encountered while processing %s", obj));
1711 }
1712
1713 int
dtrace_program_link(dtrace_hdl_t * dtp,dtrace_prog_t * pgp,uint_t dflags,const char * file,int objc,char * const objv[])1714 dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
1715 const char *file, int objc, char *const objv[])
1716 {
1717 char tfile[PATH_MAX];
1718 char drti[PATH_MAX];
1719 dof_hdr_t *dof;
1720 int fd, status, i, cur;
1721 char *cmd, tmp;
1722 size_t len;
1723 int eprobes = 0, ret = 0;
1724
1725 /*
1726 * A NULL program indicates a special use in which we just link
1727 * together a bunch of object files specified in objv and then
1728 * unlink(2) those object files.
1729 */
1730 if (pgp == NULL) {
1731 const char *fmt = "%s -o %s -r";
1732
1733 len = snprintf(&tmp, 1, fmt, dtp->dt_ld_path, file) + 1;
1734
1735 for (i = 0; i < objc; i++)
1736 len += strlen(objv[i]) + 1;
1737
1738 cmd = alloca(len);
1739
1740 cur = snprintf(cmd, len, fmt, dtp->dt_ld_path, file);
1741
1742 for (i = 0; i < objc; i++)
1743 cur += snprintf(cmd + cur, len - cur, " %s", objv[i]);
1744
1745 if ((status = system(cmd)) == -1) {
1746 return (dt_link_error(dtp, NULL, -1, NULL,
1747 "failed to run %s: %s", dtp->dt_ld_path,
1748 strerror(errno)));
1749 }
1750
1751 if (WIFSIGNALED(status)) {
1752 return (dt_link_error(dtp, NULL, -1, NULL,
1753 "failed to link %s: %s failed due to signal %d",
1754 file, dtp->dt_ld_path, WTERMSIG(status)));
1755 }
1756
1757 if (WEXITSTATUS(status) != 0) {
1758 return (dt_link_error(dtp, NULL, -1, NULL,
1759 "failed to link %s: %s exited with status %d\n",
1760 file, dtp->dt_ld_path, WEXITSTATUS(status)));
1761 }
1762
1763 for (i = 0; i < objc; i++) {
1764 if (strcmp(objv[i], file) != 0)
1765 (void) unlink(objv[i]);
1766 }
1767
1768 return (0);
1769 }
1770
1771 for (i = 0; i < objc; i++) {
1772 if (process_obj(dtp, objv[i], &eprobes) != 0)
1773 return (-1); /* errno is set for us */
1774 }
1775
1776 /*
1777 * If there are is-enabled probes then we need to force use of DOF
1778 * version 2.
1779 */
1780 if (eprobes && pgp->dp_dofversion < DOF_VERSION_2)
1781 pgp->dp_dofversion = DOF_VERSION_2;
1782
1783 if ((dof = dtrace_dof_create(dtp, pgp, dflags)) == NULL)
1784 return (-1); /* errno is set for us */
1785
1786 snprintf(tfile, sizeof(tfile), "%s.XXXXXX", file);
1787 if ((fd = mkostemp(tfile, O_CLOEXEC)) == -1)
1788 return (dt_link_error(dtp, NULL, -1, NULL,
1789 "failed to create temporary file %s: %s",
1790 tfile, strerror(errno)));
1791
1792 /*
1793 * If -xlinktype=DOF has been selected, just write out the DOF.
1794 * Otherwise proceed to the default of generating and linking ELF.
1795 */
1796 switch (dtp->dt_linktype) {
1797 case DT_LTYP_DOF:
1798 if (dt_write(dtp, fd, dof, dof->dofh_filesz) < dof->dofh_filesz)
1799 ret = errno;
1800
1801 if (close(fd) != 0 && ret == 0)
1802 ret = errno;
1803
1804 if (ret != 0) {
1805 return (dt_link_error(dtp, NULL, -1, NULL,
1806 "failed to write %s: %s", file, strerror(ret)));
1807 }
1808
1809 return (0);
1810
1811 case DT_LTYP_ELF:
1812 break; /* fall through to the rest of dtrace_program_link() */
1813
1814 default:
1815 return (dt_link_error(dtp, NULL, -1, NULL,
1816 "invalid link type %u\n", dtp->dt_linktype));
1817 }
1818
1819
1820 if (dtp->dt_oflags & DTRACE_O_LP64)
1821 status = dump_elf64(dtp, dof, fd);
1822 else
1823 status = dump_elf32(dtp, dof, fd);
1824
1825 if (status != 0)
1826 return (dt_link_error(dtp, NULL, -1, NULL,
1827 "failed to write %s: %s", tfile,
1828 strerror(dtrace_errno(dtp))));
1829
1830 if (!dtp->dt_lazyload) {
1831 const char *fmt = "%s -o %s -r %s %s";
1832 dt_dirpath_t *dp = dt_list_next(&dtp->dt_lib_path);
1833
1834 (void) snprintf(drti, sizeof (drti), "%s/drti.o", dp->dir_path);
1835
1836 len = snprintf(&tmp, 1, fmt, dtp->dt_ld_path, file, tfile,
1837 drti) + 1;
1838
1839 cmd = alloca(len);
1840
1841 (void) snprintf(cmd, len, fmt, dtp->dt_ld_path, file, tfile,
1842 drti);
1843 if ((status = system(cmd)) == -1) {
1844 ret = dt_link_error(dtp, NULL, fd, NULL,
1845 "failed to run %s: %s", dtp->dt_ld_path,
1846 strerror(errno));
1847 goto done;
1848 }
1849
1850 if (WIFSIGNALED(status)) {
1851 ret = dt_link_error(dtp, NULL, fd, NULL,
1852 "failed to link %s: %s failed due to signal %d",
1853 file, dtp->dt_ld_path, WTERMSIG(status));
1854 goto done;
1855 }
1856
1857 if (WEXITSTATUS(status) != 0) {
1858 ret = dt_link_error(dtp, NULL, fd, NULL,
1859 "failed to link %s: %s exited with status %d\n",
1860 file, dtp->dt_ld_path, WEXITSTATUS(status));
1861 goto done;
1862 }
1863 (void) close(fd); /* release temporary file */
1864
1865 /*
1866 * Now that we've linked drti.o, reduce the global __SUNW_dof
1867 * symbol to a local symbol. This is needed to so that multiple
1868 * generated object files (for different providers, for
1869 * instance) can be linked together. This is accomplished using
1870 * the -Blocal flag with Sun's linker, but GNU ld doesn't appear
1871 * to have an equivalent option.
1872 */
1873 asprintf(&cmd, "%s --localize-hidden %s", dtp->dt_objcopy_path,
1874 file);
1875 if ((status = system(cmd)) == -1) {
1876 ret = dt_link_error(dtp, NULL, -1, NULL,
1877 "failed to run %s: %s", dtp->dt_objcopy_path,
1878 strerror(errno));
1879 free(cmd);
1880 goto done;
1881 }
1882 free(cmd);
1883
1884 if (WIFSIGNALED(status)) {
1885 ret = dt_link_error(dtp, NULL, -1, NULL,
1886 "failed to link %s: %s failed due to signal %d",
1887 file, dtp->dt_objcopy_path, WTERMSIG(status));
1888 goto done;
1889 }
1890
1891 if (WEXITSTATUS(status) != 0) {
1892 ret = dt_link_error(dtp, NULL, -1, NULL,
1893 "failed to link %s: %s exited with status %d\n",
1894 file, dtp->dt_objcopy_path, WEXITSTATUS(status));
1895 goto done;
1896 }
1897 } else {
1898 if (rename(tfile, file) != 0) {
1899 ret = dt_link_error(dtp, NULL, fd, NULL,
1900 "failed to rename %s to %s: %s", tfile, file,
1901 strerror(errno));
1902 goto done;
1903 }
1904 (void) close(fd);
1905 }
1906
1907 done:
1908 dtrace_dof_destroy(dtp, dof);
1909
1910 if (!dtp->dt_lazyload)
1911 (void) unlink(tfile);
1912 return (ret);
1913 }
1914