1 | /* The library used by gdb. |
2 | Copyright (C) 2014-2024 Free Software Foundation, Inc. |
3 | |
4 | This file is part of GCC. |
5 | |
6 | GCC is free software; you can redistribute it and/or modify it under |
7 | the terms of the GNU General Public License as published by the Free |
8 | Software Foundation; either version 3, or (at your option) any later |
9 | version. |
10 | |
11 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or |
13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
14 | for more details. |
15 | |
16 | You should have received a copy of the GNU General Public License |
17 | along with GCC; see the file COPYING3. If not see |
18 | <http://www.gnu.org/licenses/>. */ |
19 | |
20 | #include <cc1plugin-config.h> |
21 | #include <vector> |
22 | #include <string> |
23 | #include <sys/socket.h> |
24 | #include <sys/types.h> |
25 | #include <unistd.h> |
26 | #include <sys/wait.h> |
27 | #include <stdio.h> |
28 | #include <errno.h> |
29 | #include <sys/stat.h> |
30 | #include <stdlib.h> |
31 | #include "marshall.hh" |
32 | #include "rpc.hh" |
33 | #include "connection.hh" |
34 | #include "names.hh" |
35 | #include "callbacks.hh" |
36 | #include "libiberty.h" |
37 | #include "compiler-name.hh" |
38 | #include "gcc-c-interface.h" |
39 | #include "compiler.hh" |
40 | #include "gdbctx.hh" |
41 | |
42 | // The C compiler context that we hand back to our caller. |
43 | struct libcc1 : public cc1_plugin::base_gdb_plugin<gcc_c_context> |
44 | { |
45 | explicit libcc1 (const gcc_c_fe_vtable *); |
46 | |
47 | void add_callbacks () override; |
48 | |
49 | gcc_c_oracle_function *binding_oracle = nullptr; |
50 | gcc_c_symbol_address_function *address_oracle = nullptr; |
51 | void *oracle_datum = nullptr; |
52 | }; |
53 | |
54 | libcc1::libcc1 (const gcc_c_fe_vtable *cv) |
55 | : cc1_plugin::base_gdb_plugin<gcc_c_context> ("libcc1plugin" , |
56 | C_COMPILER_NAME, |
57 | cv->c_version) |
58 | { |
59 | c_ops = cv; |
60 | } |
61 | |
62 | |
63 | |
64 | // Enclose these functions in an anonymous namespace because they |
65 | // shouldn't be exported, but they can't be static because they're |
66 | // used as template arguments. |
67 | namespace { |
68 | // This is a wrapper function that is called by the RPC system and |
69 | // that then forwards the call to the library user. Note that the |
70 | // return value is not used; the type cannot be 'void' due to |
71 | // limitations in our simple RPC. |
72 | int |
73 | c_call_binding_oracle (cc1_plugin::connection *conn, |
74 | enum gcc_c_oracle_request request, |
75 | const char *identifier) |
76 | { |
77 | libcc1 *self = (libcc1 *) (((libcc1::local_connection *) conn)->back_ptr); |
78 | |
79 | self->binding_oracle (self->oracle_datum, self, request, identifier); |
80 | return 1; |
81 | } |
82 | |
83 | // This is a wrapper function that is called by the RPC system and |
84 | // that then forwards the call to the library user. |
85 | gcc_address |
86 | c_call_symbol_address (cc1_plugin::connection *conn, const char *identifier) |
87 | { |
88 | libcc1 *self = (libcc1 *) (((libcc1::local_connection *) conn)->back_ptr); |
89 | |
90 | return self->address_oracle (self->oracle_datum, self, identifier); |
91 | } |
92 | } /* anonymous namespace */ |
93 | |
94 | |
95 | |
96 | static void |
97 | set_callbacks (struct gcc_c_context *s, |
98 | gcc_c_oracle_function *binding_oracle, |
99 | gcc_c_symbol_address_function *address_oracle, |
100 | void *datum) |
101 | { |
102 | libcc1 *self = (libcc1 *) s; |
103 | |
104 | self->binding_oracle = binding_oracle; |
105 | self->address_oracle = address_oracle; |
106 | self->oracle_datum = datum; |
107 | } |
108 | |
109 | static const struct gcc_c_fe_vtable c_vtable = |
110 | { |
111 | .c_version: GCC_C_FE_VERSION_2, |
112 | .set_callbacks: set_callbacks, |
113 | |
114 | #define GCC_METHOD0(R, N) \ |
115 | cc1_plugin::rpc<gcc_c_context, R, cc1_plugin::c::N>, |
116 | #define GCC_METHOD1(R, N, A) \ |
117 | cc1_plugin::rpc<gcc_c_context, R, cc1_plugin::c::N, A>, |
118 | #define GCC_METHOD2(R, N, A, B) \ |
119 | cc1_plugin::rpc<gcc_c_context, R, cc1_plugin::c::N, A, B>, |
120 | #define GCC_METHOD3(R, N, A, B, C) \ |
121 | cc1_plugin::rpc<gcc_c_context, R, cc1_plugin::c::N, A, B, C>, |
122 | #define GCC_METHOD4(R, N, A, B, C, D) \ |
123 | cc1_plugin::rpc<gcc_c_context, R, cc1_plugin::c::N, A, B, C, D>, |
124 | #define GCC_METHOD5(R, N, A, B, C, D, E) \ |
125 | cc1_plugin::rpc<gcc_c_context, R, cc1_plugin::c::N, A, B, C, D, E>, |
126 | #define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \ |
127 | cc1_plugin::rpc<gcc_c_context, R, cc1_plugin::c::N, A, B, C, D, E, F, G>, |
128 | |
129 | #include "gcc-c-fe.def" |
130 | |
131 | #undef GCC_METHOD0 |
132 | #undef GCC_METHOD1 |
133 | #undef GCC_METHOD2 |
134 | #undef GCC_METHOD3 |
135 | #undef GCC_METHOD4 |
136 | #undef GCC_METHOD5 |
137 | #undef GCC_METHOD7 |
138 | }; |
139 | |
140 | |
141 | |
142 | void |
143 | libcc1::add_callbacks () |
144 | { |
145 | cc1_plugin::callback_ftype *fun |
146 | = cc1_plugin::invoker<int, |
147 | enum gcc_c_oracle_request, |
148 | const char *>::invoke<c_call_binding_oracle>; |
149 | connection->add_callback (name: "binding_oracle" , func: fun); |
150 | |
151 | fun = cc1_plugin::invoker<gcc_address, |
152 | const char *>::invoke<c_call_symbol_address>; |
153 | connection->add_callback (name: "address_oracle" , func: fun); |
154 | } |
155 | |
156 | extern "C" gcc_c_fe_context_function gcc_c_fe_context; |
157 | |
158 | #ifdef __GNUC__ |
159 | #pragma GCC visibility push(default) |
160 | #endif |
161 | |
162 | extern "C" |
163 | struct gcc_c_context * |
164 | gcc_c_fe_context (enum gcc_base_api_version base_version, |
165 | enum gcc_c_api_version c_version) |
166 | { |
167 | if ((base_version != GCC_FE_VERSION_0 && base_version != GCC_FE_VERSION_1) |
168 | || (c_version != GCC_C_FE_VERSION_0 && c_version != GCC_C_FE_VERSION_1 |
169 | && c_version != GCC_C_FE_VERSION_2)) |
170 | return NULL; |
171 | |
172 | return new libcc1 (&c_vtable); |
173 | } |
174 | |