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