Home | History | Annotate | Download | only in src
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "elf_file.h"
      6 
      7 #include <limits.h>
      8 #include <stdio.h>
      9 #include <unistd.h>
     10 #include <string>
     11 #include <vector>
     12 #include "debug.h"
     13 #include "testing/gtest/include/gtest/gtest.h"
     14 
     15 // Macro stringification.
     16 // https://gcc.gnu.org/onlinedocs/cpp/Stringification.html
     17 #define XSTR(S) STR(S)
     18 #define STR(S) #S
     19 
     20 namespace {
     21 
     22 void GetDataFilePath(const char* name, std::string* path) {
     23   std::string data_dir;
     24 
     25   const char* bindir = getenv("bindir");
     26   if (bindir) {
     27     data_dir = std::string(bindir);
     28   } else {
     29     // Test data is in the gyp INTERMEDIATE_DIR subdirectory of the directory
     30     // that contains the current binary.
     31     char path[PATH_MAX];
     32     memset(path, 0, sizeof(path));
     33     ASSERT_NE(-1, readlink("/proc/self/exe", path, sizeof(path) - 1));
     34 
     35     data_dir = std::string(path);
     36     size_t pos = data_dir.rfind('/');
     37     ASSERT_NE(std::string::npos, pos);
     38 
     39     data_dir.erase(pos + 1);
     40     data_dir += std::string(XSTR(INTERMEDIATE_DIR));
     41   }
     42 
     43   *path = data_dir + "/" + name;
     44 }
     45 
     46 void OpenRelocsTestFile(const char* name, FILE** stream) {
     47   std::string path;
     48   GetDataFilePath(name, &path);
     49 
     50   FILE* testfile = fopen(path.c_str(), "rb");
     51   ASSERT_FALSE(testfile == NULL);
     52 
     53   FILE* temporary = tmpfile();
     54   ASSERT_FALSE(temporary == NULL);
     55 
     56   static const size_t buffer_size = 4096;
     57   unsigned char buffer[buffer_size];
     58 
     59   size_t bytes;
     60   do {
     61     bytes = fread(buffer, 1, sizeof(buffer), testfile);
     62     ASSERT_EQ(bytes, fwrite(buffer, 1, bytes, temporary));
     63   } while (bytes > 0);
     64 
     65   ASSERT_EQ(0, fclose(testfile));
     66   ASSERT_EQ(0, fseek(temporary, 0, SEEK_SET));
     67   ASSERT_EQ(0, lseek(fileno(temporary), 0, SEEK_SET));
     68 
     69   *stream = temporary;
     70 }
     71 
     72 void OpenRelocsTestFiles(FILE** relocs_so, FILE** packed_relocs_so) {
     73   OpenRelocsTestFile("elf_file_unittest_relocs.so", relocs_so);
     74   OpenRelocsTestFile("elf_file_unittest_relocs_packed.so", packed_relocs_so);
     75 }
     76 
     77 void CloseRelocsTestFile(FILE* temporary) {
     78   fclose(temporary);
     79 }
     80 
     81 void CloseRelocsTestFiles(FILE* relocs_so, FILE* packed_relocs_so) {
     82   CloseRelocsTestFile(relocs_so);
     83   CloseRelocsTestFile(packed_relocs_so);
     84 }
     85 
     86 void CheckFileContentsEqual(FILE* first, FILE* second) {
     87   ASSERT_EQ(0, fseek(first, 0, SEEK_SET));
     88   ASSERT_EQ(0, fseek(second, 0, SEEK_SET));
     89 
     90   static const size_t buffer_size = 4096;
     91   unsigned char first_buffer[buffer_size];
     92   unsigned char second_buffer[buffer_size];
     93 
     94   do {
     95     size_t first_read = fread(first_buffer, 1, sizeof(first_buffer), first);
     96     size_t second_read = fread(second_buffer, 1, sizeof(second_buffer), second);
     97 
     98     EXPECT_EQ(first_read, second_read);
     99     EXPECT_EQ(0, memcmp(first_buffer, second_buffer, first_read));
    100   } while (!feof(first) && !feof(second));
    101 
    102   EXPECT_TRUE(feof(first) && feof(second));
    103 }
    104 
    105 }  // namespace
    106 
    107 namespace relocation_packer {
    108 
    109 TEST(ElfFile, PackRelocations) {
    110   ASSERT_NE(EV_NONE, elf_version(EV_CURRENT));
    111 
    112   FILE* relocs_so = NULL;
    113   FILE* packed_relocs_so = NULL;
    114   OpenRelocsTestFiles(&relocs_so, &packed_relocs_so);
    115   if (HasFatalFailure())
    116     return;
    117 
    118   ElfFile elf_file(fileno(relocs_so));
    119 
    120   // Ensure unpacking fails (not packed).
    121   EXPECT_FALSE(elf_file.UnpackRelocations());
    122 
    123   // Pack relocations, and check files are now identical.
    124   EXPECT_TRUE(elf_file.PackRelocations());
    125   CheckFileContentsEqual(relocs_so, packed_relocs_so);
    126 
    127   CloseRelocsTestFiles(relocs_so, packed_relocs_so);
    128 }
    129 
    130 TEST(ElfFile, UnpackRelocations) {
    131   ASSERT_NE(EV_NONE, elf_version(EV_CURRENT));
    132 
    133   FILE* relocs_so = NULL;
    134   FILE* packed_relocs_so = NULL;
    135   OpenRelocsTestFiles(&relocs_so, &packed_relocs_so);
    136   if (HasFatalFailure())
    137     return;
    138 
    139   ElfFile elf_file(fileno(packed_relocs_so));
    140 
    141   // Ensure packing fails (already packed).
    142   EXPECT_FALSE(elf_file.PackRelocations());
    143 
    144   // Unpack golden relocations, and check files are now identical.
    145   EXPECT_TRUE(elf_file.UnpackRelocations());
    146   CheckFileContentsEqual(packed_relocs_so, relocs_so);
    147 
    148   CloseRelocsTestFiles(relocs_so, packed_relocs_so);
    149 }
    150 
    151 }  // namespace relocation_packer
    152