Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
|
rmcilroy
2014/06/07 11:49:07
All uppercase for macro names.
simonb (inactive)
2014/06/09 14:39:19
Done.
| |
| 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 | |
| OLD | NEW |