...
1/*
2 * Copyright 2022 ByteDance Inc.
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#pragma once
18
19#include <sys/types.h>
20
21#ifdef LOG_LEVEL
22#define DEBUG
23#define LOG_TRACE(_VA_ARGS__...) do { if (LOG_LEVEL >= 0) xprintf(_VA_ARGS__ ); } while (0)
24#define LOG_DEBUG(_VA_ARGS__...) do { if (LOG_LEVEL >= 1) xprintf(_VA_ARGS__ ); } while (0)
25#define LOG_INFO(_VA_ARGS__...) do { if (LOG_LEVEL >= 2) xprintf(_VA_ARGS__ ); } while (0)
26#else
27#define LOG_TRACE(_VA_ARGS__...) ((void)0)
28#define LOG_DEBUG(_VA_ARGS__...) ((void)0)
29#define LOG_INFO(_VA_ARGS__...) ((void)0)
30#endif
31
32// Note: this code is on cross-compile, so we can't use System-specific Predefined Macros here.
33#if USE_APPLE
34static inline void __attribute__((naked)) write_syscall(const char *s, size_t n)
35{
36 asm volatile(
37 "movq %rsi, %rdx"
38 "\n"
39 "movq %rdi, %rsi"
40 "\n"
41 "movq $1, %rdi"
42 "\n"
43 "movq $0x02000004, %rax"
44 "\n"
45 "syscall"
46 "\n"
47 "retq"
48 "\n");
49}
50#else
51static inline void __attribute__((naked)) write_syscall(const char *s, size_t n)
52{
53 asm volatile(
54 "movq %rsi, %rdx"
55 "\n"
56 "movq %rdi, %rsi"
57 "\n"
58 "movq $1, %rdi"
59 "\n"
60 "movq $1, %rax"
61 "\n"
62 "syscall"
63 "\n"
64 "retq"
65 "\n");
66}
67#endif
68
69static inline void printch(const char ch)
70{
71 write_syscall(&ch, 1);
72}
73
74static inline void printstr(const char *s)
75{
76 size_t n = 0;
77 const char *p = s;
78 while (*p++)
79 n++;
80 write_syscall(s, n);
81}
82
83static inline void printint(int64_t v)
84{
85 char neg = 0;
86 char buf[32] = {};
87 char *p = &buf[31];
88 uint64_t u;
89 if (v < 0) {
90 u = ~v + 1;
91 neg = 1;
92 } else {
93 u = v;
94 }
95 if (u == 0) {
96 *--p = '0';
97 goto sig;
98 }
99 while (u)
100 {
101 *--p = (u % 10) + '0';
102 u /= 10;
103 }
104sig:
105 if (neg) {
106 *--p = '-';
107 }
108 printstr(p);
109}
110
111static inline void printuint(uint64_t v)
112{
113 char buf[32] = {};
114 char *p = &buf[31];
115 if (v == 0)
116 {
117 printch('0');
118 return;
119 }
120 while (v)
121 {
122 *--p = (v % 10) + '0';
123 v /= 10;
124 }
125 printstr(p);
126}
127
128static const char tab[] = "0123456789abcdef";
129
130static inline void printhex(uintptr_t v)
131{
132 if (v == 0)
133 {
134 printch('0');
135 return;
136 }
137 char buf[32] = {};
138 char *p = &buf[31];
139
140 while (v)
141 {
142 *--p = tab[v & 0x0f];
143 v >>= 4;
144 }
145 printstr(p);
146}
147
148#define MAX_BUF_LEN 1000
149
150static inline void printbytes(GoSlice *s)
151{
152 printch('[');
153 int i = 0;
154 if (s->len > MAX_BUF_LEN)
155 {
156 i = s->len - MAX_BUF_LEN;
157 }
158 for (; i < s->len; i++)
159 {
160 char* bytes = (char*)(s->buf);
161 printch(tab[(bytes[i] & 0xf0) >> 4]);
162 printch(tab[bytes[i] & 0x0f]);
163 if (i != s->len - 1)
164 printch(',');
165 }
166 printch(']');
167}
168
169static inline void printgostr(GoString *s)
170{
171 printch('"');
172 if (s->len < MAX_BUF_LEN)
173 {
174 write_syscall(s->buf, s->len);
175 }
176 else
177 {
178 write_syscall(s->buf, MAX_BUF_LEN);
179 }
180 printch('"');
181}
182
183static inline void do_xprintf(const char *fmt, ...)
184{
185 __builtin_va_list va;
186 char buf[256] = {};
187 char *p = buf;
188 __builtin_va_start(va, fmt);
189 for (;;)
190 {
191 if (*fmt == 0)
192 {
193 break;
194 }
195 if (*fmt != '%')
196 {
197 *p++ = *fmt++;
198 continue;
199 }
200 *p = 0;
201 p = buf;
202 fmt++;
203 printstr(buf);
204 switch (*fmt++)
205 {
206 case '%':
207 {
208 printch('%');
209 break;
210 }
211 case 'g':
212 {
213 printgostr(__builtin_va_arg(va, GoString *));
214 break;
215 }
216 case 's':
217 {
218 printstr(__builtin_va_arg(va, const char *));
219 break;
220 }
221 case 'd':
222 {
223 printint(__builtin_va_arg(va, int64_t));
224 break;
225 }
226 case 'u':
227 {
228 printuint(__builtin_va_arg(va, uint64_t));
229 break;
230 }
231 case 'f':
232 {
233 printint(__builtin_va_arg(va, double));
234 break;
235 }
236 case 'c':
237 {
238 printch((char)(__builtin_va_arg(va, int)));
239 break;
240 }
241 case 'x':
242 {
243 printhex(__builtin_va_arg(va, uintptr_t));
244 break;
245 }
246 case 'l':
247 {
248 printbytes(__builtin_va_arg(va, GoSlice *));
249 break;
250 }
251 }
252 }
253 __builtin_va_end(va);
254 if (p != buf)
255 {
256 *p = 0;
257 printstr(buf);
258 }
259}
260
261#ifdef DEBUG
262#define xprintf(_VA_ARGS__...) do_xprintf(_VA_ARGS__)
263#else
264#define xprintf(_VA_ARGS__...) ((void)0)
265#endif
266
267static always_inline void print_longhex(const void *input, const char* s, int bytes) {
268 const uint8_t* p = (const uint8_t*)(input);
269 xprintf("%s : ", s);
270 for (int i = 0; i < bytes; i++) {
271 uintptr_t u = p[i];
272 if (u < 0x10) xprintf("0");
273 xprintf("%x", u);
274 if ((i + 1) < bytes && (i + 1) % 4 == 0) {
275 xprintf("-");
276 }
277 }
278 xprintf("\n");
279}
280
281#define psimd(simd) print_longhex((const void *)(simd), #simd, sizeof(*simd))
View as plain text