// 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_ASSEMBLY_PROGRAM_H_ #define COURGETTE_ASSEMBLY_PROGRAM_H_ #include <map> #include <set> #include <vector> #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" #include "courgette/disassembler.h" #include "courgette/memory_allocator.h" namespace courgette { class EncodedProgram; class Instruction; typedef NoThrowBuffer<Instruction*> InstructionVector; // A Label is a symbolic reference to an address. Unlike a conventional // assembly language, we always know the address. The address will later be // stored in a table and the Label will be replaced with the index into the // table. // // TODO(sra): Make fields private and add setters and getters. class Label { public: static const int kNoIndex = -1; Label() : rva_(0), index_(kNoIndex), count_(0) {} explicit Label(RVA rva) : rva_(rva), index_(kNoIndex), count_(0) {} RVA rva_; // Address referred to by the label. int index_; // Index of address in address table, kNoIndex until assigned. int count_; }; typedef std::map<RVA, Label*> RVAToLabel; // An AssemblyProgram is the result of disassembling an executable file. // // * The disassembler creates labels in the AssemblyProgram and emits // 'Instructions'. // * The disassembler then calls DefaultAssignIndexes to assign // addresses to positions in the address tables. // * [Optional step] // * At this point the AssemblyProgram can be converted into an // EncodedProgram and serialized to an output stream. // * Later, the EncodedProgram can be deserialized and assembled into // the original file. // // The optional step is to modify the AssemblyProgram. One form of modification // is to assign indexes in such a way as to make the EncodedProgram for this // AssemblyProgram look more like the EncodedProgram for some other // AssemblyProgram. The modification process should call UnassignIndexes, do // its own assignment, and then call AssignRemainingIndexes to ensure all // indexes are assigned. // class AssemblyProgram { public: explicit AssemblyProgram(ExecutableType kind); ~AssemblyProgram(); ExecutableType kind() const { return kind_; } void set_image_base(uint64 image_base) { image_base_ = image_base; } // Instructions will be assembled in the order they are emitted. // Generates an entire base relocation table. CheckBool EmitPeRelocsInstruction() WARN_UNUSED_RESULT; // Generates an ELF style relocation table for X86. CheckBool EmitElfRelocationInstruction() WARN_UNUSED_RESULT; // Generates an ELF style relocation table for ARM. CheckBool EmitElfARMRelocationInstruction() WARN_UNUSED_RESULT; // Following instruction will be assembled at address 'rva'. CheckBool EmitOriginInstruction(RVA rva) WARN_UNUSED_RESULT; // Generates a single byte of data or machine instruction. CheckBool EmitByteInstruction(uint8 byte) WARN_UNUSED_RESULT; // Generates multiple bytes of data or machine instructions. CheckBool EmitBytesInstruction(const uint8* value, uint32 len) WARN_UNUSED_RESULT; // Generates 4-byte relative reference to address of 'label'. CheckBool EmitRel32(Label* label) WARN_UNUSED_RESULT; // Generates 4-byte relative reference to address of 'label' for // ARM. CheckBool EmitRel32ARM(uint16 op, Label* label, const uint8* arm_op, uint16 op_size) WARN_UNUSED_RESULT; // Generates 4-byte absolute reference to address of 'label'. CheckBool EmitAbs32(Label* label) WARN_UNUSED_RESULT; // Looks up a label or creates a new one. Might return NULL. Label* FindOrMakeAbs32Label(RVA rva); // Looks up a label or creates a new one. Might return NULL. Label* FindOrMakeRel32Label(RVA rva); void DefaultAssignIndexes(); void UnassignIndexes(); void AssignRemainingIndexes(); EncodedProgram* Encode() const; // Accessor for instruction list. const InstructionVector& instructions() const { return instructions_; } // Returns the label if the instruction contains and absolute address, // otherwise returns NULL. Label* InstructionAbs32Label(const Instruction* instruction) const; // Returns the label if the instruction contains and rel32 offset, // otherwise returns NULL. Label* InstructionRel32Label(const Instruction* instruction) const; // Trim underused labels CheckBool TrimLabels(); void PrintLabelCounts(RVAToLabel* labels); void CountRel32ARM(); private: ExecutableType kind_; CheckBool Emit(Instruction* instruction) WARN_UNUSED_RESULT; static const int kLabelLowerLimit; // Looks up a label or creates a new one. Might return NULL. Label* FindLabel(RVA rva, RVAToLabel* labels); // Helper methods for the public versions. static void UnassignIndexes(RVAToLabel* labels); static void DefaultAssignIndexes(RVAToLabel* labels); static void AssignRemainingIndexes(RVAToLabel* labels); // Sharing instructions that emit a single byte saves a lot of space. Instruction* GetByteInstruction(uint8 byte); scoped_ptr<Instruction*[]> byte_instruction_cache_; uint64 image_base_; // Desired or mandated base address of image. InstructionVector instructions_; // All the instructions in program. // These are lookup maps to find the label associated with a given address. // We have separate label spaces for addresses referenced by rel32 labels and // abs32 labels. This is somewhat arbitrary. RVAToLabel rel32_labels_; RVAToLabel abs32_labels_; DISALLOW_COPY_AND_ASSIGN(AssemblyProgram); }; } // namespace courgette #endif // COURGETTE_ASSEMBLY_PROGRAM_H_