• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GetDataFilePath(const char * name,std::string * path)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 
OpenRelocsTestFile(const char * name,FILE ** stream)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 
OpenRelocsTestFiles(FILE ** relocs_so,FILE ** packed_relocs_so)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 
CloseRelocsTestFile(FILE * temporary)77 void CloseRelocsTestFile(FILE* temporary) {
78   fclose(temporary);
79 }
80 
CloseRelocsTestFiles(FILE * relocs_so,FILE * packed_relocs_so)81 void CloseRelocsTestFiles(FILE* relocs_so, FILE* packed_relocs_so) {
82   CloseRelocsTestFile(relocs_so);
83   CloseRelocsTestFile(packed_relocs_so);
84 }
85 
CheckFileContentsEqual(FILE * first,FILE * second)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 
TEST(ElfFile,PackRelocations)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 
TEST(ElfFile,UnpackRelocations)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