diff options
author | Etienne Pierre-doray <etiennep@chromium.org> | 2018-08-10 17:44:37 +0000 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2021-07-25 20:34:00 -0700 |
commit | e57c4e6bb4c122686c16f40e0b9d50a2e683d42b (patch) | |
tree | 2cf002c3499a23f698d92eb0ae2b51bfe9bc1606 /disassembler_elf.h | |
parent | a88cad0485f1c73d63ba0a1bcfccc8a68bd300c6 (diff) | |
download | zucchini-e57c4e6bb4c122686c16f40e0b9d50a2e683d42b.tar.gz |
[Zucchini] Create elf disassembler.
Creates Disassembler that recognises and parses ELF format. For now, it only supports Intel architeture. Support for Arm will be added in follow-up CLs.
Change-Id: Ibdcf113b573f22844b6a1611c5ff6df46829b9b3
Reviewed-on: https://chromium-review.googlesource.com/1136841
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@{#582233}
NOKEYCHECK=True
GitOrigin-RevId: 3c64e078fea9f23e44939c25ca02cf05b72b2c40
Diffstat (limited to 'disassembler_elf.h')
-rw-r--r-- | disassembler_elf.h | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/disassembler_elf.h b/disassembler_elf.h new file mode 100644 index 0000000..a5b0a72 --- /dev/null +++ b/disassembler_elf.h @@ -0,0 +1,189 @@ +// 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. + +#ifndef COMPONENTS_ZUCCHINI_DISASSEMBLER_ELF_H_ +#define COMPONENTS_ZUCCHINI_DISASSEMBLER_ELF_H_ + +#include <stdint.h> + +#include <memory> +#include <string> +#include <vector> + +#include "base/macros.h" +#include "components/zucchini/address_translator.h" +#include "components/zucchini/buffer_view.h" +#include "components/zucchini/disassembler.h" +#include "components/zucchini/image_utils.h" +#include "components/zucchini/rel32_finder.h" +#include "components/zucchini/rel32_utils.h" +#include "components/zucchini/reloc_elf.h" +#include "components/zucchini/type_elf.h" + +namespace zucchini { + +struct Elf32Traits { + static constexpr Bitness kBitness = kBit32; + static constexpr elf::FileClass kIdentificationClass = elf::ELFCLASS32; + using Elf_Shdr = elf::Elf32_Shdr; + using Elf_Phdr = elf::Elf32_Phdr; + using Elf_Ehdr = elf::Elf32_Ehdr; + using Elf_Rel = elf::Elf32_Rel; + using Elf_Rela = elf::Elf32_Rela; +}; + +// Architecture-specific definitions. +struct Elf32IntelTraits : public Elf32Traits { + static constexpr ExecutableType kExeType = kExeTypeElfX86; + static const char kExeTypeString[]; + static constexpr elf::MachineArchitecture kMachineValue = elf::EM_386; + static constexpr uint32_t kRelType = elf::R_386_RELATIVE; + using Rel32FinderUse = Rel32FinderX86; +}; + +struct Elf64Traits { + static constexpr Bitness kBitness = kBit64; + static constexpr elf::FileClass kIdentificationClass = elf::ELFCLASS64; + using Elf_Shdr = elf::Elf64_Shdr; + using Elf_Phdr = elf::Elf64_Phdr; + using Elf_Ehdr = elf::Elf64_Ehdr; + using Elf_Rel = elf::Elf64_Rel; + using Elf_Rela = elf::Elf64_Rela; +}; + +// Architecture-specific definitions. +struct Elf64IntelTraits : public Elf64Traits { + static constexpr ExecutableType kExeType = kExeTypeElfX64; + static const char kExeTypeString[]; + static constexpr elf::MachineArchitecture kMachineValue = elf::EM_X86_64; + static constexpr uint32_t kRelType = elf::R_X86_64_RELATIVE; + using Rel32FinderUse = Rel32FinderX64; +}; + +// Disassembler for ELF. +template <class Traits> +class DisassemblerElf : public Disassembler { + public: + using HeaderVector = std::vector<const typename Traits::Elf_Shdr*>; + + // Applies quick checks to determine whether |image| *may* point to the start + // of an executable. Returns true iff the check passes. + static bool QuickDetect(ConstBufferView image); + + ~DisassemblerElf() override; + + // Disassembler: + ExecutableType GetExeType() const override; + std::string GetExeTypeString() const override; + std::vector<ReferenceGroup> MakeReferenceGroups() const override = 0; + + // Find/Receive functions that are common among different architectures. + std::unique_ptr<ReferenceReader> MakeReadRelocs(offset_t lo, offset_t hi); + std::unique_ptr<ReferenceWriter> MakeWriteRelocs(MutableBufferView image); + std::unique_ptr<ReferenceReader> MakeReadAbs32(offset_t lo, offset_t hi); + std::unique_ptr<ReferenceWriter> MakeWriteAbs32(MutableBufferView image); + + const AddressTranslator& translator() const { return translator_; } + + protected: + friend Disassembler; + + DisassemblerElf(); + + bool Parse(ConstBufferView image) override; + + // Returns the supported Elf_Ehdr::e_machine enum. + static constexpr elf::MachineArchitecture supported_architecture() { + return Traits::kMachineValue; + } + + // Returns the type to look for in the reloc section. + static constexpr uint32_t supported_relocation_type() { + return Traits::kRelType; + } + + // Performs architecture-specific parsing of an executable section, to extract + // rel32 references. + virtual void ParseExecSection(const typename Traits::Elf_Shdr& section) = 0; + + // Processes rel32 data after they are extracted from executable sections. + virtual void PostProcessRel32() = 0; + + // The parsing routines below return true on success, and false on failure. + + // Parses ELF header and section headers, and performs basic validation. + bool ParseHeader(); + + // Extracts and stores section headers that we need. + void ExtractInterestingSectionHeaders(); + + // Parsing functions that extract references from various sections. + void GetAbs32FromRelocSections(); + void GetRel32FromCodeSections(); + void ParseSections(); + + // Main ELF header. + const typename Traits::Elf_Ehdr* header_ = nullptr; + + // Section header table, ordered by section id. + elf::Elf32_Half sections_count_ = 0; + const typename Traits::Elf_Shdr* sections_ = nullptr; + + // Program header table. + elf::Elf32_Half segments_count_ = 0; + const typename Traits::Elf_Phdr* segments_ = nullptr; + + // Translator between offsets and RVAs. + AddressTranslator translator_; + + // Identity translator for abs32 translation. + AddressTranslator identity_translator_; + + // Extracted relocation section dimensions data, sorted by file offsets. + std::vector<SectionDimensionsElf> reloc_section_dims_; + + // Headers of executable sections, sorted by file offsets of the data each + // header points to. + std::vector<const typename Traits::Elf_Shdr*> exec_headers_; + + // Sorted file offsets of abs32 locations. + std::vector<offset_t> abs32_locations_; + + private: + DISALLOW_COPY_AND_ASSIGN(DisassemblerElf); +}; + +// Disassembler for ELF with Intel architectures. +template <class Traits> +class DisassemblerElfIntel : public DisassemblerElf<Traits> { + public: + enum ReferenceType : uint8_t { kReloc, kAbs32, kRel32, kTypeCount }; + + DisassemblerElfIntel(); + ~DisassemblerElfIntel() override; + + // Disassembler: + std::vector<ReferenceGroup> MakeReferenceGroups() const override; + + // DisassemblerElf: + void ParseExecSection(const typename Traits::Elf_Shdr& section) override; + void PostProcessRel32() override; + + // Specialized Find/Receive functions. + std::unique_ptr<ReferenceReader> MakeReadRel32(offset_t lo, offset_t hi); + std::unique_ptr<ReferenceWriter> MakeWriteRel32(MutableBufferView image); + + private: + // Sorted file offsets of rel32 locations. + std::vector<offset_t> rel32_locations_; + + DISALLOW_COPY_AND_ASSIGN(DisassemblerElfIntel); +}; + +using DisassemblerElfX86 = DisassemblerElfIntel<Elf32IntelTraits>; +using DisassemblerElfX64 = DisassemblerElfIntel<Elf64IntelTraits>; + +} // namespace zucchini + +#endif // COMPONENTS_ZUCCHINI_DISASSEMBLER_ELF_H_ |