• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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 
21 #include <cstring>
22 
23 #include "pw_span/span.h"
24 #include "pw_tokenizer/encode_args.h"
25 
26 namespace pw {
27 namespace tokenizer {
28 namespace {
29 
30 static_assert(sizeof(PW_TOKENIZER_NESTED_PREFIX_STR) == 2,
31               "The nested prefix must be a single character string");
32 
33 // Store metadata about this compilation's string tokenization in the ELF.
34 //
35 // The tokenizer metadata will not go into the on-device executable binary code.
36 // This metadata will be present in the ELF file's .pw_tokenizer.info section,
37 // from which the host-side tooling (Python, Java, etc.) can understand how to
38 // decode tokenized strings for the given binary. Only attributes that affect
39 // the decoding process are recorded.
40 //
41 // Tokenizer metadata is stored in an array of key-value pairs. Each Metadata
42 // object is 32 bytes: a 24-byte string and an 8-byte value. Metadata structs
43 // may be parsed in Python with the struct format '24s<Q'.
PW_PACKED(struct)44 PW_PACKED(struct) Metadata {
45   char name[24];   // name of the metadata field
46   uint64_t value;  // value of the field
47 };
48 
49 static_assert(sizeof(Metadata) == 32, "Metadata should be exactly 32 bytes");
50 
51 // Store tokenization metadata in its own section. Mach-O files are not
52 // supported by pw_tokenizer, but a short, Mach-O compatible section name is
53 // used on macOS so that this file can at least compile.
54 #ifdef __APPLE__
55 #define PW_TOKENIZER_INFO_SECTION PW_KEEP_IN_SECTION(".pw_tokenizer")
56 #else
57 #define PW_TOKENIZER_INFO_SECTION PW_KEEP_IN_SECTION(".pw_tokenizer.info")
58 #endif  // __APPLE__
59 
60 constexpr Metadata metadata[] PW_TOKENIZER_INFO_SECTION = {
61     {"c_hash_length_bytes", PW_TOKENIZER_CFG_C_HASH_LENGTH},
62     {"sizeof_long", sizeof(long)},            // %l conversion specifier
63     {"sizeof_intmax_t", sizeof(intmax_t)},    // %j conversion specifier
64     {"sizeof_size_t", sizeof(size_t)},        // %z conversion specifier
65     {"sizeof_ptrdiff_t", sizeof(ptrdiff_t)},  // %t conversion specifier
66 };
67 
68 }  // namespace
69 
_pw_tokenizer_ToBuffer(void * buffer,size_t * buffer_size_bytes,Token token,pw_tokenizer_ArgTypes types,...)70 extern "C" void _pw_tokenizer_ToBuffer(void* buffer,
71                                        size_t* buffer_size_bytes,
72                                        Token token,
73                                        pw_tokenizer_ArgTypes types,
74                                        ...) {
75   if (*buffer_size_bytes < sizeof(token)) {
76     *buffer_size_bytes = 0;
77     return;
78   }
79 
80   std::memcpy(buffer, &token, sizeof(token));
81 
82   va_list args;
83   va_start(args, types);
84 #if PW_CXX_STANDARD_IS_SUPPORTED(17)
85   const size_t encoded_bytes = EncodeArgs(
86       types,
87       args,
88       span<std::byte>(static_cast<std::byte*>(buffer) + sizeof(token),
89                       *buffer_size_bytes - sizeof(token)));
90 #else
91   const size_t encoded_bytes =
92       pw_tokenizer_EncodeArgs(types,
93                               args,
94                               static_cast<std::byte*>(buffer) + sizeof(token),
95                               *buffer_size_bytes - sizeof(token));
96 #endif  // PW_CXX_STANDARD_IS_SUPPORTED(17)
97   va_end(args);
98 
99   *buffer_size_bytes = sizeof(token) + encoded_bytes;
100 }
101 
102 }  // namespace tokenizer
103 }  // namespace pw
104