1*5f7ddb14SDimitry Andric /*
2*5f7ddb14SDimitry Andric * ompd-specific.cpp -- OpenMP debug support
3*5f7ddb14SDimitry Andric */
4*5f7ddb14SDimitry Andric
5*5f7ddb14SDimitry Andric //===----------------------------------------------------------------------===//
6*5f7ddb14SDimitry Andric //
7*5f7ddb14SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
8*5f7ddb14SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
9*5f7ddb14SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
10*5f7ddb14SDimitry Andric //
11*5f7ddb14SDimitry Andric //===----------------------------------------------------------------------===//
12*5f7ddb14SDimitry Andric
13*5f7ddb14SDimitry Andric #include "ompd-specific.h"
14*5f7ddb14SDimitry Andric
15*5f7ddb14SDimitry Andric #if OMPD_SUPPORT
16*5f7ddb14SDimitry Andric
17*5f7ddb14SDimitry Andric /**
18*5f7ddb14SDimitry Andric * Declaration of symbols to hold struct size and member offset information
19*5f7ddb14SDimitry Andric */
20*5f7ddb14SDimitry Andric
21*5f7ddb14SDimitry Andric #define ompd_declare_access(t, m) uint64_t ompd_access__##t##__##m;
22*5f7ddb14SDimitry Andric OMPD_FOREACH_ACCESS(ompd_declare_access)
23*5f7ddb14SDimitry Andric #undef ompd_declare_access
24*5f7ddb14SDimitry Andric
25*5f7ddb14SDimitry Andric #define ompd_declare_sizeof_member(t, m) uint64_t ompd_sizeof__##t##__##m;
26*5f7ddb14SDimitry Andric OMPD_FOREACH_ACCESS(ompd_declare_sizeof_member)
27*5f7ddb14SDimitry Andric #undef ompd_declare_sizeof_member
28*5f7ddb14SDimitry Andric
29*5f7ddb14SDimitry Andric #define ompd_declare_bitfield(t, m) uint64_t ompd_bitfield__##t##__##m;
30*5f7ddb14SDimitry Andric OMPD_FOREACH_BITFIELD(ompd_declare_bitfield)
31*5f7ddb14SDimitry Andric #undef ompd_declare_bitfield
32*5f7ddb14SDimitry Andric
33*5f7ddb14SDimitry Andric #define ompd_declare_sizeof(t) uint64_t ompd_sizeof__##t;
34*5f7ddb14SDimitry Andric OMPD_FOREACH_SIZEOF(ompd_declare_sizeof)
35*5f7ddb14SDimitry Andric #undef ompd_declare_sizeof
36*5f7ddb14SDimitry Andric
37*5f7ddb14SDimitry Andric volatile const char **ompd_dll_locations = NULL;
38*5f7ddb14SDimitry Andric uint64_t ompd_state = 0;
39*5f7ddb14SDimitry Andric
40*5f7ddb14SDimitry Andric char *ompd_env_block = NULL;
41*5f7ddb14SDimitry Andric ompd_size_t ompd_env_block_size = 0;
42*5f7ddb14SDimitry Andric
ompd_init()43*5f7ddb14SDimitry Andric void ompd_init() {
44*5f7ddb14SDimitry Andric
45*5f7ddb14SDimitry Andric static int ompd_initialized = 0;
46*5f7ddb14SDimitry Andric
47*5f7ddb14SDimitry Andric if (ompd_initialized)
48*5f7ddb14SDimitry Andric return;
49*5f7ddb14SDimitry Andric
50*5f7ddb14SDimitry Andric /**
51*5f7ddb14SDimitry Andric * Calculate member offsets for structs and unions
52*5f7ddb14SDimitry Andric */
53*5f7ddb14SDimitry Andric
54*5f7ddb14SDimitry Andric #define ompd_init_access(t, m) \
55*5f7ddb14SDimitry Andric ompd_access__##t##__##m = (uint64_t) & (((t *)0)->m);
56*5f7ddb14SDimitry Andric OMPD_FOREACH_ACCESS(ompd_init_access)
57*5f7ddb14SDimitry Andric #undef ompd_init_access
58*5f7ddb14SDimitry Andric
59*5f7ddb14SDimitry Andric /**
60*5f7ddb14SDimitry Andric * Create bit mask for bitfield access
61*5f7ddb14SDimitry Andric */
62*5f7ddb14SDimitry Andric
63*5f7ddb14SDimitry Andric #define ompd_init_bitfield(t, m) \
64*5f7ddb14SDimitry Andric ompd_bitfield__##t##__##m = 0; \
65*5f7ddb14SDimitry Andric ((t *)(&ompd_bitfield__##t##__##m))->m = 1;
66*5f7ddb14SDimitry Andric OMPD_FOREACH_BITFIELD(ompd_init_bitfield)
67*5f7ddb14SDimitry Andric #undef ompd_init_bitfield
68*5f7ddb14SDimitry Andric
69*5f7ddb14SDimitry Andric /**
70*5f7ddb14SDimitry Andric * Calculate type size information
71*5f7ddb14SDimitry Andric */
72*5f7ddb14SDimitry Andric
73*5f7ddb14SDimitry Andric #define ompd_init_sizeof_member(t, m) \
74*5f7ddb14SDimitry Andric ompd_sizeof__##t##__##m = sizeof(((t *)0)->m);
75*5f7ddb14SDimitry Andric OMPD_FOREACH_ACCESS(ompd_init_sizeof_member)
76*5f7ddb14SDimitry Andric #undef ompd_init_sizeof_member
77*5f7ddb14SDimitry Andric
78*5f7ddb14SDimitry Andric #define ompd_init_sizeof(t) ompd_sizeof__##t = sizeof(t);
79*5f7ddb14SDimitry Andric OMPD_FOREACH_SIZEOF(ompd_init_sizeof)
80*5f7ddb14SDimitry Andric #undef ompd_init_sizeof
81*5f7ddb14SDimitry Andric
82*5f7ddb14SDimitry Andric char *libname = NULL;
83*5f7ddb14SDimitry Andric
84*5f7ddb14SDimitry Andric #if KMP_OS_UNIX
85*5f7ddb14SDimitry Andric // Find the location of libomp.so thru dladdr and replace the libomp with
86*5f7ddb14SDimitry Andric // libompd to get the full path of libompd
87*5f7ddb14SDimitry Andric Dl_info dl_info;
88*5f7ddb14SDimitry Andric int ret = dladdr((void *)ompd_init, &dl_info);
89*5f7ddb14SDimitry Andric if (!ret) {
90*5f7ddb14SDimitry Andric fprintf(stderr, "%s\n", dlerror());
91*5f7ddb14SDimitry Andric }
92*5f7ddb14SDimitry Andric int lib_path_length;
93*5f7ddb14SDimitry Andric if (strrchr(dl_info.dli_fname, '/')) {
94*5f7ddb14SDimitry Andric lib_path_length = strrchr(dl_info.dli_fname, '/') - dl_info.dli_fname;
95*5f7ddb14SDimitry Andric libname =
96*5f7ddb14SDimitry Andric (char *)malloc(lib_path_length + 12 /*for '/libompd.so' and '\0'*/);
97*5f7ddb14SDimitry Andric strncpy(libname, dl_info.dli_fname, lib_path_length);
98*5f7ddb14SDimitry Andric memcpy(libname + lib_path_length, "/libompd.so\0", 12);
99*5f7ddb14SDimitry Andric }
100*5f7ddb14SDimitry Andric #endif
101*5f7ddb14SDimitry Andric
102*5f7ddb14SDimitry Andric const char *ompd_env_var = getenv("OMP_DEBUG");
103*5f7ddb14SDimitry Andric if (ompd_env_var && !strcmp(ompd_env_var, "enabled")) {
104*5f7ddb14SDimitry Andric fprintf(stderr, "OMP_OMPD active\n");
105*5f7ddb14SDimitry Andric ompt_enabled.enabled = 1;
106*5f7ddb14SDimitry Andric ompd_state |= OMPD_ENABLE_BP;
107*5f7ddb14SDimitry Andric }
108*5f7ddb14SDimitry Andric
109*5f7ddb14SDimitry Andric ompd_initialized = 1;
110*5f7ddb14SDimitry Andric ompd_dll_locations = (volatile const char **)malloc(3 * sizeof(const char *));
111*5f7ddb14SDimitry Andric ompd_dll_locations[0] = "libompd.so";
112*5f7ddb14SDimitry Andric ompd_dll_locations[1] = libname;
113*5f7ddb14SDimitry Andric ompd_dll_locations[2] = NULL;
114*5f7ddb14SDimitry Andric ompd_dll_locations_valid();
115*5f7ddb14SDimitry Andric }
116*5f7ddb14SDimitry Andric
ompd_dll_locations_valid(void)117*5f7ddb14SDimitry Andric void __attribute__((noinline)) ompd_dll_locations_valid(void) {
118*5f7ddb14SDimitry Andric /* naive way of implementing hard to opt-out empty function
119*5f7ddb14SDimitry Andric we might want to use a separate object file? */
120*5f7ddb14SDimitry Andric asm("");
121*5f7ddb14SDimitry Andric }
122*5f7ddb14SDimitry Andric
ompd_bp_parallel_begin(void)123*5f7ddb14SDimitry Andric void ompd_bp_parallel_begin(void) {
124*5f7ddb14SDimitry Andric /* naive way of implementing hard to opt-out empty function
125*5f7ddb14SDimitry Andric we might want to use a separate object file? */
126*5f7ddb14SDimitry Andric asm("");
127*5f7ddb14SDimitry Andric }
ompd_bp_parallel_end(void)128*5f7ddb14SDimitry Andric void ompd_bp_parallel_end(void) {
129*5f7ddb14SDimitry Andric /* naive way of implementing hard to opt-out empty function
130*5f7ddb14SDimitry Andric we might want to use a separate object file? */
131*5f7ddb14SDimitry Andric asm("");
132*5f7ddb14SDimitry Andric }
ompd_bp_task_begin(void)133*5f7ddb14SDimitry Andric void ompd_bp_task_begin(void) {
134*5f7ddb14SDimitry Andric /* naive way of implementing hard to opt-out empty function
135*5f7ddb14SDimitry Andric we might want to use a separate object file? */
136*5f7ddb14SDimitry Andric asm("");
137*5f7ddb14SDimitry Andric }
ompd_bp_task_end(void)138*5f7ddb14SDimitry Andric void ompd_bp_task_end(void) {
139*5f7ddb14SDimitry Andric /* naive way of implementing hard to opt-out empty function
140*5f7ddb14SDimitry Andric we might want to use a separate object file? */
141*5f7ddb14SDimitry Andric asm("");
142*5f7ddb14SDimitry Andric }
ompd_bp_thread_begin(void)143*5f7ddb14SDimitry Andric void ompd_bp_thread_begin(void) {
144*5f7ddb14SDimitry Andric /* naive way of implementing hard to opt-out empty function
145*5f7ddb14SDimitry Andric we might want to use a separate object file? */
146*5f7ddb14SDimitry Andric asm("");
147*5f7ddb14SDimitry Andric }
ompd_bp_thread_end(void)148*5f7ddb14SDimitry Andric void ompd_bp_thread_end(void) {
149*5f7ddb14SDimitry Andric /* naive way of implementing hard to opt-out empty function
150*5f7ddb14SDimitry Andric we might want to use a separate object file? */
151*5f7ddb14SDimitry Andric asm("");
152*5f7ddb14SDimitry Andric }
153*5f7ddb14SDimitry Andric
154*5f7ddb14SDimitry Andric #endif /* OMPD_SUPPORT */
155