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