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