diff --git a/llvm/test/ExecutionEngine/OrcLazy/dump-jit-debug-descriptor.c b/llvm/test/ExecutionEngine/OrcLazy/dump-jit-debug-descriptor.c new file mode 100644 --- /dev/null +++ b/llvm/test/ExecutionEngine/OrcLazy/dump-jit-debug-descriptor.c @@ -0,0 +1,98 @@ +//===----- dump-jit-debug-descriptor.c -- C debug info source -----*- C -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// C source of the same-named IR file that implements a test for lli. It is +// referenced as the source file in the IR file's debug info tags and acts as a +// template for regenerating it via: +// +// clang -c -g -fPIC -emit-llvm -S dump-jit-debug-descriptor.c +// +//===----------------------------------------------------------------------===// + +#include "inttypes.h" +#include "stdint.h" +#include "stdio.h" +#include "stdlib.h" + +// Declarations follow the GDB JIT interface (version 1, 2009) and must match +// those of the DYLD used for testing. See: +// +// llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.cpp +// llvm/lib/ExecutionEngine/GDBRegistrationListener.cpp +// +typedef enum { + JIT_NOACTION = 0, + JIT_REGISTER_FN, + JIT_UNREGISTER_FN +} jit_actions_t; + +struct jit_code_entry { + struct jit_code_entry *next_entry; + struct jit_code_entry *prev_entry; + const char *symfile_addr; + uint64_t symfile_size; +}; + +struct jit_descriptor { + uint32_t version; + // This should be jit_actions_t, but we want to be specific about the + // bit-width. + uint32_t action_flag; + struct jit_code_entry *relevant_entry; + struct jit_code_entry *first_entry; +}; + +// The JIT defines this symbol and injects entries dynamically. +extern struct jit_descriptor __jit_debug_descriptor; + +const char *actionFlagToStr(uint32_t ActionFlag) { + switch (ActionFlag) { + case JIT_NOACTION: + return "JIT_NOACTION"; + case JIT_REGISTER_FN: + return "JIT_REGISTER_FN"; + case JIT_UNREGISTER_FN: + return "JIT_UNREGISTER_FN"; + } + return ""; +} + +// Sample output: +// +// Reading __jit_debug_descriptor at 0x0000000000404048 +// +// Version: 0 +// Action: JIT_REGISTER_FN +// +// Entry Symbol File Size Previous Entry +// [ 0] 0x0000000000451290 0x0000000000002000 200 0x0000000000000000 +// [ 1] 0x0000000000451260 0x0000000000001000 100 0x0000000000451290 +// ... +// +int main() { + printf("Reading __jit_debug_descriptor at 0x%016" PRIX64 "\n\n", + (uintptr_t)(&__jit_debug_descriptor)); + printf("Version: %d\n", __jit_debug_descriptor.version); + printf("Action: %s\n\n", actionFlagToStr(__jit_debug_descriptor.action_flag)); + + const char *FmtHead = "%11s %24s %15s %14s\n"; + const char *FmtRow = "[%2d] 0x%016" PRIX64 " 0x%016" PRIX64 " %8ld " + "0x%016" PRIX64 "\n"; + + unsigned Idx = 0; + struct jit_code_entry *Entry = __jit_debug_descriptor.first_entry; + printf(FmtHead, "Entry", "Symbol File", "Size", "Previous Entry"); + while (Entry) { + printf(FmtRow, Idx, (uintptr_t)Entry, (uintptr_t)Entry->symfile_addr, + Entry->symfile_size, (uintptr_t)Entry->prev_entry); + Entry = Entry->next_entry; + Idx += 1; + } + + return 0; +} diff --git a/llvm/test/ExecutionEngine/OrcLazy/dump-jit-debug-descriptor.ll b/llvm/test/ExecutionEngine/OrcLazy/dump-jit-debug-descriptor.ll new file mode 100644 --- /dev/null +++ b/llvm/test/ExecutionEngine/OrcLazy/dump-jit-debug-descriptor.ll @@ -0,0 +1,220 @@ +; REQUIRES: target-x86_64 +; XFAIL: system-windows + +; RUN: lli --jit-kind=orc-lazy --per-module-lazy --dyld=jitlink %s | FileCheck %s + +; CHECK: Reading __jit_debug_descriptor at 0x{{.*}} +; CHECK: Version: 1 +; CHECK: Action: JIT_REGISTER_FN +; CHECK: Entry Symbol File Size Previous Entry +; CHECK: [ 0] 0x{{.*}} 0x{{.*}} {{.*}} 0x0000000000000000 + +source_filename = "dump-jit-debug-descriptor.c" +target triple = "x86_64-pc-linux-gnu" + +%struct.jit_descriptor = type { i32, i32, %struct.jit_code_entry*, %struct.jit_code_entry* } +%struct.jit_code_entry = type { %struct.jit_code_entry*, %struct.jit_code_entry*, i8*, i64 } + +@.str = private unnamed_addr constant [13 x i8] c"JIT_NOACTION\00", align 1 +@.str.1 = private unnamed_addr constant [16 x i8] c"JIT_REGISTER_FN\00", align 1 +@.str.2 = private unnamed_addr constant [18 x i8] c"JIT_UNREGISTER_FN\00", align 1 +@.str.3 = private unnamed_addr constant [22 x i8] c"\00", align 1 +@.str.4 = private unnamed_addr constant [45 x i8] c"Reading __jit_debug_descriptor at 0x%016lX\0A\0A\00", align 1 +@.str.5 = private unnamed_addr constant [13 x i8] c"Version: %d\0A\00", align 1 +@.str.6 = private unnamed_addr constant [13 x i8] c"Action: %s\0A\0A\00", align 1 +@.str.7 = private unnamed_addr constant [24 x i8] c"%11s %24s %15s %14s\0A\00", align 1 +@.str.8 = private unnamed_addr constant [43 x i8] c"[%2d] 0x%016lX 0x%016lX %8ld 0x%016lX\0A\00", align 1 +@.str.9 = private unnamed_addr constant [6 x i8] c"Entry\00", align 1 +@.str.10 = private unnamed_addr constant [12 x i8] c"Symbol File\00", align 1 +@.str.11 = private unnamed_addr constant [5 x i8] c"Size\00", align 1 +@.str.12 = private unnamed_addr constant [15 x i8] c"Previous Entry\00", align 1 +@__jit_debug_descriptor = external global %struct.jit_descriptor, align 8 + +declare i32 @printf(i8*, ...) +declare void @llvm.dbg.declare(metadata, metadata, metadata) + +; Function Attrs: noinline nounwind optnone uwtable +define i8* @actionFlagToStr(i32) !dbg !12 { + %2 = alloca i8*, align 8 + %3 = alloca i32, align 4 + store i32 %0, i32* %3, align 4 + call void @llvm.dbg.declare(metadata i32* %3, metadata !23, metadata !DIExpression()), !dbg !24 + %4 = load i32, i32* %3, align 4, !dbg !25 + switch i32 %4, label %8 [ + i32 0, label %5 + i32 1, label %6 + i32 2, label %7 + ], !dbg !26 + +;