1 : // Copyright 2012 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 : // Declares a mutator for adding named streams to a PDB file. Takes care of
16 : // reading and rewriting the named stream table in the header stream.
17 :
18 : #ifndef SYZYGY_PDB_MUTATORS_ADD_NAMED_STREAM_MUTATOR_H_
19 : #define SYZYGY_PDB_MUTATORS_ADD_NAMED_STREAM_MUTATOR_H_
20 :
21 : #include <map>
22 :
23 : #include "base/strings/string_piece.h"
24 : #include "syzygy/pdb/pdb_stream.h"
25 : #include "syzygy/pdb/pdb_util.h"
26 : #include "syzygy/pdb/mutators/named_mutator.h"
27 :
28 : namespace pdb {
29 : namespace mutators {
30 :
31 : // A partial mutator implementation for easily adding named streams to a PDB.
32 : // This is intended for adding streams whose contents are dynamic and not known
33 : // until post-transform/post-ordering.
34 : // @tparam DerivedType the type of the derived class.
35 : template<typename DerivedType>
36 : class AddNamedStreamMutatorImpl : public NamedPdbMutatorImpl<DerivedType> {
37 : public:
38 : // The main body of the mutator.
39 : virtual bool MutatePdb(PdbFile* pdb_file) override;
40 :
41 : protected:
42 : // This is called by MutatePdb and is the hook where the derived class can
43 : // actually add new streams to the PDB. The @p pdb_file is passed for
44 : // introspection purposes but it should not be modified directly. Rather,
45 : // streams should be added using the AddNamedStream utility function. This
46 : // function should be overridden by the derived class as no implementation is
47 : // provided here.
48 : // @param pdb_file The PDB file to which we will be adding streams.
49 : // @returns true on success, false otherwise.
50 : // bool AddNamedStreams(const PdbFile& pdb_file);
51 :
52 : // TODO(chrisha): The following utility functions need to be members of
53 : // PdbFile. In fact, the current PdbFile should become MsfFile, and we
54 : // need to have a 'smarter' PdbFile than the one we have now (aware of
55 : // the header streams, named streams, stream types, etc). With all of that
56 : // machinery available this entire class can disappear. In the meantime,
57 : // we'll live with the ugliness.
58 :
59 : // A utility function for retrieving an individual named stream from a PDB.
60 : // @param name the name of the stream to lookup.
61 : // @returns a pointer to the stream if found, NULL if none exists.
62 : scoped_refptr<PdbStream> GetNamedStream(const base::StringPiece& name) const;
63 :
64 : // A utility function for adding an individual name stream to a PDB. If a
65 : // stream already exists with this name, it will be replaced.
66 : // @param name the name of the stream to add.
67 : // @param stream the stream to add.
68 : // @returns true if the stream was added, false if it replaced an existing
69 : // stream.
70 : bool SetNamedStream(const base::StringPiece& name, PdbStream* stream);
71 :
72 : private:
73 : PdbFile* pdb_file_;
74 : NameStreamMap name_stream_map_;
75 : };
76 :
77 : template<typename DerivedType>
78 E : bool AddNamedStreamMutatorImpl<DerivedType>::MutatePdb(PdbFile* pdb_file) {
79 E : DCHECK(pdb_file != NULL);
80 :
81 : // Parse the header and named streams.
82 E : pdb_file_ = pdb_file;
83 E : pdb::PdbInfoHeader70 header = {};
84 E : if (!ReadHeaderInfoStream(*pdb_file, &header, &name_stream_map_))
85 E : return false;
86 :
87 : // Call the hook.
88 E : DerivedType* self = static_cast<DerivedType*>(this);
89 E : if (!self->AddNamedStreams(*pdb_file))
90 E : return false;
91 :
92 : // Write back the header with the updated map.
93 E : if (!WriteHeaderInfoStream(header, name_stream_map_, pdb_file))
94 i : return false;
95 :
96 E : pdb_file_ = NULL;
97 E : name_stream_map_.clear();
98 :
99 E : return true;
100 E : }
101 :
102 : template<typename DerivedType>
103 : scoped_refptr<PdbStream>
104 : AddNamedStreamMutatorImpl<DerivedType>::GetNamedStream(
105 E : const base::StringPiece& name) const {
106 E : DCHECK(pdb_file_ != NULL);
107 :
108 E : NameStreamMap::const_iterator it = name_stream_map_.find(name.as_string());
109 E : if (it == name_stream_map_.end())
110 i : return NULL;
111 :
112 E : size_t index = it->second;
113 E : return pdb_file_->GetStream(index);
114 E : }
115 :
116 : template<typename DerivedType>
117 : bool AddNamedStreamMutatorImpl<DerivedType>::SetNamedStream(
118 E : const base::StringPiece& name, PdbStream* stream) {
119 E : DCHECK(pdb_file_ != NULL);
120 :
121 E : size_t index = 0;
122 E : NameStreamMap::const_iterator it = name_stream_map_.find(name.as_string());
123 :
124 : // We are adding a new stream.
125 E : if (it == name_stream_map_.end()) {
126 E : index = pdb_file_->AppendStream(stream);
127 E : name_stream_map_.insert(std::make_pair(name.as_string(), index));
128 E : return true;
129 : }
130 :
131 : // We are replacing an existing stream.
132 E : index = it->second;
133 E : pdb_file_->ReplaceStream(index, stream);
134 E : return false;
135 E : }
136 :
137 : } // namespace mutators
138 : } // namespace pdb
139 :
140 : #endif // SYZYGY_PDB_MUTATORS_ADD_NAMED_STREAM_MUTATOR_H_
|