blob: 39373f90827b5a252c80135057421660021eb2e1 [file] [log] [blame]
Florian Mayerb85a9382018-09-27 13:59:01 +01001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "src/profiling/memory/wire_protocol.h"
18
19#include "perfetto/base/logging.h"
20#include "perfetto/base/utils.h"
21
22#include <sys/socket.h>
23#include <sys/types.h>
24
25namespace perfetto {
26
27namespace {
28template <typename T>
29bool ViewAndAdvance(char** ptr, T** out, const char* end) {
30 if (end - sizeof(T) < *ptr)
31 return false;
32 *out = reinterpret_cast<T*>(ptr);
33 ptr += sizeof(T);
34 return true;
35}
36} // namespace
37
38bool SendWireMessage(int sock, const WireMessage& msg) {
39 uint64_t total_size;
40 struct iovec iovecs[4] = {};
41 // TODO(fmayer): Maye pack these two.
42 iovecs[0].iov_base = &total_size;
43 iovecs[0].iov_len = sizeof(total_size);
44 iovecs[1].iov_base = const_cast<RecordType*>(&msg.record_type);
45 iovecs[1].iov_len = sizeof(msg.record_type);
46 if (msg.alloc_header) {
47 iovecs[2].iov_base = msg.alloc_header;
48 iovecs[2].iov_len = sizeof(*msg.alloc_header);
49 } else if (msg.free_header) {
50 iovecs[2].iov_base = msg.free_header;
51 iovecs[2].iov_len = sizeof(*msg.free_header);
52 } else {
53 PERFETTO_DCHECK(false);
54 return false;
55 }
56
57 iovecs[3].iov_base = msg.payload;
58 iovecs[3].iov_len = msg.payload_size;
59
60 struct msghdr hdr = {};
61 hdr.msg_iov = iovecs;
62 if (msg.payload) {
63 hdr.msg_iovlen = base::ArraySize(iovecs);
64 total_size = iovecs[1].iov_len + iovecs[2].iov_len + iovecs[3].iov_len;
65 } else {
66 // If we are not sending payload, just ignore that iovec.
67 hdr.msg_iovlen = base::ArraySize(iovecs) - 1;
68 total_size = iovecs[1].iov_len + iovecs[2].iov_len;
69 }
70
71 ssize_t sent = sendmsg(sock, &hdr, MSG_NOSIGNAL);
72 return sent == static_cast<ssize_t>(total_size + sizeof(total_size));
73}
74
75bool ReceiveWireMessage(char* buf, size_t size, WireMessage* out) {
76 RecordType* record_type;
77 char* end = buf + size;
78 if (!ViewAndAdvance<RecordType>(&buf, &record_type, end))
79 return false;
80 switch (*record_type) {
81 case RecordType::Malloc:
82 if (!ViewAndAdvance<AllocMetadata>(&buf, &out->alloc_header, end))
83 return false;
84 out->payload = buf;
85 if (buf > end) {
86 PERFETTO_DCHECK(false);
87 return false;
88 }
89 out->payload_size = static_cast<size_t>(end - buf);
90 break;
91 case RecordType::Free:
92 if (!ViewAndAdvance<FreeMetadata>(&buf, &out->free_header, end))
93 return false;
94 break;
95 }
96 out->record_type = *record_type;
97 return true;
98}
99
100} // namespace perfetto