Print this page
10476 file(1) could be smatch clean
10366 ld(1) should support GNU-style linker sets
10581 ld(1) should know kernel modules are a thing


  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 <elfcap.h>
  83 #include "file.h"
  84 #include "elf_read.h"
  85 
  86 extern const char *File;
  87 
  88 static int get_class(void);
  89 static int get_version(void);
  90 static int get_format(void);
  91 static int process_shdr(Elf_Info *);
  92 static int process_phdr(Elf_Info *);
  93 static int file_xlatetom(Elf_Type, char *);
  94 static int xlatetom_nhdr(Elf_Nhdr *);
  95 static int get_phdr(Elf_Info *, int);
  96 static int get_shdr(Elf_Info *, int);
  97 
  98 static Elf_Ehdr EI_Ehdr;                /* Elf_Ehdr to be stored */
  99 static Elf_Word EI_Ehdr_shnum;          /* # section headers */
 100 static Elf_Word EI_Ehdr_phnum;          /* # program headers */
 101 static Elf_Word EI_Ehdr_shstrndx;       /* Index of section hdr string table */


 124 }
 125 
 126 /*
 127  * file_xlatetom:       translate different headers from file
 128  *                      representation to memory representaion.
 129  */
 130 #define HDRSZ 512
 131 static int
 132 file_xlatetom(Elf_Type type, char *hdr)
 133 {
 134         Elf_Data src, dst;
 135         char *hbuf[HDRSZ];
 136         int version, format;
 137 
 138         version = get_version();
 139         format = get_format();
 140 
 141         /* will convert only these types */
 142         if (type != ELF_T_EHDR && type != ELF_T_PHDR &&
 143             type != ELF_T_SHDR && type != ELF_T_WORD &&
 144             type != ELF_T_CAP)
 145                 return (ELF_READ_FAIL);
 146 
 147         src.d_buf = (Elf_Void *)hdr;
 148         src.d_type = type;
 149         src.d_version = version;
 150 
 151         dst.d_buf = (Elf_Void *)&hbuf;
 152         dst.d_version = EV_CURRENT;
 153 
 154         src.d_size = elf_fsize(type, 1, version);
 155         dst.d_size = elf_fsize(type, 1, EV_CURRENT);
 156         if (elf_xlatetom(&dst, &src, format) == NULL)
 157                 return (ELF_READ_FAIL);
 158 
 159         (void) memcpy(hdr, &hbuf, dst.d_size);
 160         return (ELF_READ_OKAY);
 161 }
 162 
 163 /*
 164  * xlatetom_nhdr:       There is no routine to convert Note header


 398                         free(psinfo);
 399                 }
 400                 if (phdr->p_type == PT_DYNAMIC) {
 401                         EI->dynamic = B_TRUE;
 402                 }
 403         }
 404         return (ELF_READ_OKAY);
 405 }
 406 
 407 /*
 408  * process_shdr:        Read Section Headers to attempt to get HW/SW
 409  *                      capabilities by looking at the SUNW_cap
 410  *                      section and set string in Elf_Info.
 411  *                      Also look for symbol tables and debug
 412  *                      information sections. Set the "stripped" field
 413  *                      in Elf_Info with corresponding flags.
 414  */
 415 static int
 416 process_shdr(Elf_Info *EI)
 417 {
 418         int             capn, mac;
 419         int             i, j, idx;
 420         FILE_ELF_OFF_T  cap_off;
 421         FILE_ELF_SIZE_T csize;
 422         char            *strtab;
 423         size_t          strtab_sz;
 424         Elf_Cap         Chdr;
 425         Elf_Shdr        *shdr = &EI_Shdr;
 426 
 427 
 428         csize = sizeof (Elf_Cap);
 429         mac = EI_Ehdr.e_machine;
 430 
 431         /* if there are no sections, return success anyway */
 432         if (EI_Ehdr.e_shoff == 0 && EI_Ehdr_shnum == 0)
 433                 return (ELF_READ_OKAY);
 434 
 435         /* read section names from String Section */
 436         if (get_shdr(EI, EI_Ehdr_shstrndx) == ELF_READ_FAIL)
 437                 return (ELF_READ_FAIL);
 438 
 439         if ((strtab = malloc(shdr->sh_size)) == NULL)
 440                 return (ELF_READ_FAIL);
 441 
 442         if (pread64(EI->elffd, strtab, shdr->sh_size, shdr->sh_offset)
 443             != shdr->sh_size)
 444                 return (ELF_READ_FAIL);
 445 
 446         strtab_sz = shdr->sh_size;
 447 
 448         /* read all the sections and process them */
 449         for (idx = 1, i = 0; i < EI_Ehdr_shnum; idx++, i++) {
 450                 char *shnam;
 451 
 452                 if (get_shdr(EI, i) == ELF_READ_FAIL)
 453                         return (ELF_READ_FAIL);
 454 
 455                 if (shdr->sh_type == SHT_NULL) {
 456                         idx--;
 457                         continue;
 458                 }
 459 
 460                 cap_off = shdr->sh_offset;
 461                 if (shdr->sh_type == SHT_SUNW_cap) {
 462                         char capstr[128];







 463 
 464                         if (shdr->sh_size == 0 || shdr->sh_entsize == 0) {
 465                                 (void) fprintf(stderr, ELF_ERR_ELFCAP1,
 466                                     File, EI->file);
 467                                 return (ELF_READ_FAIL);
 468                         }
 469                         capn = (shdr->sh_size / shdr->sh_entsize);
 470                         for (j = 0; j < capn; j++) {
 471                                 /*
 472                                  * read cap and xlate the values
 473                                  */
 474                                 if (pread64(EI->elffd, &Chdr, csize, cap_off)
 475                                     != csize ||
 476                                     file_xlatetom(ELF_T_CAP, (char *)&Chdr)
 477                                     == 0) {
 478                                         (void) fprintf(stderr, ELF_ERR_ELFCAP2,
 479                                             File, EI->file);
 480                                         return (ELF_READ_FAIL);
 481                                 }
 482 
 483                                 cap_off += csize;
 484 
 485                                 /*
 486                                  * Each capatibility group is terminated with
 487                                  * CA_SUNW_NULL.  Groups other than the first
 488                                  * represent symbol capabilities, and aren't
 489                                  * interesting here.
 490                                  */
 491                                 if (Chdr.c_tag == CA_SUNW_NULL)
 492                                         break;
 493 
 494                                 (void) elfcap_tag_to_str(ELFCAP_STYLE_UC,
 495                                     Chdr.c_tag, Chdr.c_un.c_val, capstr,
 496                                     sizeof (capstr), ELFCAP_FMT_SNGSPACE,
 497                                     mac);
 498 
 499                                 if ((*EI->cap_str != '\0') && (*capstr != '\0'))
 500                                         (void) strlcat(EI->cap_str, " ",
 501                                             sizeof (EI->cap_str));
 502 
 503                                 (void) strlcat(EI->cap_str, capstr,
 504                                     sizeof (EI->cap_str));

































 505                         }
 506                 }
 507 
 508                 /*
 509                  * Definition time:
 510                  *      - "not stripped" means that an executable file
 511                  *      contains a Symbol Table (.symtab)
 512                  *      - "stripped" means that an executable file
 513                  *      does not contain a Symbol Table.
 514                  * When strip -l or strip -x is run, it strips the
 515                  * debugging information (.line section name (strip -l),
 516                  * .line, .debug*, .stabs*, .dwarf* section names
 517                  * and SHT_SUNW_DEBUGSTR and SHT_SUNW_DEBUG
 518                  * section types (strip -x), however the Symbol
 519                  * Table will still be present.
 520                  * Therefore, if
 521                  *      - No Symbol Table present, then report
 522                  *              "stripped"
 523                  *      - Symbol Table present with debugging
 524                  *      information (line number or debug section names,




  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 */


 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


 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,