187a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov// Copyright 2014 The Chromium Authors. All rights reserved.
287a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov// Use of this source code is governed by a BSD-style license that can be
387a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov// found in the LICENSE file.
487a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
587a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov#include "elf_file.h"
687a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
787a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov#include <limits.h>
887a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov#include <stdio.h>
987a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov#include <unistd.h>
1087a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov#include <string>
1187a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov#include <vector>
1287a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov#include "debug.h"
1387a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov#include "elf_traits.h"
14f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov#include "gtest/gtest.h"
1587a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
1687a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanovnamespace {
1787a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
1887a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanovvoid GetDataFilePath(const char* name, std::string* path) {
1987a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  std::string data_dir;
2087a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
2187a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  const char* bindir = getenv("bindir");
2287a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  if (bindir) {
2387a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov    data_dir = std::string(bindir);
2487a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  } else {
2587a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov    char path[PATH_MAX];
2687a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov    memset(path, 0, sizeof(path));
2787a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov    ASSERT_NE(-1, readlink("/proc/self/exe", path, sizeof(path) - 1));
2887a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
2987a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov    data_dir = std::string(path);
3087a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov    size_t pos = data_dir.rfind('/');
3187a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov    ASSERT_NE(std::string::npos, pos);
3287a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
33f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov    data_dir.erase(pos);
3487a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  }
3587a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
3687a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  *path = data_dir + "/" + name;
3787a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov}
3887a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
3987a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanovvoid OpenRelocsTestFile(const char* name, FILE** stream) {
4087a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  std::string path;
4187a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  GetDataFilePath(name, &path);
4287a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
4387a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  FILE* testfile = fopen(path.c_str(), "rb");
44f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov  ASSERT_FALSE(testfile == NULL) << "Error opening '" << path << "'";
4587a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
4687a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  FILE* temporary = tmpfile();
4787a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  ASSERT_FALSE(temporary == NULL);
4887a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
4987a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  static const size_t buffer_size = 4096;
5087a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  unsigned char buffer[buffer_size];
5187a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
5287a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  size_t bytes;
5387a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  do {
5487a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov    bytes = fread(buffer, 1, sizeof(buffer), testfile);
5587a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov    ASSERT_EQ(bytes, fwrite(buffer, 1, bytes, temporary));
5687a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  } while (bytes > 0);
5787a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
5887a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  ASSERT_EQ(0, fclose(testfile));
5987a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  ASSERT_EQ(0, fseek(temporary, 0, SEEK_SET));
6087a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  ASSERT_EQ(0, lseek(fileno(temporary), 0, SEEK_SET));
6187a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
6287a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  *stream = temporary;
6387a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov}
6487a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
65f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanovvoid OpenRelocsTestFiles(const std::string& arch, FILE** relocs_so, FILE** packed_relocs_so) {
6687a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  const std::string base = std::string("elf_file_unittest_relocs_") + arch;
6787a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  const std::string relocs = base + ".so";
6887a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  const std::string packed_relocs = base + "_packed.so";
6987a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
7087a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  OpenRelocsTestFile(relocs.c_str(), relocs_so);
7187a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  OpenRelocsTestFile(packed_relocs.c_str(), packed_relocs_so);
7287a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov}
7387a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
7487a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanovvoid CloseRelocsTestFile(FILE* temporary) {
7587a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  fclose(temporary);
7687a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov}
7787a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
7887a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanovvoid CloseRelocsTestFiles(FILE* relocs_so, FILE* packed_relocs_so) {
7987a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  CloseRelocsTestFile(relocs_so);
8087a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  CloseRelocsTestFile(packed_relocs_so);
8187a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov}
8287a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
8387a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanovvoid CheckFileContentsEqual(FILE* first, FILE* second) {
8487a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  ASSERT_EQ(0, fseek(first, 0, SEEK_SET));
8587a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  ASSERT_EQ(0, fseek(second, 0, SEEK_SET));
8687a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
8787a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  static const size_t buffer_size = 4096;
8887a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  unsigned char first_buffer[buffer_size];
8987a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  unsigned char second_buffer[buffer_size];
9087a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
9187a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  do {
9287a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov    size_t first_read = fread(first_buffer, 1, sizeof(first_buffer), first);
9387a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov    size_t second_read = fread(second_buffer, 1, sizeof(second_buffer), second);
9487a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
9587a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov    EXPECT_EQ(first_read, second_read);
9687a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov    EXPECT_EQ(0, memcmp(first_buffer, second_buffer, first_read));
9787a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  } while (!feof(first) && !feof(second));
9887a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
9987a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  EXPECT_TRUE(feof(first) && feof(second));
10087a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov}
10187a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
102f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanovtemplate <typename ELF>
103f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanovstatic void ProcessUnpack(FILE* relocs_so, FILE* packed_relocs_so) {
104f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov  relocation_packer::ElfFile<ELF> elf_file(fileno(packed_relocs_so));
10587a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
106b0b9338ff8655394311aeef77e2b795e6d8a453dDmitriy Ivanov  // Ensure packing already packed elf-file does not fail the build.
107b0b9338ff8655394311aeef77e2b795e6d8a453dDmitriy Ivanov  EXPECT_TRUE(elf_file.PackRelocations());
10887a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
109f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov  // Unpack golden relocations, and check files are now identical.
110f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov  EXPECT_TRUE(elf_file.UnpackRelocations());
111f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov  CheckFileContentsEqual(packed_relocs_so, relocs_so);
112f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov
113f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov  CloseRelocsTestFiles(relocs_so, packed_relocs_so);
114f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov}
115f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov
116f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanovstatic void RunUnpackRelocationsTestFor(const std::string& arch) {
117f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov  ASSERT_NE(static_cast<uint32_t>(EV_NONE), elf_version(EV_CURRENT));
11887a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
11987a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  FILE* relocs_so = NULL;
12087a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  FILE* packed_relocs_so = NULL;
121f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov  OpenRelocsTestFiles(arch, &relocs_so, &packed_relocs_so);
122f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov
123f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov  if (relocs_so != NULL && packed_relocs_so != NULL) {
124f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov    // lets detect elf class
125f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov    ASSERT_EQ(0, fseek(relocs_so, EI_CLASS, SEEK_SET))
126f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov        << "Invalid file length: " << strerror(errno);
127f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov    uint8_t elf_class = 0;
128f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov    ASSERT_EQ(1U, fread(&elf_class, 1, 1, relocs_so));
129f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov    ASSERT_EQ(0, fseek(relocs_so, 0, SEEK_SET));
130f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov    if (elf_class == ELFCLASS32) {
131f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov      ProcessUnpack<ELF32_traits>(relocs_so, packed_relocs_so);
132f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov    } else {
133f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov      ProcessUnpack<ELF64_traits>(relocs_so, packed_relocs_so);
134f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov    }
135f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov  }
136f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov}
13787a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
138f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanovtemplate <typename ELF>
139f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanovstatic void ProcessPack(FILE* relocs_so, FILE* packed_relocs_so) {
140f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov  relocation_packer::ElfFile<ELF> elf_file(fileno(relocs_so));
14187a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
14287a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  // Ensure unpacking fails (not packed).
14387a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  EXPECT_FALSE(elf_file.UnpackRelocations());
14487a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
14587a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  // Pack relocations, and check files are now identical.
14687a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  EXPECT_TRUE(elf_file.PackRelocations());
14787a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  CheckFileContentsEqual(relocs_so, packed_relocs_so);
14887a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
14987a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  CloseRelocsTestFiles(relocs_so, packed_relocs_so);
15087a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov}
15187a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
152f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanovstatic void RunPackRelocationsTestFor(const std::string& arch) {
153f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov  ASSERT_NE(static_cast<uint32_t>(EV_NONE), elf_version(EV_CURRENT));
15487a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
15587a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  FILE* relocs_so = NULL;
15687a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov  FILE* packed_relocs_so = NULL;
157f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov  OpenRelocsTestFiles(arch, &relocs_so, &packed_relocs_so);
158f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov
159f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov  if (relocs_so != NULL && packed_relocs_so != NULL) {
160f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov    // lets detect elf class
161f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov    ASSERT_EQ(0, fseek(packed_relocs_so, EI_CLASS, SEEK_SET))
162f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov        << "Invalid file length: " << strerror(errno);
163f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov    uint8_t elf_class = 0;
164f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov    ASSERT_EQ(1U, fread(&elf_class, 1, 1, packed_relocs_so));
165f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov    fseek(packed_relocs_so, 0, SEEK_SET);
166f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov    if (elf_class == ELFCLASS32) {
167f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov      ProcessPack<ELF32_traits>(relocs_so, packed_relocs_so);
168f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov    } else {
169f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov      ProcessPack<ELF64_traits>(relocs_so, packed_relocs_so);
170f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov    }
171f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov  }
172f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov}
17387a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
174f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov}  // namespace
17587a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
176f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanovnamespace relocation_packer {
17787a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
178f15ceeb7841ef97c24a0b7708732756d433c5d0dDmitriy IvanovTEST(ElfFile, PackRelocationsArm32) {
179f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov  RunPackRelocationsTestFor("arm32");
180f15ceeb7841ef97c24a0b7708732756d433c5d0dDmitriy Ivanov}
181f15ceeb7841ef97c24a0b7708732756d433c5d0dDmitriy Ivanov
182f15ceeb7841ef97c24a0b7708732756d433c5d0dDmitriy IvanovTEST(ElfFile, PackRelocationsArm64) {
183f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov  RunPackRelocationsTestFor("arm64");
184f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov}
18587a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
186f15ceeb7841ef97c24a0b7708732756d433c5d0dDmitriy IvanovTEST(ElfFile, UnpackRelocationsArm32) {
187f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov  RunUnpackRelocationsTestFor("arm32");
188f15ceeb7841ef97c24a0b7708732756d433c5d0dDmitriy Ivanov}
189f15ceeb7841ef97c24a0b7708732756d433c5d0dDmitriy Ivanov
190f15ceeb7841ef97c24a0b7708732756d433c5d0dDmitriy IvanovTEST(ElfFile, UnpackRelocationsArm64) {
191f8ff6b103bde3433d6f7dbf762fc7bf657d7de5fDmitriy Ivanov  RunUnpackRelocationsTestFor("arm64");
19287a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov}
19387a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov
19487a0617ebe7561bf28d3a19fbe192372598969b8Dmitriy Ivanov}  // namespace relocation_packer
195