aboutsummaryrefslogtreecommitdiff
path: root/reloc_elf_unittest.cc
diff options
context:
space:
mode:
authorEtienne Pierre-Doray <etiennep@chromium.org>2018-07-25 20:16:02 +0000
committerCopybara-Service <copybara-worker@google.com>2021-07-25 20:33:17 -0700
commita88cad0485f1c73d63ba0a1bcfccc8a68bd300c6 (patch)
treea1e2e0302064526dd50280e84651979b656f0ad2 /reloc_elf_unittest.cc
parentae27d8ed0116c53fb530b141e96df91e90c3671c (diff)
downloadzucchini-a88cad0485f1c73d63ba0a1bcfccc8a68bd300c6.tar.gz
[Zucchini] Create elf types and utils.
Creates types and utility class to manipulate ELF header format and relocation references. BufferView: :modify() was also added. Change-Id: Iacec212a2fb2f8a6c85d551eed4b8e0a84926d89 Reviewed-on: https://chromium-review.googlesource.com/1136846 Commit-Queue: Etienne Pierre-Doray <etiennep@chromium.org> Reviewed-by: Greg Thompson <grt@chromium.org> Reviewed-by: Samuel Huang <huangs@chromium.org> Cr-Commit-Position: refs/heads/master@{#578034} NOKEYCHECK=True GitOrigin-RevId: 320f7d9d2cff9702e632af296867bf6ce7b14f8b
Diffstat (limited to 'reloc_elf_unittest.cc')
-rw-r--r--reloc_elf_unittest.cc127
1 files changed, 127 insertions, 0 deletions
diff --git a/reloc_elf_unittest.cc b/reloc_elf_unittest.cc
new file mode 100644
index 0000000..104694e
--- /dev/null
+++ b/reloc_elf_unittest.cc
@@ -0,0 +1,127 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/zucchini/reloc_elf.h"
+
+#include <stdint.h>
+
+#include <algorithm>
+#include <memory>
+#include <vector>
+
+#include "base/numerics/safe_conversions.h"
+#include "components/zucchini/address_translator.h"
+#include "components/zucchini/algorithm.h"
+#include "components/zucchini/image_utils.h"
+#include "components/zucchini/test_utils.h"
+#include "components/zucchini/type_elf.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace zucchini {
+
+namespace {
+
+template <class Elf_Shdr>
+SectionDimensionsElf MakeSectionDimensions(const BufferRegion& region,
+ offset_t entry_size) {
+ using sh_offset_t = decltype(Elf_Shdr::sh_offset);
+ using sh_size_t = decltype(Elf_Shdr::sh_size);
+ using sh_entsize_t = decltype(Elf_Shdr::sh_entsize);
+ return SectionDimensionsElf{Elf_Shdr{
+ 0, // sh_name
+ 0, // sh_type
+ 0, // sh_flags
+ 0, // sh_addr
+ // sh_offset
+ base::checked_cast<sh_offset_t>(region.offset),
+ // sh_size
+ base::checked_cast<sh_size_t>(region.size),
+ 0, // sh_link
+ 0, // sh_info
+ 0, // sh_addralign
+ // sh_entsize
+ base::checked_cast<sh_entsize_t>(entry_size),
+ }};
+}
+
+} // namespace
+
+TEST(RelocElfTest, ReadWrite32) {
+ // Set up mock image: Size = 0x3000, .reloc at 0x600. RVA is 0x40000 + offset.
+ constexpr rva_t kBaseRva = 0x40000;
+ std::vector<uint8_t> image_data(0x3000, 0xFF);
+ // "C0 10 04 00 08 00 00 00" represents
+ // (r_sym, r_type, r_offset) = (0x000000, 0x08, 0x000410C0).
+ // r_type = 0x08 = R_386_RELATIVE, and under this r_offset is an RVA
+ // 0x000410C0. Zucchini does not care about r_sym.
+ std::vector<uint8_t> reloc_data1 = ParseHexString(
+ "C0 10 04 00 08 00 00 00 " // R_386_RELATIVE.
+ "F8 10 04 00 08 AB CD EF " // R_386_RELATIVE.
+ "00 10 04 00 00 AB CD EF " // R_386_NONE.
+ "00 10 04 00 07 AB CD EF" // R_386_JMP_SLOT.
+ );
+ BufferRegion reloc_region1 = {0x600, reloc_data1.size()};
+ std::copy(reloc_data1.begin(), reloc_data1.end(),
+ image_data.begin() + reloc_region1.lo());
+
+ std::vector<uint8_t> reloc_data2 = ParseHexString(
+ "BC 20 04 00 08 00 00 00 " // R_386_RELATIVE.
+ "A0 20 04 00 08 AB CD EF" // R_386_RELATIVE.
+ );
+ BufferRegion reloc_region2 = {0x620, reloc_data2.size()};
+ std::copy(reloc_data2.begin(), reloc_data2.end(),
+ image_data.begin() + reloc_region2.lo());
+
+ ConstBufferView image = {image_data.data(), image_data.size()};
+ offset_t image_size = base::checked_cast<offset_t>(image_data.size());
+
+ AddressTranslator translator;
+ translator.Initialize({{0, image_size, kBaseRva, image_size}});
+
+ std::vector<SectionDimensionsElf> section_dimensions{
+ MakeSectionDimensions<elf::Elf32_Shdr>(reloc_region1, 8),
+ MakeSectionDimensions<elf::Elf32_Shdr>(reloc_region2, 8)};
+
+ // Make RelocReaderElf.
+ auto reader = std::make_unique<RelocReaderElf>(
+ image, kBit32, section_dimensions, elf::R_386_RELATIVE, 0, image_size,
+ translator);
+
+ // Read all references and check.
+ std::vector<Reference> refs;
+ for (base::Optional<Reference> ref = reader->GetNext(); ref.has_value();
+ ref = reader->GetNext()) {
+ refs.push_back(ref.value());
+ }
+ // Only R_386_RELATIVE references are extracted. Targets are translated from
+ // address (e.g., 0x000420BC) to offset (e.g., 0x20BC).
+ std::vector<Reference> exp_refs{
+ {0x600, 0x10C0}, {0x608, 0x10F8}, {0x620, 0x20BC}, {0x628, 0x20A0}};
+ EXPECT_EQ(exp_refs, refs);
+
+ // Write reference, extract bytes and check.
+ MutableBufferView mutable_image(&image_data[0], image_data.size());
+ auto writer =
+ std::make_unique<RelocWriterElf>(mutable_image, kBit32, translator);
+
+ writer->PutNext({0x608, 0x1F83});
+ std::vector<uint8_t> exp_reloc_data1 = ParseHexString(
+ "C0 10 04 00 08 00 00 00 " // R_386_RELATIVE.
+ "83 1F 04 00 08 AB CD EF " // R_386_RELATIVE (address modified).
+ "00 10 04 00 00 AB CD EF " // R_386_NONE.
+ "00 10 04 00 07 AB CD EF " // R_386_JMP_SLOT.
+ );
+ EXPECT_EQ(exp_reloc_data1,
+ Sub(image_data, reloc_region1.lo(), reloc_region1.hi()));
+
+ writer->PutNext({0x628, 0x2950});
+ std::vector<uint8_t> exp_reloc_data2 = ParseHexString(
+ "BC 20 04 00 08 00 00 00 " // R_386_RELATIVE.
+ "50 29 04 00 08 AB CD EF" // R_386_RELATIVE (address modified).
+ );
+ EXPECT_EQ(exp_reloc_data2,
+ Sub(image_data, reloc_region2.lo(), reloc_region2.hi()));
+}
+
+} // namespace zucchini