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