LCOV - code coverage report
Current view: directory - src/trusted/validator/driver - elf_load.cc (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 76 53 69.7 %
Date: 2014-06-18 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            5180 : void ReadImage(const char *filename, Image *image) {
      20            5180 :   FILE *fp = fopen(filename, "rb");
      21            5180 :   if (fp == NULL) {
      22               0 :     printf("Failed to open input file: %s\n", filename);
      23               0 :     exit(1);
      24                 :   }
      25                 : 
      26            5180 :   fseek(fp, 0, SEEK_END);
      27            5180 :   size_t file_size = ftell(fp);
      28                 : 
      29            5180 :   image->resize(file_size);
      30                 : 
      31            5180 :   fseek(fp, 0, SEEK_SET);
      32            5180 :   size_t got = fread(&(*image)[0], 1, file_size, fp);
      33            5180 :   if (got != file_size) {
      34               0 :     printf("Unable to read image from input file: %s\n", filename);
      35               0 :     exit(1);
      36                 :   }
      37            5180 :   fclose(fp);
      38            5180 : }
      39                 : 
      40                 : 
      41                 : template<typename ElfEhdrType, typename ElfPhdrType>
      42            5180 : Segment FindTextSegment(const Image &image) {
      43                 :   // Initialization only to suppress 'uninitialized' warning.
      44            5180 :   Segment segment = {NULL, 0, 0};
      45            5180 :   bool found = false;
      46                 : 
      47            5180 :   const ElfEhdrType &header = *reinterpret_cast<const ElfEhdrType *>(&image[0]);
      48           15540 :   CHECK(sizeof(header) <= image.size());
      49           15540 :   CHECK(memcmp(header.e_ident, ELFMAG, SELFMAG) == 0);
      50                 : 
      51           20748 :   for (uint64_t index = 0; index < header.e_phnum; ++index) {
      52            5194 :     uint64_t phdr_offset = header.e_phoff + header.e_phentsize * index;
      53                 :     // static_cast to silence msvc on 32-bit platform
      54            5194 :     const ElfPhdrType &phdr = *reinterpret_cast<const ElfPhdrType *>(
      55            5194 :         &image[static_cast<size_t>(phdr_offset)]);
      56                 : 
      57                 :     // TODO(shcherbina): size of other loadable segments
      58           10378 :     if (phdr.p_type == PT_LOAD && (phdr.p_flags & PF_X)) {
      59            5180 :       if (found) {
      60               0 :         printf("More than one text segment.\n");
      61               0 :         exit(1);
      62                 :       }
      63                 : 
      64            5180 :       if (phdr.p_flags != (PF_R | PF_X)) {
      65                 :         // Cast to support 64-bit ELF.
      66               0 :         printf("Text segment is expected to have flags PF_R | PF_X "
      67                 :                "(has 0x%" NACL_PRIx64 " instead).\n",
      68                 :                static_cast<uint64_t>(phdr.p_flags));
      69               0 :         exit(1);
      70                 :       }
      71                 : 
      72           15540 :       CHECK(phdr.p_filesz <= phdr.p_memsz);
      73            5180 :       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            5180 :       if (phdr.p_filesz > 256 << 20) {
      80               0 :         printf("Test segment is too large.\n");
      81               0 :         exit(1);
      82                 :       }
      83                 : 
      84            5180 :       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            5180 :       segment.data = &image[static_cast<size_t>(phdr.p_offset)];
      90            5180 :       segment.size = static_cast<uint32_t>(phdr.p_filesz);
      91            5180 :       segment.vaddr = static_cast<uint32_t>(phdr.p_vaddr);
      92            5180 :       found = true;
      93            5180 :     }
      94            5194 :   }
      95            5180 :   if (!found) {
      96               0 :     printf("Text segment not found.\n");
      97               0 :     exit(1);
      98                 :   }
      99            5180 :   return segment;
     100                 : }
     101                 : 
     102                 : 
     103            5180 : Architecture GetElfArch(const Image &image) {
     104                 :   // e_machine field is the same for Elf32_Ehdr and Elf64_Ehdr.
     105            5180 :   const Elf32_Ehdr &header = *reinterpret_cast<const Elf32_Ehdr *>(&image[0]);
     106            5180 :   switch (header.e_machine) {
     107                 :     case EM_386:
     108             626 :       return X86_32;
     109                 :     case EM_X86_64:
     110            4554 :       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            5180 : }
     118                 : 
     119                 : 
     120            5180 : 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            5180 :   const Elf32_Ehdr &header = *reinterpret_cast<const Elf32_Ehdr *>(&image[0]);
     125            5180 :   if (image.size() < sizeof(header) ||
     126            5180 :       memcmp(header.e_ident, ELFMAG, SELFMAG) != 0) {
     127               0 :     printf("Not an ELF file.\n");
     128               0 :     exit(1);
     129                 :   }
     130                 : 
     131            5180 :   Segment segment;
     132            5180 :   switch (header.e_ident[EI_CLASS]) {
     133                 :     case ELFCLASS32:
     134             626 :       segment = FindTextSegment<Elf32_Ehdr, Elf32_Phdr>(image);
     135             626 :       break;
     136                 :     case ELFCLASS64:
     137            4554 :       segment = FindTextSegment<Elf64_Ehdr, Elf64_Phdr>(image);
     138            4554 :       break;
     139                 :     default:
     140               0 :       printf("Invalid ELF class %d.\n", header.e_ident[EI_CLASS]);
     141               0 :       exit(1);
     142                 :   }
     143                 : 
     144            5180 :   return segment;
     145                 : }
     146                 : 
     147                 : }  // namespace elf_load

Generated by: LCOV version 1.7