encoded_program.cc revision 868fa2fe829687343ffae624259930155e16dbd8
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" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string_util.h" 16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "courgette/courgette.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "courgette/streams.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "courgette/types_elf.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace courgette { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Stream indexes. 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kStreamMisc = 0; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kStreamOps = 1; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kStreamBytes = 2; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kStreamAbs32Indexes = 3; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kStreamRel32Indexes = 4; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kStreamAbs32Addresses = 5; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kStreamRel32Addresses = 6; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kStreamCopyCounts = 7; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kStreamOriginAddresses = kStreamMisc; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kStreamLimit = 9; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Constructor is here rather than in the header. Although the constructor 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// appears to do nothing it is fact quite large because of the implicit calls to 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// field constructors. Ditto for the destructor. 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EncodedProgram::EncodedProgram() : image_base_(0) {} 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EncodedProgram::~EncodedProgram() {} 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Serializes a vector of integral values using Varint32 coding. 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename V> 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool WriteVector(const V& items, SinkStream* buffer) { 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t count = items.size(); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ok = buffer->WriteSizeVarint32(count); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; ok && i < count; ++i) { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) COMPILE_ASSERT(sizeof(items[0]) <= sizeof(uint32), // NOLINT 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) T_must_fit_in_uint32); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ok = buffer->WriteSizeVarint32(items[i]); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ok; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename V> 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ReadVector(V* items, SourceStream* buffer) { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 count; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!buffer->ReadVarint32(&count)) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) items->clear(); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ok = items->reserve(count); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; ok && i < count; ++i) { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 item; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ok = buffer->ReadVarint32(&item); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ok) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ok = items->push_back(static_cast<typename V::value_type>(item)); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ok; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Serializes a vector, using delta coding followed by Varint32 coding. 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename V> 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool WriteU32Delta(const V& set, SinkStream* buffer) { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t count = set.size(); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ok = buffer->WriteSizeVarint32(count); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 prev = 0; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; ok && i < count; ++i) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 current = set[i]; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 delta = current - prev; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ok = buffer->WriteVarint32(delta); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prev = current; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ok; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename V> 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static CheckBool ReadU32Delta(V* set, SourceStream* buffer) { 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 count; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!buffer->ReadVarint32(&count)) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set->clear(); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ok = set->reserve(count); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 prev = 0; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; ok && i < count; ++i) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 delta; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ok = buffer->ReadVarint32(&delta); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ok) { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 current = prev + delta; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ok = set->push_back(current); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prev = current; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ok; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Write a vector as the byte representation of the contents. 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (This only really makes sense for a type T that has sizeof(T)==1, otherwise 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// serialized representation is not endian-agnostic. But it is useful to keep 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the possibility of a greater size for experiments comparing Varint32 encoding 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of a vector of larger integrals vs a plain form.) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename V> 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool WriteVectorU8(const V& items, SinkStream* buffer) { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t count = items.size(); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ok = buffer->WriteSizeVarint32(count); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (count != 0 && ok) { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t byte_count = count * sizeof(typename V::value_type); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ok = buffer->Write(static_cast<const void*>(&items[0]), byte_count); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ok; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename V> 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ReadVectorU8(V* items, SourceStream* buffer) { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 count; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!buffer->ReadVarint32(&count)) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) items->clear(); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ok = items->resize(count, 0); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ok && count != 0) { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t byte_count = count * sizeof(typename V::value_type); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buffer->Read(static_cast<void*>(&((*items)[0])), byte_count); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ok; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool EncodedProgram::DefineRel32Label(int index, RVA value) { 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DefineLabelCommon(&rel32_rva_, index, value); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool EncodedProgram::DefineAbs32Label(int index, RVA value) { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DefineLabelCommon(&abs32_rva_, index, value); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const RVA kUnassignedRVA = static_cast<RVA>(-1); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool EncodedProgram::DefineLabelCommon(RvaVector* rvas, 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index, 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RVA rva) { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ok = true; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (static_cast<int>(rvas->size()) <= index) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ok = rvas->resize(index + 1, kUnassignedRVA); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ok) { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ((*rvas)[index], kUnassignedRVA) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "DefineLabel double assigned " << index; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*rvas)[index] = rva; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ok; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EncodedProgram::EndLabels() { 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FinishLabelsCommon(&abs32_rva_); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FinishLabelsCommon(&rel32_rva_); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EncodedProgram::FinishLabelsCommon(RvaVector* rvas) { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Replace all unassigned slots with the value at the previous index so they 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // delta-encode to zero. (There might be better values than zero. The way to 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // get that is have the higher level assembly program assign the unassigned 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // slots.) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RVA previous = 0; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t size = rvas->size(); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < size; ++i) { 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((*rvas)[i] == kUnassignedRVA) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*rvas)[i] = previous; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previous = (*rvas)[i]; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool EncodedProgram::AddOrigin(RVA origin) { 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ops_.push_back(ORIGIN) && origins_.push_back(origin); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool EncodedProgram::AddCopy(uint32 count, const void* bytes) { 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8* source = static_cast<const uint8*>(bytes); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ok = true; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fold adjacent COPY instructions into one. This nearly halves the size of 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // an EncodedProgram with only COPY1 instructions since there are approx plain 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 16 bytes per reloc. This has a working-set benefit during decompression. 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For compression of files with large differences this makes a small (4%) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // improvement in size. For files with small differences this degrades the 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // compressed size by 1.3% 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ops_.empty()) { 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ops_.back() == COPY1) { 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ops_.back() = COPY; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ok = copy_counts_.push_back(1); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ok && ops_.back() == COPY) { 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) copy_counts_.back() += count; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (uint32 i = 0; ok && i < count; ++i) { 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ok = copy_bytes_.push_back(source[i]); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ok; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ok) { 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (count == 1) { 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ok = ops_.push_back(COPY1) && copy_bytes_.push_back(source[0]); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ok = ops_.push_back(COPY) && copy_counts_.push_back(count); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (uint32 i = 0; ok && i < count; ++i) { 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ok = copy_bytes_.push_back(source[i]); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ok; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool EncodedProgram::AddAbs32(int label_index) { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ops_.push_back(ABS32) && abs32_ix_.push_back(label_index); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool EncodedProgram::AddRel32(int label_index) { 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ops_.push_back(REL32) && rel32_ix_.push_back(label_index); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool EncodedProgram::AddPeMakeRelocs() { 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ops_.push_back(MAKE_PE_RELOCATION_TABLE); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool EncodedProgram::AddElfMakeRelocs() { 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ops_.push_back(MAKE_ELF_RELOCATION_TABLE); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EncodedProgram::DebuggingSummary() { 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "EncodedProgram Summary" 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\n image base " << image_base_ 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\n abs32 rvas " << abs32_rva_.size() 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\n rel32 rvas " << rel32_rva_.size() 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\n ops " << ops_.size() 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\n origins " << origins_.size() 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\n copy_counts " << copy_counts_.size() 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\n copy_bytes " << copy_bytes_.size() 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\n abs32_ix " << abs32_ix_.size() 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\n rel32_ix " << rel32_ix_.size(); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For algorithm refinement purposes it is useful to write subsets of the file 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// format. This gives us the ability to estimate the entropy of the 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// differential compression of the individual streams, which can provide 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// invaluable insights. The default, of course, is to include all the streams. 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum FieldSelect { 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INCLUDE_ABS32_ADDRESSES = 0x0001, 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INCLUDE_REL32_ADDRESSES = 0x0002, 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INCLUDE_ABS32_INDEXES = 0x0010, 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INCLUDE_REL32_INDEXES = 0x0020, 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INCLUDE_OPS = 0x0100, 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INCLUDE_BYTES = 0x0200, 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INCLUDE_COPY_COUNTS = 0x0400, 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INCLUDE_MISC = 0x1000 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static FieldSelect GetFieldSelect() { 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 1 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(sra): Use better configuration. 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::Environment> env(base::Environment::Create()); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string s; 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) env->GetVar("A_FIELDS", &s); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!s.empty()) { 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<FieldSelect>(wcstoul(ASCIIToWide(s).c_str(), 0, 0)); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<FieldSelect>(~0); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool EncodedProgram::WriteTo(SinkStreamSet* streams) { 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FieldSelect select = GetFieldSelect(); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The order of fields must be consistent in WriteTo and ReadFrom, regardless 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of the streams used. The code can be configured with all kStreamXXX 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // constants the same. 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we change the code to pipeline reading with assembly (to avoid temporary 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // storage vectors by consuming operands directly from the stream) then we 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // need to read the base address and the random access address tables first, 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the rest can be interleaved. 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (select & INCLUDE_MISC) { 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(sra): write 64 bits. 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!streams->stream(kStreamMisc)->WriteVarint32( 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<uint32>(image_base_))) { 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = true; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (select & INCLUDE_ABS32_ADDRESSES) { 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success &= WriteU32Delta(abs32_rva_, 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) streams->stream(kStreamAbs32Addresses)); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (select & INCLUDE_REL32_ADDRESSES) { 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success &= WriteU32Delta(rel32_rva_, 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) streams->stream(kStreamRel32Addresses)); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (select & INCLUDE_MISC) 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success &= WriteVector(origins_, streams->stream(kStreamOriginAddresses)); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (select & INCLUDE_OPS) { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 5 for length. 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success &= streams->stream(kStreamOps)->Reserve(ops_.size() + 5); 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success &= WriteVector(ops_, streams->stream(kStreamOps)); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (select & INCLUDE_COPY_COUNTS) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success &= WriteVector(copy_counts_, streams->stream(kStreamCopyCounts)); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (select & INCLUDE_BYTES) 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success &= WriteVectorU8(copy_bytes_, streams->stream(kStreamBytes)); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (select & INCLUDE_ABS32_INDEXES) 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success &= WriteVector(abs32_ix_, streams->stream(kStreamAbs32Indexes)); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (select & INCLUDE_REL32_INDEXES) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success &= WriteVector(rel32_ix_, streams->stream(kStreamRel32Indexes)); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return success; 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool EncodedProgram::ReadFrom(SourceStreamSet* streams) { 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(sra): read 64 bits. 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 temp; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!streams->stream(kStreamMisc)->ReadVarint32(&temp)) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_base_ = temp; 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ReadU32Delta(&abs32_rva_, streams->stream(kStreamAbs32Addresses))) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ReadU32Delta(&rel32_rva_, streams->stream(kStreamRel32Addresses))) 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ReadVector(&origins_, streams->stream(kStreamOriginAddresses))) 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ReadVector(&ops_, streams->stream(kStreamOps))) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ReadVector(©_counts_, streams->stream(kStreamCopyCounts))) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ReadVectorU8(©_bytes_, streams->stream(kStreamBytes))) 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ReadVector(&abs32_ix_, streams->stream(kStreamAbs32Indexes))) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ReadVector(&rel32_ix_, streams->stream(kStreamRel32Indexes))) 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check that streams have been completely consumed. 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < kStreamLimit; ++i) { 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (streams->stream(i)->Remaining() > 0) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Safe, non-throwing version of std::vector::at(). Returns 'true' for success, 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 'false' for out-of-bounds index error. 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename V, typename T> 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VectorAt(const V& v, size_t index, T* output) { 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index >= v.size()) 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *output = v[index]; 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool EncodedProgram::AssembleTo(SinkStream* final_buffer) { 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For the most part, the assembly process walks the various tables. 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ix_mumble is the index into the mumble table. 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t ix_origins = 0; 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t ix_copy_counts = 0; 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t ix_copy_bytes = 0; 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t ix_abs32_ix = 0; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t ix_rel32_ix = 0; 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RVA current_rva = 0; 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool pending_pe_relocation_table = false; 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool pending_elf_relocation_table = false; 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SinkStream bytes_following_relocation_table; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SinkStream* output = final_buffer; 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t ix_ops = 0; ix_ops < ops_.size(); ++ix_ops) { 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OP op = ops_[ix_ops]; 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (op) { 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ORIGIN: { 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RVA section_rva; 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!VectorAt(origins_, ix_origins, §ion_rva)) 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++ix_origins; 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_rva = section_rva; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case COPY: { 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 count; 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!VectorAt(copy_counts_, ix_copy_counts, &count)) 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++ix_copy_counts; 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (uint32 i = 0; i < count; ++i) { 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8 b; 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!VectorAt(copy_bytes_, ix_copy_bytes, &b)) 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++ix_copy_bytes; 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!output->Write(&b, 1)) 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_rva += count; 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case COPY1: { 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8 b; 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!VectorAt(copy_bytes_, ix_copy_bytes, &b)) 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++ix_copy_bytes; 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!output->Write(&b, 1)) 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_rva += 1; 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case REL32: { 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 index; 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!VectorAt(rel32_ix_, ix_rel32_ix, &index)) 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++ix_rel32_ix; 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RVA rva; 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!VectorAt(rel32_rva_, index, &rva)) 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 offset = (rva - (current_rva + 4)); 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!output->Write(&offset, 4)) 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_rva += 4; 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ABS32: { 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 index; 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!VectorAt(abs32_ix_, ix_abs32_ix, &index)) 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++ix_abs32_ix; 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RVA rva; 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!VectorAt(abs32_rva_, index, &rva)) 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 abs32 = static_cast<uint32>(rva + image_base_); 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!abs32_relocs_.push_back(current_rva) || !output->Write(&abs32, 4)) 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_rva += 4; 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case MAKE_PE_RELOCATION_TABLE: { 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can see the base relocation anywhere, but we only have the 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // information to generate it at the very end. So we divert the bytes 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we are generating to a temporary stream. 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pending_pe_relocation_table) // Can't have two base relocation 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tables. 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_pe_relocation_table = true; 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output = &bytes_following_relocation_table; 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There is a potential problem *if* the instruction stream contains 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // some REL32 relocations following the base relocation and in the same 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // section. We don't know the size of the table, so 'current_rva' will 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be wrong, causing REL32 offsets to be miscalculated. This never 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // happens; the base relocation table is usually in a section of its 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // own, a data-only section, and following everything else in the 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // executable except some padding zero bytes. We could fix this by 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // emitting an ORIGIN after the MAKE_BASE_RELOCATION_TABLE. 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case MAKE_ELF_RELOCATION_TABLE: { 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can see the base relocation anywhere, but we only have the 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // information to generate it at the very end. So we divert the bytes 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we are generating to a temporary stream. 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pending_elf_relocation_table) // Can't have two relocation 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tables. 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_elf_relocation_table = true; 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output = &bytes_following_relocation_table; 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pending_pe_relocation_table) { 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GeneratePeRelocations(final_buffer) || 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !final_buffer->Append(&bytes_following_relocation_table)) 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pending_elf_relocation_table) { 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GenerateElfRelocations(final_buffer) || 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !final_buffer->Append(&bytes_following_relocation_table)) 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Final verification check: did we consume all lists? 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ix_copy_counts != copy_counts_.size()) 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ix_copy_bytes != copy_bytes_.size()) 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ix_abs32_ix != abs32_ix_.size()) 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ix_rel32_ix != rel32_ix_.size()) 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// RelocBlock has the layout of a block of relocations in the base relocation 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// table file format. 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct RelocBlockPOD { 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 page_rva; 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 block_size; 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16 relocs[4096]; // Allow up to one relocation per byte of a 4k page. 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)COMPILE_ASSERT(offsetof(RelocBlockPOD, relocs) == 8, reloc_block_header_size); 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RelocBlock { 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RelocBlock() { 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pod.page_rva = ~0; 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pod.block_size = 8; 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Add(uint16 item) { 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pod.relocs[(pod.block_size-8)/2] = item; 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pod.block_size += 2; 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckBool Flush(SinkStream* buffer) WARN_UNUSED_RESULT { 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ok = true; 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pod.block_size != 8) { 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pod.block_size % 4 != 0) { // Pad to make size multiple of 4 bytes. 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Add(0); 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ok = buffer->Write(&pod, pod.block_size); 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pod.block_size = 8; 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ok; 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RelocBlockPOD pod; 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool EncodedProgram::GeneratePeRelocations(SinkStream* buffer) { 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::sort(abs32_relocs_.begin(), abs32_relocs_.end()); 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RelocBlock block; 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ok = true; 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; ok && i < abs32_relocs_.size(); ++i) { 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 rva = abs32_relocs_[i]; 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 page_rva = rva & ~0xFFF; 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (page_rva != block.pod.page_rva) { 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ok &= block.Flush(buffer); 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) block.pod.page_rva = page_rva; 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ok) 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) block.Add(0x3000 | (rva & 0xFFF)); 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ok &= block.Flush(buffer); 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ok; 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckBool EncodedProgram::GenerateElfRelocations(SinkStream* buffer) { 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::sort(abs32_relocs_.begin(), abs32_relocs_.end()); 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Elf32_Rel relocation_block; 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We only handle this specific type of relocation, so far. 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) relocation_block.r_info = R_386_RELATIVE; 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ok = true; 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; ok && i < abs32_relocs_.size(); ++i) { 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) relocation_block.r_offset = abs32_relocs_[i]; 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ok = buffer->Write(&relocation_block, sizeof(Elf32_Rel)); 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ok; 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Status WriteEncodedProgram(EncodedProgram* encoded, SinkStreamSet* sink) { 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!encoded->WriteTo(sink)) 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return C_STREAM_ERROR; 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return C_OK; 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Status ReadEncodedProgram(SourceStreamSet* streams, EncodedProgram** output) { 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EncodedProgram* encoded = new EncodedProgram(); 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (encoded->ReadFrom(streams)) { 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *output = encoded; 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return C_OK; 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete encoded; 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return C_DESERIALIZATION_FAILED; 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Status Assemble(EncodedProgram* encoded, SinkStream* buffer) { 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool assembled = encoded->AssembleTo(buffer); 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (assembled) 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return C_OK; 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return C_ASSEMBLY_FAILED; 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeleteEncodedProgram(EncodedProgram* encoded) { 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete encoded; 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // end namespace 651