1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <ctime>
6 #include <fstream>
7
8 #include "generator.h"
9
10 using std::ofstream;
11 using std::string;
12
13 static constexpr char kAuthors[] = "The Fuchsia Authors";
14 static constexpr char kWrapMacro[] = "ZX_SYSCALL_PARAM_ATTR";
15 static constexpr char kDefaultHandleAnnotation[] = "handle_use";
16 bool is_identifier_keyword(const string& iden);
17
header(ofstream & os)18 bool Generator::header(ofstream& os) {
19 auto t = std::time(nullptr);
20 auto ltime = std::localtime(&t);
21
22 os << "// Copyright " << ltime->tm_year + 1900
23 << " " << kAuthors << ". All rights reserved.\n";
24 os << "// This is a GENERATED file, see //zircon/system/host/abigen.\n";
25 os << "// The license governing this file can be found in the LICENSE file.\n\n";
26
27 return os.good();
28 }
29
footer(ofstream & os)30 bool Generator::footer(ofstream& os) {
31 os << "\n";
32 return os.good();
33 }
34
syscall(ofstream & os,const Syscall & sc)35 bool VDsoAsmGenerator::syscall(ofstream& os, const Syscall& sc) {
36 if (!sc.is_vdso()) {
37 bool is_public = !sc.is_internal();
38 for (const CallWrapper* wrapper : wrappers_) {
39 if (wrapper->applies(sc)) {
40 is_public = false;
41 break;
42 }
43 }
44
45 // m_syscall name, syscall_num, nargs
46 os << syscall_macro_
47 << " " << name_prefix_ << sc.name
48 << " " << sc.index
49 << " " << sc.num_kernel_args()
50 << " " << (is_public ? 1 : 0)
51 << "\n";
52 }
53 return os.good();
54 }
55
header(ofstream & os)56 bool KernelBranchGenerator::header(ofstream& os) {
57 if (!Generator::header(os))
58 return false;
59
60 os << "start_syscall_dispatch\n";
61 return os.good();
62 }
63
syscall(ofstream & os,const Syscall & sc)64 bool KernelBranchGenerator::syscall(ofstream& os, const Syscall& sc) {
65 if (sc.is_vdso()) {
66 return os.good();
67 }
68 os << "syscall_dispatch " << sc.num_kernel_args() << " " << sc.name << "\n";
69 return os.good();
70 }
71
syscall(ofstream & os,const Syscall & sc)72 bool SyscallNumbersGenerator::syscall(ofstream& os, const Syscall& sc) {
73 if (sc.is_vdso())
74 return true;
75
76 num_calls_++;
77 os << define_prefix_ << sc.name << " " << sc.index << "\n";
78 return os.good();
79 }
80
footer(ofstream & os)81 bool SyscallNumbersGenerator::footer(ofstream& os) {
82 os << define_prefix_ << "COUNT " << num_calls_ << "\n";
83 return os.good();
84 }
85
syscall(ofstream & os,const Syscall & sc)86 bool TraceInfoGenerator::syscall(ofstream& os, const Syscall& sc) {
87 if (sc.is_vdso())
88 return true;
89
90 // Can be injected as an array of structs or into a tuple-like C++ container.
91 os << "{" << sc.index << ", " << sc.num_kernel_args() << ", "
92 << '"' << sc.name << "\"},\n";
93
94 return os.good();
95 }
96
syscall(ofstream & os,const Syscall & sc)97 bool CategoryGenerator::syscall(ofstream& os, const Syscall& sc) {
98 for (const auto& attr : sc.attributes) {
99 if (attr != "*" && attr != "internal")
100 category_map_[attr].push_back(&sc.name);
101 }
102 return true;
103 }
104
footer(ofstream & os)105 bool CategoryGenerator::footer(ofstream& os) {
106 for (const auto& category : category_map_) {
107 os << "\n#define HAVE_SYSCALL_CATEGORY_" << category.first << " 1\n";
108 os << "SYSCALL_CATEGORY_BEGIN(" << category.first << ")\n";
109
110 for (auto sc : category.second)
111 os << " SYSCALL_IN_CATEGORY(" << *sc << ")\n";
112
113 os << "SYSCALL_CATEGORY_END(" << category.first << ")\n";
114 }
115 return os.good();
116 }
117
write_syscall_signature_line(ofstream & os,const Syscall & sc,string name_prefix,string before_args,string inter_arg,bool wrap_pointers_with_user_ptr,string no_args_type)118 void write_syscall_signature_line(ofstream& os, const Syscall& sc, string name_prefix,
119 string before_args, string inter_arg,
120 bool wrap_pointers_with_user_ptr, string no_args_type) {
121 auto syscall_name = name_prefix + sc.name;
122
123 // writes "[return-type] prefix_[syscall-name]("
124 os << sc.return_type() << " " << syscall_name << "(";
125
126 // Writes all arguments.
127 os << before_args;
128 bool first = true;
129 sc.for_each_kernel_arg([&](const TypeSpec& arg) {
130 if (!first) {
131 os << inter_arg;
132 }
133 first = false;
134 write_argument_annotation(os, arg);
135 os << arg.as_cpp_declaration(wrap_pointers_with_user_ptr) << ",";
136 });
137
138 if (sc.num_kernel_args() > 0) {
139 // remove the comma.
140 os.seekp(-1, std::ios_base::end);
141 } else {
142 os << no_args_type;
143 }
144
145 os << ")";
146 }
147
write_syscall_return_var(ofstream & os,const Syscall & sc)148 string write_syscall_return_var(ofstream& os, const Syscall& sc) {
149 string return_var = sc.is_void_return() ? "" : "ret";
150 if (!sc.is_void_return()) {
151 os << sc.return_type() << " " << return_var << ";\n";
152 }
153 return return_var;
154 }
155
write_syscall_invocation(ofstream & os,const Syscall & sc,const string & return_var,const string & name_prefix)156 void write_syscall_invocation(ofstream& os, const Syscall& sc,
157 const string& return_var, const string& name_prefix) {
158 if (!return_var.empty()) {
159 os << return_var << " = ";
160 }
161
162 os << name_prefix << sc.name << "(";
163
164 // Writes all arguments.
165 sc.for_each_kernel_arg([&](const TypeSpec& arg) {
166 os << arg.name << ", ";
167 });
168
169 if (sc.num_kernel_args() > 0) {
170 // remove the comma and space.
171 os.seekp(-2, std::ios_base::end);
172 }
173
174 os << ");\n";
175 }
176
write_argument_annotation(std::ofstream & os,const TypeSpec & arg)177 void write_argument_annotation(std::ofstream& os, const TypeSpec& arg) {
178 bool has_annotation = false;
179 for (const auto& a : arg.attributes) {
180 if (!a.empty() && !is_identifier_keyword(a)) {
181 has_annotation = true;
182 os << kWrapMacro << "(" << a << ") ";
183 }
184 }
185 // If arg type is a handle (not an array) and no annotation is present, use default annotation
186 if (!has_annotation && arg.type == "zx_handle_t" && arg.arr_spec == nullptr) {
187 os << kWrapMacro << "(" << kDefaultHandleAnnotation << ") ";
188 }
189 }
190