15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "courgette/encoded_program.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/environment.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
155e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "courgette/courgette.h"
18ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "courgette/disassembler_elf_32_arm.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "courgette/streams.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "courgette/types_elf.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace courgette {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Stream indexes.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kStreamMisc    = 0;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kStreamOps     = 1;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kStreamBytes   = 2;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kStreamAbs32Indexes = 3;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kStreamRel32Indexes = 4;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kStreamAbs32Addresses = 5;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kStreamRel32Addresses = 6;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kStreamCopyCounts = 7;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kStreamOriginAddresses = kStreamMisc;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kStreamLimit = 9;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Constructor is here rather than in the header.  Although the constructor
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// appears to do nothing it is fact quite large because of the implicit calls to
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// field constructors.  Ditto for the destructor.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EncodedProgram::EncodedProgram() : image_base_(0) {}
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EncodedProgram::~EncodedProgram() {}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Serializes a vector of integral values using Varint32 coding.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename V>
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool WriteVector(const V& items, SinkStream* buffer) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t count = items.size();
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ok = buffer->WriteSizeVarint32(count);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; ok && i < count;  ++i) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    COMPILE_ASSERT(sizeof(items[0]) <= sizeof(uint32),  // NOLINT
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   T_must_fit_in_uint32);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ok = buffer->WriteSizeVarint32(items[i]);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ok;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename V>
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ReadVector(V* items, SourceStream* buffer) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 count;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!buffer->ReadVarint32(&count))
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  items->clear();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ok = items->reserve(count);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0;  ok && i < count;  ++i) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 item;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ok = buffer->ReadVarint32(&item);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ok)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ok = items->push_back(static_cast<typename V::value_type>(item));
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ok;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Serializes a vector, using delta coding followed by Varint32 coding.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename V>
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool WriteU32Delta(const V& set, SinkStream* buffer) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t count = set.size();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ok = buffer->WriteSizeVarint32(count);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 prev = 0;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0;  ok && i < count;  ++i) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 current = set[i];
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 delta = current - prev;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ok = buffer->WriteVarint32(delta);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prev = current;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ok;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename V>
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static CheckBool ReadU32Delta(V* set, SourceStream* buffer) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 count;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!buffer->ReadVarint32(&count))
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set->clear();
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ok = set->reserve(count);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 prev = 0;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; ok && i < count;  ++i) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 delta;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ok = buffer->ReadVarint32(&delta);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ok) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      uint32 current = prev + delta;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ok = set->push_back(current);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prev = current;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ok;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Write a vector as the byte representation of the contents.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (This only really makes sense for a type T that has sizeof(T)==1, otherwise
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// serialized representation is not endian-agnostic.  But it is useful to keep
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the possibility of a greater size for experiments comparing Varint32 encoding
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of a vector of larger integrals vs a plain form.)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename V>
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool WriteVectorU8(const V& items, SinkStream* buffer) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t count = items.size();
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ok = buffer->WriteSizeVarint32(count);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (count != 0 && ok) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t byte_count = count * sizeof(typename V::value_type);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ok = buffer->Write(static_cast<const void*>(&items[0]), byte_count);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ok;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename V>
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ReadVectorU8(V* items, SourceStream* buffer) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 count;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!buffer->ReadVarint32(&count))
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  items->clear();
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ok = items->resize(count, 0);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ok && count != 0) {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t byte_count = count * sizeof(typename V::value_type);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return buffer->Read(static_cast<void*>(&((*items)[0])), byte_count);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ok;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool EncodedProgram::DefineRel32Label(int index, RVA value) {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return DefineLabelCommon(&rel32_rva_, index, value);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool EncodedProgram::DefineAbs32Label(int index, RVA value) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return DefineLabelCommon(&abs32_rva_, index, value);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const RVA kUnassignedRVA = static_cast<RVA>(-1);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool EncodedProgram::DefineLabelCommon(RvaVector* rvas,
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            int index,
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            RVA rva) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ok = true;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (static_cast<int>(rvas->size()) <= index)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ok = rvas->resize(index + 1, kUnassignedRVA);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ok) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ((*rvas)[index], kUnassignedRVA)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "DefineLabel double assigned " << index;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*rvas)[index] = rva;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ok;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EncodedProgram::EndLabels() {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FinishLabelsCommon(&abs32_rva_);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FinishLabelsCommon(&rel32_rva_);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EncodedProgram::FinishLabelsCommon(RvaVector* rvas) {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Replace all unassigned slots with the value at the previous index so they
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // delta-encode to zero.  (There might be better values than zero.  The way to
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // get that is have the higher level assembly program assign the unassigned
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // slots.)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RVA previous = 0;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t size = rvas->size();
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0;  i < size;  ++i) {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*rvas)[i] == kUnassignedRVA)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (*rvas)[i] = previous;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      previous = (*rvas)[i];
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool EncodedProgram::AddOrigin(RVA origin) {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ops_.push_back(ORIGIN) && origins_.push_back(origin);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool EncodedProgram::AddCopy(uint32 count, const void* bytes) {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint8* source = static_cast<const uint8*>(bytes);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ok = true;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fold adjacent COPY instructions into one.  This nearly halves the size of
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // an EncodedProgram with only COPY1 instructions since there are approx plain
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 16 bytes per reloc.  This has a working-set benefit during decompression.
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For compression of files with large differences this makes a small (4%)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // improvement in size.  For files with small differences this degrades the
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // compressed size by 1.3%
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ops_.empty()) {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ops_.back() == COPY1) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ops_.back() = COPY;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ok = copy_counts_.push_back(1);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ok && ops_.back() == COPY) {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      copy_counts_.back() += count;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (uint32 i = 0; ok && i < count; ++i) {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ok = copy_bytes_.push_back(source[i]);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ok;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ok) {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (count == 1) {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ok = ops_.push_back(COPY1) && copy_bytes_.push_back(source[0]);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ok = ops_.push_back(COPY) && copy_counts_.push_back(count);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (uint32 i = 0; ok && i < count; ++i) {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ok = copy_bytes_.push_back(source[i]);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ok;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool EncodedProgram::AddAbs32(int label_index) {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ops_.push_back(ABS32) && abs32_ix_.push_back(label_index);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool EncodedProgram::AddRel32(int label_index) {
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ops_.push_back(REL32) && rel32_ix_.push_back(label_index);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
246a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)CheckBool EncodedProgram::AddRel32ARM(uint16 op, int label_index) {
247a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return ops_.push_back(static_cast<OP>(op)) &&
248a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      rel32_ix_.push_back(label_index);
249a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
250a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool EncodedProgram::AddPeMakeRelocs() {
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ops_.push_back(MAKE_PE_RELOCATION_TABLE);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool EncodedProgram::AddElfMakeRelocs() {
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ops_.push_back(MAKE_ELF_RELOCATION_TABLE);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
259ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochCheckBool EncodedProgram::AddElfARMMakeRelocs() {
260ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return ops_.push_back(MAKE_ELF_ARM_RELOCATION_TABLE);
261ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
262ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EncodedProgram::DebuggingSummary() {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "EncodedProgram Summary"
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << "\n  image base  " << image_base_
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << "\n  abs32 rvas  " << abs32_rva_.size()
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << "\n  rel32 rvas  " << rel32_rva_.size()
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << "\n  ops         " << ops_.size()
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << "\n  origins     " << origins_.size()
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << "\n  copy_counts " << copy_counts_.size()
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << "\n  copy_bytes  " << copy_bytes_.size()
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << "\n  abs32_ix    " << abs32_ix_.size()
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << "\n  rel32_ix    " << rel32_ix_.size();
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For algorithm refinement purposes it is useful to write subsets of the file
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// format.  This gives us the ability to estimate the entropy of the
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// differential compression of the individual streams, which can provide
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// invaluable insights.  The default, of course, is to include all the streams.
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum FieldSelect {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  INCLUDE_ABS32_ADDRESSES = 0x0001,
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  INCLUDE_REL32_ADDRESSES = 0x0002,
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  INCLUDE_ABS32_INDEXES   = 0x0010,
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  INCLUDE_REL32_INDEXES   = 0x0020,
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  INCLUDE_OPS             = 0x0100,
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  INCLUDE_BYTES           = 0x0200,
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  INCLUDE_COPY_COUNTS     = 0x0400,
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  INCLUDE_MISC            = 0x1000
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static FieldSelect GetFieldSelect() {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 1
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(sra): Use better configuration.
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::Environment> env(base::Environment::Create());
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string s;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  env->GetVar("A_FIELDS", &s);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!s.empty()) {
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return static_cast<FieldSelect>(wcstoul(ASCIIToWide(s).c_str(), 0, 0));
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return  static_cast<FieldSelect>(~0);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool EncodedProgram::WriteTo(SinkStreamSet* streams) {
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FieldSelect select = GetFieldSelect();
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The order of fields must be consistent in WriteTo and ReadFrom, regardless
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of the streams used.  The code can be configured with all kStreamXXX
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // constants the same.
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we change the code to pipeline reading with assembly (to avoid temporary
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // storage vectors by consuming operands directly from the stream) then we
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // need to read the base address and the random access address tables first,
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the rest can be interleaved.
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (select & INCLUDE_MISC) {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(sra): write 64 bits.
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!streams->stream(kStreamMisc)->WriteVarint32(
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            static_cast<uint32>(image_base_))) {
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool success = true;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (select & INCLUDE_ABS32_ADDRESSES) {
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    success &= WriteU32Delta(abs32_rva_,
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             streams->stream(kStreamAbs32Addresses));
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (select & INCLUDE_REL32_ADDRESSES) {
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    success &= WriteU32Delta(rel32_rva_,
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             streams->stream(kStreamRel32Addresses));
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (select & INCLUDE_MISC)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    success &= WriteVector(origins_, streams->stream(kStreamOriginAddresses));
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (select & INCLUDE_OPS) {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // 5 for length.
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    success &= streams->stream(kStreamOps)->Reserve(ops_.size() + 5);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    success &= WriteVector(ops_, streams->stream(kStreamOps));
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (select & INCLUDE_COPY_COUNTS)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    success &= WriteVector(copy_counts_, streams->stream(kStreamCopyCounts));
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (select & INCLUDE_BYTES)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    success &= WriteVectorU8(copy_bytes_, streams->stream(kStreamBytes));
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (select & INCLUDE_ABS32_INDEXES)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    success &= WriteVector(abs32_ix_, streams->stream(kStreamAbs32Indexes));
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (select & INCLUDE_REL32_INDEXES)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    success &= WriteVector(rel32_ix_, streams->stream(kStreamRel32Indexes));
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return success;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool EncodedProgram::ReadFrom(SourceStreamSet* streams) {
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(sra): read 64 bits.
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 temp;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!streams->stream(kStreamMisc)->ReadVarint32(&temp))
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  image_base_ = temp;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ReadU32Delta(&abs32_rva_, streams->stream(kStreamAbs32Addresses)))
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ReadU32Delta(&rel32_rva_, streams->stream(kStreamRel32Addresses)))
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ReadVector(&origins_, streams->stream(kStreamOriginAddresses)))
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ReadVector(&ops_, streams->stream(kStreamOps)))
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ReadVector(&copy_counts_, streams->stream(kStreamCopyCounts)))
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ReadVectorU8(&copy_bytes_, streams->stream(kStreamBytes)))
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ReadVector(&abs32_ix_, streams->stream(kStreamAbs32Indexes)))
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ReadVector(&rel32_ix_, streams->stream(kStreamRel32Indexes)))
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that streams have been completely consumed.
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0;  i < kStreamLimit;  ++i) {
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (streams->stream(i)->Remaining() > 0)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Safe, non-throwing version of std::vector::at().  Returns 'true' for success,
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 'false' for out-of-bounds index error.
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename V, typename T>
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VectorAt(const V& v, size_t index, T* output) {
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (index >= v.size())
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *output = v[index];
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
406a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)CheckBool EncodedProgram::EvaluateRel32ARM(OP op,
407a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                           size_t& ix_rel32_ix,
408a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                           RVA& current_rva,
409a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                           SinkStream* output) {
410a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  switch (op & 0x0000F000) {
411a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    case REL32ARM8: {
412a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      uint32 index;
413a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      if (!VectorAt(rel32_ix_, ix_rel32_ix, &index))
414a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        return false;
415a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      ++ix_rel32_ix;
416a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      RVA rva;
417a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      if (!VectorAt(rel32_rva_, index, &rva))
418a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        return false;
419a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      uint32 decompressed_op;
420a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      if (!DisassemblerElf32ARM::Decompress(ARM_OFF8,
421a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                            static_cast<uint16>(op),
422a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                            static_cast<uint32>(rva -
423a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                                                current_rva),
424a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                            &decompressed_op)) {
425a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        return false;
426a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      }
427a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      uint16 op16 = decompressed_op;
428a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      if (!output->Write(&op16, 2))
429a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        return false;
430a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      current_rva += 2;
431a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      break;
432a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    }
433a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    case REL32ARM11: {
434a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      uint32 index;
435a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      if (!VectorAt(rel32_ix_, ix_rel32_ix, &index))
436a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        return false;
437a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      ++ix_rel32_ix;
438a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      RVA rva;
439a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      if (!VectorAt(rel32_rva_, index, &rva))
440a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        return false;
441a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      uint32 decompressed_op;
442a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      if (!DisassemblerElf32ARM::Decompress(ARM_OFF11, (uint16) op,
443a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                            (uint32) (rva - current_rva),
444a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                            &decompressed_op)) {
445a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        return false;
446a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      }
447a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      uint16 op16 = decompressed_op;
448a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      if (!output->Write(&op16, 2))
449a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        return false;
450a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      current_rva += 2;
451a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      break;
452a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    }
453a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    case REL32ARM24: {
454a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      uint32 index;
455a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      if (!VectorAt(rel32_ix_, ix_rel32_ix, &index))
456a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        return false;
457a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      ++ix_rel32_ix;
458a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      RVA rva;
459a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      if (!VectorAt(rel32_rva_, index, &rva))
460a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        return false;
461a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      uint32 decompressed_op;
462a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      if (!DisassemblerElf32ARM::Decompress(ARM_OFF24, (uint16) op,
463a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                            (uint32) (rva - current_rva),
464a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                            &decompressed_op)) {
465a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        return false;
466a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      }
467a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      if (!output->Write(&decompressed_op, 4))
468a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        return false;
469a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      current_rva += 4;
470a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      break;
471a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    }
472a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    case REL32ARM25: {
473a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      uint32 index;
474a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      if (!VectorAt(rel32_ix_, ix_rel32_ix, &index))
475a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        return false;
476a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      ++ix_rel32_ix;
477a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      RVA rva;
478a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      if (!VectorAt(rel32_rva_, index, &rva))
479a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        return false;
480a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      uint32 decompressed_op;
481a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      if (!DisassemblerElf32ARM::Decompress(ARM_OFF25, (uint16) op,
482a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                            (uint32) (rva - current_rva),
483a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                            &decompressed_op)) {
484a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        return false;
485a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      }
486a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      uint32 words = (decompressed_op << 16) | (decompressed_op >> 16);
487a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      if (!output->Write(&words, 4))
488a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        return false;
489a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      current_rva += 4;
490a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      break;
491a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    }
492a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    case REL32ARM21: {
493a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      uint32 index;
494a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      if (!VectorAt(rel32_ix_, ix_rel32_ix, &index))
495a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        return false;
496a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      ++ix_rel32_ix;
497a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      RVA rva;
498a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      if (!VectorAt(rel32_rva_, index, &rva))
499a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        return false;
500a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      uint32 decompressed_op;
501a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      if (!DisassemblerElf32ARM::Decompress(ARM_OFF21, (uint16) op,
502a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                            (uint32) (rva - current_rva),
503a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                            &decompressed_op)) {
504a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        return false;
505a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      }
506a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      uint32 words = (decompressed_op << 16) | (decompressed_op >> 16);
507a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      if (!output->Write(&words, 4))
508a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        return false;
509a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      current_rva += 4;
510a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      break;
511a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    }
512a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    default:
513a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return false;
514a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
515a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
516a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return true;
517a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
518a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool EncodedProgram::AssembleTo(SinkStream* final_buffer) {
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For the most part, the assembly process walks the various tables.
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ix_mumble is the index into the mumble table.
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t ix_origins = 0;
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t ix_copy_counts = 0;
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t ix_copy_bytes = 0;
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t ix_abs32_ix = 0;
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t ix_rel32_ix = 0;
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RVA current_rva = 0;
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool pending_pe_relocation_table = false;
531ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  Elf32_Word pending_elf_relocation_table_type = 0;
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SinkStream bytes_following_relocation_table;
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SinkStream* output = final_buffer;
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t ix_ops = 0;  ix_ops < ops_.size();  ++ix_ops) {
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OP op = ops_[ix_ops];
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (op) {
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
541a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        if (!EvaluateRel32ARM(op, ix_rel32_ix, current_rva, output))
542a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          return false;
543a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        break;
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case ORIGIN: {
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RVA section_rva;
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!VectorAt(origins_, ix_origins, &section_rva))
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ++ix_origins;
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        current_rva = section_rva;
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case COPY: {
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        uint32 count;
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!VectorAt(copy_counts_, ix_copy_counts, &count))
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ++ix_copy_counts;
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (uint32 i = 0;  i < count;  ++i) {
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          uint8 b;
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (!VectorAt(copy_bytes_, ix_copy_bytes, &b))
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return false;
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ++ix_copy_bytes;
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (!output->Write(&b, 1))
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return false;
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        current_rva += count;
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case COPY1: {
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        uint8 b;
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!VectorAt(copy_bytes_, ix_copy_bytes, &b))
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ++ix_copy_bytes;
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!output->Write(&b, 1))
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        current_rva += 1;
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case REL32: {
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        uint32 index;
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!VectorAt(rel32_ix_, ix_rel32_ix, &index))
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ++ix_rel32_ix;
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RVA rva;
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!VectorAt(rel32_rva_, index, &rva))
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        uint32 offset = (rva - (current_rva + 4));
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!output->Write(&offset, 4))
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        current_rva += 4;
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case ABS32: {
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        uint32 index;
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!VectorAt(abs32_ix_, ix_abs32_ix, &index))
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ++ix_abs32_ix;
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RVA rva;
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!VectorAt(abs32_rva_, index, &rva))
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        uint32 abs32 = static_cast<uint32>(rva + image_base_);
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!abs32_relocs_.push_back(current_rva) || !output->Write(&abs32, 4))
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        current_rva += 4;
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case MAKE_PE_RELOCATION_TABLE: {
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We can see the base relocation anywhere, but we only have the
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // information to generate it at the very end.  So we divert the bytes
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // we are generating to a temporary stream.
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (pending_pe_relocation_table)  // Can't have two base relocation
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            // tables.
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pending_pe_relocation_table = true;
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output = &bytes_following_relocation_table;
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // There is a potential problem *if* the instruction stream contains
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // some REL32 relocations following the base relocation and in the same
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // section.  We don't know the size of the table, so 'current_rva' will
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // be wrong, causing REL32 offsets to be miscalculated.  This never
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // happens; the base relocation table is usually in a section of its
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // own, a data-only section, and following everything else in the
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // executable except some padding zero bytes.  We could fix this by
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // emitting an ORIGIN after the MAKE_BASE_RELOCATION_TABLE.
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
633ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      case MAKE_ELF_ARM_RELOCATION_TABLE: {
634ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        // We can see the base relocation anywhere, but we only have the
635ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        // information to generate it at the very end.  So we divert the bytes
636ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        // we are generating to a temporary stream.
637ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        if (pending_elf_relocation_table_type)  // Can't have two relocation
638ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                                // tables.
639ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          return false;
640ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
641ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        pending_elf_relocation_table_type = R_ARM_RELATIVE;
642ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        output = &bytes_following_relocation_table;
643ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        break;
644ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      }
645ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case MAKE_ELF_RELOCATION_TABLE: {
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We can see the base relocation anywhere, but we only have the
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // information to generate it at the very end.  So we divert the bytes
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // we are generating to a temporary stream.
650ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        if (pending_elf_relocation_table_type)  // Can't have two relocation
651ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                                // tables.
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
654ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        pending_elf_relocation_table_type = R_386_RELATIVE;
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output = &bytes_following_relocation_table;
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pending_pe_relocation_table) {
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!GeneratePeRelocations(final_buffer) ||
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !final_buffer->Append(&bytes_following_relocation_table))
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
667ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (pending_elf_relocation_table_type) {
668ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (!GenerateElfRelocations(pending_elf_relocation_table_type,
669ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                final_buffer) ||
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !final_buffer->Append(&bytes_following_relocation_table))
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Final verification check: did we consume all lists?
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ix_copy_counts != copy_counts_.size())
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ix_copy_bytes != copy_bytes_.size())
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ix_abs32_ix != abs32_ix_.size())
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ix_rel32_ix != rel32_ix_.size())
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// RelocBlock has the layout of a block of relocations in the base relocation
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// table file format.
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct RelocBlockPOD {
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 page_rva;
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 block_size;
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint16 relocs[4096];  // Allow up to one relocation per byte of a 4k page.
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)COMPILE_ASSERT(offsetof(RelocBlockPOD, relocs) == 8, reloc_block_header_size);
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RelocBlock {
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RelocBlock() {
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pod.page_rva = ~0;
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pod.block_size = 8;
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Add(uint16 item) {
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pod.relocs[(pod.block_size-8)/2] = item;
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pod.block_size += 2;
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckBool Flush(SinkStream* buffer) WARN_UNUSED_RESULT {
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool ok = true;
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pod.block_size != 8) {
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (pod.block_size % 4 != 0) {  // Pad to make size multiple of 4 bytes.
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Add(0);
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ok = buffer->Write(&pod, pod.block_size);
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pod.block_size = 8;
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ok;
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RelocBlockPOD pod;
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool EncodedProgram::GeneratePeRelocations(SinkStream* buffer) {
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::sort(abs32_relocs_.begin(), abs32_relocs_.end());
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RelocBlock block;
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ok = true;
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0;  ok && i < abs32_relocs_.size();  ++i) {
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 rva = abs32_relocs_[i];
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 page_rva = rva & ~0xFFF;
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (page_rva != block.pod.page_rva) {
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ok &= block.Flush(buffer);
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      block.pod.page_rva = page_rva;
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ok)
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      block.Add(0x3000 | (rva & 0xFFF));
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ok &= block.Flush(buffer);
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ok;
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
744ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochCheckBool EncodedProgram::GenerateElfRelocations(Elf32_Word r_info,
745ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                                 SinkStream* buffer) {
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::sort(abs32_relocs_.begin(), abs32_relocs_.end());
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Elf32_Rel relocation_block;
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
750ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  relocation_block.r_info = r_info;
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ok = true;
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0;  ok && i < abs32_relocs_.size();  ++i) {
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    relocation_block.r_offset = abs32_relocs_[i];
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ok = buffer->Write(&relocation_block, sizeof(Elf32_Rel));
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ok;
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Status WriteEncodedProgram(EncodedProgram* encoded, SinkStreamSet* sink) {
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!encoded->WriteTo(sink))
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return C_STREAM_ERROR;
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return C_OK;
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Status ReadEncodedProgram(SourceStreamSet* streams, EncodedProgram** output) {
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EncodedProgram* encoded = new EncodedProgram();
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (encoded->ReadFrom(streams)) {
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *output = encoded;
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return C_OK;
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete encoded;
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return C_DESERIALIZATION_FAILED;
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Status Assemble(EncodedProgram* encoded, SinkStream* buffer) {
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool assembled = encoded->AssembleTo(buffer);
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (assembled)
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return C_OK;
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return C_ASSEMBLY_FAILED;
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeleteEncodedProgram(EncodedProgram* encoded) {
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete encoded;
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // end namespace
790