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