LCOV - code coverage report
Current view: directory - src/trusted/validator/driver - elf_load.cc (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 74 51 68.9 %
Date: 2014-09-25 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2012 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : #include <stdio.h>
       8                 : #include <stdlib.h>
       9                 : #include <string.h>
      10                 : 
      11                 : #include "native_client/src/include/elf.h"
      12                 : #include "native_client/src/include/elf_constants.h"
      13                 : #include "native_client/src/shared/platform/nacl_check.h"
      14                 : #include "native_client/src/trusted/validator/driver/elf_load.h"
      15                 : 
      16                 : 
      17                 : namespace elf_load {
      18                 : 
      19               1 : void ReadImage(const char *filename, Image *image) {
      20               1 :   FILE *fp = fopen(filename, "rb");
      21               1 :   if (fp == NULL) {
      22               0 :     printf("Failed to open input file: %s\n", filename);
      23               0 :     exit(1);
      24                 :   }
      25                 : 
      26               1 :   fseek(fp, 0, SEEK_END);
      27               1 :   size_t file_size = ftell(fp);
      28                 : 
      29               1 :   image->resize(file_size);
      30                 : 
      31               1 :   fseek(fp, 0, SEEK_SET);
      32               1 :   size_t got = fread(&(*image)[0], 1, file_size, fp);
      33               1 :   if (got != file_size) {
      34               0 :     printf("Unable to read image from input file: %s\n", filename);
      35               0 :     exit(1);
      36                 :   }
      37               1 :   fclose(fp);
      38               1 : }
      39                 : 
      40                 : 
      41                 : template<typename ElfEhdrType, typename ElfPhdrType>
      42               2 : Segment FindTextSegment(const Image &image) {
      43                 :   // Initialization only to suppress 'uninitialized' warning.
      44               2 :   Segment segment = {NULL, 0, 0};
      45               2 :   bool found = false;
      46                 : 
      47               2 :   const ElfEhdrType &header = *reinterpret_cast<const ElfEhdrType *>(&image[0]);
      48               2 :   CHECK(sizeof(header) <= image.size());
      49               2 :   CHECK(memcmp(header.e_ident, ELFMAG, SELFMAG) == 0);
      50                 : 
      51               2 :   for (uint64_t index = 0; index < header.e_phnum; ++index) {
      52               2 :     uint64_t phdr_offset = header.e_phoff + header.e_phentsize * index;
      53                 :     // static_cast to silence msvc on 32-bit platform
      54                 :     const ElfPhdrType &phdr = *reinterpret_cast<const ElfPhdrType *>(
      55               2 :         &image[static_cast<size_t>(phdr_offset)]);
      56                 : 
      57                 :     // TODO(shcherbina): size of other loadable segments
      58               2 :     if (phdr.p_type == PT_LOAD && (phdr.p_flags & PF_X)) {
      59               2 :       if (found) {
      60               0 :         printf("More than one text segment.\n");
      61               0 :         exit(1);
      62                 :       }
      63                 : 
      64               2 :       if (phdr.p_flags != (PF_R | PF_X)) {
      65                 :         // Cast to support 64-bit ELF.
      66                 :         printf("Text segment is expected to have flags PF_R | PF_X "
      67                 :                "(has 0x%" NACL_PRIx64 " instead).\n",
      68               0 :                static_cast<uint64_t>(phdr.p_flags));
      69               0 :         exit(1);
      70                 :       }
      71                 : 
      72               2 :       CHECK(phdr.p_filesz <= phdr.p_memsz);
      73               2 :       if (phdr.p_filesz < phdr.p_memsz) {
      74               0 :         printf("File image is smaller than memory image size.\n");
      75               0 :         exit(1);
      76                 :       }
      77                 : 
      78                 :       // TODO(shcherbina): find or introduce proper constant.
      79               2 :       if (phdr.p_filesz > 256 << 20) {
      80               0 :         printf("Test segment is too large.\n");
      81               0 :         exit(1);
      82                 :       }
      83                 : 
      84               2 :       if (phdr.p_vaddr > UINT32_MAX - phdr.p_filesz) {
      85               0 :         printf("Text segment does not fit in 4GB.\n");
      86               0 :         exit(1);
      87                 :       }
      88                 : 
      89               2 :       segment.data = &image[static_cast<size_t>(phdr.p_offset)];
      90               2 :       segment.size = static_cast<uint32_t>(phdr.p_filesz);
      91               2 :       segment.vaddr = static_cast<uint32_t>(phdr.p_vaddr);
      92               2 :       found = true;
      93                 :     }
      94               2 :   }
      95               2 :   if (!found) {
      96               0 :     printf("Text segment not found.\n");
      97               0 :     exit(1);
      98                 :   }
      99               2 :   return segment;
     100               2 : }
     101                 : 
     102                 : 
     103               1 : Architecture GetElfArch(const Image &image) {
     104                 :   // e_machine field is the same for Elf32_Ehdr and Elf64_Ehdr.
     105               1 :   const Elf32_Ehdr &header = *reinterpret_cast<const Elf32_Ehdr *>(&image[0]);
     106               1 :   switch (header.e_machine) {
     107                 :     case EM_386:
     108               1 :       return X86_32;
     109                 :     case EM_X86_64:
     110               1 :       return X86_64;
     111                 :     case EM_ARM:
     112               0 :       return ARM;
     113                 :     default:
     114               0 :       printf("Unsupported e_machine %" NACL_PRIu16 ".\n", header.e_machine);
     115               0 :       exit(1);
     116                 :   }
     117               1 : }
     118                 : 
     119                 : 
     120               1 : Segment GetElfTextSegment(const Image &image) {
     121                 :   // We don't know in advance whether it's elf32 or elf64, but we are only
     122                 :   // looking at few first fields of the header, and they are the same for
     123                 :   // Elf32_Ehdr and Elf64_Ehdr.
     124               1 :   const Elf32_Ehdr &header = *reinterpret_cast<const Elf32_Ehdr *>(&image[0]);
     125                 :   if (image.size() < sizeof(header) ||
     126               1 :       memcmp(header.e_ident, ELFMAG, SELFMAG) != 0) {
     127               0 :     printf("Not an ELF file.\n");
     128               0 :     exit(1);
     129                 :   }
     130                 : 
     131                 :   Segment segment;
     132               1 :   switch (header.e_ident[EI_CLASS]) {
     133                 :     case ELFCLASS32:
     134               1 :       segment = FindTextSegment<Elf32_Ehdr, Elf32_Phdr>(image);
     135               1 :       break;
     136                 :     case ELFCLASS64:
     137               1 :       segment = FindTextSegment<Elf64_Ehdr, Elf64_Phdr>(image);
     138               1 :       break;
     139                 :     default:
     140               0 :       printf("Invalid ELF class %d.\n", header.e_ident[EI_CLASS]);
     141               0 :       exit(1);
     142                 :   }
     143                 : 
     144               1 :   return segment;
     145               1 : }
     146                 : 
     147                 : }  // namespace elf_load

Generated by: LCOV version 1.7