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