Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: minidump/minidump_file_writer.cc

Issue 432863006: Add MinidumpFileWriter (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Address review feedback. Add MinidumpFileWriter test. Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 The Crashpad Authors. 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 "minidump/minidump_file_writer.h"
16
17 #include "base/logging.h"
18 #include "minidump/minidump_writer_util.h"
19 #include "util/numeric/safe_assignment.h"
20
21 namespace crashpad {
22
23 MinidumpFileWriter::MinidumpFileWriter()
24 : MinidumpWritable(), header_(), streams_(), stream_types_() {
25 // Don’t set the signature field right away. Leave it set to 0, so that a
26 // partially-written minidump file isn’t confused for a complete and valid
27 // one. The header will be rewritten in WriteToFile().
28 header_.Signature = 0;
29
30 header_.Version = MINIDUMP_VERSION;
31 header_.CheckSum = 0;
32 header_.Flags = MiniDumpNormal;
33 }
34
35 MinidumpFileWriter::~MinidumpFileWriter() {
36 }
37
38 void MinidumpFileWriter::SetTimestamp(time_t timestamp) {
39 DCHECK_EQ(state(), kStateMutable);
40
41 internal::MinidumpWriterUtil::AssignTimeT(&header_.TimeDateStamp, timestamp);
42 }
43
44 void MinidumpFileWriter::AddStream(internal::MinidumpStreamWriter* stream) {
45 DCHECK_EQ(state(), kStateMutable);
46
47 MinidumpStreamType stream_type = stream->StreamType();
48
49 auto rv = stream_types_.insert(stream_type);
50 CHECK(rv.second) << "stream_type " << stream_type << " already present";
51
52 streams_.push_back(stream);
53
54 DCHECK_EQ(streams_.size(), stream_types_.size());
55 }
56
57 bool MinidumpFileWriter::WriteEverything(FileWriterInterface* file_writer) {
58 DCHECK_EQ(state(), kStateMutable);
59
60 off_t start_offset = file_writer->Seek(0, SEEK_CUR);
61 if (start_offset < 0) {
62 return false;
63 }
64
65 if (!MinidumpWritable::WriteEverything(file_writer)) {
66 return false;
67 }
68
69 off_t end_offset = file_writer->Seek(0, SEEK_CUR);
70 if (end_offset < 0) {
71 return false;
72 }
73
74 // Now that the entire minidump file has been completely written, go back to
75 // the beginning and rewrite the header with the correct signature to identify
76 // it as a valid minidump file.
77 header_.Signature = MINIDUMP_SIGNATURE;
78
79 if (file_writer->Seek(start_offset, SEEK_SET) != 0) {
80 return false;
81 }
82
83 if (!file_writer->Write(&header_, sizeof(header_))) {
84 return false;
85 }
86
87 // Seek back to the end of the file, in case some non-minidump content will be
88 // written to the file after the minidump content.
89 return file_writer->Seek(end_offset, SEEK_SET);
90 }
91
92 bool MinidumpFileWriter::Freeze() {
93 DCHECK_EQ(state(), kStateMutable);
94
95 if (!MinidumpWritable::Freeze()) {
96 return false;
97 }
98
99 size_t stream_count = streams_.size();
100 CHECK_EQ(stream_count, stream_types_.size());
101
102 if (!AssignIfInRange(&header_.NumberOfStreams, stream_count)) {
103 LOG(ERROR) << "stream_count " << stream_count << " out of range";
104 return false;
105 }
106
107 return true;
108 }
109
110 size_t MinidumpFileWriter::SizeOfObject() {
111 DCHECK_GE(state(), kStateFrozen);
112 DCHECK_EQ(streams_.size(), stream_types_.size());
113
114 return sizeof(header_) + streams_.size() * sizeof(MINIDUMP_DIRECTORY);
115 }
116
117 std::vector<internal::MinidumpWritable*> MinidumpFileWriter::Children() {
118 DCHECK_GE(state(), kStateFrozen);
119 DCHECK_EQ(streams_.size(), stream_types_.size());
120
121 std::vector<MinidumpWritable*> children;
122 for (internal::MinidumpStreamWriter* stream : streams_) {
123 children.push_back(stream);
124 }
125
126 return children;
127 }
128
129 bool MinidumpFileWriter::WillWriteAtOffsetImpl(off_t offset) {
130 DCHECK_EQ(state(), kStateFrozen);
131 DCHECK_EQ(offset, 0);
132 DCHECK_EQ(streams_.size(), stream_types_.size());
133
134 auto directory_offset = streams_.empty() ? 0 : offset + sizeof(header_);
135 if (!AssignIfInRange(&header_.StreamDirectoryRva, directory_offset)) {
136 LOG(ERROR) << "offset " << directory_offset << " out of range";
137 return false;
138 }
139
140 return MinidumpWritable::WillWriteAtOffsetImpl(offset);
141 }
142
143 bool MinidumpFileWriter::WriteObject(FileWriterInterface* file_writer) {
144 DCHECK_EQ(state(), kStateWritable);
145 DCHECK_EQ(streams_.size(), stream_types_.size());
146
147 WritableIoVec iov;
148 iov.iov_base = &header_;
149 iov.iov_len = sizeof(header_);
150 std::vector<WritableIoVec> iovecs(1, iov);
151
152 for (internal::MinidumpStreamWriter* stream : streams_) {
153 iov.iov_len = sizeof(MINIDUMP_DIRECTORY);
154 iov.iov_base = stream->DirectoryListEntry();
155 iovecs.push_back(iov);
156 }
157
158 return file_writer->WriteIoVec(&iovecs);
159 }
160
161 } // namespace crashpad
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698