blob: 255bae27d0b64759f4c719740380af6e8c579f74 [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"
Florian Mayerf3c0ac82018-10-02 11:53:55 +010020#include "perfetto/base/unix_socket.h"
Florian Mayerb85a9382018-09-27 13:59:01 +010021#include "perfetto/base/utils.h"
22
23#include <sys/socket.h>
24#include <sys/types.h>
25
26namespace perfetto {
27
28namespace {
29template <typename T>
30bool ViewAndAdvance(char** ptr, T** out, const char* end) {
31 if (end - sizeof(T) < *ptr)
32 return false;
Florian Mayer7ad12752018-10-02 16:48:44 +010033 *out = reinterpret_cast<T*>(*ptr);
34 *ptr += sizeof(T);
Florian Mayerb85a9382018-09-27 13:59:01 +010035 return true;
36}
37} // namespace
38
39bool SendWireMessage(int sock, const WireMessage& msg) {
40 uint64_t total_size;
41 struct iovec iovecs[4] = {};
42 // TODO(fmayer): Maye pack these two.
43 iovecs[0].iov_base = &total_size;
44 iovecs[0].iov_len = sizeof(total_size);
45 iovecs[1].iov_base = const_cast<RecordType*>(&msg.record_type);
46 iovecs[1].iov_len = sizeof(msg.record_type);
47 if (msg.alloc_header) {
Florian Mayer7ad12752018-10-02 16:48:44 +010048 PERFETTO_DCHECK(msg.record_type == RecordType::Malloc);
Florian Mayerb85a9382018-09-27 13:59:01 +010049 iovecs[2].iov_base = msg.alloc_header;
50 iovecs[2].iov_len = sizeof(*msg.alloc_header);
51 } else if (msg.free_header) {
Florian Mayer7ad12752018-10-02 16:48:44 +010052 PERFETTO_DCHECK(msg.record_type == RecordType::Free);
Florian Mayerb85a9382018-09-27 13:59:01 +010053 iovecs[2].iov_base = msg.free_header;
54 iovecs[2].iov_len = sizeof(*msg.free_header);
55 } else {
56 PERFETTO_DCHECK(false);
57 return false;
58 }
59
60 iovecs[3].iov_base = msg.payload;
61 iovecs[3].iov_len = msg.payload_size;
62
63 struct msghdr hdr = {};
64 hdr.msg_iov = iovecs;
65 if (msg.payload) {
66 hdr.msg_iovlen = base::ArraySize(iovecs);
67 total_size = iovecs[1].iov_len + iovecs[2].iov_len + iovecs[3].iov_len;
68 } else {
69 // If we are not sending payload, just ignore that iovec.
70 hdr.msg_iovlen = base::ArraySize(iovecs) - 1;
71 total_size = iovecs[1].iov_len + iovecs[2].iov_len;
72 }
73
Florian Mayerf3c0ac82018-10-02 11:53:55 +010074 ssize_t sent = base::SendMsgAll(sock, &hdr, MSG_NOSIGNAL);
Florian Mayerb85a9382018-09-27 13:59:01 +010075 return sent == static_cast<ssize_t>(total_size + sizeof(total_size));
76}
77
78bool ReceiveWireMessage(char* buf, size_t size, WireMessage* out) {
79 RecordType* record_type;
80 char* end = buf + size;
81 if (!ViewAndAdvance<RecordType>(&buf, &record_type, end))
82 return false;
Florian Mayer7ad12752018-10-02 16:48:44 +010083
84 out->payload = nullptr;
85 out->payload_size = 0;
Florian Mayerb85a9382018-09-27 13:59:01 +010086 out->record_type = *record_type;
Florian Mayer7ad12752018-10-02 16:48:44 +010087
88 if (*record_type == RecordType::Malloc) {
89 if (!ViewAndAdvance<AllocMetadata>(&buf, &out->alloc_header, end))
90 return false;
91 out->payload = buf;
92 if (buf > end) {
93 PERFETTO_DCHECK(false);
94 return false;
95 }
96 out->payload_size = static_cast<size_t>(end - buf);
97 } else if (*record_type == RecordType::Free) {
98 if (!ViewAndAdvance<FreeMetadata>(&buf, &out->free_header, end))
99 return false;
100 } else {
101 PERFETTO_DCHECK(false);
102 return false;
103 }
Florian Mayerb85a9382018-09-27 13:59:01 +0100104 return true;
105}
106
107} // namespace perfetto