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