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 <algorithm> 6#include <ctime> 7 8#include "generator.h" 9#include "header_generator.h" 10#include "vdso_wrapper_generator.h" 11 12#include "abigen_generator.h" 13 14using std::string; 15using std::map; 16using std::vector; 17 18const map<string, string> user_attrs = { 19 {"noreturn", "__NO_RETURN"}, 20 {"const", "__CONST"}, 21 {"deprecated", "__DEPRECATE"}, 22 23 // All vDSO calls are "leaf" in the sense of the GCC attribute. 24 // It just means they can't ever call back into their callers' 25 // own translation unit. No vDSO calls make callbacks at all. 26 {"*", "__LEAF_FN"}, 27}; 28 29const map<string, string> kernel_attrs = { 30 {"noreturn", "__NO_RETURN"}, 31}; 32 33static TestWrapper test_wrapper; 34static BlockingRetryWrapper blocking_wrapper; 35static vector<CallWrapper*> wrappers = {&test_wrapper, &blocking_wrapper}; 36 37static VdsoWrapperGenerator vdso_wrapper_generator( 38 "_zx_", // wrapper function name 39 "SYSCALL_zx_", // syscall implementation name 40 wrappers); 41 42static KernelBranchGenerator kernel_branch; 43 44static KernelWrapperGenerator kernel_wrappers( 45 "sys_", // function prefix 46 "wrapper_", // wrapper prefix 47 "ZX_SYS_"); // syscall numbers constant prefix 48 49static bool skip_nothing(const Syscall&) { 50 return false; 51} 52 53static bool skip_internal(const Syscall& sc) { 54 return sc.is_internal(); 55} 56 57static bool skip_vdso(const Syscall& sc) { 58 return sc.is_vdso(); 59} 60 61static HeaderGenerator user_header( 62 "extern ", // function prefix 63 { 64 {"zx_", skip_internal}, 65 {"_zx_", skip_internal}, 66 }, 67 "void", // no-args special type 68 false, // wrap pointers 69 user_attrs); 70 71static HeaderGenerator vdso_header( 72 "__LOCAL extern ", // function prefix 73 { 74 {"VDSO_zx_", skip_nothing}, 75 {"SYSCALL_zx_", skip_vdso}, 76 }, 77 "void", // no-args special type 78 false, 79 user_attrs); 80 81static HeaderGenerator kernel_header( 82 "", 83 { 84 {"sys_", skip_vdso}, 85 }, 86 "", 87 true, 88 kernel_attrs); 89 90static VDsoAsmGenerator vdso_asm_generator( 91 "m_syscall", // syscall macro name 92 "zx_", // syscall name prefix 93 wrappers); 94 95static SyscallNumbersGenerator syscall_num_generator("#define ZX_SYS_"); 96 97static RustBindingGenerator rust_binding_generator; 98static TraceInfoGenerator trace_generator; 99static CategoryGenerator category_generator; 100static JsonGenerator json_generator; 101 102const map<string, Generator&> type_to_generator = { 103 // The user header, pure C. 104 {"user-header", user_header}, 105 106 // The vDSO-internal header, pure C. (VDsoHeaderC) 107 {"vdso-header", vdso_header}, 108 109 // The kernel header, C++. 110 {"kernel-header", kernel_header}, 111 112 // The kernel assembly branches and jump table. 113 {"kernel-branch", kernel_branch}, 114 115 // The kernel C++ wrappers. 116 {"kernel-wrappers", kernel_wrappers}, 117 118 // The assembly file for x86-64. 119 {"x86-asm", vdso_asm_generator}, 120 121 // The assembly include file for ARM64. 122 {"arm-asm", vdso_asm_generator}, 123 124 // A C header defining ZX_SYS_* syscall number macros. 125 {"numbers", syscall_num_generator}, 126 127 // The trace subsystem data, to be interpreted as an array of structs. 128 {"trace", trace_generator}, 129 130 // Rust bindings. 131 {"rust", rust_binding_generator}, 132 133 // vDSO wrappers for additional behaviour in user space. 134 {"vdso-wrappers", vdso_wrapper_generator}, 135 136 // Category list. 137 {"category", category_generator}, 138 139 // JSON list of syscalls. 140 {"json", json_generator}, 141}; 142 143const map<string, string> type_to_default_suffix = { 144 {"user-header", ".user.h"}, 145 {"vdso-header", ".vdso.h"}, 146 {"kernel-header", ".kernel.h"}, 147 {"kernel-branch", ".kernel-branch.S"}, 148 {"kernel-wrappers", ".kernel-wrappers.inc"}, 149 {"x86-asm", ".x86-64.S"}, 150 {"arm-asm", ".arm64.S"}, 151 {"numbers", ".syscall-numbers.h"}, 152 {"trace", ".trace.inc"}, 153 {"rust", ".rs"}, 154 {"vdso-wrappers", ".vdso-wrappers.inc"}, 155 {"category", ".category.inc"}, 156 {"json", ".json"}, 157}; 158 159const map<string, string>& get_type_to_default_suffix() { 160 return type_to_default_suffix; 161} 162 163const map<string, Generator&>& get_type_to_generator() { 164 return type_to_generator; 165} 166 167bool AbigenGenerator::AddSyscall(Syscall&& syscall) { 168 if (!syscall.validate()) 169 return false; 170 syscall.assign_index(&next_index_); 171 calls_.emplace_back(std::move(syscall)); 172 return true; 173} 174 175bool AbigenGenerator::Generate(const map<string, string>& type_to_filename) { 176 for (auto& entry : type_to_filename) { 177 if (!generate_one(entry.second, type_to_generator.at(entry.first), entry.first)) 178 return false; 179 } 180 return true; 181} 182 183bool AbigenGenerator::verbose() const { 184 return verbose_; 185} 186 187bool AbigenGenerator::generate_one( 188 const string& output_file, Generator& generator, const string& type) { 189 std::ofstream ofile; 190 ofile.open(output_file.c_str(), std::ofstream::out); 191 192 if (!generator.header(ofile)) { 193 print_error("i/o error", output_file); 194 return false; 195 } 196 197 if (!std::all_of(calls_.begin(), calls_.end(), 198 [&generator, &ofile](const Syscall& sc) { 199 return generator.syscall(ofile, sc); 200 })) { 201 print_error("generation failed", output_file); 202 return false; 203 } 204 205 if (!generator.footer(ofile)) { 206 print_error("i/o error", output_file); 207 return false; 208 } 209 210 return true; 211} 212 213void AbigenGenerator::print_error(const char* what, const string& file) { 214 fprintf(stderr, "error: %s for %s\n", what, file.c_str()); 215} 216