xref: /aosp_15_r20/system/core/debuggerd/libdebuggerd/utility_host.cpp (revision 00c7fec1bb09f3284aad6a6f96d2f63dfc3650ad)
1 /*
2  * Copyright 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 "libdebuggerd/utility_host.h"
18 
19 #include <sys/prctl.h>
20 
21 #include <charconv>
22 #include <limits>
23 #include <string>
24 
25 #include <android-base/stringprintf.h>
26 
27 using android::base::StringPrintf;
28 
29 #ifndef PR_MTE_TAG_SHIFT
30 #define PR_MTE_TAG_SHIFT 3
31 #endif
32 
33 #ifndef PR_MTE_TAG_MASK
34 #define PR_MTE_TAG_MASK (0xffffUL << PR_MTE_TAG_SHIFT)
35 #endif
36 
37 #ifndef PR_MTE_TCF_ASYNC
38 #define PR_MTE_TCF_ASYNC (1UL << 2)
39 #endif
40 
41 #ifndef PR_MTE_TCF_SYNC
42 #define PR_MTE_TCF_SYNC (1UL << 1)
43 #endif
44 
45 #ifndef PR_PAC_APIAKEY
46 #define PR_PAC_APIAKEY (1UL << 0)
47 #endif
48 
49 #ifndef PR_PAC_APIBKEY
50 #define PR_PAC_APIBKEY (1UL << 1)
51 #endif
52 
53 #ifndef PR_PAC_APDAKEY
54 #define PR_PAC_APDAKEY (1UL << 2)
55 #endif
56 
57 #ifndef PR_PAC_APDBKEY
58 #define PR_PAC_APDBKEY (1UL << 3)
59 #endif
60 
61 #ifndef PR_PAC_APGAKEY
62 #define PR_PAC_APGAKEY (1UL << 4)
63 #endif
64 
65 #ifndef PR_TAGGED_ADDR_ENABLE
66 #define PR_TAGGED_ADDR_ENABLE (1UL << 0)
67 #endif
68 
69 #define DESCRIBE_FLAG(flag) \
70   if (value & flag) {       \
71     desc += ", ";           \
72     desc += #flag;          \
73     value &= ~flag;         \
74   }
75 
describe_end(long value,std::string & desc)76 static std::string describe_end(long value, std::string& desc) {
77   if (value) {
78     desc += StringPrintf(", unknown 0x%lx", value);
79   }
80   return desc.empty() ? "" : " (" + desc.substr(2) + ")";
81 }
82 
describe_tagged_addr_ctrl(long value)83 std::string describe_tagged_addr_ctrl(long value) {
84   std::string desc;
85   DESCRIBE_FLAG(PR_TAGGED_ADDR_ENABLE);
86   DESCRIBE_FLAG(PR_MTE_TCF_SYNC);
87   DESCRIBE_FLAG(PR_MTE_TCF_ASYNC);
88   if (value & PR_MTE_TAG_MASK) {
89     desc += StringPrintf(", mask 0x%04lx", (value & PR_MTE_TAG_MASK) >> PR_MTE_TAG_SHIFT);
90     value &= ~PR_MTE_TAG_MASK;
91   }
92   return describe_end(value, desc);
93 }
94 
describe_pac_enabled_keys(long value)95 std::string describe_pac_enabled_keys(long value) {
96   std::string desc;
97   DESCRIBE_FLAG(PR_PAC_APIAKEY);
98   DESCRIBE_FLAG(PR_PAC_APIBKEY);
99   DESCRIBE_FLAG(PR_PAC_APDAKEY);
100   DESCRIBE_FLAG(PR_PAC_APDBKEY);
101   DESCRIBE_FLAG(PR_PAC_APGAKEY);
102   return describe_end(value, desc);
103 }
104 
oct_encode(const std::string & data)105 std::string oct_encode(const std::string& data) {
106   std::string oct_encoded;
107   oct_encoded.reserve(data.size());
108 
109   // N.B. the unsigned here is very important, otherwise e.g. \255 would render as
110   // \-123 (and overflow our buffer).
111   for (unsigned char c : data) {
112     if (isprint(c)) {
113       oct_encoded += c;
114     } else {
115       std::string oct_digits("\\\0\0\0", 4);
116       // char is encodable in 3 oct digits
117       static_assert(std::numeric_limits<unsigned char>::max() <= 8 * 8 * 8);
118       auto [ptr, ec] = std::to_chars(oct_digits.data() + 1, oct_digits.data() + 4, c, 8);
119       oct_digits.resize(ptr - oct_digits.data());
120       oct_encoded += oct_digits;
121     }
122   }
123   return oct_encoded;
124 }
125