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