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)// This is the transformation and adjustment for Windows X86 executables. 668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// The same code can be used for Windows X64 executables. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef COURGETTE_WIN32_X86_GENERATOR_H_ 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define COURGETTE_WIN32_X86_GENERATOR_H_ 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "courgette/assembly_program.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "courgette/ensemble.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace courgette { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PatchGeneratorX86_32 : public TransformationPatchGenerator { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PatchGeneratorX86_32(Element* old_element, 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Element* new_element, 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PatcherX86_32* patcher, 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExecutableType kind) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : TransformationPatchGenerator(old_element, new_element, patcher), 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kind_(kind) { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ExecutableType Kind() { return kind_; } 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status WriteInitialParameters(SinkStream* parameter_stream) { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!parameter_stream->WriteSizeVarint32( 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_element_->offset_in_ensemble()) || 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !parameter_stream->WriteSizeVarint32(old_element_->region().length())) { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return C_STREAM_ERROR; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return C_OK; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(sra): Initialize |patcher_| with these parameters. 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status PredictTransformParameters(SinkStreamSet* prediction) { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TransformationPatchGenerator::PredictTransformParameters(prediction); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status CorrectedTransformParameters(SinkStreamSet* parameters) { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No code needed to write an 'empty' parameter set. 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return C_OK; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The format of a transformed_element is a serialized EncodedProgram. We 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // first disassemble the original old and new Elements into AssemblyPrograms. 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Then we adjust the new AssemblyProgram to make it as much like the old one 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // as possible, before converting the AssemblyPrograms to EncodedPrograms and 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // serializing them. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status Transform(SourceStreamSet* corrected_parameters, 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SinkStreamSet* old_transformed_element, 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SinkStreamSet* new_transformed_element) { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't expect any corrected parameters. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!corrected_parameters->Empty()) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return C_GENERAL_ERROR; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Generate old version of program using |corrected_parameters|. 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(sra): refactor to use same code from patcher_. 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AssemblyProgram* old_program = NULL; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status old_parse_status = 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ParseDetectedExecutable(old_element_->region().start(), 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_element_->region().length(), 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &old_program); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (old_parse_status != C_OK) { 7068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) LOG(ERROR) << "Cannot parse as WinPE " << old_element_->Name(); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return old_parse_status; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AssemblyProgram* new_program = NULL; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status new_parse_status = 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ParseDetectedExecutable(new_element_->region().start(), 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_element_->region().length(), 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &new_program); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (new_parse_status != C_OK) { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeleteAssemblyProgram(old_program); 8168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) LOG(ERROR) << "Cannot parse as WinPE " << new_element_->Name(); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new_parse_status; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 852385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch // Trim labels below a certain threshold 862385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch Status trim_old_status = TrimLabels(old_program); 872385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch if (trim_old_status != C_OK) { 882385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch DeleteAssemblyProgram(old_program); 892385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch return trim_old_status; 902385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch } 912385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch 922385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch Status trim_new_status = TrimLabels(new_program); 932385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch if (trim_new_status != C_OK) { 942385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch DeleteAssemblyProgram(new_program); 952385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch return trim_new_status; 962385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch } 972385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EncodedProgram* old_encoded = NULL; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status old_encode_status = Encode(old_program, &old_encoded); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (old_encode_status != C_OK) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeleteAssemblyProgram(old_program); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return old_encode_status; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status old_write_status = 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteEncodedProgram(old_encoded, old_transformed_element); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeleteEncodedProgram(old_encoded); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (old_write_status != C_OK) { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeleteAssemblyProgram(old_program); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return old_write_status; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status adjust_status = Adjust(*old_program, new_program); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeleteAssemblyProgram(old_program); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (adjust_status != C_OK) { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeleteAssemblyProgram(new_program); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return adjust_status; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EncodedProgram* new_encoded = NULL; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status new_encode_status = Encode(new_program, &new_encoded); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeleteAssemblyProgram(new_program); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (new_encode_status != C_OK) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new_encode_status; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status new_write_status = 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteEncodedProgram(new_encoded, new_transformed_element); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeleteEncodedProgram(new_encoded); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (new_write_status != C_OK) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new_write_status; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return C_OK; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status Reform(SourceStreamSet* transformed_element, 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SinkStream* reformed_element) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TransformationPatchGenerator::Reform(transformed_element, 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reformed_element); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~PatchGeneratorX86_32() { } 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExecutableType kind_; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(PatchGeneratorX86_32); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace courgette 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // COURGETTE_WIN32_X86_GENERATOR_H_ 151