aboutsummaryrefslogtreecommitdiff
path: root/disassembler_elf.h
diff options
context:
space:
mode:
authorEtienne Pierre-doray <etiennep@chromium.org>2018-08-10 17:44:37 +0000
committerCopybara-Service <copybara-worker@google.com>2021-07-25 20:34:00 -0700
commite57c4e6bb4c122686c16f40e0b9d50a2e683d42b (patch)
tree2cf002c3499a23f698d92eb0ae2b51bfe9bc1606 /disassembler_elf.h
parenta88cad0485f1c73d63ba0a1bcfccc8a68bd300c6 (diff)
downloadzucchini-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.h189
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_