blob: 4efa03c8cbb71002b0122be4f4fc367426765911 [file] [log] [blame]
Peter Collingbourne39a17302024-03-07 17:50:10 -08001/*
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
Christopher Ferris6a5db682024-11-15 01:06:55 +000021#include <charconv>
22#include <limits>
Peter Collingbourne39a17302024-03-07 17:50:10 -080023#include <string>
24
25#include <android-base/stringprintf.h>
26
27using 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
76static 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
83std::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
95std::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}
Christopher Ferris6a5db682024-11-15 01:06:55 +0000104
105std::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}