diff options
author | Etienne Pierre-Doray <etiennep@chromium.org> | 2018-07-25 20:16:02 +0000 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2021-07-25 20:33:17 -0700 |
commit | a88cad0485f1c73d63ba0a1bcfccc8a68bd300c6 (patch) | |
tree | a1e2e0302064526dd50280e84651979b656f0ad2 /reloc_elf_unittest.cc | |
parent | ae27d8ed0116c53fb530b141e96df91e90c3671c (diff) | |
download | zucchini-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.cc | 127 |
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 |