OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright 2014 The Chromium Authors. All rights reserved. | 2 # Copyright 2014 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 # pylint: disable=W0104,W0106,F0401,R0201 | 6 # pylint: disable=W0104,W0106,F0401,R0201 |
7 | 7 |
8 import optparse | 8 import optparse |
9 import os.path | 9 import os.path |
10 import sys | 10 import sys |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 # Parameters passed into trusted code are handled differently depending on | 150 # Parameters passed into trusted code are handled differently depending on |
151 # details of the parameter. ParamImpl instances encapsulate these differences | 151 # details of the parameter. ParamImpl instances encapsulate these differences |
152 # and are used to generate the code that transfers parameters across the | 152 # and are used to generate the code that transfers parameters across the |
153 # untrusted/trusted boundary. | 153 # untrusted/trusted boundary. |
154 class ParamImpl(object): | 154 class ParamImpl(object): |
155 def __init__(self, param): | 155 def __init__(self, param): |
156 self.param = param | 156 self.param = param |
157 | 157 |
158 # Declare whatever variables are needed to handle this particular parameter. | 158 # Declare whatever variables are needed to handle this particular parameter. |
159 def DeclareVars(self, code): | 159 def DeclareVars(self, code): |
160 raise NotImplementedError() | 160 raise NotImplementedError(type(self)) |
161 | 161 |
162 # Convert the untrusted representation of the parameter into a trusted | 162 # Convert the untrusted representation of the parameter into a trusted |
163 # representation, such as a scalar value or a trusted pointer into the | 163 # representation, such as a scalar value or a trusted pointer into the |
164 # untrusted address space. | 164 # untrusted address space. |
165 def ConvertParam(self): | 165 def ConvertParam(self): |
166 raise NotImplementedError() | 166 raise NotImplementedError(type(self)) |
167 | 167 |
168 # For this particular parameter, what expression should be passed when | 168 # For this particular parameter, what expression should be passed when |
169 # invoking the trusted Mojo API function? | 169 # invoking the trusted Mojo API function? |
170 def CallParam(self): | 170 def CallParam(self): |
171 raise NotImplementedError() | 171 raise NotImplementedError(type(self)) |
172 | 172 |
173 # After invoking the trusted Mojo API function, transfer data back into | 173 # After invoking the trusted Mojo API function, transfer data back into |
174 # untrusted memory. Overriden for Out and InOut parameters. | 174 # untrusted memory. Overriden for Out and InOut parameters. |
175 def CopyOut(self, code): | 175 def CopyOut(self, code): |
176 pass | 176 pass |
177 | 177 |
178 # Converting array parameters needs to be defered until after the scalar | 178 # Converting array parameters needs to be defered until after the scalar |
179 # parameter containing the size of the array has itself been converted. | 179 # parameter containing the size of the array has itself been converted. |
180 def IsArray(self): | 180 def IsArray(self): |
181 return False | 181 return False |
(...skipping 12 matching lines...) Expand all Loading... |
194 return '%s_value' % self.param.name | 194 return '%s_value' % self.param.name |
195 | 195 |
196 | 196 |
197 class ScalarOutputImpl(ParamImpl): | 197 class ScalarOutputImpl(ParamImpl): |
198 def DeclareVars(self, code): | 198 def DeclareVars(self, code): |
199 code << '%s volatile* %s_ptr;' % (self.param.base_type, self.param.name) | 199 code << '%s volatile* %s_ptr;' % (self.param.base_type, self.param.name) |
200 code << '%s %s_value;' % (self.param.base_type, self.param.name) | 200 code << '%s %s_value;' % (self.param.base_type, self.param.name) |
201 | 201 |
202 def ConvertParam(self): | 202 def ConvertParam(self): |
203 p = self.param | 203 p = self.param |
204 return 'ConvertScalarOutput(nap, params[%d], &%s_ptr)' % (p.uid + 1, p.name) | 204 return ('ConvertScalarOutput(nap, params[%d], %s, &%s_ptr)' % |
| 205 (p.uid + 1, CBool(p.is_optional), p.name)) |
205 | 206 |
206 def CallParam(self): | 207 def CallParam(self): |
207 return '&%s_value' % self.param.name | 208 name = self.param.name |
| 209 expr = '&%s_value' % name |
| 210 if self.param.is_optional: |
| 211 expr = '%s_ptr ? %s : NULL' % (name, expr) |
| 212 return expr |
208 | 213 |
209 def CopyOut(self, code): | 214 def CopyOut(self, code): |
210 name = self.param.name | 215 name = self.param.name |
211 code << '*%s_ptr = %s_value;' % (name, name) | 216 if self.param.is_struct: |
| 217 # C++ errors when you try to copy a volatile struct pointer. |
| 218 # (There are no default copy constructors for this case.) |
| 219 # memcpy instead. |
| 220 copy_stmt = ('memcpy_volatile_out(%s_ptr, &%s_value, sizeof(%s));' % |
| 221 (name, name, self.param.base_type)) |
| 222 else: |
| 223 copy_stmt = '*%s_ptr = %s_value;' % (name, name) |
| 224 |
| 225 if self.param.is_optional: |
| 226 code << 'if (%s_ptr != NULL) {' % (name) |
| 227 with code.Indent(): |
| 228 code << copy_stmt |
| 229 code << '}' |
| 230 else: |
| 231 code << copy_stmt |
212 | 232 |
213 | 233 |
214 class ScalarInOutImpl(ParamImpl): | 234 class ScalarInOutImpl(ParamImpl): |
215 def DeclareVars(self, code): | 235 def DeclareVars(self, code): |
216 code << '%s volatile* %s_ptr;' % (self.param.base_type, self.param.name) | 236 code << '%s volatile* %s_ptr;' % (self.param.base_type, self.param.name) |
217 code << '%s %s_value;' % (self.param.base_type, self.param.name) | 237 code << '%s %s_value;' % (self.param.base_type, self.param.name) |
218 | 238 |
219 def ConvertParam(self): | 239 def ConvertParam(self): |
220 p = self.param | 240 p = self.param |
221 return ('ConvertScalarInOut(nap, params[%d], %s, &%s_value, &%s_ptr)' % | 241 return ('ConvertScalarInOut(nap, params[%d], %s, &%s_value, &%s_ptr)' % |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
254 (p.uid + 1, p.size + '_value', element_size, CBool(p.is_optional), | 274 (p.uid + 1, p.size + '_value', element_size, CBool(p.is_optional), |
255 p.name)) | 275 p.name)) |
256 | 276 |
257 def CallParam(self): | 277 def CallParam(self): |
258 return self.param.name | 278 return self.param.name |
259 | 279 |
260 def IsArray(self): | 280 def IsArray(self): |
261 return True | 281 return True |
262 | 282 |
263 | 283 |
264 class StructInputImpl(ParamImpl): | 284 class ExtensibleStructInputImpl(ParamImpl): |
265 def DeclareVars(self, code): | 285 def DeclareVars(self, code): |
266 code << '%s %s;' % (self.param.param_type, self.param.name) | 286 code << '%s %s;' % (self.param.param_type, self.param.name) |
267 | 287 |
268 def ConvertParam(self): | 288 def ConvertParam(self): |
269 p = self.param | 289 p = self.param |
270 return ('ConvertStruct(nap, params[%d], %s, &%s)' % | 290 return ('ConvertExtensibleStructInput(nap, params[%d], %s, &%s)' % |
271 (p.uid + 1, CBool(p.is_optional), p.name)) | 291 (p.uid + 1, CBool(p.is_optional), p.name)) |
272 | 292 |
273 def CallParam(self): | 293 def CallParam(self): |
274 return self.param.name | 294 return self.param.name |
275 | 295 |
276 | |
277 def ImplForParam(p): | 296 def ImplForParam(p): |
278 if p.IsScalar(): | 297 if p.IsScalar(): |
279 if p.is_output: | 298 if p.is_output: |
280 if p.is_input: | 299 if p.is_input: |
281 return ScalarInOutImpl(p) | 300 return ScalarInOutImpl(p) |
282 else: | 301 else: |
283 return ScalarOutputImpl(p) | 302 if p.is_always_written: |
| 303 return ScalarOutputImpl(p) |
| 304 else: |
| 305 # Mojo defines that some of its outputs will not be set in specific |
| 306 # cases. To avoid the complexity of determining if the output was set |
| 307 # by Mojo, copy the output's current value (possibly junk) and copy it |
| 308 # back to untrusted memory afterwards. |
| 309 return ScalarInOutImpl(p) |
284 else: | 310 else: |
285 return ScalarInputImpl(p) | 311 return ScalarInputImpl(p) |
286 elif p.is_array: | 312 elif p.is_array: |
287 return ArrayImpl(p) | 313 return ArrayImpl(p) |
288 elif p.is_struct: | 314 elif p.is_struct: |
289 return StructInputImpl(p) | 315 if p.is_input and not p.is_output and p.is_extensible: |
290 else: | 316 return ExtensibleStructInputImpl(p) |
291 assert False, p | 317 if not p.is_input and p.is_output and not p.is_extensible: |
| 318 return ScalarOutputImpl(p) |
| 319 assert False, p.name |
292 | 320 |
293 | 321 |
294 def CBool(value): | 322 def CBool(value): |
295 return 'true' if value else 'false' | 323 return 'true' if value else 'false' |
296 | 324 |
297 | 325 |
298 # A trusted wrapper that validates the arguments passed from untrusted code | 326 # A trusted wrapper that validates the arguments passed from untrusted code |
299 # before passing them to the underlying public Mojo API. | 327 # before passing them to the underlying public Mojo API. |
300 def GenerateMojoSyscall(functions, out): | 328 def GenerateMojoSyscall(functions, out): |
301 template = jinja_env.get_template('mojo_syscall.cc.tmpl') | 329 template = jinja_env.get_template('mojo_syscall.cc.tmpl') |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
395 | 423 |
396 out = OutFile(options.out_dir, 'libmojo.cc') | 424 out = OutFile(options.out_dir, 'libmojo.cc') |
397 GenerateLibMojo(mojo.functions, out) | 425 GenerateLibMojo(mojo.functions, out) |
398 | 426 |
399 out = OutFile(options.out_dir, 'mojo_syscall.cc') | 427 out = OutFile(options.out_dir, 'mojo_syscall.cc') |
400 GenerateMojoSyscall(mojo.functions, out) | 428 GenerateMojoSyscall(mojo.functions, out) |
401 | 429 |
402 | 430 |
403 if __name__ == '__main__': | 431 if __name__ == '__main__': |
404 main(sys.argv[1:]) | 432 main(sys.argv[1:]) |
OLD | NEW |