blob: d515f0cde967b1716576e4c014300bbcb653aa62 [file] [log] [blame]
Wyatt Hepler80c6ee52020-01-03 09:54:58 -08001// Copyright 2020 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://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, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14
15// This file defines the functions that encode tokenized logs at runtime. These
16// are the only pw_tokenizer functions present in a binary that tokenizes
17// strings. All other tokenizing code is resolved at compile time.
18
19#include "pw_tokenizer/tokenize.h"
20
Wyatt Hepler80c6ee52020-01-03 09:54:58 -080021#include <cstring>
22
Wyatt Hepler7c8b3392021-04-05 18:00:24 -070023#include "pw_tokenizer/encode_args.h"
Wyatt Hepler80c6ee52020-01-03 09:54:58 -080024
Wyatt Heplera6d5cc62020-01-17 14:15:40 -080025namespace pw {
26namespace tokenizer {
Wyatt Heplereb020a12020-10-28 14:01:51 -070027namespace {
28
29// Store metadata about this compilation's string tokenization in the ELF.
30//
31// The tokenizer metadata will not go into the on-device executable binary code.
32// This metadata will be present in the ELF file's .pw_tokenizer.info section,
33// from which the host-side tooling (Python, Java, etc.) can understand how to
34// decode tokenized strings for the given binary. Only attributes that affect
35// the decoding process are recorded.
36//
37// Tokenizer metadata is stored in an array of key-value pairs. Each Metadata
38// object is 32 bytes: a 24-byte string and an 8-byte value. Metadata structs
39// may be parsed in Python with the struct format '24s<Q'.
40PW_PACKED(struct) Metadata {
41 char name[24]; // name of the metadata field
42 uint64_t value; // value of the field
43};
44
45static_assert(sizeof(Metadata) == 32);
46
47// Store tokenization metadata in its own section. Mach-O files are not
48// supported by pw_tokenizer, but a short, Mach-O compatible section name is
49// used on macOS so that this file can at least compile.
50#ifdef __APPLE__
51#define PW_TOKENIZER_INFO_SECTION PW_KEEP_IN_SECTION(".pw_tokenizer")
52#else
53#define PW_TOKENIZER_INFO_SECTION PW_KEEP_IN_SECTION(".pw_tokenizer.info")
54#endif // __APPLE__
55
56constexpr Metadata metadata[] PW_TOKENIZER_INFO_SECTION = {
Wyatt Heplerbcf07352021-04-05 14:44:30 -070057 {"c_hash_length_bytes", PW_TOKENIZER_CFG_C_HASH_LENGTH},
Wyatt Heplereb020a12020-10-28 14:01:51 -070058 {"sizeof_long", sizeof(long)}, // %l conversion specifier
59 {"sizeof_intmax_t", sizeof(intmax_t)}, // %j conversion specifier
60 {"sizeof_size_t", sizeof(size_t)}, // %z conversion specifier
61 {"sizeof_ptrdiff_t", sizeof(ptrdiff_t)}, // %t conversion specifier
62};
63
64} // namespace
Wyatt Hepler80c6ee52020-01-03 09:54:58 -080065
Wyatt Hepler7a5e4d62020-08-31 08:39:16 -070066extern "C" void _pw_tokenizer_ToBuffer(void* buffer,
67 size_t* buffer_size_bytes,
68 Token token,
Wyatt Heplerbcf07352021-04-05 14:44:30 -070069 pw_tokenizer_ArgTypes types,
Wyatt Hepler7a5e4d62020-08-31 08:39:16 -070070 ...) {
Wyatt Hepler80c6ee52020-01-03 09:54:58 -080071 if (*buffer_size_bytes < sizeof(token)) {
72 *buffer_size_bytes = 0;
73 return;
74 }
75
76 std::memcpy(buffer, &token, sizeof(token));
77
78 va_list args;
79 va_start(args, types);
Wyatt Heplere2cbadf2020-06-22 11:21:45 -070080 const size_t encoded_bytes = EncodeArgs(
81 types,
82 args,
Wyatt Heplerbcf07352021-04-05 14:44:30 -070083 std::span<std::byte>(static_cast<std::byte*>(buffer) + sizeof(token),
84 *buffer_size_bytes - sizeof(token)));
Wyatt Hepler80c6ee52020-01-03 09:54:58 -080085 va_end(args);
86
87 *buffer_size_bytes = sizeof(token) + encoded_bytes;
88}
89
Wyatt Hepler7a5e4d62020-08-31 08:39:16 -070090extern "C" void _pw_tokenizer_ToCallback(
Wyatt Hepler6639c452020-05-06 11:43:07 -070091 void (*callback)(const uint8_t* encoded_message, size_t size_bytes),
Wyatt Hepler7a5e4d62020-08-31 08:39:16 -070092 Token token,
Wyatt Heplerbcf07352021-04-05 14:44:30 -070093 pw_tokenizer_ArgTypes types,
Wyatt Hepler6639c452020-05-06 11:43:07 -070094 ...) {
Wyatt Hepler80c6ee52020-01-03 09:54:58 -080095 va_list args;
96 va_start(args, types);
Wyatt Heplerbcf07352021-04-05 14:44:30 -070097 EncodedMessage encoded(token, types, args);
Wyatt Hepler80c6ee52020-01-03 09:54:58 -080098 va_end(args);
99
Wyatt Heplerbcf07352021-04-05 14:44:30 -0700100 callback(encoded.data_as_uint8(), encoded.size());
Wyatt Hepler80c6ee52020-01-03 09:54:58 -0800101}
102
Wyatt Heplera6d5cc62020-01-17 14:15:40 -0800103} // namespace tokenizer
104} // namespace pw