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 #pragma once
6 
7 #include <ctime>
8 #include <fstream>
9 #include <string>
10 
11 #include "types.h"
12 
13 // Interface for syscall generators.
14 class Generator {
15 public:
16     virtual bool header(std::ofstream& os);
17     virtual bool syscall(std::ofstream& os, const Syscall& sc) = 0;
18     virtual bool footer(std::ofstream& os);
19 
20 protected:
~Generator()21     virtual ~Generator() {}
22 };
23 
24 // Interface for vDSO wrappers.
25 class CallWrapper {
26 public:
27     virtual bool applies(const Syscall& sc) const = 0;
preCall(std::ofstream & os,const Syscall & sc)28     virtual void preCall(std::ofstream& os, const Syscall& sc) const {}
postCall(std::ofstream & os,const Syscall & sc,std::string return_var)29     virtual void postCall(std::ofstream& os, const Syscall& sc, std::string return_var) const {}
30 
31 protected:
~CallWrapper()32     virtual ~CallWrapper() {}
33 };
34 
35 // Generate the vDSO assembly stubs.
36 class VDsoAsmGenerator : public Generator {
37 public:
VDsoAsmGenerator(const std::string & syscall_macro,const std::string & name_prefix,const std::vector<CallWrapper * > & call_wrappers)38     VDsoAsmGenerator(const std::string& syscall_macro,
39                      const std::string& name_prefix,
40                      const std::vector<CallWrapper*>& call_wrappers)
41         : syscall_macro_(syscall_macro),
42           name_prefix_(name_prefix),
43           wrappers_(call_wrappers) {}
44 
45     bool syscall(std::ofstream& os, const Syscall& sc) override;
46 
47 private:
48     const std::string syscall_macro_;
49     const std::string name_prefix_;
50     const std::vector<CallWrapper*> wrappers_;
51 };
52 
53 // Generate the syscall number definitions.
54 class SyscallNumbersGenerator : public Generator {
55 public:
SyscallNumbersGenerator(const std::string & define_prefix)56     SyscallNumbersGenerator(const std::string& define_prefix)
57         : define_prefix_(define_prefix) {}
58 
59     bool syscall(std::ofstream& os, const Syscall& sc) override;
60     bool footer(std::ofstream& os) override;
61 
62 private:
63     const std::string define_prefix_;
64     int num_calls_ = 0;
65 };
66 
67 // Generate debug trace info.
68 class TraceInfoGenerator : public Generator {
69 public:
70     bool syscall(std::ofstream& os, const Syscall& sc) override;
71 };
72 
73 // Generate category list.
74 class CategoryGenerator : public Generator {
75 public:
76     bool syscall(std::ofstream& os, const Syscall& sc) override;
77     bool footer(std::ofstream& os) override;
78 
79 private:
80     std::map<const std::string, std::vector<const std::string*>> category_map_;
81 };
82 
83 /* Generates the kernel syscall jump table and accoutrements. */
84 class KernelBranchGenerator : public Generator {
85 public:
86     bool header(std::ofstream& os) override;
87     bool syscall(std::ofstream& os, const Syscall& sc) override;
88 };
89 
90 /* Generates the kernel syscall wrappers. */
91 class KernelWrapperGenerator : public Generator {
92 public:
KernelWrapperGenerator(const std::string & syscall_prefix,const std::string & wrapper_prefix,const std::string & define_prefix)93     KernelWrapperGenerator(const std::string& syscall_prefix, const std::string& wrapper_prefix,
94                            const std::string& define_prefix)
95         : syscall_prefix_(syscall_prefix), wrapper_prefix_(wrapper_prefix),
96           define_prefix_(define_prefix) {}
97 
98     bool header(std::ofstream& os) override;
99     bool syscall(std::ofstream& os, const Syscall& sc) override;
100     bool footer(std::ofstream& os) override;
101 
102 private:
103     const std::string syscall_prefix_;
104     const std::string wrapper_prefix_;
105     const std::string define_prefix_;
106 };
107 
108 /* Generates the Rust bindings. */
109 class RustBindingGenerator : public Generator {
110 public:
111     bool header(std::ofstream& os) override;
112     bool footer(std::ofstream& os) override;
113     bool syscall(std::ofstream& os, const Syscall& sc) override;
114 };
115 
116 /* Generates a JSON representation of the syscall list. */
117 class JsonGenerator : public Generator {
118 public:
119     bool header(std::ofstream& os) override;
120     bool footer(std::ofstream& os) override;
121     bool syscall(std::ofstream& os, const Syscall& sc) override;
122 
123 private:
124     bool first_syscall_ = true;
125 };
126 
127 // Writes the signature of a syscall, up to the end of the args list.
128 //
129 // Can wrap pointers with user_ptr.
130 // Can specify a type to substitute for no args.
131 // Doesn't write ';', '{}' or attributes.
132 void write_syscall_signature_line(std::ofstream& os, const Syscall& sc, std::string name_prefix,
133                                   std::string before_args, std::string inter_arg,
134                                   bool wrap_pointers_with_user_ptr, std::string no_args_type);
135 
136 // Writes the return variable declaration for a syscall.
137 //
138 // Returns the name of the variable (or an empty string if the call was void).
139 std::string write_syscall_return_var(std::ofstream& os, const Syscall& sc);
140 
141 // Writes an invocation of a syscall.
142 //
143 // Uses the argument names specified in the type description
144 // Performs no casting or pointer wrapping.
145 void write_syscall_invocation(std::ofstream& os, const Syscall& sc,
146                               const std::string& return_var, const std::string& name_prefix);
147 
148 void write_argument_annotation(std::ofstream& os, const TypeSpec& arg);
149