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