ReactOS 0.4.15-dev-7842-g558ab78
main.cpp
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS SDK
3 * LICENSE: BSD Zero Clause License (https://spdx.org/licenses/0BSD)
4 * PURPOSE: Helper pragma implementation for pseh library (amd64)
5 * COPYRIGHT: Copyright 2021 Jérôme Gardou
6 */
7
8#include <gcc-plugin.h>
9#include <plugin-version.h>
10#include <function.h>
11#include <tree.h>
12#include <c-family/c-pragma.h>
13#include <c-family/c-common.h>
14
15#include <iostream>
16#include <sstream>
17#include <unordered_map>
18#include <vector>
19
20#define is_alpha(c) (((c)>64 && (c)<91) || ((c)>96 && (c)<123))
21
22#if defined(_WIN32) || defined(WIN32)
23#define VISIBLE __declspec(dllexport)
24#else
25#define VISIBLE __attribute__((__visibility__("default")))
26#endif
27
28#define UNUSED __attribute__((__unused__))
29
30int
33
35{
36 bool unwind;
37 bool except;
40 size_t count;
41
42 seh_function(struct function* fun)
43 : unwind(false)
44 , except(false)
45 , count(0)
46 {
47 /* Reserve space for our header statement */
48 char buf[256];
49 memset(buf, 0, sizeof(buf));
50 asm_header_text = build_string(sizeof(buf), buf);
51 asm_header = build_stmt(fun->function_start_locus, ASM_EXPR, asm_header_text, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE);
52 ASM_VOLATILE_P(asm_header) = 1;
53 add_stmt(asm_header);
54 }
55};
56
57static std::unordered_map<struct function*, struct seh_function*> func_seh_map = {};
58
59static
60struct seh_function*
62{
63 auto search = func_seh_map.find(cfun);
64 if (search != func_seh_map.end())
65 return search->second;
66
67 auto seh_fun = new seh_function(cfun);
68 func_seh_map.insert({cfun, seh_fun});
69
70 return seh_fun;
71}
72
73static
74void
76{
77 tree x, arg;
78 std::stringstream label_decl;
79
80 if (!cfun)
81 {
82 error("%<#pragma REACTOS seh%> is not allowed outside functions");
83 return;
84 }
85
86 if ((pragma_lex(&x) != CPP_OPEN_PAREN) ||
87 (pragma_lex(&arg) != CPP_NAME) ||
88 (pragma_lex(&x) != CPP_CLOSE_PAREN) ||
89 (pragma_lex(&x) != CPP_EOF))
90 {
91 error("%<#pragma REACTOS seh%> needs one parameter%>");
92 return;
93 }
94
95 const char* op = IDENTIFIER_POINTER(arg);
96
97 seh_function* seh_fun = get_seh_function();
98 if (strcmp(op, "except") == 0)
99 seh_fun->except = true;
100 else if (strcmp(op, "finally") == 0)
101 seh_fun->unwind = true;
102 else
103 {
104 error("Wrong argument for %<#pragma REACTOS seh%>. Expected \"except\" or \"finally\"");
105 return;
106 }
107 seh_fun->count++;
108
109 /* Make sure we use a frame pointer. REACTOS' PSEH depends on this */
110 cfun->machine->accesses_prev_frame = 1;
111}
112
113static
114void
115finish_seh_function(void* event_data, void* UNUSED user_data)
116{
117 tree fndef = (tree)event_data;
118 struct function* fun = DECL_STRUCT_FUNCTION(fndef);
119
120 auto search = func_seh_map.find(fun);
121 if (search == func_seh_map.end())
122 return;
123
124 /* Get our SEH details and remove us from the map */
125 seh_function* seh_fun = search->second;
126 func_seh_map.erase(search);
127
128 if (DECL_FUNCTION_PERSONALITY(fndef) != nullptr)
129 {
130 error("Function %s has a personality. Are you mixing SEH with C++ exceptions ?",
131 IDENTIFIER_POINTER(fndef));
132 return;
133 }
134
135 /* Update asm statement */
136 std::stringstream asm_str;
137 asm_str << ".seh_handler __C_specific_handler";
138 if (seh_fun->unwind)
139 asm_str << ", @unwind";
140 if (seh_fun->except)
141 asm_str << ", @except";
142 asm_str << "\n";
143 asm_str << "\t.seh_handlerdata\n";
144 asm_str << "\t.long " << seh_fun->count << "\n";
145 asm_str << "\t.seh_code";
146
147 strncpy(const_cast<char*>(TREE_STRING_POINTER(seh_fun->asm_header_text)),
148 asm_str.str().c_str(),
149 TREE_STRING_LENGTH(seh_fun->asm_header_text));
150
151 delete seh_fun;
152}
153
154static
155void
156register_seh_pragmas(void* UNUSED event_data, void* UNUSED user_data)
157{
158 c_register_pragma("REACTOS", "seh", handle_seh_pragma);
159}
160
161/* Return 0 on success or error code on failure */
162extern "C"
164int plugin_init(struct plugin_name_args *info, /* Argument infor */
165 struct plugin_gcc_version *version) /* Version of GCC */
166{
167 if (!plugin_default_version_check (version, &gcc_version))
168 {
169 std::cerr << "This GCC plugin is for version " << GCCPLUGIN_VERSION_MAJOR << "." << GCCPLUGIN_VERSION_MINOR << "\n";
170 return 1;
171 }
172
173 register_callback(info->base_name, PLUGIN_PRAGMAS, register_seh_pragmas, NULL);
174 register_callback(info->base_name, PLUGIN_FINISH_PARSE_FUNCTION, finish_seh_function, NULL);
175
176 return 0;
177}
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
struct _tree tree
#define NULL
Definition: types.h:112
UINT op
Definition: effect.c:236
static const WCHAR version[]
Definition: asmname.c:66
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define error(str)
Definition: mkdosfs.c:1605
static short search(int val, const short *table, int size)
Definition: msg711.c:255
#define memset(x, y, z)
Definition: compat.h:39
static void handle_seh_pragma(cpp_reader *UNUSED parser)
Definition: main.cpp:75
static struct seh_function * get_seh_function()
Definition: main.cpp:61
static void register_seh_pragmas(void *UNUSED event_data, void *UNUSED user_data)
Definition: main.cpp:156
int VISIBLE plugin_is_GPL_compatible
Definition: main.cpp:32
static std::unordered_map< struct function *, struct seh_function * > func_seh_map
Definition: main.cpp:57
#define UNUSED
Definition: main.cpp:28
static void finish_seh_function(void *event_data, void *UNUSED user_data)
Definition: main.cpp:115
VISIBLE int plugin_init(struct plugin_name_args *info, struct plugin_gcc_version *version)
Definition: main.cpp:164
#define VISIBLE
Definition: main.cpp:25
#define false
Definition: stdbool.h:37
Definition: import.c:81
size_t count
Definition: main.cpp:40
tree asm_header_text
Definition: main.cpp:38
tree asm_header
Definition: main.cpp:39
bool unwind
Definition: main.cpp:36
seh_function(struct function *fun)
Definition: main.cpp:42
bool except
Definition: main.cpp:37
void * arg
Definition: msvc.h:10