1 : // Copyright 2012 Google Inc.
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 utility functions used by the call trace client and its unit
16 : // tests.
17 :
18 : #include "syzygy/trace/client/client_utils.h"
19 :
20 : #include "base/logging.h"
21 :
22 : namespace trace {
23 : namespace client {
24 :
25 : int ReasonToEventType(DWORD reason) {
26 : switch (reason) {
27 : case DLL_PROCESS_ATTACH:
28 : return TRACE_PROCESS_ATTACH_EVENT;
29 :
30 : case DLL_PROCESS_DETACH:
31 : return TRACE_PROCESS_DETACH_EVENT;
32 :
33 : case DLL_THREAD_ATTACH:
34 : return TRACE_THREAD_ATTACH_EVENT;
35 :
36 : case DLL_THREAD_DETACH:
37 : return TRACE_THREAD_DETACH_EVENT;
38 :
39 : default:
40 : NOTREACHED() << "Invalid reason: " << reason << ".";
41 : return -1;
42 : }
43 : }
44 :
45 E : RecordPrefix* GetRecordPrefix(void *record) {
46 E : DCHECK(record != NULL);
47 :
48 E : return reinterpret_cast<RecordPrefix*>(record) - 1;
49 E : }
50 :
51 : TraceFileSegment::TraceFileSegment()
52 : : header(NULL),
53 : base_ptr(NULL),
54 : write_ptr(NULL),
55 E : end_ptr(NULL) {
56 : // Zero the RPC buffer.
57 E : memset(&buffer_info, 0, sizeof(buffer_info));
58 E : }
59 :
60 : // Returns true if there's enough space left in the given segment to write
61 : // num_bytes of raw data.
62 E : bool TraceFileSegment::CanAllocateRaw(size_t num_bytes) const {
63 E : DCHECK(write_ptr != NULL);
64 E : DCHECK(end_ptr != NULL);
65 E : DCHECK(num_bytes != 0);
66 E : return (write_ptr + num_bytes) <= end_ptr;
67 E : }
68 :
69 : // Returns true if there's enough space left in the given segment to write
70 : // a prefixed record of length num_bytes.
71 E : bool TraceFileSegment::CanAllocate(size_t num_bytes) const {
72 E : DCHECK(num_bytes != 0);
73 E : return CanAllocateRaw(num_bytes + sizeof(RecordPrefix));
74 E : }
75 :
76 E : void FillPrefix(RecordPrefix* prefix, int type, size_t size) {
77 E : prefix->size = size;
78 E : prefix->version.hi = TRACE_VERSION_HI;
79 E : prefix->version.lo = TRACE_VERSION_LO;
80 E : prefix->type = static_cast<uint16>(type);
81 E : prefix->timestamp = ::GetTickCount();
82 E : }
83 :
84 : // Writes the segment header at the top of a segment, updating the bytes
85 : // consumed and initializing the segment header structures.
86 E : void TraceFileSegment::WriteSegmentHeader(SessionHandle session_handle) {
87 E : DCHECK(header == NULL);
88 E : DCHECK(write_ptr != NULL);
89 E : DCHECK(CanAllocate(sizeof(TraceFileSegmentHeader)));
90 :
91 : // The trace record allocation will write the record prefix and update
92 : // the number of bytes consumed within the buffer.
93 :
94 E : RecordPrefix* prefix = reinterpret_cast<RecordPrefix*>(write_ptr);
95 : FillPrefix(prefix,
96 : TraceFileSegmentHeader::kTypeId,
97 E : sizeof(TraceFileSegmentHeader));
98 :
99 E : header = reinterpret_cast<TraceFileSegmentHeader*>(prefix + 1);
100 E : header->thread_id = ::GetCurrentThreadId();
101 E : header->segment_length = 0;
102 :
103 E : write_ptr = reinterpret_cast<uint8*>(header + 1);
104 E : }
105 :
106 : void* TraceFileSegment::AllocateTraceRecordImpl(int record_type,
107 E : size_t record_size) {
108 E : DCHECK(header != NULL);
109 E : DCHECK(write_ptr != NULL);
110 E : DCHECK(record_size != 0);
111 :
112 E : const size_t total_size = sizeof(RecordPrefix) + record_size;
113 :
114 E : DCHECK(CanAllocateRaw(total_size));
115 :
116 : // Clear the memory we're about to allocate. If this thread gets killed
117 : // before it can finish updating the trace record we want the allocated
118 : // record to have a somewhat consistent state.
119 E : ::memset(write_ptr, 0, total_size);
120 :
121 E : RecordPrefix* prefix = reinterpret_cast<RecordPrefix*>(write_ptr);
122 E : FillPrefix(prefix, record_type, record_size);
123 :
124 E : write_ptr += total_size;
125 E : header->segment_length += total_size;
126 :
127 E : return prefix + 1;
128 E : }
129 :
130 : } // namespace trace::client
131 : } // namespace trace
|