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