// Copyright (c) 2011 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 COURGETTE_ENCODED_PROGRAM_H_ #define COURGETTE_ENCODED_PROGRAM_H_ #include #include #include #include #include "courgette/courgette.h" #include "courgette/image_utils.h" #include "courgette/instruction_utils.h" #include "courgette/memory_allocator.h" #include "courgette/types_elf.h" namespace courgette { // Stream indexes. const int kStreamMisc = 0; const int kStreamOps = 1; const int kStreamBytes = 2; const int kStreamAbs32Indexes = 3; const int kStreamRel32Indexes = 4; const int kStreamAbs32Addresses = 5; const int kStreamRel32Addresses = 6; const int kStreamCopyCounts = 7; const int kStreamOriginAddresses = kStreamMisc; const int kStreamLimit = 9; class LabelManager; class SinkStream; class SinkStreamSet; class SourceStreamSet; // EncodedProgram encodes Courgette's simple "binary assembly language", which // can be assembled to produce a sequence of bytes (e.g., a Windows 32-bit // executable). class EncodedProgram { public: EncodedProgram(); EncodedProgram(const EncodedProgram&) = delete; EncodedProgram& operator=(const EncodedProgram&) = delete; ~EncodedProgram(); // Generating an EncodedProgram: // // (1) The image base can be specified at any time. void set_image_base(uint64_t base) { image_base_ = base; } // (2) Address tables and indexes imported first. [[nodiscard]] CheckBool ImportLabels(const LabelManager& abs32_label_manager, const LabelManager& rel32_label_manager); // (3) Add instructions in the order needed to generate bytes of file. // NOTE: If any of these methods ever fail, the EncodedProgram instance // has failed and should be discarded. [[nodiscard]] CheckBool AddOrigin(RVA rva); [[nodiscard]] CheckBool AddCopy(size_t count, const void* bytes); [[nodiscard]] CheckBool AddRel32(int label_index); [[nodiscard]] CheckBool AddAbs32(int label_index); [[nodiscard]] CheckBool AddAbs64(int label_index); [[nodiscard]] CheckBool AddPeMakeRelocs(ExecutableType kind); [[nodiscard]] CheckBool AddElfMakeRelocs(); // (3) Serialize binary assembly language tables to a set of streams. [[nodiscard]] CheckBool WriteTo(SinkStreamSet* streams); // Using an EncodedProgram to generate a byte stream: // // (4) Deserializes a fresh EncodedProgram from a set of streams. bool ReadFrom(SourceStreamSet* streams); // (5) Assembles the 'binary assembly language' into final file. [[nodiscard]] CheckBool AssembleTo(SinkStream* buffer); // Calls |gen| to extract all instructions, which are then encoded and stored. CheckBool GenerateInstructions(ExecutableType exe_type, const InstructionGenerator& gen); private: // Binary assembly language operations. // These are part of the patch format. Reusing an existing value will // break backwards compatibility. enum OP { ORIGIN = 0, // ORIGIN - set address for subsequent assembly. COPY = 1, // COPY - copy bytes to output. COPY1 = 2, // COPY1 - same as COPY 1 . REL32 = 3, // REL32 - emit rel32 encoded reference to address at // address table offset . ABS32 = 4, // ABS32 - emit abs32 encoded reference to address at // address table offset . MAKE_PE_RELOCATION_TABLE = 5, // Emit PE base relocation table blocks. MAKE_ELF_RELOCATION_TABLE = 6, // Emit ELF relocation table for X86. // DEPCREATED: ELF relocation table for ARM. // MAKE_ELF_ARM_RELOCATION_TABLE_DEPRECATED = 7, MAKE_PE64_RELOCATION_TABLE = 8, // Emit PE64 base relocation table blocks. ABS64 = 9, // ABS64 - emit abs64 encoded reference to address at // address table offset . }; typedef NoThrowBuffer RvaVector; typedef NoThrowBuffer SizeTVector; typedef NoThrowBuffer UInt32Vector; typedef NoThrowBuffer UInt8Vector; typedef NoThrowBuffer OPVector; void DebuggingSummary(); // Helper for ImportLabels(). static CheckBool WriteRvasToList(const LabelManager& label_manager, RvaVector* rvas); // Helper for ImportLabels(). static void FillUnassignedRvaSlots(RvaVector* rvas); [[nodiscard]] CheckBool GeneratePeRelocations(SinkStream* buffer, uint8_t type); [[nodiscard]] CheckBool GenerateElfRelocations( Elf32_Word pending_elf_relocation_table, SinkStream* buffer); // Binary assembly language tables. uint64_t image_base_ = 0; RvaVector rel32_rva_; RvaVector abs32_rva_; OPVector ops_; RvaVector origins_; SizeTVector copy_counts_; UInt8Vector copy_bytes_; UInt32Vector rel32_ix_; UInt32Vector abs32_ix_; // Table of the addresses containing abs32 relocations; computed during // assembly, used to generate base relocation table. UInt32Vector abs32_relocs_; }; // Deserializes program from a stream set to |*output|. Returns C_OK if // successful, otherwise assigns |*output| to null and returns an error status. Status ReadEncodedProgram(SourceStreamSet* source, std::unique_ptr* output); } // namespace courgette #endif // COURGETTE_ENCODED_PROGRAM_H_