| Index: third_party/courgette/assembly_program.cc
 | 
| ===================================================================
 | 
| --- third_party/courgette/assembly_program.cc	(revision 15668)
 | 
| +++ third_party/courgette/assembly_program.cc	(working copy)
 | 
| @@ -1,373 +0,0 @@
 | 
| -// Copyright (c) 2009 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 "third_party/courgette/assembly_program.h"
 | 
| -
 | 
| -#include <memory.h>
 | 
| -#include <algorithm>
 | 
| -#include <map>
 | 
| -#include <set>
 | 
| -#include <sstream>
 | 
| -#include <vector>
 | 
| -
 | 
| -#include "base/logging.h"
 | 
| -
 | 
| -#include "third_party/courgette/courgette.h"
 | 
| -#include "third_party/courgette/encoded_program.h"
 | 
| -
 | 
| -namespace courgette {
 | 
| -
 | 
| -// Opcodes of simple assembly language
 | 
| -enum OP {
 | 
| -  ORIGIN,         // ORIGIN <rva> - set current address for assembly.
 | 
| -  MAKERELOCS,     // Generates a base relocation table.
 | 
| -  DEFBYTE,        // DEFBYTE <value> - emit a byte literal.
 | 
| -  REL32,          // REL32 <label> - emit a rel32 encoded reference to 'label'.
 | 
| -  ABS32,          // REL32 <label> - emit am abs32 encoded reference to 'label'.
 | 
| -  LAST_OP
 | 
| -};
 | 
| -
 | 
| -// Base class for instructions.  Because we have so many instructions we want to
 | 
| -// keep them as small as possible.  For this reason we avoid virtual functions.
 | 
| -//
 | 
| -class Instruction {
 | 
| - public:
 | 
| -  OP op() const { return static_cast<OP>(op_); }
 | 
| -
 | 
| - protected:
 | 
| -  explicit Instruction(OP op) : op_(op), info_(0) {}
 | 
| -  Instruction(OP op, unsigned int info) : op_(op), info_(info) {}
 | 
| -
 | 
| -  uint32 op_   : 4;    // A few bits to store the OP code.
 | 
| -  uint32 info_ : 28;   // Remaining bits in first word available to subclass.
 | 
| -
 | 
| - private:
 | 
| -  DISALLOW_COPY_AND_ASSIGN(Instruction);
 | 
| -};
 | 
| -
 | 
| -namespace {
 | 
| -
 | 
| -// Sets the current address for the emitting instructions.
 | 
| -class OriginInstruction : public Instruction {
 | 
| - public:
 | 
| -  explicit OriginInstruction(RVA rva) : Instruction(ORIGIN, 0), rva_(rva) {}
 | 
| -  RVA origin_rva() const { return rva_; }
 | 
| - private:
 | 
| -  RVA  rva_;
 | 
| -};
 | 
| -
 | 
| -// Emits an entire base relocation table.
 | 
| -class MakeRelocsInstruction : public Instruction {
 | 
| - public:
 | 
| -  MakeRelocsInstruction() : Instruction(MAKERELOCS) {}
 | 
| -};
 | 
| -
 | 
| -// Emits a single byte.
 | 
| -class ByteInstruction : public Instruction {
 | 
| - public:
 | 
| -  explicit ByteInstruction(uint8 value) : Instruction(DEFBYTE, value) {}
 | 
| -  uint8 byte_value() const { return info_; }
 | 
| -};
 | 
| -
 | 
| -// A ABS32 to REL32 instruction emits a reference to a label's address.
 | 
| -class InstructionWithLabel : public Instruction {
 | 
| - public:
 | 
| -  InstructionWithLabel(OP op, Label* label)
 | 
| -    : Instruction(op, 0), label_(label) {
 | 
| -    if (label == NULL) NOTREACHED();
 | 
| -  }
 | 
| -  Label* label() const { return label_; }
 | 
| - private:
 | 
| -  Label* label_;
 | 
| -};
 | 
| -
 | 
| -}  // namespace
 | 
| -
 | 
| -AssemblyProgram::AssemblyProgram()
 | 
| -  : image_base_(0),
 | 
| -    byte_instruction_cache_(NULL) {
 | 
| -}
 | 
| -
 | 
| -static void DeleteContainedLabels(const RVAToLabel& labels) {
 | 
| -  for (RVAToLabel::const_iterator p = labels.begin();  p != labels.end();  ++p)
 | 
| -    delete p->second;
 | 
| -}
 | 
| -
 | 
| -AssemblyProgram::~AssemblyProgram() {
 | 
| -  for (size_t i = 0;  i < instructions_.size();  ++i) {
 | 
| -    Instruction* instruction = instructions_[i];
 | 
| -    if (instruction->op() != DEFBYTE)  // Will be in byte_instruction_cache_.
 | 
| -      delete instruction;
 | 
| -  }
 | 
| -  if (byte_instruction_cache_) {
 | 
| -    for (size_t i = 0;  i < 256;  ++i)
 | 
| -      delete byte_instruction_cache_[i];
 | 
| -    delete[] byte_instruction_cache_;
 | 
| -  }
 | 
| -  DeleteContainedLabels(rel32_labels_);
 | 
| -  DeleteContainedLabels(abs32_labels_);
 | 
| -}
 | 
| -
 | 
| -void AssemblyProgram::EmitMakeRelocsInstruction() {
 | 
| -  Emit(new MakeRelocsInstruction());
 | 
| -}
 | 
| -
 | 
| -void AssemblyProgram::EmitOriginInstruction(RVA rva) {
 | 
| -  Emit(new OriginInstruction(rva));
 | 
| -}
 | 
| -
 | 
| -void AssemblyProgram::EmitByteInstruction(uint8 byte) {
 | 
| -  Emit(GetByteInstruction(byte));
 | 
| -}
 | 
| -
 | 
| -void AssemblyProgram::EmitRel32(Label* label) {
 | 
| -  Emit(new InstructionWithLabel(REL32, label));
 | 
| -}
 | 
| -
 | 
| -void AssemblyProgram::EmitAbs32(Label* label) {
 | 
| -  Emit(new InstructionWithLabel(ABS32, label));
 | 
| -}
 | 
| -
 | 
| -Label* AssemblyProgram::FindOrMakeAbs32Label(RVA rva) {
 | 
| -  return FindLabel(rva, &abs32_labels_);
 | 
| -}
 | 
| -
 | 
| -Label* AssemblyProgram::FindOrMakeRel32Label(RVA rva) {
 | 
| -  return FindLabel(rva, &rel32_labels_);
 | 
| -}
 | 
| -
 | 
| -void AssemblyProgram::DefaultAssignIndexes() {
 | 
| -  DefaultAssignIndexes(&abs32_labels_);
 | 
| -  DefaultAssignIndexes(&rel32_labels_);
 | 
| -}
 | 
| -
 | 
| -void AssemblyProgram::UnassignIndexes() {
 | 
| -  UnassignIndexes(&abs32_labels_);
 | 
| -  UnassignIndexes(&rel32_labels_);
 | 
| -}
 | 
| -
 | 
| -void AssemblyProgram::AssignRemainingIndexes() {
 | 
| -  AssignRemainingIndexes(&abs32_labels_);
 | 
| -  AssignRemainingIndexes(&rel32_labels_);
 | 
| -}
 | 
| -
 | 
| -Label* AssemblyProgram::InstructionAbs32Label(
 | 
| -    const Instruction* instruction) const {
 | 
| -  if (instruction->op() == ABS32)
 | 
| -    return static_cast<const InstructionWithLabel*>(instruction)->label();
 | 
| -  return NULL;
 | 
| -}
 | 
| -
 | 
| -Label* AssemblyProgram::InstructionRel32Label(
 | 
| -    const Instruction* instruction) const {
 | 
| -  if (instruction->op() == REL32)
 | 
| -    return static_cast<const InstructionWithLabel*>(instruction)->label();
 | 
| -  return NULL;
 | 
| -}
 | 
| -
 | 
| -Label* AssemblyProgram::FindLabel(RVA rva, RVAToLabel* labels) {
 | 
| -  Label*& slot = (*labels)[rva];
 | 
| -  if (slot == 0) {
 | 
| -    slot = new Label(rva);
 | 
| -  }
 | 
| -  return slot;
 | 
| -}
 | 
| -
 | 
| -void AssemblyProgram::UnassignIndexes(RVAToLabel* labels) {
 | 
| -  for (RVAToLabel::iterator p = labels->begin();  p != labels->end();  ++p) {
 | 
| -    Label* current = p->second;
 | 
| -    current->index_ = Label::kNoIndex;
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -// DefaultAssignIndexes takes a set of labels and assigns indexes in increasing
 | 
| -// address order.
 | 
| -//
 | 
| -void AssemblyProgram::DefaultAssignIndexes(RVAToLabel* labels) {
 | 
| -  int index = 0;
 | 
| -  for (RVAToLabel::iterator p = labels->begin();  p != labels->end();  ++p) {
 | 
| -    Label* current = p->second;
 | 
| -    if (current->index_ != Label::kNoIndex)
 | 
| -      NOTREACHED();
 | 
| -    current->index_ = index;
 | 
| -    ++index;
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -// AssignRemainingIndexes assigns indexes to any addresses (labels) that are not
 | 
| -// yet assigned an index.
 | 
| -//
 | 
| -void AssemblyProgram::AssignRemainingIndexes(RVAToLabel* labels) {
 | 
| -  // An address table compresses best when each index is associated with an
 | 
| -  // address that is slight larger than the previous index.
 | 
| -
 | 
| -  // First see which indexes have not been used.  The 'available' vector could
 | 
| -  // grow even bigger, but the number of addresses is a better starting size
 | 
| -  // than empty.
 | 
| -  std::vector<bool> available(labels->size(), true);
 | 
| -  int used = 0;
 | 
| -
 | 
| -  for (RVAToLabel::iterator p = labels->begin();  p != labels->end();  ++p) {
 | 
| -    size_t index = p->second->index_;
 | 
| -    if (index != Label::kNoIndex) {
 | 
| -      while (index >= available.size())
 | 
| -        available.push_back(true);
 | 
| -      available.at(index) = false;
 | 
| -      ++used;
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  LOG(INFO) << used << " of " << labels->size() << " labels pre-assigned";
 | 
| -
 | 
| -  // Are there any unused labels that happen to be adjacent following a used
 | 
| -  // label?
 | 
| -  //
 | 
| -  int fill_forward_count = 0;
 | 
| -  Label* prev = 0;
 | 
| -  for (RVAToLabel::iterator p = labels->begin();  p != labels->end();  ++p) {
 | 
| -    Label* current = p->second;
 | 
| -    if (current->index_ == Label::kNoIndex) {
 | 
| -      size_t index = 0;
 | 
| -      if (prev  &&  prev->index_ != Label::kNoIndex)
 | 
| -        index = prev->index_ + 1;
 | 
| -      if (index < available.size() && available.at(index)) {
 | 
| -        current->index_ = index;
 | 
| -        available.at(index) = false;
 | 
| -        ++fill_forward_count;
 | 
| -      }
 | 
| -    }
 | 
| -    prev = current;
 | 
| -  }
 | 
| -
 | 
| -  // Are there any unused labels that happen to be adjacent preceeding a used
 | 
| -  // label?
 | 
| -  //
 | 
| -  int fill_backward_count = 0;
 | 
| -  int backward_refs = 0;
 | 
| -  prev = 0;
 | 
| -  for (RVAToLabel::reverse_iterator p = labels->rbegin();
 | 
| -       p != labels->rend();
 | 
| -       ++p) {
 | 
| -    Label* current = p->second;
 | 
| -    if (current->index_ == Label::kNoIndex) {
 | 
| -      int prev_index;
 | 
| -      if (prev)
 | 
| -        prev_index = prev->index_;
 | 
| -      else
 | 
| -        prev_index = available.size();
 | 
| -      if (prev_index != 0  &&
 | 
| -          prev_index != Label::kNoIndex  &&
 | 
| -          available.at(prev_index - 1)) {
 | 
| -        current->index_ = prev_index - 1;
 | 
| -        available.at(current->index_) = false;
 | 
| -        ++fill_backward_count;
 | 
| -      }
 | 
| -    }
 | 
| -    prev = current;
 | 
| -  }
 | 
| -
 | 
| -  // Fill in any remaining indexes
 | 
| -  int fill_infill_count = 0;
 | 
| -  int index = 0;
 | 
| -  for (RVAToLabel::iterator p = labels->begin();  p != labels->end();  ++p) {
 | 
| -    Label* current = p->second;
 | 
| -    if (current->index_ == Label::kNoIndex) {
 | 
| -      while (!available.at(index)) {
 | 
| -        ++index;
 | 
| -      }
 | 
| -      current->index_ = index;
 | 
| -      available.at(index) = false;
 | 
| -      ++index;
 | 
| -      ++fill_infill_count;
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  LOG(INFO) << "  fill"
 | 
| -            << " forward " << fill_forward_count << " "
 | 
| -            << " backward " << fill_backward_count << " "
 | 
| -            << " infill " << fill_infill_count;
 | 
| -}
 | 
| -
 | 
| -typedef void (EncodedProgram::*DefineLabelMethod)(int index, RVA value);
 | 
| -
 | 
| -static void DefineLabels(const RVAToLabel& labels,
 | 
| -                         EncodedProgram* encoded_format,
 | 
| -                         DefineLabelMethod define_label) {
 | 
| -  for (RVAToLabel::const_iterator p = labels.begin(); p != labels.end(); ++p) {
 | 
| -    Label* label = p->second;
 | 
| -    (encoded_format->*define_label)(label->index_, label->rva_);
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -EncodedProgram* AssemblyProgram::Encode() const {
 | 
| -  EncodedProgram* encoded = new EncodedProgram();
 | 
| -
 | 
| -  encoded->set_image_base(image_base_);
 | 
| -  DefineLabels(abs32_labels_, encoded, &EncodedProgram::DefineAbs32Label);
 | 
| -  DefineLabels(rel32_labels_, encoded, &EncodedProgram::DefineRel32Label);
 | 
| -  encoded->EndLabels();
 | 
| -
 | 
| -  for (size_t i = 0;  i < instructions_.size();  ++i) {
 | 
| -    Instruction* instruction = instructions_[i];
 | 
| -
 | 
| -    switch (instruction->op()) {
 | 
| -      case ORIGIN: {
 | 
| -        OriginInstruction* org = static_cast<OriginInstruction*>(instruction);
 | 
| -        encoded->AddOrigin(org->origin_rva());
 | 
| -        break;
 | 
| -      }
 | 
| -      case DEFBYTE: {
 | 
| -        uint8 b = static_cast<ByteInstruction*>(instruction)->byte_value();
 | 
| -        encoded->AddCopy(1, &b);
 | 
| -        break;
 | 
| -      }
 | 
| -      case REL32: {
 | 
| -        Label* label = static_cast<InstructionWithLabel*>(instruction)->label();
 | 
| -        encoded->AddRel32(label->index_);
 | 
| -        break;
 | 
| -      }
 | 
| -      case ABS32: {
 | 
| -        Label* label = static_cast<InstructionWithLabel*>(instruction)->label();
 | 
| -        encoded->AddAbs32(label->index_);
 | 
| -        break;
 | 
| -      }
 | 
| -      case MAKERELOCS: {
 | 
| -        encoded->AddMakeRelocs();
 | 
| -        break;
 | 
| -      }
 | 
| -      default: {
 | 
| -        NOTREACHED() << "Unknown Insn OP kind";
 | 
| -      }
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  return encoded;
 | 
| -}
 | 
| -
 | 
| -Instruction* AssemblyProgram::GetByteInstruction(uint8 byte) {
 | 
| -  if (!byte_instruction_cache_) {
 | 
| -    byte_instruction_cache_ = new Instruction*[256];
 | 
| -    for (int i = 0; i < 256; ++i) {
 | 
| -      byte_instruction_cache_[i] = new ByteInstruction(static_cast<uint8>(i));
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  return byte_instruction_cache_[byte];
 | 
| -}
 | 
| -
 | 
| -////////////////////////////////////////////////////////////////////////////////
 | 
| -
 | 
| -Status Encode(AssemblyProgram* program, EncodedProgram** output) {
 | 
| -  *output = NULL;
 | 
| -  EncodedProgram *encoded = program->Encode();
 | 
| -  if (encoded) {
 | 
| -    *output = encoded;
 | 
| -    return C_OK;
 | 
| -  } else {
 | 
| -    return C_GENERAL_ERROR;
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -}  // namespace courgette
 | 
| -
 | 
| 
 |