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, j, idx; 421 char *strtab; 422 size_t strtab_sz; 423 Elf_Shdr *shdr = &EI_Shdr; 424 425 mac = EI_Ehdr.e_machine; 426 427 /* if there are no sections, return success anyway */ 428 if (EI_Ehdr.e_shoff == 0 && EI_Ehdr_shnum == 0) 429 return (ELF_READ_OKAY); 430 431 /* read section names from String Section */ 432 if (get_shdr(EI, EI_Ehdr_shstrndx) == ELF_READ_FAIL) 433 return (ELF_READ_FAIL); 434 435 if ((strtab = malloc(shdr->sh_size)) == NULL) 436 return (ELF_READ_FAIL); 437 438 if (pread64(EI->elffd, strtab, shdr->sh_size, shdr->sh_offset) 439 != shdr->sh_size) 440 return (ELF_READ_FAIL); 441 442 strtab_sz = shdr->sh_size; 443 444 /* read all the sections and process them */ 445 for (idx = 1, i = 0; i < EI_Ehdr_shnum; idx++, i++) { 446 char *shnam; 447 448 if (get_shdr(EI, i) == ELF_READ_FAIL) 449 return (ELF_READ_FAIL); 450 451 if (shdr->sh_type == SHT_NULL) { 452 idx--; 453 continue; 454 } 455 456 if (shdr->sh_type == SHT_SUNW_cap) { 457 char capstr[128]; 458 Elf_Cap Chdr; 459 FILE_ELF_OFF_T cap_off; 460 FILE_ELF_SIZE_T csize; 461 int capn; 462 463 cap_off = shdr->sh_offset; 464 csize = sizeof (Elf_Cap); 465 466 if (shdr->sh_size == 0 || shdr->sh_entsize == 0) { 467 (void) fprintf(stderr, ELF_ERR_ELFCAP1, 468 File, EI->file); 469 return (ELF_READ_FAIL); 470 } 471 capn = (shdr->sh_size / shdr->sh_entsize); 472 for (j = 0; j < capn; j++) { 473 /* 474 * read cap and xlate the values 475 */ 476 if ((pread64(EI->elffd, &Chdr, csize, cap_off) 477 != csize) || 478 file_xlatetom(ELF_T_CAP, (char *)&Chdr) 479 == 0) { 480 (void) fprintf(stderr, ELF_ERR_ELFCAP2, 481 File, EI->file); 482 return (ELF_READ_FAIL); 483 } 484 485 cap_off += csize; 486 487 /* 488 * Each capatibility group is terminated with 489 * CA_SUNW_NULL. Groups other than the first 490 * represent symbol capabilities, and aren't 491 * interesting here. 492 */ 493 if (Chdr.c_tag == CA_SUNW_NULL) 494 break; 495 496 (void) elfcap_tag_to_str(ELFCAP_STYLE_UC, 497 Chdr.c_tag, Chdr.c_un.c_val, capstr, 498 sizeof (capstr), ELFCAP_FMT_SNGSPACE, 499 mac); 500 501 if ((*EI->cap_str != '\0') && (*capstr != '\0')) 502 (void) strlcat(EI->cap_str, " ", 503 sizeof (EI->cap_str)); 504 505 (void) strlcat(EI->cap_str, capstr, 506 sizeof (EI->cap_str)); 507 } 508 } else if (shdr->sh_type == SHT_DYNAMIC) { 509 Elf_Dyn dyn; 510 FILE_ELF_SIZE_T dsize; 511 FILE_ELF_OFF_T doff; 512 int dynn; 513 514 doff = shdr->sh_offset; 515 dsize = sizeof (Elf_Dyn); 516 517 if (shdr->sh_size == 0 || shdr->sh_entsize == 0) { 518 (void) fprintf(stderr, ELF_ERR_DYNAMIC1, 519 File, EI->file); 520 return (ELF_READ_FAIL); 521 } 522 523 dynn = (shdr->sh_size / shdr->sh_entsize); 524 for (j = 0; j < dynn; j++) { 525 if (pread64(EI->elffd, &dyn, dsize, doff) 526 != dsize || 527 file_xlatetom(ELF_T_DYN, (char *)&dyn) 528 == 0) { 529 (void) fprintf(stderr, ELF_ERR_DYNAMIC2, 530 File, EI->file); 531 return (ELF_READ_FAIL); 532 } 533 534 doff += dsize; 535 536 if ((dyn.d_tag == DT_SUNW_KMOD) && 537 (dyn.d_un.d_val == 1)) { 538 EI->kmod = B_TRUE; 539 } 540 } 541 } 542 543 /* 544 * Definition time: 545 * - "not stripped" means that an executable file 546 * contains a Symbol Table (.symtab) 547 * - "stripped" means that an executable file 548 * does not contain a Symbol Table. 549 * When strip -l or strip -x is run, it strips the 550 * debugging information (.line section name (strip -l), 551 * .line, .debug*, .stabs*, .dwarf* section names 552 * and SHT_SUNW_DEBUGSTR and SHT_SUNW_DEBUG 553 * section types (strip -x), however the Symbol 554 * Table will still be present. 555 * Therefore, if 556 * - No Symbol Table present, then report 557 * "stripped" 558 * - Symbol Table present with debugging 559 * information (line number or debug section names, 560 * or SHT_SUNW_DEBUGSTR or SHT_SUNW_DEBUG section 561 * types) then report: 562 * "not stripped" 563 * - Symbol Table present with no debugging 564 * information (line number or debug section names, 565 * or SHT_SUNW_DEBUGSTR or SHT_SUNW_DEBUG section 566 * types) then report: 567 * "not stripped, no debugging information 568 * available" 569 */ 570 if ((EI->stripped & E_NOSTRIP) == E_NOSTRIP) 571 continue; 572 573 if (!(EI->stripped & E_SYMTAB) && 574 (shdr->sh_type == SHT_SYMTAB)) { 575 EI->stripped |= E_SYMTAB; 576 continue; 577 } 578 579 if (shdr->sh_name >= strtab_sz) 580 shnam = NULL; 581 else 582 shnam = &strtab[shdr->sh_name]; 583 584 if (!(EI->stripped & E_DBGINF) && 585 ((shdr->sh_type == SHT_SUNW_DEBUG) || 586 (shdr->sh_type == SHT_SUNW_DEBUGSTR) || 587 (shnam != NULL && is_in_list(shnam)))) { 588 EI->stripped |= E_DBGINF; 589 } 590 } 591 free(strtab); 592 593 return (ELF_READ_OKAY); 594 }