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 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 22 /* All Rights Reserved */ 23 24 25 /* Copyright (c) 1987, 1988 Microsoft Corporation */ 26 /* All Rights Reserved */ 27 28 /* 29 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 30 * Use is subject to license terms. 31 */ 32 33 /* 34 * ELF files can exceed 2GB in size. A standard 32-bit program 35 * like 'file' cannot read past 2GB, and will be unable to see 36 * the ELF section headers that typically are at the end of the 37 * object. The simplest solution to this problem would be to make 38 * the 'file' command a 64-bit application. However, as a matter of 39 * policy, we do not want to require this. A simple command like 40 * 'file' should not carry such a requirement, especially as we 41 * support 32-bit only hardware. 42 * 43 * An alternative solution is to build this code as 32-bit 44 * large file aware. The usual way to do this is to define a pair 45 * of preprocessor definitions: 46 * 47 * _LARGEFILE64_SOURCE 48 * Map standard I/O routines to their largefile aware versions. 49 * 50 * _FILE_OFFSET_BITS=64 51 * Map off_t to off64_t 52 * 53 * The problem with this solution is that libelf is not large file capable, 54 * and the libelf header file will prevent compilation if 55 * _FILE_OFFSET_BITS is set to 64. 56 * 57 * So, the solution used in this code is to define _LARGEFILE64_SOURCE 58 * to get access to the 64-bit APIs, not to define _FILE_OFFSET_BITS, and to 59 * use our own types in place of off_t, and size_t. We read all the file 60 * data directly using pread64(), and avoid the use of libelf for anything 61 * other than the xlate functionality. 62 */ 63 #define _LARGEFILE64_SOURCE 64 #define FILE_ELF_OFF_T off64_t 65 #define FILE_ELF_SIZE_T uint64_t 66 67 #include <ctype.h> 68 #include <unistd.h> 69 #include <fcntl.h> 70 #include <stdio.h> 71 #include <libelf.h> 72 #include <stdlib.h> 73 #include <limits.h> 74 #include <locale.h> 75 #include <string.h> 76 #include <errno.h> 77 #include <procfs.h> 78 #include <sys/param.h> 79 #include <sys/types.h> 80 #include <sys/stat.h> 81 #include <sys/elf.h> 82 #include <sys/link.h> 83 #include <elfcap.h> 84 #include "file.h" 85 #include "elf_read.h" 86 87 extern const char *File; 88 89 static int get_class(void); 90 static int get_version(void); 91 static int get_format(void); 92 static int process_shdr(Elf_Info *); 93 static int process_phdr(Elf_Info *); 94 static int file_xlatetom(Elf_Type, char *); 95 static int xlatetom_nhdr(Elf_Nhdr *); 96 static int get_phdr(Elf_Info *, int); 97 static int get_shdr(Elf_Info *, int); 98 99 static Elf_Ehdr EI_Ehdr; /* Elf_Ehdr to be stored */ 100 static Elf_Word EI_Ehdr_shnum; /* # section headers */ 101 static Elf_Word EI_Ehdr_phnum; /* # program headers */ 102 static Elf_Word EI_Ehdr_shstrndx; /* Index of section hdr string table */ 103 static Elf_Shdr EI_Shdr; /* recent Elf_Shdr to be stored */ 104 static Elf_Phdr EI_Phdr; /* recent Elf_Phdr to be stored */ 105 106 107 static int 108 get_class(void) 109 { 110 return (EI_Ehdr.e_ident[EI_CLASS]); 111 } 112 113 static int 114 get_version(void) 115 { 116 /* do as what libelf:_elf_config() does */ 117 return (EI_Ehdr.e_ident[EI_VERSION] ? 118 EI_Ehdr.e_ident[EI_VERSION] : 1); 119 } 120 121 static int 122 get_format(void) 123 { 124 return (EI_Ehdr.e_ident[EI_DATA]); 125 } 126 127 /* 128 * file_xlatetom: translate different headers from file 129 * representation to memory representaion. 130 */ 131 #define HDRSZ 512 132 static int 133 file_xlatetom(Elf_Type type, char *hdr) 134 { 135 Elf_Data src, dst; 136 char *hbuf[HDRSZ]; 137 int version, format; 138 139 version = get_version(); 140 format = get_format(); 141 142 /* will convert only these types */ 143 if (type != ELF_T_EHDR && type != ELF_T_PHDR && 144 type != ELF_T_SHDR && type != ELF_T_WORD && 145 type != ELF_T_CAP && type != ELF_T_DYN) 146 return (ELF_READ_FAIL); 147 148 src.d_buf = (Elf_Void *)hdr; 149 src.d_type = type; 150 src.d_version = version; 151 152 dst.d_buf = (Elf_Void *)&hbuf; 153 dst.d_version = EV_CURRENT; 154 155 src.d_size = elf_fsize(type, 1, version); 156 dst.d_size = elf_fsize(type, 1, EV_CURRENT); 157 if (elf_xlatetom(&dst, &src, format) == NULL) 158 return (ELF_READ_FAIL); 159 160 (void) memcpy(hdr, &hbuf, dst.d_size); 161 return (ELF_READ_OKAY); 162 } 163 164 /* 165 * xlatetom_nhdr: There is no routine to convert Note header 166 * so we convert each field of this header. 167 */ 168 static int 169 xlatetom_nhdr(Elf_Nhdr *nhdr) 170 { 171 int r = ELF_READ_FAIL; 172 173 r |= file_xlatetom(ELF_T_WORD, (char *)&nhdr->n_namesz); 174 r |= file_xlatetom(ELF_T_WORD, (char *)&nhdr->n_descsz); 175 r |= file_xlatetom(ELF_T_WORD, (char *)&nhdr->n_type); 176 return (r); 177 } 178 179 /* 180 * elf_read: reads elf header, program, section headers to 181 * collect all information needed for file(1) 182 * output and stores them in Elf_Info. 183 */ 184 int 185 elf_read(int fd, Elf_Info *EI) 186 { 187 FILE_ELF_SIZE_T size; 188 int ret = 1; 189 190 Elf_Ehdr *ehdr = &EI_Ehdr; 191 192 EI->elffd = fd; 193 size = sizeof (Elf_Ehdr); 194 195 if (pread64(EI->elffd, (void*)ehdr, size, 0) != size) 196 ret = 0; 197 198 199 if (file_xlatetom(ELF_T_EHDR, (char *)ehdr) == ELF_READ_FAIL) 200 ret = 0; 201 202 if (EI->file == NULL) 203 return (ELF_READ_FAIL); 204 205 /* 206 * Extended section or program indexes in use? If so, special 207 * values in the ELF header redirect us to get the real values 208 * from shdr[0]. 209 */ 210 EI_Ehdr_shnum = EI_Ehdr.e_shnum; 211 EI_Ehdr_phnum = EI_Ehdr.e_phnum; 212 EI_Ehdr_shstrndx = EI_Ehdr.e_shstrndx; 213 if (((EI_Ehdr_shnum == 0) || (EI_Ehdr_phnum == PN_XNUM)) && 214 (EI_Ehdr.e_shoff != 0)) { 215 if (get_shdr(EI, 0) == ELF_READ_FAIL) 216 return (ELF_READ_FAIL); 217 if (EI_Ehdr_shnum == 0) 218 EI_Ehdr_shnum = EI_Shdr.sh_size; 219 if ((EI_Ehdr_phnum == PN_XNUM) && (EI_Shdr.sh_info != 0)) 220 EI_Ehdr_phnum = EI_Shdr.sh_info; 221 if (EI_Ehdr_shstrndx == SHN_XINDEX) 222 EI_Ehdr_shstrndx = EI_Shdr.sh_link; 223 } 224 225 EI->type = ehdr->e_type; 226 EI->machine = ehdr->e_machine; 227 EI->flags = ehdr->e_flags; 228 229 if (ret == 0) { 230 (void) fprintf(stderr, gettext("%s: %s: can't " 231 "read ELF header\n"), File, EI->file); 232 return (ELF_READ_FAIL); 233 } 234 if (process_phdr(EI) == ELF_READ_FAIL) 235 return (ELF_READ_FAIL); 236 237 /* We don't need section info for core files */ 238 if (ehdr->e_type != ET_CORE) 239 if (process_shdr(EI) == ELF_READ_FAIL) 240 return (ELF_READ_FAIL); 241 242 return (ELF_READ_OKAY); 243 } 244 245 /* 246 * get_phdr: reads program header of specified index. 247 */ 248 static int 249 get_phdr(Elf_Info *EI, int inx) 250 { 251 FILE_ELF_OFF_T off = 0; 252 FILE_ELF_SIZE_T size; 253 254 if (inx >= EI_Ehdr_phnum) 255 return (ELF_READ_FAIL); 256 257 size = sizeof (Elf_Phdr); 258 off = (FILE_ELF_OFF_T)EI_Ehdr.e_phoff + (inx * size); 259 if (pread64(EI->elffd, (void *)&EI_Phdr, size, off) != size) 260 return (ELF_READ_FAIL); 261 262 if (file_xlatetom(ELF_T_PHDR, (char *)&EI_Phdr) == ELF_READ_FAIL) 263 return (ELF_READ_FAIL); 264 265 return (ELF_READ_OKAY); 266 } 267 268 /* 269 * get_shdr: reads section header of specified index. 270 */ 271 static int 272 get_shdr(Elf_Info *EI, int inx) 273 { 274 FILE_ELF_OFF_T off = 0; 275 FILE_ELF_SIZE_T size; 276 277 /* 278 * Prevent access to non-existent section headers. 279 * 280 * A value of 0 for e_shoff means that there is no section header 281 * array in the file. A value of 0 for e_shndx does not necessarily 282 * mean this - there can still be a 1-element section header array 283 * to support extended section or program header indexes that 284 * exceed the 16-bit fields used in the ELF header to represent them. 285 */ 286 if ((EI_Ehdr.e_shoff == 0) || ((inx > 0) && (inx >= EI_Ehdr_shnum))) 287 return (ELF_READ_FAIL); 288 289 size = sizeof (Elf_Shdr); 290 off = (FILE_ELF_OFF_T)EI_Ehdr.e_shoff + (inx * size); 291 292 if (pread64(EI->elffd, (void *)&EI_Shdr, size, off) != size) 293 return (ELF_READ_FAIL); 294 295 if (file_xlatetom(ELF_T_SHDR, (char *)&EI_Shdr) == ELF_READ_FAIL) 296 return (ELF_READ_FAIL); 297 298 return (ELF_READ_OKAY); 299 } 300 301 /* 302 * process_phdr: Read Program Headers and see if it is a core 303 * file of either new or (pre-restructured /proc) 304 * type, read the name of the file that dumped this 305 * core, else see if this is a dynamically linked. 306 */ 307 static int 308 process_phdr(Elf_Info *EI) 309 { 310 register int inx; 311 312 Elf_Nhdr Nhdr, *nhdr; /* note header just read */ 313 Elf_Phdr *phdr = &EI_Phdr; 314 315 FILE_ELF_SIZE_T nsz, nmsz, dsz; 316 FILE_ELF_OFF_T offset; 317 int class; 318 int ntype; 319 char *psinfo, *fname; 320 321 nsz = sizeof (Elf_Nhdr); 322 nhdr = &Nhdr; 323 class = get_class(); 324 for (inx = 0; inx < EI_Ehdr_phnum; inx++) { 325 if (get_phdr(EI, inx) == ELF_READ_FAIL) 326 return (ELF_READ_FAIL); 327 328 /* read the note if it is a core */ 329 if (phdr->p_type == PT_NOTE && 330 EI_Ehdr.e_type == ET_CORE) { 331 /* 332 * If the next segment is also a note, use it instead. 333 */ 334 if (get_phdr(EI, inx+1) == ELF_READ_FAIL) 335 return (ELF_READ_FAIL); 336 if (phdr->p_type != PT_NOTE) { 337 /* read the first phdr back */ 338 if (get_phdr(EI, inx) == ELF_READ_FAIL) 339 return (ELF_READ_FAIL); 340 } 341 offset = phdr->p_offset; 342 if (pread64(EI->elffd, (void *)nhdr, nsz, offset) 343 != nsz) 344 return (ELF_READ_FAIL); 345 346 /* Translate the ELF note header */ 347 if (xlatetom_nhdr(nhdr) == ELF_READ_FAIL) 348 return (ELF_READ_FAIL); 349 350 ntype = nhdr->n_type; 351 nmsz = nhdr->n_namesz; 352 dsz = nhdr->n_descsz; 353 354 offset += nsz + ((nmsz + 0x03) & ~0x3); 355 if ((psinfo = malloc(dsz)) == NULL) { 356 int err = errno; 357 (void) fprintf(stderr, gettext("%s: malloc " 358 "failed: %s\n"), File, strerror(err)); 359 exit(1); 360 } 361 if (pread64(EI->elffd, psinfo, dsz, offset) != dsz) 362 return (ELF_READ_FAIL); 363 /* 364 * We want to print the string contained 365 * in psinfo->pr_fname[], where 'psinfo' 366 * is either an old NT_PRPSINFO structure 367 * or a new NT_PSINFO structure. 368 * 369 * Old core files have only type NT_PRPSINFO. 370 * New core files have type NT_PSINFO. 371 * 372 * These structures are also different by 373 * virtue of being contained in a core file 374 * of either 32-bit or 64-bit type. 375 * 376 * To further complicate matters, we ourself 377 * might be compiled either 32-bit or 64-bit. 378 * 379 * For these reason, we just *know* the offsets of 380 * pr_fname[] into the four different structures 381 * here, regardless of how we are compiled. 382 */ 383 if (class == ELFCLASS32) { 384 /* 32-bit core file, 32-bit structures */ 385 if (ntype == NT_PSINFO) 386 fname = psinfo + 88; 387 else /* old: NT_PRPSINFO */ 388 fname = psinfo + 84; 389 } else if (class == ELFCLASS64) { 390 /* 64-bit core file, 64-bit structures */ 391 if (ntype == NT_PSINFO) 392 fname = psinfo + 136; 393 else /* old: NT_PRPSINFO */ 394 fname = psinfo + 120; 395 } 396 EI->core_type = (ntype == NT_PRPSINFO)? 397 EC_OLDCORE : EC_NEWCORE; 398 (void) memcpy(EI->fname, fname, strlen(fname)); 399 free(psinfo); 400 } 401 if (phdr->p_type == PT_DYNAMIC) { 402 EI->dynamic = B_TRUE; 403 } 404 } 405 return (ELF_READ_OKAY); 406 } 407 408 /* 409 * process_shdr: Read Section Headers to attempt to get HW/SW 410 * capabilities by looking at the SUNW_cap 411 * section and set string in Elf_Info. 412 * Also look for symbol tables and debug 413 * information sections. Set the "stripped" field 414 * in Elf_Info with corresponding flags. 415 */ 416 static int 417 process_shdr(Elf_Info *EI) 418 { 419 int mac; 420 int i, idx; 421 char *strtab; 422 size_t strtab_sz; 423 uint64_t j; 424 Elf_Shdr *shdr = &EI_Shdr; 425 426 mac = EI_Ehdr.e_machine; 427 428 /* if there are no sections, return success anyway */ 429 if (EI_Ehdr.e_shoff == 0 && EI_Ehdr_shnum == 0) 430 return (ELF_READ_OKAY); 431 432 /* read section names from String Section */ 433 if (get_shdr(EI, EI_Ehdr_shstrndx) == ELF_READ_FAIL) 434 return (ELF_READ_FAIL); 435 436 if ((strtab = malloc(shdr->sh_size)) == NULL) 437 return (ELF_READ_FAIL); 438 439 if (pread64(EI->elffd, strtab, shdr->sh_size, shdr->sh_offset) 440 != shdr->sh_size) 441 return (ELF_READ_FAIL); 442 443 strtab_sz = shdr->sh_size; 444 445 /* read all the sections and process them */ 446 for (idx = 1, i = 0; i < EI_Ehdr_shnum; idx++, i++) { 447 char *shnam; 448 449 if (get_shdr(EI, i) == ELF_READ_FAIL) 450 return (ELF_READ_FAIL); 451 452 if (shdr->sh_type == SHT_NULL) { 453 idx--; 454 continue; 455 } 456 457 if (shdr->sh_type == SHT_SUNW_cap) { 458 char capstr[128]; 459 Elf_Cap Chdr; 460 FILE_ELF_OFF_T cap_off; 461 FILE_ELF_SIZE_T csize; 462 uint64_t capn; 463 464 cap_off = shdr->sh_offset; 465 csize = sizeof (Elf_Cap); 466 467 if (shdr->sh_size == 0 || shdr->sh_entsize == 0) { 468 (void) fprintf(stderr, ELF_ERR_ELFCAP1, 469 File, EI->file); 470 return (ELF_READ_FAIL); 471 } 472 capn = (shdr->sh_size / shdr->sh_entsize); 473 for (j = 0; j < capn; j++) { 474 /* 475 * read cap and xlate the values 476 */ 477 if ((pread64(EI->elffd, &Chdr, csize, cap_off) 478 != csize) || 479 file_xlatetom(ELF_T_CAP, (char *)&Chdr) 480 == 0) { 481 (void) fprintf(stderr, ELF_ERR_ELFCAP2, 482 File, EI->file); 483 return (ELF_READ_FAIL); 484 } 485 486 cap_off += csize; 487 488 /* 489 * Each capatibility group is terminated with 490 * CA_SUNW_NULL. Groups other than the first 491 * represent symbol capabilities, and aren't 492 * interesting here. 493 */ 494 if (Chdr.c_tag == CA_SUNW_NULL) 495 break; 496 497 (void) elfcap_tag_to_str(ELFCAP_STYLE_UC, 498 Chdr.c_tag, Chdr.c_un.c_val, capstr, 499 sizeof (capstr), ELFCAP_FMT_SNGSPACE, 500 mac); 501 502 if ((*EI->cap_str != '\0') && (*capstr != '\0')) 503 (void) strlcat(EI->cap_str, " ", 504 sizeof (EI->cap_str)); 505 506 (void) strlcat(EI->cap_str, capstr, 507 sizeof (EI->cap_str)); 508 } 509 } else if (shdr->sh_type == SHT_DYNAMIC) { 510 Elf_Dyn dyn; 511 FILE_ELF_SIZE_T dsize; 512 FILE_ELF_OFF_T doff; 513 uint64_t dynn; 514 515 doff = shdr->sh_offset; 516 dsize = sizeof (Elf_Dyn); 517 518 if (shdr->sh_size == 0 || shdr->sh_entsize == 0) { 519 (void) fprintf(stderr, ELF_ERR_DYNAMIC1, 520 File, EI->file); 521 return (ELF_READ_FAIL); 522 } 523 524 dynn = (shdr->sh_size / shdr->sh_entsize); 525 for (j = 0; j < dynn; j++) { 526 if (pread64(EI->elffd, &dyn, dsize, doff) 527 != dsize || 528 file_xlatetom(ELF_T_DYN, (char *)&dyn) 529 == 0) { 530 (void) fprintf(stderr, ELF_ERR_DYNAMIC2, 531 File, EI->file); 532 return (ELF_READ_FAIL); 533 } 534 535 doff += dsize; 536 537 if ((dyn.d_tag == DT_SUNW_KMOD) && 538 (dyn.d_un.d_val == 1)) { 539 EI->kmod = B_TRUE; 540 } 541 } 542 } 543 544 /* 545 * Definition time: 546 * - "not stripped" means that an executable file 547 * contains a Symbol Table (.symtab) 548 * - "stripped" means that an executable file 549 * does not contain a Symbol Table. 550 * When strip -l or strip -x is run, it strips the 551 * debugging information (.line section name (strip -l), 552 * .line, .debug*, .stabs*, .dwarf* section names 553 * and SHT_SUNW_DEBUGSTR and SHT_SUNW_DEBUG 554 * section types (strip -x), however the Symbol 555 * Table will still be present. 556 * Therefore, if 557 * - No Symbol Table present, then report 558 * "stripped" 559 * - Symbol Table present with debugging 560 * information (line number or debug section names, 561 * or SHT_SUNW_DEBUGSTR or SHT_SUNW_DEBUG section 562 * types) then report: 563 * "not stripped" 564 * - Symbol Table present with no debugging 565 * information (line number or debug section names, 566 * or SHT_SUNW_DEBUGSTR or SHT_SUNW_DEBUG section 567 * types) then report: 568 * "not stripped, no debugging information 569 * available" 570 */ 571 if ((EI->stripped & E_NOSTRIP) == E_NOSTRIP) 572 continue; 573 574 if (!(EI->stripped & E_SYMTAB) && 575 (shdr->sh_type == SHT_SYMTAB)) { 576 EI->stripped |= E_SYMTAB; 577 continue; 578 } 579 580 if (shdr->sh_name >= strtab_sz) 581 shnam = NULL; 582 else 583 shnam = &strtab[shdr->sh_name]; 584 585 if (!(EI->stripped & E_DBGINF) && 586 ((shdr->sh_type == SHT_SUNW_DEBUG) || 587 (shdr->sh_type == SHT_SUNW_DEBUGSTR) || 588 (shnam != NULL && is_in_list(shnam)))) { 589 EI->stripped |= E_DBGINF; 590 } 591 } 592 free(strtab); 593 594 return (ELF_READ_OKAY); 595 }