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 #pragma ident "%Z%%M% %I% %E% SMI" 34 35 #define _LARGEFILE64_SOURCE 36 37 #include <ctype.h> 38 #include <unistd.h> 39 #include <fcntl.h> 40 #include <stdio.h> 41 #include <libelf.h> 42 #include <stdlib.h> 43 #include <limits.h> 44 #include <locale.h> 45 #include <string.h> 46 #include <errno.h> 47 #include <procfs.h> 48 #include <sys/param.h> 49 #include <sys/types.h> 50 #include <sys/stat.h> 51 #include <sys/elf.h> 52 #include <elfcap.h> 53 #include "file.h" 54 #include "elf_read.h" 55 56 extern const char *File; 57 58 static int get_class(void); 59 static int get_version(void); 60 static int get_format(void); 61 static int process_shdr(Elf_Info *); 62 static int process_phdr(Elf_Info *); 63 static int file_xlatetom(Elf_Type, char *); 64 static int xlatetom_nhdr(Elf_Nhdr *); 65 static int get_phdr(Elf_Info *, int); 66 static int get_shdr(Elf_Info *, int); 67 68 static Elf_Ehdr EI_Ehdr; /* Elf_Ehdr to be stored */ 69 static Elf_Shdr EI_Shdr; /* recent Elf_Shdr to be stored */ 70 static Elf_Phdr EI_Phdr; /* recent Elf_Phdr to be stored */ 71 72 73 static int 74 get_class(void) 75 { 76 return (EI_Ehdr.e_ident[EI_CLASS]); 77 } 78 79 static int 80 get_version(void) 81 { 82 /* do as what libelf:_elf_config() does */ 83 return (EI_Ehdr.e_ident[EI_VERSION] ? 84 EI_Ehdr.e_ident[EI_VERSION] : 1); 85 } 86 87 static int 88 get_format(void) 89 { 90 return (EI_Ehdr.e_ident[EI_DATA]); 91 } 92 93 /* 94 * file_xlatetom: translate different headers from file 95 * representation to memory representaion. 96 */ 97 #define HDRSZ 512 98 static int 99 file_xlatetom(Elf_Type type, char *hdr) 100 { 101 Elf_Data src, dst; 102 char *hbuf[HDRSZ]; 103 int version, format; 104 105 version = get_version(); 106 format = get_format(); 107 108 /* will convert only these types */ 109 if (type != ELF_T_EHDR && type != ELF_T_PHDR && 110 type != ELF_T_SHDR && type != ELF_T_WORD && 111 type != ELF_T_CAP) 112 return (ELF_READ_FAIL); 113 114 src.d_buf = (Elf_Void *)hdr; 115 src.d_type = type; 116 src.d_version = version; 117 118 dst.d_buf = (Elf_Void *)&hbuf; 119 dst.d_version = EV_CURRENT; 120 121 src.d_size = elf_fsize(type, 1, version); 122 dst.d_size = elf_fsize(type, 1, EV_CURRENT); 123 if (elf_xlatetom(&dst, &src, format) == NULL) 124 return (ELF_READ_FAIL); 125 126 (void) memcpy(hdr, &hbuf, dst.d_size); 127 return (ELF_READ_OKAY); 128 } 129 130 /* 131 * xlatetom_nhdr: There is no routine to convert Note header 132 * so we convert each field of this header. 133 */ 134 static int 135 xlatetom_nhdr(Elf_Nhdr *nhdr) 136 { 137 int r = ELF_READ_FAIL; 138 139 r |= file_xlatetom(ELF_T_WORD, (char *)&nhdr->n_namesz); 140 r |= file_xlatetom(ELF_T_WORD, (char *)&nhdr->n_descsz); 141 r |= file_xlatetom(ELF_T_WORD, (char *)&nhdr->n_type); 142 return (r); 143 } 144 145 /* 146 * elf_read: reads elf header, program, section headers to 147 * collect all information needed for file(1) 148 * output and stores them in Elf_Info. 149 */ 150 int 151 elf_read(int fd, Elf_Info *EI) 152 { 153 size_t size; 154 int ret = 1; 155 156 Elf_Ehdr *ehdr = &EI_Ehdr; 157 158 EI->elffd = fd; 159 size = sizeof (Elf_Ehdr); 160 161 if (pread64(EI->elffd, (void*)ehdr, size, 0) != size) 162 ret = 0; 163 164 if (file_xlatetom(ELF_T_EHDR, (char *)ehdr) == ELF_READ_FAIL) 165 ret = 0; 166 167 if (EI->file == NULL) 168 return (ELF_READ_FAIL); 169 170 EI->type = ehdr->e_type; 171 EI->machine = ehdr->e_machine; 172 EI->flags = ehdr->e_flags; 173 174 if (ret == 0) { 175 (void) fprintf(stderr, gettext("%s: %s: can't " 176 "read ELF header\n"), File, EI->file); 177 return (ELF_READ_FAIL); 178 } 179 if (process_phdr(EI) == ELF_READ_FAIL) 180 return (ELF_READ_FAIL); 181 182 /* We don't need section info for core files */ 183 if (ehdr->e_type != ET_CORE) 184 if (process_shdr(EI) == ELF_READ_FAIL) 185 return (ELF_READ_FAIL); 186 187 return (ELF_READ_OKAY); 188 } 189 190 /* 191 * get_phdr: reads program header of specified index. 192 */ 193 static int 194 get_phdr(Elf_Info *EI, int inx) 195 { 196 off_t off = 0; 197 size_t size; 198 Elf_Ehdr *ehdr = &EI_Ehdr; 199 200 if (inx >= ehdr->e_phnum) 201 return (ELF_READ_FAIL); 202 203 size = sizeof (Elf_Phdr); 204 off = (off_t)ehdr->e_phoff + (inx * size); 205 if (pread64(EI->elffd, (void *)&EI_Phdr, size, off) != size) 206 return (ELF_READ_FAIL); 207 208 if (file_xlatetom(ELF_T_PHDR, (char *)&EI_Phdr) == ELF_READ_FAIL) 209 return (ELF_READ_FAIL); 210 211 return (ELF_READ_OKAY); 212 } 213 214 /* 215 * get_shdr: reads section header of specified index. 216 */ 217 static int 218 get_shdr(Elf_Info *EI, int inx) 219 { 220 off_t off = 0; 221 size_t size; 222 Elf_Ehdr *ehdr = &EI_Ehdr; 223 224 if (inx >= ehdr->e_shnum) 225 return (ELF_READ_FAIL); 226 227 size = sizeof (Elf_Shdr); 228 off = (off_t)ehdr->e_shoff + (inx * size); 229 230 if (pread64(EI->elffd, (void *)&EI_Shdr, size, off) != size) 231 return (ELF_READ_FAIL); 232 233 if (file_xlatetom(ELF_T_SHDR, (char *)&EI_Shdr) == ELF_READ_FAIL) 234 return (ELF_READ_FAIL); 235 236 return (ELF_READ_OKAY); 237 } 238 239 /* 240 * process_phdr: Read Program Headers and see if it is a core 241 * file of either new or (pre-restructured /proc) 242 * type, read the name of the file that dumped this 243 * core, else see if this is a dynamically linked. 244 */ 245 static int 246 process_phdr(Elf_Info *EI) 247 { 248 register int inx; 249 250 Elf_Nhdr Nhdr, *nhdr; /* note header just read */ 251 Elf_Phdr *phdr = &EI_Phdr; 252 253 int class; 254 int ntype; 255 size_t nsz, nmsz, dsz; 256 off_t offset; 257 char *psinfo, *fname; 258 259 nsz = sizeof (Elf_Nhdr); 260 nhdr = &Nhdr; 261 class = get_class(); 262 for (inx = 0; inx < EI_Ehdr.e_phnum; inx++) { 263 if (get_phdr(EI, inx) == ELF_READ_FAIL) 264 return (ELF_READ_FAIL); 265 266 /* read the note if it is a core */ 267 if (phdr->p_type == PT_NOTE && 268 EI_Ehdr.e_type == ET_CORE) { 269 /* 270 * If the next segment is also a note, use it instead. 271 */ 272 if (get_phdr(EI, inx+1) == ELF_READ_FAIL) 273 return (ELF_READ_FAIL); 274 if (phdr->p_type != PT_NOTE) { 275 /* read the first phdr back */ 276 if (get_phdr(EI, inx) == ELF_READ_FAIL) 277 return (ELF_READ_FAIL); 278 } 279 offset = phdr->p_offset; 280 if (pread64(EI->elffd, (void *)nhdr, nsz, offset) 281 != nsz) 282 return (ELF_READ_FAIL); 283 284 /* Translate the ELF note header */ 285 if (xlatetom_nhdr(nhdr) == ELF_READ_FAIL) 286 return (ELF_READ_FAIL); 287 288 ntype = nhdr->n_type; 289 nmsz = nhdr->n_namesz; 290 dsz = nhdr->n_descsz; 291 292 offset += nsz + ((nmsz + 0x03) & ~0x3); 293 if ((psinfo = malloc(dsz)) == NULL) { 294 int err = errno; 295 (void) fprintf(stderr, gettext("%s: malloc " 296 "failed: %s\n"), File, strerror(err)); 297 exit(1); 298 } 299 if (pread64(EI->elffd, psinfo, dsz, offset) != dsz) 300 return (ELF_READ_FAIL); 301 /* 302 * We want to print the string contained 303 * in psinfo->pr_fname[], where 'psinfo' 304 * is either an old NT_PRPSINFO structure 305 * or a new NT_PSINFO structure. 306 * 307 * Old core files have only type NT_PRPSINFO. 308 * New core files have type NT_PSINFO. 309 * 310 * These structures are also different by 311 * virtue of being contained in a core file 312 * of either 32-bit or 64-bit type. 313 * 314 * To further complicate matters, we ourself 315 * might be compiled either 32-bit or 64-bit. 316 * 317 * For these reason, we just *know* the offsets of 318 * pr_fname[] into the four different structures 319 * here, regardless of how we are compiled. 320 */ 321 if (class == ELFCLASS32) { 322 /* 32-bit core file, 32-bit structures */ 323 if (ntype == NT_PSINFO) 324 fname = psinfo + 88; 325 else /* old: NT_PRPSINFO */ 326 fname = psinfo + 84; 327 } else if (class == ELFCLASS64) { 328 /* 64-bit core file, 64-bit structures */ 329 if (ntype == NT_PSINFO) 330 fname = psinfo + 136; 331 else /* old: NT_PRPSINFO */ 332 fname = psinfo + 120; 333 } 334 EI->core_type = (ntype == NT_PRPSINFO)? 335 EC_OLDCORE : EC_NEWCORE; 336 (void) memcpy(EI->fname, fname, strlen(fname)); 337 free(psinfo); 338 } 339 if (phdr->p_type == PT_DYNAMIC) { 340 EI->dynamic = B_TRUE; 341 } 342 } 343 return (ELF_READ_OKAY); 344 } 345 346 /* 347 * process_shdr: Read Section Headers to attempt to get HW/SW 348 * capabilities by looking at the SUNW_cap 349 * section and set string in Elf_Info. 350 * Also look for symbol tables and debug 351 * information sections. Set the "stripped" field 352 * in Elf_Info with corresponding flags. 353 */ 354 static int 355 process_shdr(Elf_Info *EI) 356 { 357 int capn, mac; 358 int i, j, idx; 359 off_t cap_off; 360 size_t csize; 361 char *section_name; 362 Elf_Cap Chdr; 363 Elf_Shdr *shdr = &EI_Shdr; 364 365 366 csize = sizeof (Elf_Cap); 367 mac = EI_Ehdr.e_machine; 368 369 /* if there are no sections, return success anyway */ 370 if (EI_Ehdr.e_shoff == 0 && EI_Ehdr.e_shnum == 0) 371 return (ELF_READ_OKAY); 372 373 /* read section names from String Section */ 374 if (get_shdr(EI, EI_Ehdr.e_shstrndx) == ELF_READ_FAIL) 375 return (ELF_READ_FAIL); 376 377 if ((section_name = malloc(shdr->sh_size)) == NULL) 378 return (ELF_READ_FAIL); 379 380 if (pread64(EI->elffd, section_name, shdr->sh_size, shdr->sh_offset) 381 != shdr->sh_size) 382 return (ELF_READ_FAIL); 383 384 /* read all the sections and process them */ 385 for (idx = 1, i = 0; i < EI_Ehdr.e_shnum; idx++, i++) { 386 char *str; 387 388 if (get_shdr(EI, i) == ELF_READ_FAIL) 389 return (ELF_READ_FAIL); 390 391 if (shdr->sh_type == SHT_NULL) { 392 idx--; 393 continue; 394 } 395 396 cap_off = shdr->sh_offset; 397 if (shdr->sh_type == SHT_SUNW_cap) { 398 if (shdr->sh_size == 0 || shdr->sh_entsize == 0) { 399 (void) fprintf(stderr, ELF_ERR_ELFCAP1, 400 File, EI->file); 401 return (ELF_READ_FAIL); 402 } 403 capn = (shdr->sh_size / shdr->sh_entsize); 404 for (j = 0; j < capn; j++) { 405 /* 406 * read cap and xlate the values 407 */ 408 if (pread64(EI->elffd, &Chdr, csize, cap_off) 409 != csize || 410 file_xlatetom(ELF_T_CAP, (char *)&Chdr) 411 == 0) { 412 (void) fprintf(stderr, ELF_ERR_ELFCAP2, 413 File, EI->file); 414 return (ELF_READ_FAIL); 415 } 416 417 if (Chdr.c_tag != CA_SUNW_NULL) { 418 (void) cap_val2str(Chdr.c_tag, 419 Chdr.c_un.c_val, 420 EI->cap_str, 421 sizeof (EI->cap_str), 422 0, mac); 423 } 424 cap_off += csize; 425 } 426 } 427 428 /* 429 * Definition time: 430 * - "not stripped" means that an executable file 431 * contains a Symbol Table (.symtab) 432 * - "stripped" means that an executable file 433 * does not contain a Symbol Table. 434 * When strip -l or strip -x is run, it strips the 435 * debugging information (.line section name (strip -l), 436 * .line, .debug*, .stabs*, .dwarf* section names 437 * and SHT_SUNW_DEBUGSTR and SHT_SUNW_DEBUG 438 * section types (strip -x), however the Symbol 439 * Table will still be present. 440 * Therefore, if 441 * - No Symbol Table present, then report 442 * "stripped" 443 * - Symbol Table present with debugging 444 * information (line number or debug section names, 445 * or SHT_SUNW_DEBUGSTR or SHT_SUNW_DEBUG section 446 * types) then report: 447 * "not stripped" 448 * - Symbol Table present with no debugging 449 * information (line number or debug section names, 450 * or SHT_SUNW_DEBUGSTR or SHT_SUNW_DEBUG section 451 * types) then report: 452 * "not stripped, no debugging information 453 * available" 454 */ 455 if ((EI->stripped & E_NOSTRIP) == E_NOSTRIP) 456 continue; 457 458 if (!(EI->stripped & E_SYMTAB) && 459 (shdr->sh_type == SHT_SYMTAB)) { 460 EI->stripped |= E_SYMTAB; 461 continue; 462 } 463 464 str = §ion_name[shdr->sh_name]; 465 466 if (!(EI->stripped & E_DBGINF) && 467 ((shdr->sh_type == SHT_SUNW_DEBUG) || 468 (shdr->sh_type == SHT_SUNW_DEBUGSTR) || 469 (is_in_list(str)))) { 470 EI->stripped |= E_DBGINF; 471 } 472 } 473 free(section_name); 474 475 return (ELF_READ_OKAY); 476 } 477