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