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(©_counts_, streams->stream(kStreamCopyCounts))) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ReadVectorU8(©_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, §ion_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