1 // Copyright (C) 2019 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "repr/protobuf/ir_reader.h"
16
17 #include "repr/ir_representation_internal.h"
18 #include "repr/protobuf/api.h"
19 #include "repr/protobuf/converter.h"
20
21 #include <fstream>
22 #include <memory>
23
24 #include <google/protobuf/text_format.h>
25
26
27 namespace header_checker {
28 namespace repr {
29
30
ReadTypeInfo(const abi_dump::BasicNamedAndTypedDecl & type_info,TypeIR * typep)31 void ProtobufIRReader::ReadTypeInfo(
32 const abi_dump::BasicNamedAndTypedDecl &type_info, TypeIR *typep) {
33 typep->SetLinkerSetKey(type_info.linker_set_key());
34 typep->SetName(type_info.name());
35 typep->SetSourceFile(type_info.source_file());
36 typep->SetReferencedType(type_info.referenced_type());
37 typep->SetSelfType(type_info.self_type());
38 typep->SetSize(type_info.size());
39 typep->SetAlignment(type_info.alignment());
40 }
41
ReadDump(const std::string & dump_file)42 bool ProtobufIRReader::ReadDump(const std::string &dump_file) {
43 abi_dump::TranslationUnit tu;
44 std::ifstream input(dump_file);
45 google::protobuf::io::IstreamInputStream text_is(&input);
46
47 if (!google::protobuf::TextFormat::Parse(&text_is, &tu)) {
48 llvm::errs() << "Failed to parse protobuf TextFormat file\n";
49 return false;
50 }
51 ReadFunctions(tu);
52 ReadGlobalVariables(tu);
53
54 ReadEnumTypes(tu);
55 ReadRecordTypes(tu);
56 ReadFunctionTypes(tu);
57 ReadArrayTypes(tu);
58 ReadPointerTypes(tu);
59 ReadQualifiedTypes(tu);
60 ReadBuiltinTypes(tu);
61 ReadLvalueReferenceTypes(tu);
62 ReadRvalueReferenceTypes(tu);
63
64 ReadElfFunctions(tu);
65 ReadElfObjects(tu);
66 return true;
67 }
68
TemplateInfoProtobufToIR(const abi_dump::TemplateInfo & template_info_protobuf)69 TemplateInfoIR ProtobufIRReader::TemplateInfoProtobufToIR(
70 const abi_dump::TemplateInfo &template_info_protobuf) {
71 TemplateInfoIR template_info_ir;
72 for (auto &&template_element : template_info_protobuf.elements()) {
73 TemplateElementIR template_element_ir(template_element.referenced_type());
74 template_info_ir.AddTemplateElement(std::move(template_element_ir));
75 }
76 return template_info_ir;
77 }
78
79 template <typename T>
SetupCFunctionLikeIR(const T & cfunction_like_protobuf,CFunctionLikeIR * cfunction_like_ir)80 static void SetupCFunctionLikeIR(const T &cfunction_like_protobuf,
81 CFunctionLikeIR *cfunction_like_ir) {
82 cfunction_like_ir->SetReturnType(cfunction_like_protobuf.return_type());
83 for (auto &¶meter: cfunction_like_protobuf.parameters()) {
84 ParamIR param_ir(parameter.referenced_type(), parameter.default_arg(),
85 false);
86 cfunction_like_ir->AddParameter(std::move(param_ir));
87 }
88 }
89
FunctionProtobufToIR(const abi_dump::FunctionDecl & function_protobuf)90 FunctionIR ProtobufIRReader::FunctionProtobufToIR(
91 const abi_dump::FunctionDecl &function_protobuf) {
92 FunctionIR function_ir;
93 function_ir.SetReturnType(function_protobuf.return_type());
94 function_ir.SetLinkerSetKey(function_protobuf.linker_set_key());
95 function_ir.SetName(function_protobuf.function_name());
96 function_ir.SetAccess(AccessProtobufToIR(function_protobuf.access()));
97 function_ir.SetSourceFile(function_protobuf.source_file());
98 // Set parameters
99 for (auto &¶meter: function_protobuf.parameters()) {
100 ParamIR param_ir(parameter.referenced_type(), parameter.default_arg(),
101 parameter.is_this_ptr());
102 function_ir.AddParameter(std::move(param_ir));
103 }
104 // Set Template info
105 function_ir.SetTemplateInfo(
106 TemplateInfoProtobufToIR(function_protobuf.template_info()));
107 return function_ir;
108 }
109
FunctionTypeProtobufToIR(const abi_dump::FunctionType & function_type_protobuf)110 FunctionTypeIR ProtobufIRReader::FunctionTypeProtobufToIR(
111 const abi_dump::FunctionType &function_type_protobuf) {
112 FunctionTypeIR function_type_ir;
113 ReadTypeInfo(function_type_protobuf.type_info(), &function_type_ir);
114 SetupCFunctionLikeIR(function_type_protobuf, &function_type_ir);
115 return function_type_ir;
116 }
117
VTableLayoutProtobufToIR(const abi_dump::VTableLayout & vtable_layout_protobuf)118 VTableLayoutIR ProtobufIRReader::VTableLayoutProtobufToIR(
119 const abi_dump::VTableLayout &vtable_layout_protobuf) {
120 VTableLayoutIR vtable_layout_ir;
121 for (auto &&vtable_component : vtable_layout_protobuf.vtable_components()) {
122 VTableComponentIR vtable_component_ir(
123 vtable_component.mangled_component_name(),
124 VTableComponentKindProtobufToIR(vtable_component.kind()),
125 vtable_component.component_value(),
126 vtable_component.is_pure());
127 vtable_layout_ir.AddVTableComponent(std::move(vtable_component_ir));
128 }
129 return vtable_layout_ir;
130 }
131
RecordFieldsProtobufToIR(const google::protobuf::RepeatedPtrField<abi_dump::RecordFieldDecl> & rfp)132 std::vector<RecordFieldIR> ProtobufIRReader::RecordFieldsProtobufToIR(
133 const google::protobuf::RepeatedPtrField<abi_dump::RecordFieldDecl> &rfp) {
134 std::vector<RecordFieldIR> record_type_fields_ir;
135 for (auto &&field : rfp) {
136 RecordFieldIR record_field_ir(field.field_name(), field.referenced_type(),
137 field.field_offset(),
138 AccessProtobufToIR(field.access()));
139 record_type_fields_ir.emplace_back(std::move(record_field_ir));
140 }
141 return record_type_fields_ir;
142 }
143
144 std::vector<CXXBaseSpecifierIR>
RecordCXXBaseSpecifiersProtobufToIR(const google::protobuf::RepeatedPtrField<abi_dump::CXXBaseSpecifier> & rbs)145 ProtobufIRReader::RecordCXXBaseSpecifiersProtobufToIR(
146 const google::protobuf::RepeatedPtrField<abi_dump::CXXBaseSpecifier> &rbs) {
147 std::vector<CXXBaseSpecifierIR> record_type_bases_ir;
148 for (auto &&base : rbs) {
149 CXXBaseSpecifierIR record_base_ir(
150 base.referenced_type(), base.is_virtual(),
151 AccessProtobufToIR(base.access()));
152 record_type_bases_ir.emplace_back(std::move(record_base_ir));
153 }
154 return record_type_bases_ir;
155 }
156
RecordTypeProtobufToIR(const abi_dump::RecordType & record_type_protobuf)157 RecordTypeIR ProtobufIRReader::RecordTypeProtobufToIR(
158 const abi_dump::RecordType &record_type_protobuf) {
159 RecordTypeIR record_type_ir;
160 ReadTypeInfo(record_type_protobuf.type_info(), &record_type_ir);
161 record_type_ir.SetTemplateInfo(
162 TemplateInfoProtobufToIR(record_type_protobuf.template_info()));
163 record_type_ir.SetAccess(AccessProtobufToIR(record_type_protobuf.access()));
164 record_type_ir.SetVTableLayout(
165 VTableLayoutProtobufToIR(record_type_protobuf.vtable_layout()));
166 // Get fields
167 record_type_ir.SetRecordFields(RecordFieldsProtobufToIR(
168 record_type_protobuf.fields()));
169 // Base Specifiers
170 record_type_ir.SetCXXBaseSpecifiers(RecordCXXBaseSpecifiersProtobufToIR(
171 record_type_protobuf.base_specifiers()));
172 record_type_ir.SetRecordKind(
173 RecordKindProtobufToIR(record_type_protobuf.record_kind()));
174 record_type_ir.SetAnonymity(record_type_protobuf.is_anonymous());
175 record_type_ir.SetUniqueId(record_type_protobuf.tag_info().unique_id());
176 return record_type_ir;
177 }
178
EnumFieldsProtobufToIR(const google::protobuf::RepeatedPtrField<abi_dump::EnumFieldDecl> & efp)179 std::vector<EnumFieldIR> ProtobufIRReader::EnumFieldsProtobufToIR(
180 const google::protobuf::RepeatedPtrField<abi_dump::EnumFieldDecl> &efp) {
181 std::vector<EnumFieldIR> enum_type_fields_ir;
182 for (auto &&field : efp) {
183 EnumFieldIR enum_field_ir(field.name(), field.enum_field_value());
184 enum_type_fields_ir.emplace_back(std::move(enum_field_ir));
185 }
186 return enum_type_fields_ir;
187 }
188
EnumTypeProtobufToIR(const abi_dump::EnumType & enum_type_protobuf)189 EnumTypeIR ProtobufIRReader::EnumTypeProtobufToIR(
190 const abi_dump::EnumType &enum_type_protobuf) {
191 EnumTypeIR enum_type_ir;
192 ReadTypeInfo(enum_type_protobuf.type_info(), &enum_type_ir);
193 enum_type_ir.SetUnderlyingType(enum_type_protobuf.underlying_type());
194 enum_type_ir.SetAccess(AccessProtobufToIR(enum_type_protobuf.access()));
195 enum_type_ir.SetFields(
196 EnumFieldsProtobufToIR(enum_type_protobuf.enum_fields()));
197 enum_type_ir.SetUniqueId(enum_type_protobuf.tag_info().unique_id());
198 return enum_type_ir;
199 }
200
ReadGlobalVariables(const abi_dump::TranslationUnit & tu)201 void ProtobufIRReader::ReadGlobalVariables(
202 const abi_dump::TranslationUnit &tu) {
203 for (auto &&global_variable_protobuf : tu.global_vars()) {
204 GlobalVarIR global_variable_ir;
205 global_variable_ir.SetName(global_variable_protobuf.name());
206 global_variable_ir.SetAccess(AccessProtobufToIR(global_variable_protobuf.access()));
207 global_variable_ir.SetSourceFile(global_variable_protobuf.source_file());
208 global_variable_ir.SetReferencedType(
209 global_variable_protobuf.referenced_type());
210 global_variable_ir.SetLinkerSetKey(
211 global_variable_protobuf.linker_set_key());
212 module_->AddGlobalVariable(std::move(global_variable_ir));
213 }
214 }
215
ReadPointerTypes(const abi_dump::TranslationUnit & tu)216 void ProtobufIRReader::ReadPointerTypes(const abi_dump::TranslationUnit &tu) {
217 for (auto &&pointer_type_protobuf : tu.pointer_types()) {
218 PointerTypeIR pointer_type_ir;
219 ReadTypeInfo(pointer_type_protobuf.type_info(), &pointer_type_ir);
220 module_->AddPointerType(std::move(pointer_type_ir));
221 }
222 }
223
ReadBuiltinTypes(const abi_dump::TranslationUnit & tu)224 void ProtobufIRReader::ReadBuiltinTypes(const abi_dump::TranslationUnit &tu) {
225 for (auto &&builtin_type_protobuf : tu.builtin_types()) {
226 BuiltinTypeIR builtin_type_ir;
227 ReadTypeInfo(builtin_type_protobuf.type_info(), &builtin_type_ir);
228 builtin_type_ir.SetSignedness(builtin_type_protobuf.is_unsigned());
229 builtin_type_ir.SetIntegralType(builtin_type_protobuf.is_integral());
230 module_->AddBuiltinType(std::move(builtin_type_ir));
231 }
232 }
233
ReadQualifiedTypes(const abi_dump::TranslationUnit & tu)234 void ProtobufIRReader::ReadQualifiedTypes(const abi_dump::TranslationUnit &tu) {
235 for (auto &&qualified_type_protobuf : tu.qualified_types()) {
236 QualifiedTypeIR qualified_type_ir;
237 ReadTypeInfo(qualified_type_protobuf.type_info(), &qualified_type_ir);
238 qualified_type_ir.SetConstness(qualified_type_protobuf.is_const());
239 qualified_type_ir.SetVolatility(qualified_type_protobuf.is_volatile());
240 qualified_type_ir.SetRestrictedness(
241 qualified_type_protobuf.is_restricted());
242 module_->AddQualifiedType(std::move(qualified_type_ir));
243 }
244 }
245
ReadArrayTypes(const abi_dump::TranslationUnit & tu)246 void ProtobufIRReader::ReadArrayTypes(const abi_dump::TranslationUnit &tu) {
247 for (auto &&array_type_protobuf : tu.array_types()) {
248 ArrayTypeIR array_type_ir;
249 ReadTypeInfo(array_type_protobuf.type_info(), &array_type_ir);
250 module_->AddArrayType(std::move(array_type_ir));
251 }
252 }
253
ReadLvalueReferenceTypes(const abi_dump::TranslationUnit & tu)254 void ProtobufIRReader::ReadLvalueReferenceTypes(
255 const abi_dump::TranslationUnit &tu) {
256 for (auto &&lvalue_reference_type_protobuf : tu.lvalue_reference_types()) {
257 LvalueReferenceTypeIR lvalue_reference_type_ir;
258 ReadTypeInfo(lvalue_reference_type_protobuf.type_info(),
259 &lvalue_reference_type_ir);
260 module_->AddLvalueReferenceType(std::move(lvalue_reference_type_ir));
261 }
262 }
263
ReadRvalueReferenceTypes(const abi_dump::TranslationUnit & tu)264 void ProtobufIRReader::ReadRvalueReferenceTypes(
265 const abi_dump::TranslationUnit &tu) {
266 for (auto &&rvalue_reference_type_protobuf : tu.rvalue_reference_types()) {
267 RvalueReferenceTypeIR rvalue_reference_type_ir;
268 ReadTypeInfo(rvalue_reference_type_protobuf.type_info(),
269 &rvalue_reference_type_ir);
270 module_->AddRvalueReferenceType(std::move(rvalue_reference_type_ir));
271 }
272 }
273
ReadFunctions(const abi_dump::TranslationUnit & tu)274 void ProtobufIRReader::ReadFunctions(const abi_dump::TranslationUnit &tu) {
275 for (auto &&function_protobuf : tu.functions()) {
276 FunctionIR function_ir = FunctionProtobufToIR(function_protobuf);
277 module_->AddFunction(std::move(function_ir));
278 }
279 }
280
ReadRecordTypes(const abi_dump::TranslationUnit & tu)281 void ProtobufIRReader::ReadRecordTypes(const abi_dump::TranslationUnit &tu) {
282 for (auto &&record_type_protobuf : tu.record_types()) {
283 RecordTypeIR record_type_ir = RecordTypeProtobufToIR(record_type_protobuf);
284 module_->AddRecordType(std::move(record_type_ir));
285 }
286 }
287
ReadFunctionTypes(const abi_dump::TranslationUnit & tu)288 void ProtobufIRReader::ReadFunctionTypes(const abi_dump::TranslationUnit &tu) {
289 for (auto &&function_type_protobuf : tu.function_types()) {
290 FunctionTypeIR function_type_ir =
291 FunctionTypeProtobufToIR(function_type_protobuf);
292 module_->AddFunctionType(std::move(function_type_ir));
293 }
294 }
295
ReadEnumTypes(const abi_dump::TranslationUnit & tu)296 void ProtobufIRReader::ReadEnumTypes(const abi_dump::TranslationUnit &tu) {
297 for (auto &&enum_type_protobuf : tu.enum_types()) {
298 EnumTypeIR enum_type_ir = EnumTypeProtobufToIR(enum_type_protobuf);
299 module_->AddEnumType(std::move(enum_type_ir));
300 }
301 }
302
ReadElfFunctions(const abi_dump::TranslationUnit & tu)303 void ProtobufIRReader::ReadElfFunctions(const abi_dump::TranslationUnit &tu) {
304 for (auto &&elf_function : tu.elf_functions()) {
305 ElfFunctionIR elf_function_ir(
306 elf_function.name(),
307 ElfSymbolBindingProtobufToIR(elf_function.binding()));
308 module_->AddElfFunction(std::move(elf_function_ir));
309 }
310 }
311
ReadElfObjects(const abi_dump::TranslationUnit & tu)312 void ProtobufIRReader::ReadElfObjects(const abi_dump::TranslationUnit &tu) {
313 for (auto &&elf_object : tu.elf_objects()) {
314 ElfObjectIR elf_object_ir(
315 elf_object.name(), ElfSymbolBindingProtobufToIR(elf_object.binding()));
316 module_->AddElfObject(std::move(elf_object_ir));
317 }
318 }
319
CreateProtobufIRReader(const std::set<std::string> * exported_headers)320 std::unique_ptr<IRReader> CreateProtobufIRReader(
321 const std::set<std::string> *exported_headers) {
322 return std::make_unique<ProtobufIRReader>(exported_headers);
323 }
324
325
326 } // namespace repr
327 } // namespace header_checker
328