summaryrefslogtreecommitdiffstats
path: root/courgette
diff options
context:
space:
mode:
authordcheng <dcheng@chromium.org>2016-01-28 19:14:24 -0800
committerCommit bot <commit-bot@chromium.org>2016-01-29 03:15:34 +0000
commit7958406fb94ffb798859006fef04dbd0d4164079 (patch)
tree2f7837ec4c53a3b7daa1a9313a2448d6b9c2bcca /courgette
parentb34b862c7cb041ac86a1bb28b35a76c6f716bb02 (diff)
downloadchromium_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.gn2
-rw-r--r--courgette/adjustment_method_unittest.cc53
-rw-r--r--courgette/assembly_program.cc50
-rw-r--r--courgette/assembly_program.h11
-rw-r--r--courgette/courgette.gyp2
-rw-r--r--courgette/courgette.h36
-rw-r--r--courgette/courgette_tool.cc79
-rw-r--r--courgette/disassembler.cc93
-rw-r--r--courgette/encode_decode_unittest.cc27
-rw-r--r--courgette/encoded_program.cc24
-rw-r--r--courgette/encoded_program.h7
-rw-r--r--courgette/encoded_program_fuzz_unittest.cc28
-rw-r--r--courgette/encoded_program_unittest.cc1
-rw-r--r--courgette/ensemble.cc4
-rw-r--r--courgette/patch_generator_x86_32.h50
-rw-r--r--courgette/patcher_x86_32.h26
-rw-r--r--courgette/program_detector.cc85
-rw-r--r--courgette/program_detector.h43
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