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