1 /*
2 * Copyright (C) 2024 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 <emscripten/emscripten.h>
18
19 #include <cstddef>
20 #include <cstdint>
21 #include <cstring>
22 #include <string>
23
24 #include "perfetto/ext/base/string_utils.h"
25 #include "src/trace_config_utils/pb_to_txt.h"
26 #include "src/trace_config_utils/txt_to_pb.h"
27
28 namespace {
29 // The buffer used to exchange input and output arguments. We assume 16MB
30 // is enough to handle trace configs.
31 char wasm_buf[16 * 1024 * 1024];
32 } // namespace
33
34 extern "C" {
35
36 // Returns the pointer to the buffer.
37 void* EMSCRIPTEN_KEEPALIVE trace_config_utils_buf();
trace_config_utils_buf()38 void* trace_config_utils_buf() {
39 return &wasm_buf;
40 }
41
42 // Returns the size of the buffer, so trace_config_utils_wasm.ts doesn't have
43 // to hardcode the 16MB.
44 uint32_t EMSCRIPTEN_KEEPALIVE trace_config_utils_buf_size();
trace_config_utils_buf_size()45 uint32_t trace_config_utils_buf_size() {
46 return static_cast<uint32_t>(sizeof(wasm_buf));
47 }
48
49 // Converts a proto-encoded protos.TraceConfig to text.
50 // The caller must memcpy the bytes into the wasm_buf and pass the size of the
51 // copied data into `size`. The returned pbtxt will be written in wasm_buf and
52 // its size returned here.
53 uint32_t EMSCRIPTEN_KEEPALIVE trace_config_pb_to_txt(uint32_t size);
54
trace_config_pb_to_txt(uint32_t size)55 uint32_t trace_config_pb_to_txt(uint32_t size) {
56 std::string txt = perfetto::TraceConfigPbToTxt(wasm_buf, size);
57 size_t wsize = perfetto::base::SprintfTrunc(wasm_buf, sizeof(wasm_buf), "%s",
58 txt.c_str());
59 return static_cast<uint32_t>(wsize);
60 }
61
62 // Like the above, but converts a pbtxt into proto-encoded bytes.
63 // Because this can fail (the C++ function returns a StatusOr) we write
64 // a success/failure in the first byte to tell the diffrence.
65 uint32_t EMSCRIPTEN_KEEPALIVE trace_config_txt_to_pb(uint32_t size);
66
trace_config_txt_to_pb(uint32_t size)67 uint32_t trace_config_txt_to_pb(uint32_t size) {
68 auto res = perfetto::TraceConfigTxtToPb(std::string(wasm_buf, size));
69 if (!res.ok()) {
70 wasm_buf[0] = 0;
71 size_t wsize = perfetto::base::SprintfTrunc(
72 &wasm_buf[1], sizeof(wasm_buf) - 1, "%s", res.status().c_message());
73 return static_cast<uint32_t>(wsize);
74 }
75 const size_t resp_size = std::min(res->size(), sizeof(wasm_buf) - 1);
76 wasm_buf[0] = 1;
77 memcpy(&wasm_buf[1], res->data(), resp_size);
78 return static_cast<uint32_t>(resp_size);
79 }
80 } // extern "C"
81
82 // This is unused but is needed to keep emscripten happy.
main(int,char **)83 int main(int, char**) {
84 return 0;
85 }
86