diff options
author | dcheng <dcheng@chromium.org> | 2016-01-28 19:14:24 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-01-29 03:15:34 +0000 |
commit | 7958406fb94ffb798859006fef04dbd0d4164079 (patch) | |
tree | 2f7837ec4c53a3b7daa1a9313a2448d6b9c2bcca /courgette | |
parent | b34b862c7cb041ac86a1bb28b35a76c6f716bb02 (diff) | |
download | chromium_src-7958406fb94ffb798859006fef04dbd0d4164079.zip chromium_src-7958406fb94ffb798859006fef04dbd0d4164079.tar.gz chromium_src-7958406fb94ffb798859006fef04dbd0d4164079.tar.bz2 |
Revert of [Courgette] Refactor: Manage AssemblyProgram and EncodedProgram with scoped_ptr. (patchset #5 id:80001 of https://codereview.chromium.org/1629703002/ )
Reason for revert:
Breaks ninja build on Linux GN.
Original issue's description:
> [Courgette] Refactor: Manage AssemblyProgram and EncodedProgram with scoped_ptr.
>
> Previously naked pointers AssemblyProgram and EncodedProgram are used over the
> place, and are deallocated using Delete{AssemblyProgram, EncodedProgram}().
> In this CL we use scoped_ptr to manage the life cycles of these objects.
>
> - Removed DeleteAssemblyProgram() and DeleteEncodedProgram() and replaced calls
> with e.g., program.reset(nullptr); if the manual deallocation is a peak
> memory optimization.
> - Moved Encode() and ReadEncodedProgram() to the .h files matching the .cc files.
> - Extracted DetectExecutableType() and ParseDetectedExecutable() from
> disassembly.* to new files program_detector*c, since Disassembly is really an
> implementation that caller's don't care about.
>
> Committed: https://crrev.com/0a9cbf1781a114b35a4e0f4a834f2d24ade2e917
> Cr-Commit-Position: refs/heads/master@{#372212}
TBR=wfh@chromium.org,grt@chromium.org,huangs@chromium.org
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
Review URL: https://codereview.chromium.org/1650013002
Cr-Commit-Position: refs/heads/master@{#372274}
Diffstat (limited to 'courgette')
-rw-r--r-- | courgette/BUILD.gn | 2 | ||||
-rw-r--r-- | courgette/adjustment_method_unittest.cc | 53 | ||||
-rw-r--r-- | courgette/assembly_program.cc | 50 | ||||
-rw-r--r-- | courgette/assembly_program.h | 11 | ||||
-rw-r--r-- | courgette/courgette.gyp | 2 | ||||
-rw-r--r-- | courgette/courgette.h | 36 | ||||
-rw-r--r-- | courgette/courgette_tool.cc | 79 | ||||
-rw-r--r-- | courgette/disassembler.cc | 93 | ||||
-rw-r--r-- | courgette/encode_decode_unittest.cc | 27 | ||||
-rw-r--r-- | courgette/encoded_program.cc | 24 | ||||
-rw-r--r-- | courgette/encoded_program.h | 7 | ||||
-rw-r--r-- | courgette/encoded_program_fuzz_unittest.cc | 28 | ||||
-rw-r--r-- | courgette/encoded_program_unittest.cc | 1 | ||||
-rw-r--r-- | courgette/ensemble.cc | 4 | ||||
-rw-r--r-- | courgette/patch_generator_x86_32.h | 50 | ||||
-rw-r--r-- | courgette/patcher_x86_32.h | 26 | ||||
-rw-r--r-- | courgette/program_detector.cc | 85 | ||||
-rw-r--r-- | courgette/program_detector.h | 43 |
18 files changed, 300 insertions, 321 deletions
diff --git a/courgette/BUILD.gn b/courgette/BUILD.gn index 8916c15..6645093 100644 --- a/courgette/BUILD.gn +++ b/courgette/BUILD.gn @@ -42,8 +42,6 @@ static_library("courgette_lib") { "memory_allocator.h", "patch_generator_x86_32.h", "patcher_x86_32.h", - "program_detector.cc", - "program_detector.h", "region.h", "rel32_finder_win32_x86.cc", "rel32_finder_win32_x86.h", diff --git a/courgette/adjustment_method_unittest.cc b/courgette/adjustment_method_unittest.cc index e25a8e7..5b213dc 100644 --- a/courgette/adjustment_method_unittest.cc +++ b/courgette/adjustment_method_unittest.cc @@ -3,13 +3,11 @@ // found in the LICENSE file. #include <string> -#include <utility> -#include "base/memory/scoped_ptr.h" #include "base/strings/string_util.h" + #include "courgette/assembly_program.h" #include "courgette/courgette.h" -#include "courgette/encoded_program.h" #include "courgette/streams.h" #include "testing/gtest/include/gtest/gtest.h" @@ -25,11 +23,11 @@ class AdjustmentMethodTest : public testing::Test { void TearDown() { } - // Returns one of two similar simple programs. These differ only in Label - // assignment, so it is possible to make them look identical. - scoped_ptr<courgette::AssemblyProgram> MakeProgram(int kind) const { - scoped_ptr<courgette::AssemblyProgram> prog( - new courgette::AssemblyProgram(courgette::EXE_WIN_32_X86)); + // Returns one of two similar a simple programs. They differ only in the + // label assignment, so that it is possible to make them look identical. + courgette::AssemblyProgram* MakeProgram(int kind) const { + courgette::AssemblyProgram* prog = + new courgette::AssemblyProgram(courgette::EXE_WIN_32_X86); prog->set_image_base(0x00400000); courgette::Label* labelA = prog->FindOrMakeAbs32Label(0x00410000); @@ -54,29 +52,24 @@ class AdjustmentMethodTest : public testing::Test { return prog; } - scoped_ptr<courgette::AssemblyProgram> MakeProgramA() const { - return MakeProgram(0); - } - scoped_ptr<courgette::AssemblyProgram> MakeProgramB() const { - return MakeProgram(1); - } + courgette::AssemblyProgram* MakeProgramA() const { return MakeProgram(0); } + courgette::AssemblyProgram* MakeProgramB() const { return MakeProgram(1); } // Returns a string that is the serialized version of |program|. // Deletes |program|. - std::string Serialize(scoped_ptr<courgette::AssemblyProgram> program) const { - scoped_ptr<courgette::EncodedProgram> encoded; + std::string Serialize(courgette::AssemblyProgram *program) const { + courgette::EncodedProgram* encoded = NULL; - const courgette::Status encode_status = Encode(*program, &encoded); + const courgette::Status encode_status = Encode(program, &encoded); EXPECT_EQ(courgette::C_OK, encode_status); - program.reset(); + DeleteAssemblyProgram(program); courgette::SinkStreamSet sinks; - const courgette::Status write_status = - WriteEncodedProgram(encoded.get(), &sinks); + const courgette::Status write_status = WriteEncodedProgram(encoded, &sinks); EXPECT_EQ(courgette::C_OK, write_status); - encoded.reset(); + DeleteEncodedProgram(encoded); courgette::SinkStream sink; bool can_collect = sinks.CopyTo(&sink); @@ -89,20 +82,20 @@ class AdjustmentMethodTest : public testing::Test { void AdjustmentMethodTest::Test1() const { - scoped_ptr<courgette::AssemblyProgram> prog1 = MakeProgramA(); - scoped_ptr<courgette::AssemblyProgram> prog2 = MakeProgramB(); - std::string s1 = Serialize(std::move(prog1)); - std::string s2 = Serialize(std::move(prog2)); + courgette::AssemblyProgram* prog1 = MakeProgramA(); + courgette::AssemblyProgram* prog2 = MakeProgramB(); + std::string s1 = Serialize(prog1); + std::string s2 = Serialize(prog2); // Don't use EXPECT_EQ because strings are unprintable. EXPECT_FALSE(s1 == s2); // Unadjusted A and B differ. - scoped_ptr<courgette::AssemblyProgram> prog5 = MakeProgramA(); - scoped_ptr<courgette::AssemblyProgram> prog6 = MakeProgramB(); - courgette::Status can_adjust = Adjust(*prog5, prog6.get()); + courgette::AssemblyProgram* prog5 = MakeProgramA(); + courgette::AssemblyProgram* prog6 = MakeProgramB(); + courgette::Status can_adjust = Adjust(*prog5, prog6); EXPECT_EQ(courgette::C_OK, can_adjust); - std::string s5 = Serialize(std::move(prog5)); - std::string s6 = Serialize(std::move(prog6)); + std::string s5 = Serialize(prog5); + std::string s6 = Serialize(prog6); EXPECT_TRUE(s1 == s5); // Adjustment did not change A (prog5) EXPECT_TRUE(s5 == s6); // Adjustment did change B into A diff --git a/courgette/assembly_program.cc b/courgette/assembly_program.cc index de843f1..20eee96 100644 --- a/courgette/assembly_program.cc +++ b/courgette/assembly_program.cc @@ -7,12 +7,16 @@ #include <memory.h> #include <stddef.h> #include <stdint.h> - -#include <utility> +#include <algorithm> +#include <map> +#include <set> +#include <sstream> #include <vector> #include "base/logging.h" #include "base/macros.h" +#include "base/memory/scoped_ptr.h" + #include "courgette/courgette.h" #include "courgette/encoded_program.h" @@ -361,13 +365,13 @@ void AssemblyProgram::AssignRemainingIndexes(RVAToLabel* labels) { << " infill " << fill_infill_count; } -scoped_ptr<EncodedProgram> AssemblyProgram::Encode() const { +EncodedProgram* AssemblyProgram::Encode() const { scoped_ptr<EncodedProgram> encoded(new EncodedProgram()); encoded->set_image_base(image_base_); if (!encoded->DefineLabels(abs32_labels_, rel32_labels_)) - return nullptr; + return NULL; for (size_t i = 0; i < instructions_.size(); ++i) { Instruction* instruction = instructions_[i]; @@ -376,13 +380,13 @@ scoped_ptr<EncodedProgram> AssemblyProgram::Encode() const { case ORIGIN: { OriginInstruction* org = static_cast<OriginInstruction*>(instruction); if (!encoded->AddOrigin(org->origin_rva())) - return nullptr; + return NULL; break; } case DEFBYTE: { uint8_t b = static_cast<ByteInstruction*>(instruction)->byte_value(); if (!encoded->AddCopy(1, &b)) - return nullptr; + return NULL; break; } case DEFBYTES: { @@ -391,13 +395,13 @@ scoped_ptr<EncodedProgram> AssemblyProgram::Encode() const { size_t len = static_cast<BytesInstruction*>(instruction)->len(); if (!encoded->AddCopy(len, byte_values)) - return nullptr; + return NULL; break; } case REL32: { Label* label = static_cast<InstructionWithLabel*>(instruction)->label(); if (!encoded->AddRel32(label->index_)) - return nullptr; + return NULL; break; } case REL32ARM: { @@ -406,34 +410,34 @@ scoped_ptr<EncodedProgram> AssemblyProgram::Encode() const { uint16_t compressed_op = static_cast<InstructionWithLabelARM*>(instruction)->compressed_op(); if (!encoded->AddRel32ARM(compressed_op, label->index_)) - return nullptr; + return NULL; break; } case ABS32: { Label* label = static_cast<InstructionWithLabel*>(instruction)->label(); if (!encoded->AddAbs32(label->index_)) - return nullptr; + return NULL; break; } case ABS64: { Label* label = static_cast<InstructionWithLabel*>(instruction)->label(); if (!encoded->AddAbs64(label->index_)) - return nullptr; + return NULL; break; } case MAKEPERELOCS: { if (!encoded->AddPeMakeRelocs(kind_)) - return nullptr; + return NULL; break; } case MAKEELFRELOCS: { if (!encoded->AddElfMakeRelocs()) - return nullptr; + return NULL; break; } case MAKEELFARMRELOCS: { if (!encoded->AddElfARMMakeRelocs()) - return nullptr; + return NULL; break; } default: { @@ -442,7 +446,7 @@ scoped_ptr<EncodedProgram> AssemblyProgram::Encode() const { } } - return encoded; + return encoded.release(); } Instruction* AssemblyProgram::GetByteInstruction(uint8_t byte) { @@ -526,13 +530,15 @@ CheckBool AssemblyProgram::TrimLabels() { //////////////////////////////////////////////////////////////////////////////// -Status Encode(const AssemblyProgram& program, - scoped_ptr<EncodedProgram>* output) { - // Explicitly release any memory associated with the output before encoding. - output->reset(); - - *output = program.Encode(); - return (*output) ? C_OK : C_GENERAL_ERROR; +Status Encode(AssemblyProgram* program, EncodedProgram** output) { + *output = NULL; + EncodedProgram *encoded = program->Encode(); + if (encoded) { + *output = encoded; + return C_OK; + } else { + return C_GENERAL_ERROR; + } } } // namespace courgette diff --git a/courgette/assembly_program.h b/courgette/assembly_program.h index c256f8f..45658ab 100644 --- a/courgette/assembly_program.h +++ b/courgette/assembly_program.h @@ -14,7 +14,7 @@ #include "base/macros.h" #include "base/memory/scoped_ptr.h" -#include "courgette/courgette.h" +#include "courgette/disassembler.h" #include "courgette/image_utils.h" #include "courgette/label_manager.h" #include "courgette/memory_allocator.h" @@ -132,7 +132,7 @@ class AssemblyProgram { void UnassignIndexes(); void AssignRemainingIndexes(); - scoped_ptr<EncodedProgram> Encode() const; + EncodedProgram* Encode() const; // Accessor for instruction list. const InstructionVector& instructions() const { @@ -191,12 +191,5 @@ class AssemblyProgram { DISALLOW_COPY_AND_ASSIGN(AssemblyProgram); }; -// Converts |program| into encoded form, returning it as |*output|. -// Returns C_OK if succeeded, otherwise returns an error status and sets -// |*output| to null. -Status Encode(const AssemblyProgram& program, - scoped_ptr<EncodedProgram>* output); - } // namespace courgette - #endif // COURGETTE_ASSEMBLY_PROGRAM_H_ diff --git a/courgette/courgette.gyp b/courgette/courgette.gyp index f5e4031..3983f19 100644 --- a/courgette/courgette.gyp +++ b/courgette/courgette.gyp @@ -40,8 +40,6 @@ 'label_manager.h', 'memory_allocator.cc', 'memory_allocator.h', - 'program_detector.cc', - 'program_detector.h', 'region.h', 'rel32_finder_win32_x86.cc', 'rel32_finder_win32_x86.h', diff --git a/courgette/courgette.h b/courgette/courgette.h index 84ab7cd..5a98a46 100644 --- a/courgette/courgette.h +++ b/courgette/courgette.h @@ -90,6 +90,30 @@ Status ApplyEnsemblePatch(const base::FilePath::CharType* old_file_name, Status GenerateEnsemblePatch(SourceStream* old, SourceStream* target, SinkStream* patch); +// Detects the type of an executable file, and it's length. The length +// may be slightly smaller than some executables (like ELF), but will include +// all bytes the courgette algorithm has special benefit for. +// On success: +// Fill in type and detected_length, and return C_OK. +// On failure: +// Fill in type with UNKNOWN, detected_length with 0, and +// return C_INPUT_NOT_RECOGNIZED +Status DetectExecutableType(const void* buffer, size_t length, + ExecutableType* type, + size_t* detected_length); + +// Attempts to detect the type of executable, and parse it with the +// appropriate tools, storing the pointer to the AssemblyProgram in |*output|. +// Returns C_OK if successful, otherwise returns an error status and sets +// |*output| to NULL. +Status ParseDetectedExecutable(const void* buffer, size_t length, + AssemblyProgram** output); + +// Converts |program| into encoded form, returning it as |*output|. +// Returns C_OK if succeeded, otherwise returns an error status and +// sets |*output| to NULL +Status Encode(AssemblyProgram* program, EncodedProgram** output); + // Serializes |encoded| into the stream set. // Returns C_OK if succeeded, otherwise returns an error status. Status WriteEncodedProgram(EncodedProgram* encoded, SinkStreamSet* sink); @@ -99,10 +123,20 @@ Status WriteEncodedProgram(EncodedProgram* encoded, SinkStreamSet* sink); // |buffer| in an undefined state. Status Assemble(EncodedProgram* encoded, SinkStream* buffer); +// Deserializes program from the stream set. +// Returns C_OK if succeeded, otherwise returns an error status and +// sets |*output| to NULL +Status ReadEncodedProgram(SourceStreamSet* source, EncodedProgram** output); + +// Used to free an AssemblyProgram returned by other APIs. +void DeleteAssemblyProgram(AssemblyProgram* program); + +// Used to free an EncodedProgram returned by other APIs. +void DeleteEncodedProgram(EncodedProgram* encoded); + // Adjusts |program| to look more like |model|. // Status Adjust(const AssemblyProgram& model, AssemblyProgram *program); } // namespace courgette - #endif // COURGETTE_COURGETTE_H_ diff --git a/courgette/courgette_tool.cc b/courgette/courgette_tool.cc index 3e85657..c7e7196 100644 --- a/courgette/courgette_tool.cc +++ b/courgette/courgette_tool.cc @@ -13,14 +13,10 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/logging.h" -#include "base/memory/scoped_ptr.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" -#include "courgette/assembly_program.h" #include "courgette/courgette.h" -#include "courgette/encoded_program.h" -#include "courgette/program_detector.h" #include "courgette/streams.h" #include "courgette/third_party/bsdiff.h" @@ -80,27 +76,30 @@ void Disassemble(const base::FilePath& input_file, const base::FilePath& output_file) { std::string buffer = ReadOrFail(input_file, "input"); - scoped_ptr<courgette::AssemblyProgram> program; + courgette::AssemblyProgram* program = NULL; const courgette::Status parse_status = courgette::ParseDetectedExecutable(buffer.c_str(), buffer.length(), &program); + if (parse_status != courgette::C_OK) Problem("Can't parse input (code = %d).", parse_status); - scoped_ptr<courgette::EncodedProgram> encoded; - const courgette::Status encode_status = Encode(*program, &encoded); + courgette::EncodedProgram* encoded = NULL; + const courgette::Status encode_status = Encode(program, &encoded); + + courgette::DeleteAssemblyProgram(program); + if (encode_status != courgette::C_OK) Problem("Can't encode program."); - program.reset(); - courgette::SinkStreamSet sinks; + const courgette::Status write_status = - courgette::WriteEncodedProgram(encoded.get(), &sinks); + courgette::WriteEncodedProgram(encoded, &sinks); if (write_status != courgette::C_OK) Problem("Can't serialize encoded program."); - encoded.reset(); + courgette::DeleteEncodedProgram(encoded); courgette::SinkStream sink; if (!sinks.CopyTo(&sink)) @@ -160,7 +159,7 @@ void DisassembleAndAdjust(const base::FilePath& program_file, std::string program_buffer = ReadOrFail(program_file, "program"); std::string model_buffer = ReadOrFail(model_file, "reference"); - scoped_ptr<courgette::AssemblyProgram> program; + courgette::AssemblyProgram* program = NULL; const courgette::Status parse_program_status = courgette::ParseDetectedExecutable(program_buffer.c_str(), program_buffer.length(), @@ -168,7 +167,7 @@ void DisassembleAndAdjust(const base::FilePath& program_file, if (parse_program_status != courgette::C_OK) Problem("Can't parse program input (code = %d).", parse_program_status); - scoped_ptr<courgette::AssemblyProgram> model; + courgette::AssemblyProgram* model = NULL; const courgette::Status parse_model_status = courgette::ParseDetectedExecutable(model_buffer.c_str(), model_buffer.length(), @@ -176,26 +175,26 @@ void DisassembleAndAdjust(const base::FilePath& program_file, if (parse_model_status != courgette::C_OK) Problem("Can't parse model input (code = %d).", parse_model_status); - const courgette::Status adjust_status = Adjust(*model, program.get()); + const courgette::Status adjust_status = Adjust(*model, program); if (adjust_status != courgette::C_OK) Problem("Can't adjust program."); - model.reset(); + courgette::EncodedProgram* encoded = NULL; + const courgette::Status encode_status = Encode(program, &encoded); + + courgette::DeleteAssemblyProgram(program); - scoped_ptr<courgette::EncodedProgram> encoded; - const courgette::Status encode_status = Encode(*program, &encoded); if (encode_status != courgette::C_OK) Problem("Can't encode program."); - program.reset(); - courgette::SinkStreamSet sinks; + const courgette::Status write_status = - courgette::WriteEncodedProgram(encoded.get(), &sinks); + courgette::WriteEncodedProgram(encoded, &sinks); if (write_status != courgette::C_OK) Problem("Can't serialize encoded program."); - encoded.reset(); + courgette::DeleteEncodedProgram(encoded); courgette::SinkStream sink; if (!sinks.CopyTo(&sink)) @@ -216,7 +215,7 @@ void DisassembleAdjustDiff(const base::FilePath& model_file, std::string model_buffer = ReadOrFail(model_file, "'old'"); std::string program_buffer = ReadOrFail(program_file, "'new'"); - scoped_ptr<courgette::AssemblyProgram> model; + courgette::AssemblyProgram* model = NULL; const courgette::Status parse_model_status = courgette::ParseDetectedExecutable(model_buffer.c_str(), model_buffer.length(), @@ -224,7 +223,7 @@ void DisassembleAdjustDiff(const base::FilePath& model_file, if (parse_model_status != courgette::C_OK) Problem("Can't parse model input (code = %d).", parse_model_status); - scoped_ptr<courgette::AssemblyProgram> program; + courgette::AssemblyProgram* program = NULL; const courgette::Status parse_program_status = courgette::ParseDetectedExecutable(program_buffer.c_str(), program_buffer.length(), @@ -233,41 +232,37 @@ void DisassembleAdjustDiff(const base::FilePath& model_file, Problem("Can't parse program input (code = %d).", parse_program_status); if (adjust) { - const courgette::Status adjust_status = Adjust(*model, program.get()); + const courgette::Status adjust_status = Adjust(*model, program); if (adjust_status != courgette::C_OK) Problem("Can't adjust program."); } - scoped_ptr<courgette::EncodedProgram> encoded_program; + courgette::EncodedProgram* encoded_program = NULL; const courgette::Status encode_program_status = - Encode(*program, &encoded_program); + Encode(program, &encoded_program); + courgette::DeleteAssemblyProgram(program); if (encode_program_status != courgette::C_OK) Problem("Can't encode program."); - program.reset(); - - scoped_ptr<courgette::EncodedProgram> encoded_model; - const courgette::Status encode_model_status = Encode(*model, &encoded_model); + courgette::EncodedProgram* encoded_model = NULL; + const courgette::Status encode_model_status = Encode(model, &encoded_model); + courgette::DeleteAssemblyProgram(model); if (encode_model_status != courgette::C_OK) Problem("Can't encode model."); - model.reset(); - courgette::SinkStreamSet program_sinks; const courgette::Status write_program_status = - courgette::WriteEncodedProgram(encoded_program.get(), &program_sinks); + courgette::WriteEncodedProgram(encoded_program, &program_sinks); if (write_program_status != courgette::C_OK) Problem("Can't serialize encoded program."); - - encoded_program.reset(); + courgette::DeleteEncodedProgram(encoded_program); courgette::SinkStreamSet model_sinks; const courgette::Status write_model_status = - courgette::WriteEncodedProgram(encoded_model.get(), &model_sinks); + courgette::WriteEncodedProgram(encoded_model, &model_sinks); if (write_model_status != courgette::C_OK) Problem("Can't serialize encoded model."); - - encoded_model.reset(); + courgette::DeleteEncodedProgram(encoded_model); courgette::SinkStream empty_sink; for (int i = 0; ; ++i) { @@ -300,16 +295,14 @@ void Assemble(const base::FilePath& input_file, if (!sources.Init(buffer.c_str(), buffer.length())) Problem("Bad input file."); - scoped_ptr<courgette::EncodedProgram> encoded; - const courgette::Status read_status = - courgette::ReadEncodedProgram(&sources, &encoded); + courgette::EncodedProgram* encoded = NULL; + const courgette::Status read_status = ReadEncodedProgram(&sources, &encoded); if (read_status != courgette::C_OK) Problem("Bad encoded program."); courgette::SinkStream sink; - const courgette::Status assemble_status = - courgette::Assemble(encoded.get(), &sink); + const courgette::Status assemble_status = courgette::Assemble(encoded, &sink); if (assemble_status != courgette::C_OK) Problem("Can't assemble."); diff --git a/courgette/disassembler.cc b/courgette/disassembler.cc index b9fce8b..568114c 100644 --- a/courgette/disassembler.cc +++ b/courgette/disassembler.cc @@ -4,8 +4,101 @@ #include "courgette/disassembler.h" +#include <stddef.h> +#include <stdint.h> + +#include <algorithm> +#include <string> +#include <vector> + +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "courgette/assembly_program.h" +#include "courgette/courgette.h" +#include "courgette/disassembler_elf_32_arm.h" +#include "courgette/disassembler_elf_32_x86.h" +#include "courgette/disassembler_win32_x64.h" +#include "courgette/disassembler_win32_x86.h" +#include "courgette/encoded_program.h" + namespace courgette { +//////////////////////////////////////////////////////////////////////////////// + +Disassembler* DetectDisassembler(const void* buffer, size_t length) { + Disassembler* disassembler = NULL; + + disassembler = new DisassemblerWin32X86(buffer, length); + if (disassembler->ParseHeader()) + return disassembler; + else + delete disassembler; + + disassembler = new DisassemblerWin32X64(buffer, length); + if (disassembler->ParseHeader()) + return disassembler; + else + delete disassembler; + + disassembler = new DisassemblerElf32X86(buffer, length); + if (disassembler->ParseHeader()) + return disassembler; + else + delete disassembler; + + disassembler = new DisassemblerElf32ARM(buffer, length); + if (disassembler->ParseHeader()) + return disassembler; + else + delete disassembler; + + return NULL; +} + +Status DetectExecutableType(const void* buffer, size_t length, + ExecutableType* type, + size_t* detected_length) { + + Disassembler* disassembler = DetectDisassembler(buffer, length); + + if (disassembler) { + *type = disassembler->kind(); + *detected_length = disassembler->length(); + delete disassembler; + return C_OK; + } + + // We failed to detect anything + *type = EXE_UNKNOWN; + *detected_length = 0; + return C_INPUT_NOT_RECOGNIZED; +} + +Status ParseDetectedExecutable(const void* buffer, size_t length, + AssemblyProgram** output) { + *output = nullptr; + + scoped_ptr<Disassembler> disassembler(DetectDisassembler(buffer, length)); + if (!disassembler) + return C_INPUT_NOT_RECOGNIZED; + + scoped_ptr<AssemblyProgram> program( + new AssemblyProgram(disassembler->kind())); + + if (!disassembler->Disassemble(program.get())) + return C_DISASSEMBLY_FAILED; + + if (!program->TrimLabels()) + return C_TRIM_FAILED; + + *output = program.release(); + return C_OK; +} + +void DeleteAssemblyProgram(AssemblyProgram* program) { + delete program; +} + Disassembler::Disassembler(const void* start, size_t length) : failure_reason_("uninitialized") { start_ = reinterpret_cast<const uint8_t*>(start); diff --git a/courgette/encode_decode_unittest.cc b/courgette/encode_decode_unittest.cc index 7494785..9e89c20 100644 --- a/courgette/encode_decode_unittest.cc +++ b/courgette/encode_decode_unittest.cc @@ -4,12 +4,8 @@ #include <stddef.h> -#include "base/memory/scoped_ptr.h" -#include "courgette/assembly_program.h" #include "courgette/base_test_unittest.h" #include "courgette/courgette.h" -#include "courgette/encoded_program.h" -#include "courgette/program_detector.h" #include "courgette/streams.h" class EncodeDecodeTest : public BaseTest { @@ -24,25 +20,25 @@ void EncodeDecodeTest::TestAssembleToStreamDisassemble( const void* original_buffer = file.c_str(); size_t original_length = file.length(); - scoped_ptr<courgette::AssemblyProgram> program; + courgette::AssemblyProgram* program = NULL; const courgette::Status parse_status = courgette::ParseDetectedExecutable(original_buffer, original_length, &program); EXPECT_EQ(courgette::C_OK, parse_status); - scoped_ptr<courgette::EncodedProgram> encoded; - const courgette::Status encode_status = Encode(*program, &encoded); + courgette::EncodedProgram* encoded = NULL; + + const courgette::Status encode_status = Encode(program, &encoded); EXPECT_EQ(courgette::C_OK, encode_status); - program.reset(); + DeleteAssemblyProgram(program); courgette::SinkStreamSet sinks; - const courgette::Status write_status = - WriteEncodedProgram(encoded.get(), &sinks); + const courgette::Status write_status = WriteEncodedProgram(encoded, &sinks); EXPECT_EQ(courgette::C_OK, write_status); - encoded.reset(); + DeleteEncodedProgram(encoded); courgette::SinkStream sink; bool can_collect = sinks.CopyTo(&sink); @@ -57,22 +53,21 @@ void EncodeDecodeTest::TestAssembleToStreamDisassemble( bool can_get_source_streams = sources.Init(buffer, length); EXPECT_TRUE(can_get_source_streams); - scoped_ptr<courgette::EncodedProgram> encoded2; + courgette::EncodedProgram *encoded2 = NULL; const courgette::Status read_status = ReadEncodedProgram(&sources, &encoded2); EXPECT_EQ(courgette::C_OK, read_status); courgette::SinkStream assembled; - const courgette::Status assemble_status = - Assemble(encoded2.get(), &assembled); + const courgette::Status assemble_status = Assemble(encoded2, &assembled); EXPECT_EQ(courgette::C_OK, assemble_status); - encoded2.reset(); - const void* assembled_buffer = assembled.Buffer(); size_t assembled_length = assembled.Length(); EXPECT_EQ(original_length, assembled_length); EXPECT_EQ(0, memcmp(original_buffer, assembled_buffer, original_length)); + + DeleteEncodedProgram(encoded2); } TEST_F(EncodeDecodeTest, PE) { diff --git a/courgette/encoded_program.cc b/courgette/encoded_program.cc index 76fb33e..59800c5 100644 --- a/courgette/encoded_program.cc +++ b/courgette/encoded_program.cc @@ -10,11 +10,11 @@ #include <algorithm> #include <map> #include <string> -#include <utility> #include <vector> #include "base/environment.h" #include "base/logging.h" +#include "base/memory/scoped_ptr.h" #include "base/numerics/safe_conversions.h" #include "base/numerics/safe_math.h" #include "base/strings/string_number_conversions.h" @@ -22,6 +22,7 @@ #include "courgette/courgette.h" #include "courgette/disassembler_elf_32_arm.h" #include "courgette/streams.h" +#include "courgette/types_elf.h" namespace courgette { @@ -780,15 +781,14 @@ Status WriteEncodedProgram(EncodedProgram* encoded, SinkStreamSet* sink) { return C_OK; } -Status ReadEncodedProgram(SourceStreamSet* streams, - scoped_ptr<EncodedProgram>* output) { - output->reset(); - scoped_ptr<EncodedProgram> encoded(new EncodedProgram()); - if (!encoded->ReadFrom(streams)) - return C_DESERIALIZATION_FAILED; - - *output = std::move(encoded); - return C_OK; +Status ReadEncodedProgram(SourceStreamSet* streams, EncodedProgram** output) { + EncodedProgram* encoded = new EncodedProgram(); + if (encoded->ReadFrom(streams)) { + *output = encoded; + return C_OK; + } + delete encoded; + return C_DESERIALIZATION_FAILED; } Status Assemble(EncodedProgram* encoded, SinkStream* buffer) { @@ -798,4 +798,8 @@ Status Assemble(EncodedProgram* encoded, SinkStream* buffer) { return C_ASSEMBLY_FAILED; } +void DeleteEncodedProgram(EncodedProgram* encoded) { + delete encoded; +} + } // namespace courgette diff --git a/courgette/encoded_program.h b/courgette/encoded_program.h index 6ea3e22..e89676d 100644 --- a/courgette/encoded_program.h +++ b/courgette/encoded_program.h @@ -11,7 +11,6 @@ #include <vector> #include "base/macros.h" -#include "base/memory/scoped_ptr.h" #include "courgette/disassembler.h" #include "courgette/label_manager.h" #include "courgette/memory_allocator.h" @@ -141,11 +140,5 @@ class EncodedProgram { DISALLOW_COPY_AND_ASSIGN(EncodedProgram); }; -// Deserializes program from a stream set to |*output|. Returns C_OK if -// successful, otherwise assigns |*output| to null and returns an error status. -Status ReadEncodedProgram(SourceStreamSet* source, - scoped_ptr<EncodedProgram>* output); - } // namespace courgette - #endif // COURGETTE_ENCODED_PROGRAM_H_ diff --git a/courgette/encoded_program_fuzz_unittest.cc b/courgette/encoded_program_fuzz_unittest.cc index ed301f1..b755f85 100644 --- a/courgette/encoded_program_fuzz_unittest.cc +++ b/courgette/encoded_program_fuzz_unittest.cc @@ -10,16 +10,13 @@ // // We try a lot of arbitrary modifications to the serialized form and make sure // that the outcome is not a crash. -#include "courgette/encoded_program.h" + +#include "base/test/test_suite.h" #include <stddef.h> -#include "base/memory/scoped_ptr.h" -#include "base/test/test_suite.h" -#include "courgette/assembly_program.h" #include "courgette/base_test_unittest.h" #include "courgette/courgette.h" -#include "courgette/program_detector.h" #include "courgette/streams.h" class DecodeFuzzTest : public BaseTest { @@ -43,24 +40,24 @@ void DecodeFuzzTest::FuzzExe(const char* file_name) const { const void* original_buffer = file1.c_str(); size_t original_length = file1.length(); - scoped_ptr<courgette::AssemblyProgram> program; + courgette::AssemblyProgram* program = NULL; const courgette::Status parse_status = courgette::ParseDetectedExecutable(original_buffer, original_length, &program); EXPECT_EQ(courgette::C_OK, parse_status); - scoped_ptr<courgette::EncodedProgram> encoded; - const courgette::Status encode_status = Encode(*program, &encoded); + courgette::EncodedProgram* encoded = NULL; + + const courgette::Status encode_status = Encode(program, &encoded); EXPECT_EQ(courgette::C_OK, encode_status); - program.reset(); + DeleteAssemblyProgram(program); courgette::SinkStreamSet sinks; - const courgette::Status write_status = - WriteEncodedProgram(encoded.get(), &sinks); + const courgette::Status write_status = WriteEncodedProgram(encoded, &sinks); EXPECT_EQ(courgette::C_OK, write_status); - encoded.reset(); + DeleteEncodedProgram(encoded); courgette::SinkStream sink; bool can_collect = sinks.CopyTo(&sink); @@ -173,7 +170,7 @@ void DecodeFuzzTest::FuzzBits(const std::string& base_buffer, bool DecodeFuzzTest::TryAssemble(const std::string& buffer, std::string* output) const { - scoped_ptr<courgette::EncodedProgram> encoded; + courgette::EncodedProgram *encoded = NULL; bool result = false; courgette::SourceStreamSet sources; @@ -183,8 +180,7 @@ bool DecodeFuzzTest::TryAssemble(const std::string& buffer, ReadEncodedProgram(&sources, &encoded); if (read_status == courgette::C_OK) { courgette::SinkStream assembled; - const courgette::Status assemble_status = - Assemble(encoded.get(), &assembled); + const courgette::Status assemble_status = Assemble(encoded, &assembled); if (assemble_status == courgette::C_OK) { const void* assembled_buffer = assembled.Buffer(); @@ -198,6 +194,8 @@ bool DecodeFuzzTest::TryAssemble(const std::string& buffer, } } + DeleteEncodedProgram(encoded); + return result; } diff --git a/courgette/encoded_program_unittest.cc b/courgette/encoded_program_unittest.cc index 41ed7ee..654ef44 100644 --- a/courgette/encoded_program_unittest.cc +++ b/courgette/encoded_program_unittest.cc @@ -11,6 +11,7 @@ #include "base/macros.h" #include "base/memory/scoped_ptr.h" +#include "courgette/disassembler.h" #include "courgette/image_utils.h" #include "courgette/label_manager.h" #include "courgette/streams.h" diff --git a/courgette/ensemble.cc b/courgette/ensemble.cc index 631dd12..d5277a4 100644 --- a/courgette/ensemble.cc +++ b/courgette/ensemble.cc @@ -8,7 +8,7 @@ #include <stdint.h> #include "base/strings/string_number_conversions.h" -#include "courgette/program_detector.h" + #include "courgette/region.h" #include "courgette/simple_delta.h" #include "courgette/streams.h" @@ -41,9 +41,11 @@ Status Ensemble::FindEmbeddedElements() { while (position < length) { ExecutableType type; size_t detected_length; + Status result = DetectExecutableType(start + position, length - position, &type, &detected_length); + if (result == C_OK) { Region region(start + position, detected_length); diff --git a/courgette/patch_generator_x86_32.h b/courgette/patch_generator_x86_32.h index 40a20f2..1c56712 100644 --- a/courgette/patch_generator_x86_32.h +++ b/courgette/patch_generator_x86_32.h @@ -13,7 +13,6 @@ #include "base/memory/scoped_ptr.h" #include "courgette/assembly_program.h" #include "courgette/ensemble.h" -#include "courgette/program_detector.h" namespace courgette { @@ -62,7 +61,7 @@ class PatchGeneratorX86_32 : public TransformationPatchGenerator { // Generate old version of program using |corrected_parameters|. // TODO(sra): refactor to use same code from patcher_. - scoped_ptr<AssemblyProgram> old_program; + AssemblyProgram* old_program = NULL; Status old_parse_status = ParseDetectedExecutable(old_element_->region().start(), old_element_->region().length(), @@ -72,46 +71,52 @@ class PatchGeneratorX86_32 : public TransformationPatchGenerator { return old_parse_status; } - // TODO(huangs): Move the block below to right before |new_program| gets - // used, so we can reduce Courgette-gen peak memory. - scoped_ptr<AssemblyProgram> new_program; + AssemblyProgram* new_program = NULL; Status new_parse_status = ParseDetectedExecutable(new_element_->region().start(), new_element_->region().length(), &new_program); if (new_parse_status != C_OK) { + DeleteAssemblyProgram(old_program); LOG(ERROR) << "Cannot parse an executable " << new_element_->Name(); return new_parse_status; } - scoped_ptr<EncodedProgram> old_encoded; - Status old_encode_status = Encode(*old_program, &old_encoded); - if (old_encode_status != C_OK) + EncodedProgram* old_encoded = NULL; + Status old_encode_status = Encode(old_program, &old_encoded); + if (old_encode_status != C_OK) { + DeleteAssemblyProgram(old_program); return old_encode_status; + } Status old_write_status = - WriteEncodedProgram(old_encoded.get(), old_transformed_element); - - old_encoded.reset(); - - if (old_write_status != C_OK) + WriteEncodedProgram(old_encoded, old_transformed_element); + DeleteEncodedProgram(old_encoded); + if (old_write_status != C_OK) { + DeleteAssemblyProgram(old_program); return old_write_status; + } - Status adjust_status = Adjust(*old_program, new_program.get()); - old_program.reset(); - if (adjust_status != C_OK) + Status adjust_status = Adjust(*old_program, new_program); + DeleteAssemblyProgram(old_program); + if (adjust_status != C_OK) { + DeleteAssemblyProgram(new_program); return adjust_status; + } - scoped_ptr<EncodedProgram> new_encoded; - Status new_encode_status = Encode(*new_program, &new_encoded); + EncodedProgram* new_encoded = NULL; + Status new_encode_status = Encode(new_program, &new_encoded); + DeleteAssemblyProgram(new_program); if (new_encode_status != C_OK) return new_encode_status; - new_program.reset(); - Status new_write_status = - WriteEncodedProgram(new_encoded.get(), new_transformed_element); - return new_write_status; + WriteEncodedProgram(new_encoded, new_transformed_element); + DeleteEncodedProgram(new_encoded); + if (new_write_status != C_OK) + return new_write_status; + + return C_OK; } Status Reform(SourceStreamSet* transformed_element, @@ -129,5 +134,4 @@ class PatchGeneratorX86_32 : public TransformationPatchGenerator { }; } // namespace courgette - #endif // COURGETTE_WIN32_X86_GENERATOR_H_ diff --git a/courgette/patcher_x86_32.h b/courgette/patcher_x86_32.h index a80ccc3..28db059 100644 --- a/courgette/patcher_x86_32.h +++ b/courgette/patcher_x86_32.h @@ -8,11 +8,7 @@ #include <stdint.h> #include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "courgette/assembly_program.h" -#include "courgette/encoded_program.h" #include "courgette/ensemble.h" -#include "courgette/program_detector.h" namespace courgette { @@ -52,32 +48,39 @@ class PatcherX86_32 : public TransformationPatcher { if (!corrected_parameters->Empty()) return C_GENERAL_ERROR; // Don't expect any corrected parameters. - scoped_ptr<AssemblyProgram> program; + AssemblyProgram* program = NULL; status = ParseDetectedExecutable(ensemble_region_.start() + base_offset_, base_length_, &program); if (status != C_OK) return status; - scoped_ptr<EncodedProgram> encoded; - status = Encode(*program, &encoded); + EncodedProgram* encoded = NULL; + status = Encode(program, &encoded); + DeleteAssemblyProgram(program); if (status != C_OK) return status; - program.reset(); + status = WriteEncodedProgram(encoded, transformed_element); + DeleteEncodedProgram(encoded); - return WriteEncodedProgram(encoded.get(), transformed_element); + return status; } Status Reform(SourceStreamSet* transformed_element, SinkStream* reformed_element) { Status status; - scoped_ptr<EncodedProgram> encoded_program; + EncodedProgram* encoded_program = NULL; status = ReadEncodedProgram(transformed_element, &encoded_program); if (status != C_OK) return status; - return Assemble(encoded_program.get(), reformed_element); + status = Assemble(encoded_program, reformed_element); + DeleteEncodedProgram(encoded_program); + if (status != C_OK) + return status; + + return C_OK; } private: @@ -90,5 +93,4 @@ class PatcherX86_32 : public TransformationPatcher { }; } // namespace - #endif // COURGETTE_WIN32_X86_PATCHER_H_ diff --git a/courgette/program_detector.cc b/courgette/program_detector.cc deleted file mode 100644 index e0fe3e6..0000000 --- a/courgette/program_detector.cc +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "courgette/program_detector.h" - -#include <utility> - -#include "courgette/assembly_program.h" -#include "courgette/disassembler.h" -#include "courgette/disassembler_elf_32_arm.h" -#include "courgette/disassembler_elf_32_x86.h" -#include "courgette/disassembler_win32_x64.h" -#include "courgette/disassembler_win32_x86.h" - -namespace courgette { - -namespace { - -// Returns a new instance of Disassembler subclass if binary data given in -// |buffer| and |length| matches a known binary format, otherwise null. -scoped_ptr<Disassembler> DetectDisassembler(const void* buffer, size_t length) { - scoped_ptr<Disassembler> disassembler; - - disassembler.reset(new DisassemblerWin32X86(buffer, length)); - if (disassembler->ParseHeader()) - return disassembler; - - disassembler.reset(new DisassemblerWin32X64(buffer, length)); - if (disassembler->ParseHeader()) - return disassembler; - - disassembler.reset(new DisassemblerElf32X86(buffer, length)); - if (disassembler->ParseHeader()) - return disassembler; - - disassembler.reset(new DisassemblerElf32ARM(buffer, length)); - if (disassembler->ParseHeader()) - return disassembler; - - return nullptr; -} - -} // namespace - -Status DetectExecutableType(const void* buffer, - size_t length, - ExecutableType* type, - size_t* detected_length) { - scoped_ptr<Disassembler> disassembler(DetectDisassembler(buffer, length)); - - if (!disassembler) { // We failed to detect anything. - *type = EXE_UNKNOWN; - *detected_length = 0; - return C_INPUT_NOT_RECOGNIZED; - } - - *type = disassembler->kind(); - *detected_length = disassembler->length(); - return C_OK; -} - -Status ParseDetectedExecutable(const void* buffer, - size_t length, - scoped_ptr<AssemblyProgram>* output) { - output->reset(); - - scoped_ptr<Disassembler> disassembler(DetectDisassembler(buffer, length)); - if (!disassembler) - return C_INPUT_NOT_RECOGNIZED; - - scoped_ptr<AssemblyProgram> program( - new AssemblyProgram(disassembler->kind())); - - if (!disassembler->Disassemble(program.get())) - return C_DISASSEMBLY_FAILED; - - if (!program->TrimLabels()) - return C_TRIM_FAILED; - - *output = std::move(program); - return C_OK; -} - -} // namespace courgette diff --git a/courgette/program_detector.h b/courgette/program_detector.h deleted file mode 100644 index 81b6e2d..0000000 --- a/courgette/program_detector.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COURGETTE_PROGRAM_DETECTOR_H_ -#define COURGETTE_PROGRAM_DETECTOR_H_ - -#include <stddef.h> - -#include "base/memory/scoped_ptr.h" -#include "courgette/courgette.h" - -namespace courgette { - -class AssemblyProgram; - -// Detects the type of an executable file, and it's length. The length may be -// slightly smaller than some executables (like ELF), but will include all bytes -// the courgette algorithm has special benefit for. -// On success: -// Fills in |type| and |detected_length|, and returns C_OK. -// On failure: -// Fills in |type| with UNKNOWN, |detected_length| with 0, and returns -// C_INPUT_NOT_RECOGNIZED. -Status DetectExecutableType(const void* buffer, - size_t length, - ExecutableType* type, - size_t* detected_length); - -// Attempts to detect the type of executable, and parse it with the appropriate -// tools. -// On success: -// Parses the executable into a new AssemblyProgram in |*output|, and returns -// C_OK. -// On failure: -// Returns an error status and assigns |*output| to null. -Status ParseDetectedExecutable(const void* buffer, - size_t length, - scoped_ptr<AssemblyProgram>* output); - -} // namespace courgette - -#endif // COURGETTE_PROGRAM_DETECTOR_H_
\ No newline at end of file |