1 : // Copyright 2013 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/instrument/instrumenters/instrumenter_with_agent.h"
16 :
17 : #include "base/file_util.h"
18 : #include "base/logging.h"
19 : #include "syzygy/common/application.h"
20 :
21 : namespace instrument {
22 : namespace instrumenters {
23 :
24 E : bool InstrumenterWithAgent::ParseCommandLine(const CommandLine* command_line) {
25 E : DCHECK(command_line != NULL);
26 :
27 : // TODO(chrisha): Simplify the input/output image parsing once external
28 : // tools have been updated.
29 :
30 : // Parse the input image.
31 E : if (command_line->HasSwitch("input-dll")) {
32 E : LOG(WARNING) << "DEPRECATED: Using --input-dll.";
33 : input_dll_path_ = common::AppImplBase::AbsolutePath(
34 E : command_line->GetSwitchValuePath("input-dll"));
35 E : } else {
36 : input_dll_path_ = common::AppImplBase::AbsolutePath(
37 E : command_line->GetSwitchValuePath("input-image"));
38 : }
39 :
40 : // Parse the output image.
41 E : if (command_line->HasSwitch("output-dll")) {
42 E : LOG(WARNING) << "DEPRECATED: Using --output-dll.";
43 : output_dll_path_ = common::AppImplBase::AbsolutePath(
44 E : command_line->GetSwitchValuePath("output-dll"));
45 E : } else {
46 : output_dll_path_ = common::AppImplBase::AbsolutePath(
47 E : command_line->GetSwitchValuePath("output-image"));
48 : }
49 :
50 : // Ensure that both input and output have been specified.
51 E : if (input_dll_path_.empty() || output_dll_path_.empty()) {
52 E : LOG(ERROR) << "You must provide input and output file names.";
53 E : return false;
54 : }
55 :
56 : // Parse the remaining command line arguments.
57 : input_pdb_path_ = common::AppImplBase::AbsolutePath(
58 E : command_line->GetSwitchValuePath("input-pdb"));
59 : output_pdb_path_ = common::AppImplBase::AbsolutePath(
60 E : command_line->GetSwitchValuePath("output-pdb"));
61 E : allow_overwrite_ = command_line->HasSwitch("overwrite");
62 E : debug_friendly_ = command_line->HasSwitch("debug-friendly");
63 E : new_decomposer_ = command_line->HasSwitch("new-decomposer");
64 E : no_augment_pdb_ = command_line->HasSwitch("no-augment-pdb");
65 E : no_parse_debug_info_ = command_line->HasSwitch("no-parse-debug-info");
66 E : no_strip_strings_ = command_line->HasSwitch("no-strip-strings");
67 :
68 E : if (!agent_dll_.empty()) {
69 E : LOG(INFO) << "Default agent DLL for " << InstrumentationMode() << " mode "
70 : << "is \"" << agent_dll_ << "\".";
71 : }
72 :
73 : // Parse the custom agent if one is specified.
74 E : if (command_line->HasSwitch("agent")) {
75 E : std::string new_agent_dll = command_line->GetSwitchValueASCII("agent");
76 E : if (new_agent_dll != agent_dll_) {
77 E : agent_dll_ = new_agent_dll;
78 E : LOG(INFO) << "Using custom agent DLL \"" << agent_dll_ << "\".";
79 : }
80 E : }
81 :
82 E : if (agent_dll_.empty()) {
83 i : LOG(ERROR) << "No agent DLL has been specified.";
84 i : return false;
85 : }
86 :
87 E : if (!ParseAdditionalCommandLineArguments(command_line)) {
88 i : LOG(ERROR) << "Unable to parse the additional arguments from the command "
89 : << "line.";
90 i : return false;
91 : }
92 :
93 E : return true;
94 E : }
95 :
96 E : bool InstrumenterWithAgent::Instrument() {
97 E : pe::PERelinker* relinker = GetRelinker();
98 E : DCHECK(relinker != NULL);
99 E : relinker->set_input_path(input_dll_path_);
100 E : relinker->set_input_pdb_path(input_pdb_path_);
101 E : relinker->set_output_path(output_dll_path_);
102 E : relinker->set_output_pdb_path(output_pdb_path_);
103 E : relinker->set_allow_overwrite(allow_overwrite_);
104 E : relinker->set_augment_pdb(!no_augment_pdb_);
105 E : relinker->set_parse_debug_info(!no_parse_debug_info_);
106 E : relinker->set_use_new_decomposer(new_decomposer_);
107 E : relinker->set_strip_strings(!no_strip_strings_);
108 :
109 : // Initialize the relinker. This does the decomposition, etc.
110 E : if (!relinker->Init()) {
111 E : LOG(ERROR) << "Failed to initialize relinker.";
112 E : return false;
113 : }
114 :
115 : // Do the actual instrumentation.
116 E : if (!InstrumentImpl())
117 i : return false;
118 :
119 : // We let the PERelinker use the implicit OriginalOrderer.
120 E : if (!relinker->Relink()) {
121 E : LOG(ERROR) << "Unable to relink input image.";
122 E : return false;
123 : }
124 :
125 E : return true;
126 E : }
127 :
128 E : pe::PERelinker* InstrumenterWithAgent::GetRelinker() {
129 E : if (relinker_.get() == NULL) {
130 E : relinker_.reset(new pe::PERelinker());
131 E : CHECK(relinker_.get() != NULL);
132 : }
133 E : return relinker_.get();
134 E : }
135 :
136 : } // namespace instrumenters
137 : } // namespace instrument
|