123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- // Copyright 2017 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_COURGETTE_FLOW_H_
- #define COURGETTE_COURGETTE_FLOW_H_
- #include <memory>
- #include <string>
- #include "courgette/courgette.h"
- #include "courgette/region.h"
- #include "courgette/streams.h"
- namespace courgette {
- class AssemblyProgram;
- class Disassembler;
- class EncodedProgram;
- // An adaptor for Region as BasicBuffer.
- class RegionBuffer : public BasicBuffer {
- public:
- explicit RegionBuffer(const Region& region) : region_(region) {}
- RegionBuffer(const RegionBuffer&) = delete;
- RegionBuffer& operator=(const RegionBuffer&) = delete;
- ~RegionBuffer() override {}
- // BasicBuffer:
- const uint8_t* data() const override { return region_.start(); }
- size_t length() const override { return region_.length(); }
- private:
- Region region_;
- };
- // CourgetteFlow stores Courgette data arranged into groups, and exposes
- // "commands" that operate on them. On the first occurrence of an error, the
- // Courgette error code is recorded, error messages are generated and stored,
- // and all subsequent commands become no-op. This allows callers to concisely
- // specify high-level logic with minimal code for error handling.
- class CourgetteFlow {
- public:
- // A group of Courgette data, for a single executable. Takes negligible space
- // when unused.
- struct Data {
- Data();
- ~Data();
- std::unique_ptr<Disassembler> disassembler;
- std::unique_ptr<AssemblyProgram> program;
- std::unique_ptr<EncodedProgram> encoded;
- SinkStreamSet sinks;
- SourceStreamSet sources;
- };
- // Group enumeration into |data_*_| fields.
- enum Group {
- ONLY, // The only file processed.
- OLD, // The "old" file during patching.
- NEW, // The "new" file during patching.
- };
- CourgetteFlow();
- CourgetteFlow(const CourgetteFlow&) = delete;
- CourgetteFlow& operator=(const CourgetteFlow&) = delete;
- ~CourgetteFlow();
- static const char* name(Group group);
- Data* data(Group group); // Allows caller to modify.
- bool ok();
- bool failed();
- Status status();
- const std::string& message();
- // Commands that perform no-op on error. This allows caller to concisely
- // specify high-level logic, and perform a single error check at the end. Care
- // must be taken w.r.t. error handling if |data()| is harvested between
- // commands.
- // Reads |buffer| to initialize |data(group)->sources|.
- void ReadSourceStreamSetFromBuffer(Group group, const BasicBuffer& buffer);
- // Reads |buffer| to initialize |data(group)->disassembler|.
- void ReadDisassemblerFromBuffer(Group group, const BasicBuffer& buffer);
- // Reads |opt_sources| if given, or else |data(group)->sources| to initialize
- // |data(group).encoded|.
- void ReadEncodedProgramFromSourceStreamSet(
- Group group,
- SourceStreamSet* opt_sources = nullptr);
- // Uses |data(group)->disassembler| to initialize |data(group)->program|,
- // passing |annotate| as initialization parameter (should be true if
- // AdjustNewAssemblyProgramToMatchOld() gets called later).
- void CreateAssemblyProgramFromDisassembler(Group group, bool annotate);
- // Uses |data(group)->disassembler| and |data(group)->program| to initialize
- // |data(group)->encoded|.
- void CreateEncodedProgramFromDisassemblerAndAssemblyProgram(Group group);
- // Serializese |data(group)->sinks| to |sink|.
- void WriteSinkStreamFromSinkStreamSet(Group group, SinkStream* sink);
- // Serializes |data(group)->encoded| to |opt_sinks| if given, or else to
- // |data(group)->sinks|.
- void WriteSinkStreamSetFromEncodedProgram(Group group,
- SinkStreamSet* opt_sinks = nullptr);
- // Converts |data(group)->encoded| to an exectuable and writes the result to
- // |sink|.
- void WriteExecutableFromEncodedProgram(Group group, SinkStream* sink);
- // Adjusts |data(NEW)->program| Labels to match |data(OLD)->program| Labels.
- void AdjustNewAssemblyProgramToMatchOld();
- // Destructor commands to reduce memory usage.
- void DestroyDisassembler(Group group);
- void DestroyAssemblyProgram(Group group);
- void DestroyEncodedProgram(Group group);
- private:
- // Utilities to process return values from Courgette functions, and assign
- // |status_| and |message_|. Usage:
- // if (!check(some_courgette_function(param1, ...)))
- // setMessage("format string %s...", value1, ...);
- // Reassigns |status_|, and returns true if |C_OK|.
- bool check(Status new_status);
- // check() alternative for functions that return true on success. On failure
- // assigns |status_| to |failure_mode|.
- bool check(bool success, Status failure_mode);
- void setMessage(const char* format, ...);
- Status status_ = C_OK;
- std::string message_;
- Data data_only_;
- Data data_old_;
- Data data_new_;
- };
- } // namespace courgette
- #endif // COURGETTE_COURGETTE_FLOW_H_
|