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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 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 #include <sys/sysmacros.h> 34 35 #include <unistd.h> 36 #include <strings.h> 37 #include <alloca.h> 38 #include <limits.h> 39 #include <stddef.h> 40 #include <stdlib.h> 41 #include <stdio.h> 42 #include <fcntl.h> 43 #include <errno.h> 44 #include <wait.h> 45 #include <assert.h> 46 47 #include <dt_impl.h> 48 #include <dt_provider.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 #ifdef __sparc 71 ".rela.SUNW_dof"; /* 37 */ 72 #else 73 ".rel.SUNW_dof"; /* 37 */ 74 #endif 75 76 static const char DTRACE_SHSTRTAB64[] = "\0" 77 ".shstrtab\0" /* 1 */ 78 ".SUNW_dof\0" /* 11 */ 79 ".strtab\0" /* 21 */ 80 ".symtab\0" /* 29 */ 81 ".rela.SUNW_dof"; /* 37 */ 82 83 static const char DOFSTR[] = "__SUNW_dof"; 84 static const char DOFLAZYSTR[] = "___SUNW_dof"; 85 86 typedef struct dof_elf32 { 87 uint32_t de_nrel; /* relocation count */ 88 #ifdef __sparc 89 Elf32_Rela *de_rel; /* array of relocations for sparc */ 90 #else 91 Elf32_Rel *de_rel; /* array of relocations for x86 */ 92 #endif 93 uint32_t de_nsym; /* symbol count */ 94 Elf32_Sym *de_sym; /* array of symbols */ 95 uint32_t de_strlen; /* size of of string table */ 96 char *de_strtab; /* string table */ 97 uint32_t de_global; /* index of the first global symbol */ 98 } dof_elf32_t; 99 100 static int 101 prepare_elf32(dtrace_hdl_t *dtp, const dof_hdr_t *dof, dof_elf32_t *dep) 102 { 103 dof_sec_t *dofs, *s; 104 dof_relohdr_t *dofrh; 105 dof_relodesc_t *dofr; 106 char *strtab; 107 int i, j, nrel; 108 size_t strtabsz = 1; 109 uint32_t count = 0; 110 size_t base; 111 Elf32_Sym *sym; 112 #ifdef __sparc 113 Elf32_Rela *rel; 114 #else 115 Elf32_Rel *rel; 116 #endif 117 118 /*LINTED*/ 119 dofs = (dof_sec_t *)((char *)dof + dof->dofh_secoff); 120 121 /* 122 * First compute the size of the string table and the number of 123 * relocations present in the DOF. 124 */ 125 for (i = 0; i < dof->dofh_secnum; i++) { 126 if (dofs[i].dofs_type != DOF_SECT_URELHDR) 127 continue; 128 129 /*LINTED*/ 130 dofrh = (dof_relohdr_t *)((char *)dof + dofs[i].dofs_offset); 131 132 s = &dofs[dofrh->dofr_strtab]; 133 strtab = (char *)dof + s->dofs_offset; 134 assert(strtab[0] == '\0'); 135 strtabsz += s->dofs_size - 1; 136 137 s = &dofs[dofrh->dofr_relsec]; 138 /*LINTED*/ 139 dofr = (dof_relodesc_t *)((char *)dof + s->dofs_offset); 140 count += s->dofs_size / s->dofs_entsize; 141 } 142 143 dep->de_strlen = strtabsz; 144 dep->de_nrel = count; 145 dep->de_nsym = count + 1; /* the first symbol is always null */ 146 147 if (dtp->dt_lazyload) { 148 dep->de_strlen += sizeof (DOFLAZYSTR); 149 dep->de_nsym++; 150 } else { 151 dep->de_strlen += sizeof (DOFSTR); 152 dep->de_nsym++; 153 } 154 155 if ((dep->de_rel = calloc(dep->de_nrel, 156 sizeof (dep->de_rel[0]))) == NULL) { 157 return (dt_set_errno(dtp, EDT_NOMEM)); 158 } 159 160 if ((dep->de_sym = calloc(dep->de_nsym, sizeof (Elf32_Sym))) == NULL) { 161 free(dep->de_rel); 162 return (dt_set_errno(dtp, EDT_NOMEM)); 163 } 164 165 if ((dep->de_strtab = calloc(dep->de_strlen, 1)) == NULL) { 166 free(dep->de_rel); 167 free(dep->de_sym); 168 return (dt_set_errno(dtp, EDT_NOMEM)); 169 } 170 171 count = 0; 172 strtabsz = 1; 173 dep->de_strtab[0] = '\0'; 174 rel = dep->de_rel; 175 sym = dep->de_sym; 176 dep->de_global = 1; 177 178 /* 179 * The first symbol table entry must be zeroed and is always ignored. 180 */ 181 bzero(sym, sizeof (Elf32_Sym)); 182 sym++; 183 184 /* 185 * Take a second pass through the DOF sections filling in the 186 * memory we allocated. 187 */ 188 for (i = 0; i < dof->dofh_secnum; i++) { 189 if (dofs[i].dofs_type != DOF_SECT_URELHDR) 190 continue; 191 192 /*LINTED*/ 193 dofrh = (dof_relohdr_t *)((char *)dof + dofs[i].dofs_offset); 194 195 s = &dofs[dofrh->dofr_strtab]; 196 strtab = (char *)dof + s->dofs_offset; 197 bcopy(strtab + 1, dep->de_strtab + strtabsz, s->dofs_size); 198 base = strtabsz; 199 strtabsz += s->dofs_size - 1; 200 201 s = &dofs[dofrh->dofr_relsec]; 202 /*LINTED*/ 203 dofr = (dof_relodesc_t *)((char *)dof + s->dofs_offset); 204 nrel = s->dofs_size / s->dofs_entsize; 205 206 s = &dofs[dofrh->dofr_tgtsec]; 207 208 for (j = 0; j < nrel; j++) { 209 #if defined(__i386) || defined(__amd64) 210 rel->r_offset = s->dofs_offset + 211 dofr[j].dofr_offset; 212 rel->r_info = ELF32_R_INFO(count + dep->de_global, 213 R_386_32); 214 #elif defined(__sparc) 215 /* 216 * Add 4 bytes to hit the low half of this 64-bit 217 * big-endian address. 218 */ 219 rel->r_offset = s->dofs_offset + 220 dofr[j].dofr_offset + 4; 221 rel->r_info = ELF32_R_INFO(count + dep->de_global, 222 R_SPARC_32); 223 #else 224 #error unknown ISA 225 #endif 226 227 sym->st_name = base + dofr[j].dofr_name - 1; 228 sym->st_value = 0; 229 sym->st_size = 0; 230 sym->st_info = ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE); 231 sym->st_other = 0; 232 sym->st_shndx = SHN_UNDEF; 233 234 rel++; 235 sym++; 236 count++; 237 } 238 } 239 240 /* 241 * Add a symbol for the DOF itself. We use a different symbol for 242 * lazily and actively loaded DOF to make them easy to distinguish. 243 */ 244 sym->st_name = strtabsz; 245 sym->st_value = 0; 246 sym->st_size = dof->dofh_filesz; 247 sym->st_info = ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT); 248 sym->st_other = 0; 249 sym->st_shndx = ESHDR_DOF; 250 sym++; 251 252 if (dtp->dt_lazyload) { 253 bcopy(DOFLAZYSTR, dep->de_strtab + strtabsz, 254 sizeof (DOFLAZYSTR)); 255 strtabsz += sizeof (DOFLAZYSTR); 256 } else { 257 bcopy(DOFSTR, dep->de_strtab + strtabsz, sizeof (DOFSTR)); 258 strtabsz += sizeof (DOFSTR); 259 } 260 261 assert(count == dep->de_nrel); 262 assert(strtabsz == dep->de_strlen); 263 264 return (0); 265 } 266 267 268 typedef struct dof_elf64 { 269 uint32_t de_nrel; 270 Elf64_Rela *de_rel; 271 uint32_t de_nsym; 272 Elf64_Sym *de_sym; 273 274 uint32_t de_strlen; 275 char *de_strtab; 276 277 uint32_t de_global; 278 } dof_elf64_t; 279 280 static int 281 prepare_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, dof_elf64_t *dep) 282 { 283 dof_sec_t *dofs, *s; 284 dof_relohdr_t *dofrh; 285 dof_relodesc_t *dofr; 286 char *strtab; 287 int i, j, nrel; 288 size_t strtabsz = 1; 289 uint32_t count = 0; 290 size_t base; 291 Elf64_Sym *sym; 292 Elf64_Rela *rel; 293 294 /*LINTED*/ 295 dofs = (dof_sec_t *)((char *)dof + dof->dofh_secoff); 296 297 /* 298 * First compute the size of the string table and the number of 299 * relocations present in the DOF. 300 */ 301 for (i = 0; i < dof->dofh_secnum; i++) { 302 if (dofs[i].dofs_type != DOF_SECT_URELHDR) 303 continue; 304 305 /*LINTED*/ 306 dofrh = (dof_relohdr_t *)((char *)dof + dofs[i].dofs_offset); 307 308 s = &dofs[dofrh->dofr_strtab]; 309 strtab = (char *)dof + s->dofs_offset; 310 assert(strtab[0] == '\0'); 311 strtabsz += s->dofs_size - 1; 312 313 s = &dofs[dofrh->dofr_relsec]; 314 /*LINTED*/ 315 dofr = (dof_relodesc_t *)((char *)dof + s->dofs_offset); 316 count += s->dofs_size / s->dofs_entsize; 317 } 318 319 dep->de_strlen = strtabsz; 320 dep->de_nrel = count; 321 dep->de_nsym = count + 1; /* the first symbol is always null */ 322 323 if (dtp->dt_lazyload) { 324 dep->de_strlen += sizeof (DOFLAZYSTR); 325 dep->de_nsym++; 326 } else { 327 dep->de_strlen += sizeof (DOFSTR); 328 dep->de_nsym++; 329 } 330 331 if ((dep->de_rel = calloc(dep->de_nrel, 332 sizeof (dep->de_rel[0]))) == NULL) { 333 return (dt_set_errno(dtp, EDT_NOMEM)); 334 } 335 336 if ((dep->de_sym = calloc(dep->de_nsym, sizeof (Elf64_Sym))) == NULL) { 337 free(dep->de_rel); 338 return (dt_set_errno(dtp, EDT_NOMEM)); 339 } 340 341 if ((dep->de_strtab = calloc(dep->de_strlen, 1)) == NULL) { 342 free(dep->de_rel); 343 free(dep->de_sym); 344 return (dt_set_errno(dtp, EDT_NOMEM)); 345 } 346 347 count = 0; 348 strtabsz = 1; 349 dep->de_strtab[0] = '\0'; 350 rel = dep->de_rel; 351 sym = dep->de_sym; 352 dep->de_global = 1; 353 354 /* 355 * The first symbol table entry must be zeroed and is always ignored. 356 */ 357 bzero(sym, sizeof (Elf64_Sym)); 358 sym++; 359 360 /* 361 * Take a second pass through the DOF sections filling in the 362 * memory we allocated. 363 */ 364 for (i = 0; i < dof->dofh_secnum; i++) { 365 if (dofs[i].dofs_type != DOF_SECT_URELHDR) 366 continue; 367 368 /*LINTED*/ 369 dofrh = (dof_relohdr_t *)((char *)dof + dofs[i].dofs_offset); 370 371 s = &dofs[dofrh->dofr_strtab]; 372 strtab = (char *)dof + s->dofs_offset; 373 bcopy(strtab + 1, dep->de_strtab + strtabsz, s->dofs_size); 374 base = strtabsz; 375 strtabsz += s->dofs_size - 1; 376 377 s = &dofs[dofrh->dofr_relsec]; 378 /*LINTED*/ 379 dofr = (dof_relodesc_t *)((char *)dof + s->dofs_offset); 380 nrel = s->dofs_size / s->dofs_entsize; 381 382 s = &dofs[dofrh->dofr_tgtsec]; 383 384 for (j = 0; j < nrel; j++) { 385 #if defined(__i386) || defined(__amd64) 386 rel->r_offset = s->dofs_offset + 387 dofr[j].dofr_offset; 388 rel->r_info = ELF64_R_INFO(count + dep->de_global, 389 R_AMD64_64); 390 #elif defined(__sparc) 391 rel->r_offset = s->dofs_offset + 392 dofr[j].dofr_offset; 393 rel->r_info = ELF64_R_INFO(count + dep->de_global, 394 R_SPARC_64); 395 #else 396 #error unknown ISA 397 #endif 398 399 sym->st_name = base + dofr[j].dofr_name - 1; 400 sym->st_value = 0; 401 sym->st_size = 0; 402 sym->st_info = ELF64_ST_INFO(STB_GLOBAL, STT_NOTYPE); 403 sym->st_other = 0; 404 sym->st_shndx = SHN_UNDEF; 405 406 rel++; 407 sym++; 408 count++; 409 } 410 } 411 412 /* 413 * Add a symbol for the DOF itself. We use a different symbol for 414 * lazily and actively loaded DOF to make them easy to distinguish. 415 */ 416 sym->st_name = strtabsz; 417 sym->st_value = 0; 418 sym->st_size = dof->dofh_filesz; 419 sym->st_info = ELF64_ST_INFO(STB_GLOBAL, STT_OBJECT); 420 sym->st_other = 0; 421 sym->st_shndx = ESHDR_DOF; 422 sym++; 423 424 if (dtp->dt_lazyload) { 425 bcopy(DOFLAZYSTR, dep->de_strtab + strtabsz, 426 sizeof (DOFLAZYSTR)); 427 strtabsz += sizeof (DOFLAZYSTR); 428 } else { 429 bcopy(DOFSTR, dep->de_strtab + strtabsz, sizeof (DOFSTR)); 430 strtabsz += sizeof (DOFSTR); 431 } 432 433 assert(count == dep->de_nrel); 434 assert(strtabsz == dep->de_strlen); 435 436 return (0); 437 } 438 439 /* 440 * Write out an ELF32 file prologue consisting of a header, section headers, 441 * and a section header string table. The DOF data will follow this prologue 442 * and complete the contents of the given ELF file. 443 */ 444 static int 445 dump_elf32(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd) 446 { 447 struct { 448 Elf32_Ehdr ehdr; 449 Elf32_Shdr shdr[ESHDR_NUM]; 450 } elf_file; 451 452 Elf32_Shdr *shp; 453 Elf32_Off off; 454 dof_elf32_t de; 455 int ret = 0; 456 uint_t nshdr; 457 458 if (prepare_elf32(dtp, dof, &de) != 0) 459 return (-1); /* errno is set for us */ 460 461 /* 462 * If there are no relocations, we only need enough sections for 463 * the shstrtab and the DOF. 464 */ 465 nshdr = de.de_nrel == 0 ? ESHDR_SYMTAB + 1 : ESHDR_NUM; 466 467 bzero(&elf_file, sizeof (elf_file)); 468 469 elf_file.ehdr.e_ident[EI_MAG0] = ELFMAG0; 470 elf_file.ehdr.e_ident[EI_MAG1] = ELFMAG1; 471 elf_file.ehdr.e_ident[EI_MAG2] = ELFMAG2; 472 elf_file.ehdr.e_ident[EI_MAG3] = ELFMAG3; 473 elf_file.ehdr.e_ident[EI_VERSION] = EV_CURRENT; 474 elf_file.ehdr.e_ident[EI_CLASS] = ELFCLASS32; 475 #if defined(_BIG_ENDIAN) 476 elf_file.ehdr.e_ident[EI_DATA] = ELFDATA2MSB; 477 #elif defined(_LITTLE_ENDIAN) 478 elf_file.ehdr.e_ident[EI_DATA] = ELFDATA2LSB; 479 #endif 480 elf_file.ehdr.e_type = ET_REL; 481 #if defined(__sparc) 482 elf_file.ehdr.e_machine = EM_SPARC; 483 #elif defined(__i386) || defined(__amd64) 484 elf_file.ehdr.e_machine = EM_386; 485 #endif 486 elf_file.ehdr.e_version = EV_CURRENT; 487 elf_file.ehdr.e_shoff = sizeof (Elf32_Ehdr); 488 elf_file.ehdr.e_ehsize = sizeof (Elf32_Ehdr); 489 elf_file.ehdr.e_phentsize = sizeof (Elf32_Phdr); 490 elf_file.ehdr.e_shentsize = sizeof (Elf32_Shdr); 491 elf_file.ehdr.e_shnum = nshdr; 492 elf_file.ehdr.e_shstrndx = ESHDR_SHSTRTAB; 493 off = sizeof (elf_file) + nshdr * sizeof (Elf32_Shdr); 494 495 shp = &elf_file.shdr[ESHDR_SHSTRTAB]; 496 shp->sh_name = 1; /* DTRACE_SHSTRTAB32[1] = ".shstrtab" */ 497 shp->sh_type = SHT_STRTAB; 498 shp->sh_offset = off; 499 shp->sh_size = sizeof (DTRACE_SHSTRTAB32); 500 shp->sh_addralign = sizeof (char); 501 off = P2ROUNDUP(shp->sh_offset + shp->sh_size, 8); 502 503 shp = &elf_file.shdr[ESHDR_DOF]; 504 shp->sh_name = 11; /* DTRACE_SHSTRTAB32[11] = ".SUNW_dof" */ 505 shp->sh_flags = SHF_ALLOC; 506 shp->sh_type = SHT_SUNW_dof; 507 shp->sh_offset = off; 508 shp->sh_size = dof->dofh_filesz; 509 shp->sh_addralign = 8; 510 off = shp->sh_offset + shp->sh_size; 511 512 shp = &elf_file.shdr[ESHDR_STRTAB]; 513 shp->sh_name = 21; /* DTRACE_SHSTRTAB32[21] = ".strtab" */ 514 shp->sh_flags = SHF_ALLOC; 515 shp->sh_type = SHT_STRTAB; 516 shp->sh_offset = off; 517 shp->sh_size = de.de_strlen; 518 shp->sh_addralign = sizeof (char); 519 off = P2ROUNDUP(shp->sh_offset + shp->sh_size, 4); 520 521 shp = &elf_file.shdr[ESHDR_SYMTAB]; 522 shp->sh_name = 29; /* DTRACE_SHSTRTAB32[29] = ".symtab" */ 523 shp->sh_flags = SHF_ALLOC; 524 shp->sh_type = SHT_SYMTAB; 525 shp->sh_entsize = sizeof (Elf32_Sym); 526 shp->sh_link = ESHDR_STRTAB; 527 shp->sh_offset = off; 528 shp->sh_info = de.de_global; 529 shp->sh_size = de.de_nsym * sizeof (Elf32_Sym); 530 shp->sh_addralign = 4; 531 off = P2ROUNDUP(shp->sh_offset + shp->sh_size, 4); 532 533 if (de.de_nrel == 0) { 534 if (dt_write(dtp, fd, &elf_file, 535 sizeof (elf_file)) != sizeof (elf_file) || 536 PWRITE_SCN(ESHDR_SHSTRTAB, DTRACE_SHSTRTAB32) || 537 PWRITE_SCN(ESHDR_STRTAB, de.de_strtab) || 538 PWRITE_SCN(ESHDR_SYMTAB, de.de_sym) || 539 PWRITE_SCN(ESHDR_DOF, dof)) { 540 ret = dt_set_errno(dtp, errno); 541 } 542 } else { 543 shp = &elf_file.shdr[ESHDR_REL]; 544 shp->sh_name = 37; /* DTRACE_SHSTRTAB32[37] = ".rel.SUNW_dof" */ 545 shp->sh_flags = SHF_ALLOC; 546 #ifdef __sparc 547 shp->sh_type = SHT_RELA; 548 #else 549 shp->sh_type = SHT_REL; 550 #endif 551 shp->sh_entsize = sizeof (de.de_rel[0]); 552 shp->sh_link = ESHDR_SYMTAB; 553 shp->sh_info = ESHDR_DOF; 554 shp->sh_offset = off; 555 shp->sh_size = de.de_nrel * sizeof (de.de_rel[0]); 556 shp->sh_addralign = 4; 557 558 if (dt_write(dtp, fd, &elf_file, 559 sizeof (elf_file)) != sizeof (elf_file) || 560 PWRITE_SCN(ESHDR_SHSTRTAB, DTRACE_SHSTRTAB32) || 561 PWRITE_SCN(ESHDR_STRTAB, de.de_strtab) || 562 PWRITE_SCN(ESHDR_SYMTAB, de.de_sym) || 563 PWRITE_SCN(ESHDR_REL, de.de_rel) || 564 PWRITE_SCN(ESHDR_DOF, dof)) { 565 ret = dt_set_errno(dtp, errno); 566 } 567 } 568 569 free(de.de_strtab); 570 free(de.de_sym); 571 free(de.de_rel); 572 573 return (ret); 574 } 575 576 /* 577 * Write out an ELF64 file prologue consisting of a header, section headers, 578 * and a section header string table. The DOF data will follow this prologue 579 * and complete the contents of the given ELF file. 580 */ 581 static int 582 dump_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd) 583 { 584 struct { 585 Elf64_Ehdr ehdr; 586 Elf64_Shdr shdr[ESHDR_NUM]; 587 } elf_file; 588 589 Elf64_Shdr *shp; 590 Elf64_Off off; 591 dof_elf64_t de; 592 int ret = 0; 593 uint_t nshdr; 594 595 if (prepare_elf64(dtp, dof, &de) != 0) 596 return (-1); /* errno is set for us */ 597 598 /* 599 * If there are no relocations, we only need enough sections for 600 * the shstrtab and the DOF. 601 */ 602 nshdr = de.de_nrel == 0 ? ESHDR_SYMTAB + 1 : ESHDR_NUM; 603 604 bzero(&elf_file, sizeof (elf_file)); 605 606 elf_file.ehdr.e_ident[EI_MAG0] = ELFMAG0; 607 elf_file.ehdr.e_ident[EI_MAG1] = ELFMAG1; 608 elf_file.ehdr.e_ident[EI_MAG2] = ELFMAG2; 609 elf_file.ehdr.e_ident[EI_MAG3] = ELFMAG3; 610 elf_file.ehdr.e_ident[EI_VERSION] = EV_CURRENT; 611 elf_file.ehdr.e_ident[EI_CLASS] = ELFCLASS64; 612 #if defined(_BIG_ENDIAN) 613 elf_file.ehdr.e_ident[EI_DATA] = ELFDATA2MSB; 614 #elif defined(_LITTLE_ENDIAN) 615 elf_file.ehdr.e_ident[EI_DATA] = ELFDATA2LSB; 616 #endif 617 elf_file.ehdr.e_type = ET_REL; 618 #if defined(__sparc) 619 elf_file.ehdr.e_machine = EM_SPARCV9; 620 #elif defined(__i386) || defined(__amd64) 621 elf_file.ehdr.e_machine = EM_AMD64; 622 #endif 623 elf_file.ehdr.e_version = EV_CURRENT; 624 elf_file.ehdr.e_shoff = sizeof (Elf64_Ehdr); 625 elf_file.ehdr.e_ehsize = sizeof (Elf64_Ehdr); 626 elf_file.ehdr.e_phentsize = sizeof (Elf64_Phdr); 627 elf_file.ehdr.e_shentsize = sizeof (Elf64_Shdr); 628 elf_file.ehdr.e_shnum = nshdr; 629 elf_file.ehdr.e_shstrndx = ESHDR_SHSTRTAB; 630 off = sizeof (elf_file) + nshdr * sizeof (Elf64_Shdr); 631 632 shp = &elf_file.shdr[ESHDR_SHSTRTAB]; 633 shp->sh_name = 1; /* DTRACE_SHSTRTAB64[1] = ".shstrtab" */ 634 shp->sh_type = SHT_STRTAB; 635 shp->sh_offset = off; 636 shp->sh_size = sizeof (DTRACE_SHSTRTAB64); 637 shp->sh_addralign = sizeof (char); 638 off = P2ROUNDUP(shp->sh_offset + shp->sh_size, 8); 639 640 shp = &elf_file.shdr[ESHDR_DOF]; 641 shp->sh_name = 11; /* DTRACE_SHSTRTAB64[11] = ".SUNW_dof" */ 642 shp->sh_flags = SHF_ALLOC; 643 shp->sh_type = SHT_SUNW_dof; 644 shp->sh_offset = off; 645 shp->sh_size = dof->dofh_filesz; 646 shp->sh_addralign = 8; 647 off = shp->sh_offset + shp->sh_size; 648 649 shp = &elf_file.shdr[ESHDR_STRTAB]; 650 shp->sh_name = 21; /* DTRACE_SHSTRTAB64[21] = ".strtab" */ 651 shp->sh_flags = SHF_ALLOC; 652 shp->sh_type = SHT_STRTAB; 653 shp->sh_offset = off; 654 shp->sh_size = de.de_strlen; 655 shp->sh_addralign = sizeof (char); 656 off = P2ROUNDUP(shp->sh_offset + shp->sh_size, 8); 657 658 shp = &elf_file.shdr[ESHDR_SYMTAB]; 659 shp->sh_name = 29; /* DTRACE_SHSTRTAB64[29] = ".symtab" */ 660 shp->sh_flags = SHF_ALLOC; 661 shp->sh_type = SHT_SYMTAB; 662 shp->sh_entsize = sizeof (Elf64_Sym); 663 shp->sh_link = ESHDR_STRTAB; 664 shp->sh_offset = off; 665 shp->sh_info = de.de_global; 666 shp->sh_size = de.de_nsym * sizeof (Elf64_Sym); 667 shp->sh_addralign = 8; 668 off = P2ROUNDUP(shp->sh_offset + shp->sh_size, 8); 669 670 if (de.de_nrel == 0) { 671 if (dt_write(dtp, fd, &elf_file, 672 sizeof (elf_file)) != sizeof (elf_file) || 673 PWRITE_SCN(ESHDR_SHSTRTAB, DTRACE_SHSTRTAB64) || 674 PWRITE_SCN(ESHDR_STRTAB, de.de_strtab) || 675 PWRITE_SCN(ESHDR_SYMTAB, de.de_sym) || 676 PWRITE_SCN(ESHDR_DOF, dof)) { 677 ret = dt_set_errno(dtp, errno); 678 } 679 } else { 680 shp = &elf_file.shdr[ESHDR_REL]; 681 shp->sh_name = 37; /* DTRACE_SHSTRTAB64[37] = ".rel.SUNW_dof" */ 682 shp->sh_flags = SHF_ALLOC; 683 shp->sh_type = SHT_RELA; 684 shp->sh_entsize = sizeof (de.de_rel[0]); 685 shp->sh_link = ESHDR_SYMTAB; 686 shp->sh_info = ESHDR_DOF; 687 shp->sh_offset = off; 688 shp->sh_size = de.de_nrel * sizeof (de.de_rel[0]); 689 shp->sh_addralign = 8; 690 691 if (dt_write(dtp, fd, &elf_file, 692 sizeof (elf_file)) != sizeof (elf_file) || 693 PWRITE_SCN(ESHDR_SHSTRTAB, DTRACE_SHSTRTAB64) || 694 PWRITE_SCN(ESHDR_STRTAB, de.de_strtab) || 695 PWRITE_SCN(ESHDR_SYMTAB, de.de_sym) || 696 PWRITE_SCN(ESHDR_REL, de.de_rel) || 697 PWRITE_SCN(ESHDR_DOF, dof)) { 698 ret = dt_set_errno(dtp, errno); 699 } 700 } 701 702 free(de.de_strtab); 703 free(de.de_sym); 704 free(de.de_rel); 705 706 return (ret); 707 } 708 709 static int 710 dt_symtab_lookup(Elf_Data *data_sym, uintptr_t addr, uint_t shn, GElf_Sym *sym) 711 { 712 int i, ret = -1; 713 GElf_Sym s; 714 715 for (i = 0; gelf_getsym(data_sym, i, sym) != NULL; i++) { 716 if (GELF_ST_TYPE(sym->st_info) == STT_FUNC && 717 shn == sym->st_shndx && 718 sym->st_value <= addr && 719 addr < sym->st_value + sym->st_size) { 720 if (GELF_ST_BIND(sym->st_info) == STB_GLOBAL) 721 return (0); 722 723 ret = 0; 724 s = *sym; 725 } 726 } 727 728 if (ret == 0) 729 *sym = s; 730 return (ret); 731 } 732 733 #if defined(__sparc) 734 735 #define DT_OP_RET 0x81c7e008 736 #define DT_OP_NOP 0x01000000 737 #define DT_OP_CALL 0x40000000 738 739 #define DT_IS_MOV_O7(inst) (((inst) & 0xffffe000) == 0x9e100000) 740 #define DT_IS_RESTORE(inst) (((inst) & 0xc1f80000) == 0x81e80000) 741 #define DT_IS_RETL(inst) (((inst) & 0xfff83fff) == 0x81c02008) 742 743 #define DT_RS2(inst) ((inst) & 0x1f) 744 #define DT_MAKE_RETL(reg) (0x81c02008 | ((reg) << 14)) 745 746 static int 747 dt_modtext(char *p, GElf_Rela *rela, uint32_t *off) 748 { 749 uint32_t *ip; 750 751 if ((rela->r_offset & (sizeof (uint32_t) - 1)) != 0) 752 return (-1); 753 754 /*LINTED*/ 755 ip = (uint32_t *)(p + rela->r_offset); 756 757 /* 758 * We only know about some specific relocation types. 759 */ 760 if (GELF_R_TYPE(rela->r_info) != R_SPARC_WDISP30 && 761 GELF_R_TYPE(rela->r_info) != R_SPARC_WPLT30) 762 return (-1); 763 764 /* 765 * We may have already processed this object file in an earlier 766 * linker invocation in which case we'd expect to see a ret/restore 767 * pair, a retl-like/mov pair or a nop; return success in that case. 768 */ 769 if (DT_IS_RESTORE(ip[1])) { 770 if (ip[0] == DT_OP_RET) { 771 return (0); 772 } 773 } else if (DT_IS_MOV_O7(ip[1])) { 774 if (DT_IS_RETL(ip[0])) { 775 return (0); 776 } 777 } else { 778 if (ip[0] == DT_OP_NOP) { 779 (*off) += sizeof (ip[0]); 780 return (0); 781 } 782 } 783 784 /* 785 * We only expect call instructions with a displacement of 0. 786 */ 787 if (ip[0] != DT_OP_CALL) { 788 dt_dprintf("found %x instead of a call instruction at %llx\n", 789 ip[0], (u_longlong_t)rela->r_offset); 790 return (-1); 791 } 792 793 /* 794 * If the call is followed by a restore, it's a tail call so change 795 * the call to a ret. If the call if followed by a mov of a register 796 * into %o7, it's a tail call in leaf context so change the call to 797 * a retl-like instruction that returns to that register value + 8 798 * (rather than the typical %o7 + 8). Otherwise we adjust the offset 799 * to land on what was once the delay slot of the call so we 800 * correctly get all the arguments. 801 */ 802 if (DT_IS_RESTORE(ip[1])) { 803 ip[0] = DT_OP_RET; 804 } else if (DT_IS_MOV_O7(ip[1])) { 805 ip[0] = DT_MAKE_RETL(DT_RS2(ip[1])); 806 } else { 807 ip[0] = DT_OP_NOP; 808 (*off) += sizeof (ip[0]); 809 } 810 811 return (0); 812 } 813 814 #elif defined(__i386) || defined(__amd64) 815 816 #define DT_OP_NOP 0x90 817 #define DT_OP_CALL 0xe8 818 819 static int 820 dt_modtext(char *p, GElf_Rela *rela, uint32_t *off) 821 { 822 uint8_t *ip = (uint8_t *)(p + rela->r_offset - 1); 823 824 /* 825 * On x86, the first byte of the instruction is the call opcode and 826 * the next four bytes are the 32-bit address; the relocation is for 827 * the address so we back up one byte to land on the opcode. 828 */ 829 (*off) -= 1; 830 831 /* 832 * We only know about some specific relocation types. Luckily 833 * these types have the same values on both 32-bit and 64-bit 834 * x86 architectures. 835 */ 836 if (GELF_R_TYPE(rela->r_info) != R_386_PC32 && 837 GELF_R_TYPE(rela->r_info) != R_386_PLT32) 838 return (-1); 839 840 /* 841 * We may have already processed this object file in an earlier 842 * linker invocation in which case we'd expect to see a bunch 843 * of nops; return success in that case. 844 */ 845 if (ip[0] == DT_OP_NOP && ip[1] == DT_OP_NOP && ip[2] == DT_OP_NOP && 846 ip[3] == DT_OP_NOP && ip[4] == DT_OP_NOP) 847 return (0); 848 849 /* 850 * We only expect a call instrution with a 32-bit displacement. 851 */ 852 if (ip[0] != DT_OP_CALL) { 853 dt_dprintf("found %x instead of a call instruction at %llx\n", 854 ip[0], (u_longlong_t)rela->r_offset); 855 return (-1); 856 } 857 858 ip[0] = DT_OP_NOP; 859 ip[1] = DT_OP_NOP; 860 ip[2] = DT_OP_NOP; 861 ip[3] = DT_OP_NOP; 862 ip[4] = DT_OP_NOP; 863 864 return (0); 865 } 866 867 #else 868 #error unknown ISA 869 #endif 870 871 /*PRINTFLIKE2*/ 872 static int 873 dt_link_error(dtrace_hdl_t *dtp, const char *format, ...) 874 { 875 va_list ap; 876 877 va_start(ap, format); 878 dt_set_errmsg(dtp, NULL, NULL, NULL, 0, format, ap); 879 va_end(ap); 880 881 return (dt_set_errno(dtp, EDT_COMPILER)); 882 } 883 884 static int 885 process_obj(dtrace_hdl_t *dtp, const char *obj) 886 { 887 static const char dt_prefix[] = "__dtrace_"; 888 int fd, i, ndx, mod = 0; 889 Elf *elf; 890 GElf_Ehdr ehdr; 891 Elf_Scn *scn_rel, *scn_sym, *scn_tgt; 892 Elf_Data *data_rel, *data_sym, *data_tgt; 893 GElf_Shdr shdr_rel, shdr_sym, shdr_tgt; 894 GElf_Sym rsym, fsym; 895 GElf_Rela rela; 896 GElf_Rel rel; 897 char *s, *p; 898 char pname[DTRACE_PROVNAMELEN]; 899 dt_provider_t *pvp; 900 dt_probe_t *prp; 901 uint32_t off, eclass, emachine1, emachine2; 902 903 if ((fd = open64(obj, O_RDWR)) == -1) { 904 return (dt_link_error(dtp, "failed to open %s: %s", obj, 905 strerror(errno))); 906 } 907 908 if (elf_version(EV_CURRENT) == EV_NONE || 909 (elf = elf_begin(fd, ELF_C_RDWR, NULL)) == NULL) { 910 return (dt_link_error(dtp, "failed to process %s: %s", obj, 911 elf_errmsg(elf_errno()))); 912 } 913 914 switch (elf_kind(elf)) { 915 case ELF_K_ELF: 916 break; 917 case ELF_K_AR: 918 return (dt_link_error(dtp, "archive files are not permitted %s;" 919 " use the contents of the archive instead", obj)); 920 default: 921 return (dt_link_error(dtp, "invalid file type for %s", obj)); 922 } 923 924 if (gelf_getehdr(elf, &ehdr) == NULL) 925 return (dt_link_error(dtp, "corrupt object file %s", obj)); 926 927 if (dtp->dt_oflags & DTRACE_O_LP64) { 928 eclass = ELFCLASS64; 929 #if defined(__sparc) 930 emachine1 = emachine2 = EM_SPARCV9; 931 #elif defined(__i386) || defined(__amd64) 932 emachine1 = emachine2 = EM_AMD64; 933 #endif 934 } else { 935 eclass = ELFCLASS32; 936 #if defined(__sparc) 937 emachine1 = EM_SPARC; 938 emachine2 = EM_SPARC32PLUS; 939 #elif defined(__i386) || defined(__amd64) 940 emachine1 = emachine2 = EM_386; 941 #endif 942 } 943 944 if (ehdr.e_ident[EI_CLASS] != eclass) 945 return (dt_link_error(dtp, "incorrect ELF class for object " 946 "file %s", obj)); 947 948 if (ehdr.e_machine != emachine1 && ehdr.e_machine != emachine2) 949 return (dt_link_error(dtp, "incorrect ELF machine type for " 950 "object file %s", obj)); 951 952 scn_rel = NULL; 953 while ((scn_rel = elf_nextscn(elf, scn_rel)) != NULL) { 954 if (gelf_getshdr(scn_rel, &shdr_rel) == NULL) 955 goto err; 956 957 if (shdr_rel.sh_type != SHT_RELA && shdr_rel.sh_type != SHT_REL) 958 continue; 959 960 if ((data_rel = elf_getdata(scn_rel, NULL)) == NULL) 961 goto err; 962 963 if ((scn_sym = elf_getscn(elf, shdr_rel.sh_link)) == NULL || 964 gelf_getshdr(scn_sym, &shdr_sym) == NULL || 965 (data_sym = elf_getdata(scn_sym, NULL)) == NULL) 966 goto err; 967 968 if ((scn_tgt = elf_getscn(elf, shdr_rel.sh_info)) == NULL || 969 gelf_getshdr(scn_tgt, &shdr_tgt) == NULL || 970 (data_tgt = elf_getdata(scn_tgt, NULL)) == NULL) 971 goto err; 972 973 for (i = 0; i < shdr_rel.sh_size / shdr_rel.sh_entsize; i++) { 974 975 if (shdr_rel.sh_type == SHT_RELA) { 976 if (gelf_getrela(data_rel, i, &rela) == NULL) 977 continue; 978 } else { 979 if (gelf_getrel(data_rel, i, &rel) == NULL) 980 continue; 981 rela.r_offset = rel.r_offset; 982 rela.r_info = rel.r_info; 983 rela.r_addend = 0; 984 } 985 986 ndx = GELF_R_SYM(rela.r_info); 987 988 if (gelf_getsym(data_sym, ndx, &rsym) == NULL || 989 (s = elf_strptr(elf, shdr_sym.sh_link, 990 rsym.st_name)) == NULL) 991 goto err; 992 993 if (strncmp(s, dt_prefix, sizeof (dt_prefix) - 1) != 0) 994 continue; 995 996 if (dt_symtab_lookup(data_sym, rela.r_offset, 997 shdr_rel.sh_info, &fsym) != 0) 998 goto err; 999 1000 s += sizeof (dt_prefix) - 1; 1001 if ((p = strstr(s, "___")) == NULL || 1002 p - s >= sizeof (pname)) 1003 goto err; 1004 1005 (void) memcpy(pname, s, p - s); 1006 pname[p - s] = '\0'; 1007 1008 p = strhyphenate(p + 3); /* strlen("___") */ 1009 1010 if ((s = elf_strptr(elf, shdr_sym.sh_link, 1011 fsym.st_name)) == NULL) 1012 goto err; 1013 1014 if ((pvp = dt_provider_lookup(dtp, pname)) == NULL) { 1015 return (dt_link_error(dtp, 1016 "no such provider %s", pname)); 1017 } 1018 1019 if ((prp = dt_probe_lookup(pvp, p)) == NULL) { 1020 return (dt_link_error(dtp, 1021 "no such probe %s", p)); 1022 } 1023 1024 assert(fsym.st_value <= rela.r_offset); 1025 1026 off = rela.r_offset - fsym.st_value; 1027 if (dt_modtext(data_tgt->d_buf, &rela, &off) != 0) 1028 goto err; 1029 1030 if (dt_probe_define(pvp, prp, s, off) != 0) 1031 return (dt_set_errno(dtp, EDT_NOMEM)); 1032 1033 mod = 1; 1034 1035 /* 1036 * This symbol may already have been marked to 1037 * be ignored by another relocation referencing 1038 * the same symbol or if this object file has 1039 * already been processed by an earlier link 1040 * invocation. 1041 */ 1042 if (rsym.st_shndx != SHN_SUNW_IGNORE) { 1043 rsym.st_shndx = SHN_SUNW_IGNORE; 1044 (void) gelf_update_sym(data_sym, ndx, &rsym); 1045 } 1046 } 1047 } 1048 1049 if (mod && elf_update(elf, ELF_C_WRITE) == -1) 1050 goto err; 1051 1052 return (0); 1053 1054 err: 1055 return (dt_link_error(dtp, 1056 "an error was encountered while processing %s", obj)); 1057 } 1058 1059 int 1060 dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags, 1061 const char *file, int objc, char *const objv[]) 1062 { 1063 char drti[PATH_MAX]; 1064 dof_hdr_t *dof; 1065 int fd, status, i, cur; 1066 char *cmd, tmp; 1067 size_t len; 1068 int ret = 0; 1069 1070 /* 1071 * A NULL program indicates a special use in which we just link 1072 * together a bunch of object files specified in objv and then 1073 * unlink(2) those object files. 1074 */ 1075 if (pgp == NULL) { 1076 const char *fmt = "%s -o %s -r"; 1077 1078 len = snprintf(&tmp, 1, fmt, dtp->dt_ld_path, file) + 1; 1079 1080 for (i = 0; i < objc; i++) 1081 len += strlen(objv[i]) + 1; 1082 1083 cmd = alloca(len); 1084 1085 cur = snprintf(cmd, len, fmt, dtp->dt_ld_path, file); 1086 1087 for (i = 0; i < objc; i++) 1088 cur += snprintf(cmd + cur, len - cur, " %s", objv[i]); 1089 1090 if ((status = system(cmd)) == -1) { 1091 return (dt_link_error(dtp, "failed to run %s: %s", 1092 dtp->dt_ld_path, strerror(errno))); 1093 } 1094 1095 if (WIFSIGNALED(status)) { 1096 return (dt_link_error(dtp, 1097 "failed to link %s: %s failed due to signal %d", 1098 file, dtp->dt_ld_path, WTERMSIG(status))); 1099 } 1100 1101 if (WEXITSTATUS(status) != 0) { 1102 return (dt_link_error(dtp, 1103 "failed to link %s: %s exited with status %d\n", 1104 file, dtp->dt_ld_path, WEXITSTATUS(status))); 1105 } 1106 1107 for (i = 0; i < objc; i++) { 1108 if (strcmp(objv[i], file) != 0) 1109 (void) unlink(objv[i]); 1110 } 1111 1112 return (0); 1113 } 1114 1115 for (i = 0; i < objc; i++) { 1116 if (process_obj(dtp, objv[i]) != 0) 1117 return (-1); /* errno is set for us */ 1118 } 1119 1120 if ((dof = dtrace_dof_create(dtp, pgp, dflags)) == NULL) 1121 return (-1); /* errno is set for us */ 1122 1123 /* 1124 * Create a temporary file and then unlink it if we're going to 1125 * combine it with drti.o later. We can still refer to it in child 1126 * processes as /dev/fd/<fd>. 1127 */ 1128 if ((fd = open64(file, O_RDWR | O_CREAT | O_TRUNC, 0666)) == -1) { 1129 return (dt_link_error(dtp, 1130 "failed to open %s: %s", file, strerror(errno))); 1131 } 1132 1133 /* 1134 * If -xlinktype=DOF has been selected, just write out the DOF. 1135 * Otherwise proceed to the default of generating and linking ELF. 1136 */ 1137 switch (dtp->dt_linktype) { 1138 case DT_LTYP_DOF: 1139 if (dt_write(dtp, fd, dof, dof->dofh_filesz) < dof->dofh_filesz) 1140 ret = errno; 1141 1142 if (close(fd) != 0 && ret == 0) 1143 ret = errno; 1144 1145 if (ret != 0) { 1146 return (dt_link_error(dtp, 1147 "failed to write %s: %s", file, strerror(ret))); 1148 } 1149 1150 return (0); 1151 1152 case DT_LTYP_ELF: 1153 break; /* fall through to the rest of dtrace_program_link() */ 1154 1155 default: 1156 return (dt_link_error(dtp, 1157 "invalid link type %u\n", dtp->dt_linktype)); 1158 } 1159 1160 1161 if (!dtp->dt_lazyload) 1162 (void) unlink(file); 1163 1164 if (dtp->dt_oflags & DTRACE_O_LP64) 1165 status = dump_elf64(dtp, dof, fd); 1166 else 1167 status = dump_elf32(dtp, dof, fd); 1168 1169 if (status != 0 || lseek(fd, 0, SEEK_SET) != 0) { 1170 return (dt_link_error(dtp, 1171 "failed to write %s: %s", file, strerror(errno))); 1172 } 1173 1174 if (!dtp->dt_lazyload) { 1175 const char *fmt = "%s -o %s -r -Blocal -Breduce /dev/fd/%d %s"; 1176 1177 if (dtp->dt_oflags & DTRACE_O_LP64) { 1178 (void) snprintf(drti, sizeof (drti), 1179 "%s/64/drti.o", _dtrace_libdir); 1180 } else { 1181 (void) snprintf(drti, sizeof (drti), 1182 "%s/drti.o", _dtrace_libdir); 1183 } 1184 1185 len = snprintf(&tmp, 1, fmt, dtp->dt_ld_path, file, fd, 1186 drti) + 1; 1187 1188 cmd = alloca(len); 1189 1190 (void) snprintf(cmd, len, fmt, dtp->dt_ld_path, file, fd, drti); 1191 1192 if ((status = system(cmd)) == -1) { 1193 ret = dt_link_error(dtp, "failed to run %s: %s", 1194 dtp->dt_ld_path, strerror(errno)); 1195 goto done; 1196 } 1197 1198 (void) close(fd); /* release temporary file */ 1199 1200 if (WIFSIGNALED(status)) { 1201 ret = dt_link_error(dtp, 1202 "failed to link %s: %s failed due to signal %d", 1203 file, dtp->dt_ld_path, WTERMSIG(status)); 1204 goto done; 1205 } 1206 1207 if (WEXITSTATUS(status) != 0) { 1208 ret = dt_link_error(dtp, 1209 "failed to link %s: %s exited with status %d\n", 1210 file, dtp->dt_ld_path, WEXITSTATUS(status)); 1211 goto done; 1212 } 1213 } else { 1214 (void) close(fd); 1215 } 1216 1217 done: 1218 dtrace_dof_destroy(dtp, dof); 1219 return (ret); 1220 } 1221