elf_file_unittest.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file. 490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "elf_file.h" 690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <limits.h> 890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <stdio.h> 990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <unistd.h> 1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <string> 1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <vector> 1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "debug.h" 1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Macro stringification. 1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// https://gcc.gnu.org/onlinedocs/cpp/Stringification.html 1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#define XSTR(S) STR(S) 1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#define STR(S) #S 1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace { 2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void GetDataFilePath(const char* name, std::string* path) { 2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string data_dir; 2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const char* bindir = getenv("bindir"); 2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (bindir) { 2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) data_dir = std::string(bindir); 2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Test data is in the gyp INTERMEDIATE_DIR subdirectory of the directory 3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // that contains the current binary. 3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) char path[PATH_MAX]; 3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) memset(path, 0, sizeof(path)); 3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ASSERT_NE(-1, readlink("/proc/self/exe", path, sizeof(path) - 1)); 3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) data_dir = std::string(path); 3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) size_t pos = data_dir.rfind('/'); 3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ASSERT_NE(std::string::npos, pos); 3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) data_dir.erase(pos + 1); 4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) data_dir += std::string(XSTR(INTERMEDIATE_DIR)); 4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) *path = data_dir + "/" + name; 4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void OpenRelocsTestFile(const char* name, FILE** stream) { 4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string path; 4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) GetDataFilePath(name, &path); 4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) FILE* testfile = fopen(path.c_str(), "rb"); 5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ASSERT_FALSE(testfile == NULL); 5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) FILE* temporary = tmpfile(); 5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ASSERT_FALSE(temporary == NULL); 5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) static const size_t buffer_size = 4096; 5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) unsigned char buffer[buffer_size]; 5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) size_t bytes; 6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) do { 6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) bytes = fread(buffer, 1, sizeof(buffer), testfile); 6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ASSERT_EQ(bytes, fwrite(buffer, 1, bytes, temporary)); 6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } while (bytes > 0); 6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ASSERT_EQ(0, fclose(testfile)); 6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ASSERT_EQ(0, fseek(temporary, 0, SEEK_SET)); 6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ASSERT_EQ(0, lseek(fileno(temporary), 0, SEEK_SET)); 6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) *stream = temporary; 7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void OpenRelocsTestFiles(FILE** relocs_so, FILE** packed_relocs_so) { 7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) OpenRelocsTestFile("elf_file_unittest_relocs.so", relocs_so); 7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) OpenRelocsTestFile("elf_file_unittest_relocs_packed.so", packed_relocs_so); 7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void CloseRelocsTestFile(FILE* temporary) { 7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) fclose(temporary); 7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void CloseRelocsTestFiles(FILE* relocs_so, FILE* packed_relocs_so) { 8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CloseRelocsTestFile(relocs_so); 8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CloseRelocsTestFile(packed_relocs_so); 8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void CheckFileContentsEqual(FILE* first, FILE* second) { 8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ASSERT_EQ(0, fseek(first, 0, SEEK_SET)); 8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ASSERT_EQ(0, fseek(second, 0, SEEK_SET)); 8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) static const size_t buffer_size = 4096; 9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) unsigned char first_buffer[buffer_size]; 9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) unsigned char second_buffer[buffer_size]; 9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) do { 9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) size_t first_read = fread(first_buffer, 1, sizeof(first_buffer), first); 9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) size_t second_read = fread(second_buffer, 1, sizeof(second_buffer), second); 9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(first_read, second_read); 9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(0, memcmp(first_buffer, second_buffer, first_read)); 10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } while (!feof(first) && !feof(second)); 10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_TRUE(feof(first) && feof(second)); 10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace 10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace relocation_packer { 10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST(ElfFile, PackRelocations) { 11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ASSERT_NE(EV_NONE, elf_version(EV_CURRENT)); 11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) FILE* relocs_so = NULL; 11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) FILE* packed_relocs_so = NULL; 11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) OpenRelocsTestFiles(&relocs_so, &packed_relocs_so); 11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (HasFatalFailure()) 11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ElfFile elf_file(fileno(relocs_so)); 11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Ensure unpacking fails (not packed). 12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_FALSE(elf_file.UnpackRelocations()); 12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Pack relocations, and check files are now identical. 12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_TRUE(elf_file.PackRelocations()); 12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CheckFileContentsEqual(relocs_so, packed_relocs_so); 126 127 CloseRelocsTestFiles(relocs_so, packed_relocs_so); 128} 129 130TEST(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