1/**
2 * \file
3 * \brief Debugging functions
4 */
5
6/*
7 * Copyright (c) 2008-2011, ETH Zurich.
8 * Copyright (c) 2015, 2016 Hewlett Packard Enterprise Development LP.
9 * All rights reserved.
10 *
11 * This file is distributed under the terms in the attached LICENSE file.
12 * If you do not find this file, copies can be found by writing to:
13 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
14 */
15
16#include <stdio.h>
17#include <barrelfish/barrelfish.h>
18#include <barrelfish/caddr.h>
19#include <barrelfish/debug.h>
20#include <barrelfish/monitor_client.h>
21#include <barrelfish/sys_debug.h>
22#include <barrelfish/dispatch.h>
23#include <stdarg.h>
24#include <stdlib.h>
25#include <string.h>
26#include <inttypes.h>
27#include <barrelfish_kpi/dispatcher_shared.h>
28#include <stdio.h>
29
30#define DISP_MEMORY_SIZE            1024 // size of memory dump in bytes
31
32/**
33 * \brief Print a message and abort.
34 *
35 * Something irrecoverably bad happened. Print a panic message, then abort.
36 */
37void user_panic_fn(const char *file, const char *func, int line,
38                   const char *msg, ...)
39{
40    va_list ap;
41    char msg_str[128];
42    //int msg_str_cc;
43    va_start(ap, msg);
44    //msg_str_cc =
45        vsnprintf(msg_str, sizeof(msg_str), msg, ap);
46    va_end(ap);
47
48    char str[256];
49    //int strcc =
50        snprintf(str, sizeof(str), "%.*s.%u in %s() %s:%d\n%s\n",
51                     DISP_NAME_LEN, disp_name(), disp_get_current_core_id(),
52                     func, file, line, msg_str);
53    sys_print(str, sizeof(str));
54
55    abort();
56}
57
58/*
59 * Have this invocation here to make debug_cap_identify work for domains that
60 * have no monitor connection but hold Kernel cap (e.g. init)
61 */
62static inline errval_t
63invoke_kernel_identify_cap(capaddr_t cap, int level, struct capability *out)
64{
65    return cap_invoke4(cap_kernel, KernelCmd_Identify_cap, cap, level,
66                       (uintptr_t)out).error;
67}
68
69errval_t debug_cap_identify(struct capref cap, struct capability *ret)
70{
71    if (get_cap_addr(cap) == 0) {
72        return SYS_ERR_CAP_NOT_FOUND;
73    }
74
75    uint8_t level = get_cap_level(cap);
76    capaddr_t caddr = get_cap_addr(cap);
77    errval_t err = invoke_kernel_identify_cap(caddr, level, ret);
78    if (err_is_ok(err)) {
79        // we have kernel cap, return result;
80        return SYS_ERR_OK;
81    }
82
83    return monitor_cap_identify_remote(cap, ret);
84}
85
86/**
87 * \brief Enable fine-grained tracing of cap operations on address range
88 * [start_addr, start_addr+size)
89 * \arg types enable tracing for given set of ORed ObjType_s
90 * \arg start_addr start of region to trace for
91 * \arg size size of region to trace for
92 */
93errval_t debug_cap_trace_ctrl(uintptr_t types, genpaddr_t start_addr, gensize_t size)
94{
95    if (types) {
96        printf("enabling pmem tracing: 0x%"PRIxGENPADDR"--0x%"PRIxGENPADDR
97               " for types 0x%"PRIxPTR"\n",
98               start_addr, start_addr+size, types);
99    }
100    return sys_debug_cap_trace_ctrl(types, start_addr, size);
101}
102
103/**
104 * \brief Dump own hw page tables around a given vaddr
105 */
106errval_t debug_dump_hw_ptables_around(void *vaddr)
107{
108    return invoke_dispatcher_dump_ptables(cap_dispatcher, (lvaddr_t)vaddr);
109}
110
111/**
112 * \brief Dump full page tables
113 */
114errval_t debug_dump_hw_ptables(void)
115{
116    return debug_dump_hw_ptables_around(NULL);
117}
118
119void debug_printf(const char *fmt, ...)
120{
121
122    va_list argptr;
123    char id[32] = "-";
124    char str[1024];
125    struct thread *me = thread_self();
126    size_t len;
127
128
129
130    if (me) {
131        snprintf(id, sizeof(id), "%"PRIuPTR, thread_get_id(me));
132    } else {
133        snprintf(id, sizeof(id), "-");
134    }
135    len = snprintf(str, sizeof(str), "\033[34m%.*s.\033[31m%u.%s\033[0m: ",
136                   DISP_NAME_LEN, disp_name(), disp_get_current_core_id(), id);
137    if (len < sizeof(str)) {
138        va_start(argptr, fmt);
139        vsnprintf(str + len, sizeof(str) - len, fmt, argptr);
140        va_end(argptr);
141    }
142    sys_print(str, sizeof(str));
143}
144
145/**
146 * \brief Function to do the actual printing based on the type of capability
147 */
148STATIC_ASSERT(68 == ObjType_Num, "Knowledge of all cap types");
149int debug_print_cap(char *buf, size_t len, struct capability *cap)
150{
151    char *mappingtype;
152    switch (cap->type) {
153    case ObjType_PhysAddr:
154        return snprintf(buf, len,
155                        "physical address range cap (0x%" PRIxGENPADDR ":0x%" PRIuGENSIZE ")",
156                        cap->u.physaddr.base, cap->u.physaddr.bytes);
157
158    case ObjType_RAM:
159        return snprintf(buf, len, "RAM cap (0x%" PRIxGENPADDR ":0x%" PRIuGENSIZE ")",
160                        cap->u.ram.base, cap->u.ram.bytes);
161
162    case ObjType_L1CNode: {
163        int ret = snprintf(buf, len, "L1 CNode cap "
164                           "(allocated bytes %#"PRIxGENSIZE
165                           ", rights mask %#"PRIxCAPRIGHTS")",
166                           cap->u.l1cnode.allocated_bytes, cap->u.l1cnode.rightsmask);
167        return ret;
168    }
169
170    case ObjType_L2CNode: {
171        return snprintf(buf, len, "L2 CNode cap "
172                           "(cnode=%"PRIxLPADDR")"
173                           "(rights mask %#"PRIxCAPRIGHTS")",
174                           cap->u.l2cnode.cnode,
175                           cap->u.l2cnode.rightsmask);
176    }
177
178
179    case ObjType_Dispatcher:
180        return snprintf(buf, len, "Dispatcher cap %p", cap->u.dispatcher.dcb);
181
182    case ObjType_Frame:
183        return snprintf(buf, len, "Frame cap (0x%" PRIxGENPADDR ":0x%" PRIuGENSIZE ")",
184                        cap->u.frame.base, cap->u.frame.bytes);
185
186    case ObjType_EndPointUMP:
187        return snprintf(buf, len, "EndPoint UMP cap (0x%" PRIxGENPADDR ":0x%"
188                                   PRIuGENSIZE "), if=%" PRIu32,
189                        cap->u.endpointump.base, cap->u.endpointump.bytes,
190                        cap->u.endpointump.iftype);
191
192    case ObjType_DevFrame:
193        return snprintf(buf, len, "Device Frame cap (0x%" PRIxGENPADDR ":%" PRIuGENSIZE ")",
194                        cap->u.frame.base, cap->u.devframe.bytes);
195
196    case ObjType_VNode_ARM_l1:
197        return snprintf(buf, len, "ARM L1 table at 0x%" PRIxGENPADDR,
198                        cap->u.vnode_arm_l1.base);
199
200    case ObjType_VNode_ARM_l2:
201        return snprintf(buf, len, "ARM L2 table at 0x%" PRIxGENPADDR,
202                        cap->u.vnode_arm_l2.base);
203
204    case ObjType_VNode_AARCH64_l0:
205        return snprintf(buf, len, "AARCH64 L0 table at 0x%" PRIxGENPADDR,
206                        cap->u.vnode_aarch64_l0.base);
207
208    case ObjType_VNode_AARCH64_l1:
209        return snprintf(buf, len, "AARCH64 L1 table at 0x%" PRIxGENPADDR,
210                        cap->u.vnode_aarch64_l1.base);
211
212    case ObjType_VNode_AARCH64_l2:
213        return snprintf(buf, len, "AARCH64 L2 table at 0x%" PRIxGENPADDR,
214                        cap->u.vnode_aarch64_l2.base);
215
216    case ObjType_VNode_AARCH64_l3:
217        return snprintf(buf, len, "AARCH64 L3 table at 0x%" PRIxGENPADDR,
218                        cap->u.vnode_aarch64_l3.base);
219
220    case ObjType_VNode_x86_32_ptable:
221        return snprintf(buf, len, "x86_32 Page table at 0x%" PRIxGENPADDR,
222                        cap->u.vnode_x86_32_ptable.base);
223
224    case ObjType_VNode_x86_32_pdir:
225        return snprintf(buf, len, "x86_32 Page directory at 0x%" PRIxGENPADDR,
226                        cap->u.vnode_x86_32_pdir.base);
227
228    case ObjType_VNode_x86_32_pdpt:
229        return snprintf(buf, len, "x86_32 PDPT at 0x%" PRIxGENPADDR,
230                        cap->u.vnode_x86_32_pdpt.base);
231
232    case ObjType_VNode_x86_64_ptable:
233        return snprintf(buf, len, "x86_64 Page table at 0x%" PRIxGENPADDR,
234                        cap->u.vnode_x86_64_ptable.base);
235
236    case ObjType_VNode_x86_64_pdir:
237        return snprintf(buf, len, "x86_64 Page directory at 0x%" PRIxGENPADDR,
238                        cap->u.vnode_x86_64_pdir.base);
239
240    case ObjType_VNode_x86_64_pdpt:
241        return snprintf(buf, len, "x86_64 PDPT at 0x%" PRIxGENPADDR,
242                        cap->u.vnode_x86_64_pdpt.base);
243
244    case ObjType_VNode_x86_64_pml4:
245        return snprintf(buf, len, "x86_64 PML4 at 0x%" PRIxGENPADDR,
246                        cap->u.vnode_x86_64_pml4.base);
247
248    case ObjType_VNode_x86_64_ept_ptable:
249        return snprintf(buf, len, "x86_64 EPT Page table at 0x%" PRIxGENPADDR,
250                        cap->u.vnode_x86_64_ept_ptable.base);
251
252    case ObjType_VNode_x86_64_ept_pdir:
253        return snprintf(buf, len, "x86_64 EPT Page directory at 0x%" PRIxGENPADDR,
254                        cap->u.vnode_x86_64_ept_pdir.base);
255
256    case ObjType_VNode_x86_64_ept_pdpt:
257        return snprintf(buf, len, "x86_64 EPT PDPT at 0x%" PRIxGENPADDR,
258                        cap->u.vnode_x86_64_ept_pdpt.base);
259
260    case ObjType_VNode_x86_64_ept_pml4:
261        return snprintf(buf, len, "x86_64 EPT PML4 at 0x%" PRIxGENPADDR,
262                        cap->u.vnode_x86_64_ept_pml4.base);
263
264    case ObjType_VNode_x86_64_pml5:
265        return snprintf(buf, len, "x86_64 PML5 at 0x%" PRIxGENPADDR,
266                        cap->u.vnode_x86_64_pml5.base);
267
268    case ObjType_VNode_VTd_root_table:
269        return snprintf(buf, len, "VTd Root Table at 0x%" PRIxGENPADDR,
270                        cap->u.vnode_vtd_root_table.base);
271
272    case ObjType_VNode_VTd_ctxt_table:
273        return snprintf(buf, len, "VTd Ctxt Table at 0x%" PRIxGENPADDR,
274                        cap->u.vnode_vtd_ctxt_table.base);
275
276    case ObjType_Frame_Mapping:
277        mappingtype = "Frame";
278        goto ObjType_Mapping;
279    case ObjType_EndPointUMP_Mapping:
280        mappingtype = "Frame";
281        goto ObjType_Mapping;
282    case ObjType_DevFrame_Mapping:
283        mappingtype = "DevFrame";
284        goto ObjType_Mapping;
285    case ObjType_VNode_x86_64_pml5_Mapping:
286        mappingtype = "x86_64 PML5";
287        goto ObjType_Mapping;
288    case ObjType_VNode_x86_64_pml4_Mapping:
289        mappingtype = "x86_64 PML4";
290        goto ObjType_Mapping;
291    case ObjType_VNode_x86_64_pdpt_Mapping:
292        mappingtype = "x86_64 PDPT";
293        goto ObjType_Mapping;
294    case ObjType_VNode_x86_64_pdir_Mapping:
295        mappingtype = "x86_64 PDIR";
296        goto ObjType_Mapping;
297    case ObjType_VNode_x86_64_ptable_Mapping:
298        mappingtype = "x86_64 PTABLE";
299        goto ObjType_Mapping;
300
301    case ObjType_VNode_x86_64_ept_pml4_Mapping:
302        mappingtype = "x86_64 EPT PML4";
303        goto ObjType_Mapping;
304    case ObjType_VNode_x86_64_ept_pdpt_Mapping:
305        mappingtype = "x86_64 EPT PDPT";
306        goto ObjType_Mapping;
307    case ObjType_VNode_x86_64_ept_pdir_Mapping:
308        mappingtype = "x86_64 EPT PDIR";
309        goto ObjType_Mapping;
310    case ObjType_VNode_x86_64_ept_ptable_Mapping:
311        mappingtype = "x86_64 EPT PTABLE";
312        goto ObjType_Mapping;
313
314    case ObjType_VNode_x86_32_pdpt_Mapping:
315        mappingtype = "x86_32 PDPT";
316        goto ObjType_Mapping;
317    case ObjType_VNode_x86_32_pdir_Mapping:
318        mappingtype = "x86_32 PDIR";
319        goto ObjType_Mapping;
320    case ObjType_VNode_x86_32_ptable_Mapping:
321        mappingtype = "x86_32 PTABLE";
322        goto ObjType_Mapping;
323
324    case ObjType_VNode_ARM_l1_Mapping:
325        mappingtype = "ARM l1";
326        goto ObjType_Mapping;
327    case ObjType_VNode_ARM_l2_Mapping:
328        mappingtype = "ARM l2";
329        goto ObjType_Mapping;
330
331    case ObjType_VNode_AARCH64_l0_Mapping:
332        mappingtype = "AARCH64 l0";
333        goto ObjType_Mapping;
334    case ObjType_VNode_AARCH64_l1_Mapping:
335        mappingtype = "AARCH64 l1";
336        goto ObjType_Mapping;
337    case ObjType_VNode_AARCH64_l2_Mapping:
338        mappingtype = "AARCH64 l2";
339        goto ObjType_Mapping;
340    case ObjType_VNode_AARCH64_l3_Mapping:
341        mappingtype = "AARCH64 l3";
342        goto ObjType_Mapping;
343
344    case ObjType_VNode_VTd_root_table_Mapping:
345        mappingtype = "VTd root table";
346        goto ObjType_Mapping;
347    case ObjType_VNode_VTd_ctxt_table_Mapping:
348        mappingtype = "VTd ctxt table";
349        goto ObjType_Mapping;
350
351ObjType_Mapping:
352        return snprintf(buf, len, "%s Mapping (%s cap @%p, "
353                                  "ptable cap @0x%p, entry=%hu, pte_count=%hu)",
354                                  mappingtype, mappingtype,
355                                  cap->u.frame_mapping.cap,
356                                  cap->u.frame_mapping.ptable,
357                                  cap->u.frame_mapping.entry,
358                                  cap->u.frame_mapping.pte_count);
359
360    case ObjType_IRQTable:
361        return snprintf(buf, len, "IRQTable cap");
362
363    case ObjType_IRQSrc:
364        return snprintf(buf, len, "IRQSrc cap (vec: %"PRIu64"-%"PRIu64")",
365                cap->u.irqsrc.vec_start, cap->u.irqsrc.vec_end);
366
367    case ObjType_IRQDest:
368        return snprintf(buf, len, "IRQDest cap (vec: %"PRIu64", cpu: %"PRIu64")",
369                cap->u.irqdest.vector, cap->u.irqdest.cpu);
370
371    case ObjType_EndPointLMP:
372        return snprintf(buf, len, "EndPoint cap (disp %p offset 0x%" PRIxLVADDR ")",
373                        cap->u.endpointlmp.listener, cap->u.endpointlmp.epoffset);
374
375    case ObjType_IO:
376        return snprintf(buf, len, "IO cap (0x%hx-0x%hx)",
377                        cap->u.io.start, cap->u.io.end);
378
379    case ObjType_Kernel:
380        return snprintf(buf, len, "Kernel cap");
381
382    case ObjType_KernelControlBlock:
383        return snprintf(buf, len, "Kernel control block cap");
384
385    case ObjType_ID:
386        return snprintf(buf, len, "ID capability (coreid 0x%" PRIxCOREID
387                        " core_local_id 0x%" PRIx32 ")", cap->u.id.coreid,
388                        cap->u.id.core_local_id);
389
390    case ObjType_ProcessManager:
391        return snprintf(buf, len, "Process manager capability");
392
393    case ObjType_Domain:
394        return snprintf(buf, len, "Domain capability (coreid 0x%" PRIxCOREID
395                        " core_local_id 0x%" PRIx32 ")", cap->u.domain.coreid,
396                        cap->u.domain.core_local_id);
397    case ObjType_DeviceIDManager:
398        return snprintf(buf, len, "DeviceID manager capability");
399    case ObjType_DeviceID:
400        return snprintf(buf, len, "DeviceID capability (%u.%u.%u",
401                        cap->u.deviceid.bus, cap->u.deviceid.device,
402                        cap->u.deviceid.function);
403
404        case ObjType_PerfMon:
405        return snprintf(buf, len, "PerfMon cap");
406
407    case ObjType_Null:
408        return snprintf(buf, len, "Null cap (empty slot)");
409
410    default:
411        return snprintf(buf, len, "UNKNOWN TYPE! (%d)", cap->type);
412    }
413}
414
415int debug_print_cap_at_capref(char *buf, size_t len, struct capref cap)
416{
417    struct capability capability;
418    errval_t err;
419
420    if (capref_is_null(cap)) {
421        return snprintf(buf, len, "(null cap)");
422    }
423
424    err = cap_direct_identify(cap, &capability);
425    if (err_is_fail(err)) {
426        return snprintf(buf, len, "(ERROR identifying cap: %s!)", err_getcode(err));
427    } else {
428        return debug_print_cap(buf, len, &capability);
429    }
430}
431
432/**
433 * \brief Walk and debug print a L2 CNode
434 */
435static void walk_cspace_l2(struct capref l2cnode){
436    errval_t err;
437    struct capability cap;
438    struct cnoderef cnode = build_cnoderef(l2cnode, 1);
439
440    debug_printf("  Printing L2 CNode at L1 slot=%d\n", l2cnode.slot);
441
442    for(int i=0; i<L2_CNODE_SLOTS; i++){
443        struct capref pos = {
444            .cnode = cnode, .slot = i
445        };
446
447        // Get cap data
448        err = cap_direct_identify(pos, &cap);
449        if (err_no(err) == SYS_ERR_IDENTIFY_LOOKUP ||
450            err_no(err) == SYS_ERR_CAP_NOT_FOUND ||
451            err_no(err) == SYS_ERR_LMP_CAPTRANSFER_SRC_LOOKUP ||
452            cap.type == ObjType_Null) {
453            continue;
454        } else if (err_is_fail(err)) {
455            DEBUG_ERR(err, "debug_cap_identify failed");
456            return;
457        }
458
459        char buf[256];
460        size_t prpos = 0;
461
462        prpos += snprintf(buf, sizeof(buf),
463                          "slot %" PRIuCADDR " caddr 0x%" PRIxCADDR " is a ",
464                          pos.slot, get_cap_addr(pos));
465        assert(prpos < sizeof(buf));
466        prpos += debug_print_cap(&buf[prpos], sizeof(buf) - prpos, &cap);
467        assert(prpos < sizeof(buf));
468        debug_printf("    %s\n", buf);
469    }
470}
471
472/**
473 * \brief Dump an arbitrary cspace, given the root
474 *
475 * \bug Works correct only for own cspace. (to fix this cap_identify must
476 * be made to work with all caps)
477 *
478 */
479void debug_cspace(struct capref root)
480{
481    struct capability root_cap;
482    struct capability l2_cap;
483
484    /* find out size of root cnode */
485    errval_t err = cap_direct_identify(root, &root_cap);
486    assert(err_is_ok(err));
487    assert(root_cap.type == ObjType_L1CNode);
488
489    size_t c1size = 0;
490    err = invoke_cnode_get_size(root, &c1size);
491    assert(err_is_ok(err));
492
493    int l1slots = c1size/sizeof(struct capability);
494    debug_printf("Printing L1 CNode (slots=%u)\n", l1slots);
495    for(int slot=0; slot < l1slots; slot++){
496
497        struct cnoderef cnode = build_cnoderef(root, 0);
498        struct capref pos = {
499            .cnode = cnode, .slot = slot
500        };
501        err = cap_direct_identify(pos, &l2_cap);
502
503        // If cap type was Null, kernel returns error
504        if (err_no(err) == SYS_ERR_IDENTIFY_LOOKUP ||
505            err_no(err) == SYS_ERR_CAP_NOT_FOUND ||
506            err_no(err) == SYS_ERR_LMP_CAPTRANSFER_SRC_LOOKUP ||
507            l2_cap.type == ObjType_Null) {
508            continue;
509        } else if (err_is_fail(err)) {
510            DEBUG_ERR(err, "debug_cap_identify failed");
511            return;
512        }
513        walk_cspace_l2(pos);
514    }
515}
516
517void debug_my_cspace(void)
518{
519    debug_cspace(cap_root);
520}
521
522int debug_print_capref(char *buf, size_t len, struct capref cap)
523{
524    return snprintf(buf, len, "CSpace root addr 0x%08" PRIxCADDR", "
525                              "CNode addr 0x%08" PRIxCADDR
526                              ", level = %d, slot %" PRIuCADDR ", level = %d",
527                    get_croot_addr(cap), get_cnode_addr(cap),
528                    get_cnode_level(cap), cap.slot, get_cap_level(cap));
529}
530
531int debug_print_cnoderef(char *buf, size_t len, struct cnoderef cnode)
532{
533    return snprintf(buf, len, "CSpace root addr 0x%08"PRIxCADDR", "
534                              "CNode addr 0x%08"PRIxCADDR", level = %d",
535                              cnode.croot, cnode.cnode, cnode.level);
536}
537
538void debug_dump_mem(lvaddr_t start_addr, lvaddr_t end_addr, lvaddr_t point)
539{
540    debug_printf("Dumping memory in range 0x%" PRIxLVADDR
541                 " to 0x%" PRIxLVADDR ":\n",
542                 start_addr, end_addr);
543
544    for (uintptr_t *p = (void *)start_addr; (uintptr_t)p < end_addr; p++) {
545        uint8_t *bytes = (void *)p;
546        char buf[32];
547        size_t bufpos = 0;
548        for (int i = 0; i < sizeof(uintptr_t); i++) {
549            bufpos += snprintf(&buf[bufpos], sizeof(buf) - bufpos, "%02x ", bytes[i]);
550            assert(bufpos < sizeof(buf));
551        }
552        debug_printf("%p: %.*s %*" PRIxPTR "%s\n", p, (int)sizeof(buf), buf,
553                     (int)sizeof(uintptr_t) * 2, *p,
554                     p == (uintptr_t *)point ? " <== We are here" : "");
555    }
556}
557
558void debug_dump_mem_around_addr(lvaddr_t addr)
559{
560    /* lvaddr_t page_aligned_addr = ROUND_DOWN(addr, BASE_PAGE_SIZE); */
561    lvaddr_t start_addr = ROUND_DOWN(addr - DISP_MEMORY_SIZE/2, sizeof(uintptr_t));
562    lvaddr_t end_addr = ROUND_UP(addr + 2 * DISP_MEMORY_SIZE, sizeof(uintptr_t));
563
564    /* if (start_addr < page_aligned_addr) { */
565    /*     start_addr = page_aligned_addr; */
566    /* } */
567    /* if (end_addr > page_aligned_addr + BASE_PAGE_SIZE) { */
568    /*     end_addr = page_aligned_addr + BASE_PAGE_SIZE; */
569    /* } */
570
571    debug_dump_mem(start_addr, end_addr, addr);
572}
573
574void debug_err(const char *file, const char *func, int line, errval_t err,
575               const char *msg, ...)
576{
577    va_list ap;
578
579    char str[256];
580    char *leader = (err == 0) ? "SUCCESS" : "ERROR";
581    //int strcc =
582        snprintf(str, sizeof(str), "%s: %.*s.%u in %s() %s:%d\n%s: ",
583                     leader, DISP_NAME_LEN, disp_name(), disp_get_current_core_id(),
584                     func, file, line, leader);
585    sys_print(str, sizeof(str));
586
587    if (msg != NULL) {
588        va_start(ap, msg);
589        //int strcc2 =
590            vsnprintf(str, sizeof(str), msg, ap);
591        va_end(ap);
592        sys_print(str, sizeof(str));
593    }
594    sys_print("\n", 1);
595
596    if (err != 0) {
597        err_print_calltrace(err);
598    }
599}
600
601bool debug_notify_syscall = false;
602
603void debug_control_plane_forbidden(void);
604void debug_control_plane_forbidden(void)
605{
606    debug_notify_syscall = true;
607}
608