1 // Copyright (C) 2017 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 #ifndef IR_PROTOBUF_
15 #define IR_PROTOBUF_
16
17 #include <ir_representation.h>
18
19 #pragma clang diagnostic push
20 #pragma clang diagnostic ignored "-Wunused-parameter"
21 #pragma clang diagnostic ignored "-Wnested-anon-types"
22 #include "proto/abi_dump.pb.h"
23 #include "proto/abi_diff.pb.h"
24 #pragma clang diagnostic pop
25
26 #include <google/protobuf/text_format.h>
27 #include <google/protobuf/io/zero_copy_stream_impl.h>
28
29
30 // Classes which act as middle-men between clang AST parsing routines and
31 // message format specific dumpers.
32 namespace abi_util {
33
CompatibilityStatusIRToProtobuf(CompatibilityStatusIR status)34 inline abi_diff::CompatibilityStatus CompatibilityStatusIRToProtobuf(
35 CompatibilityStatusIR status) {
36 switch(status) {
37 case CompatibilityStatusIR::Incompatible:
38 return abi_diff::CompatibilityStatus::INCOMPATIBLE;
39 case CompatibilityStatusIR::Extension:
40 return abi_diff::CompatibilityStatus::EXTENSION;
41 default:
42 break;
43 }
44 return abi_diff::CompatibilityStatus::COMPATIBLE;
45 }
46
AccessIRToProtobuf(AccessSpecifierIR access)47 inline abi_dump::AccessSpecifier AccessIRToProtobuf(AccessSpecifierIR access) {
48 switch (access) {
49 case AccessSpecifierIR::ProtectedAccess:
50 return abi_dump::AccessSpecifier::protected_access;
51 case AccessSpecifierIR::PrivateAccess:
52 return abi_dump::AccessSpecifier::private_access;
53 default:
54 return abi_dump::AccessSpecifier::public_access;
55 }
56 return abi_dump::AccessSpecifier::public_access;
57 }
58
AccessProtobufToIR(abi_dump::AccessSpecifier access)59 inline AccessSpecifierIR AccessProtobufToIR(
60 abi_dump::AccessSpecifier access) {
61 switch (access) {
62 case abi_dump::AccessSpecifier::protected_access:
63 return AccessSpecifierIR::ProtectedAccess;
64 case abi_dump::AccessSpecifier::private_access:
65 return AccessSpecifierIR::PrivateAccess;
66 default:
67 return AccessSpecifierIR::PublicAccess;
68 }
69 return AccessSpecifierIR::PublicAccess;
70 }
71
RecordKindIRToProtobuf(RecordTypeIR::RecordKind kind)72 inline abi_dump::RecordKind RecordKindIRToProtobuf(
73 RecordTypeIR::RecordKind kind) {
74 switch (kind) {
75 case RecordTypeIR::RecordKind::struct_kind:
76 return abi_dump::RecordKind::struct_kind;
77
78 case RecordTypeIR::RecordKind::class_kind:
79 return abi_dump::RecordKind::class_kind;
80
81 case RecordTypeIR::RecordKind::union_kind:
82 return abi_dump::RecordKind::union_kind;
83
84 default:
85 return abi_dump::RecordKind::struct_kind;
86 }
87 // Should not be reached
88 assert(false);
89 }
90
RecordKindProtobufToIR(abi_dump::RecordKind kind)91 inline RecordTypeIR::RecordKind RecordKindProtobufToIR(
92 abi_dump::RecordKind kind) {
93 switch (kind) {
94 case abi_dump::RecordKind::struct_kind:
95 return RecordTypeIR::struct_kind;
96
97 case abi_dump::RecordKind::class_kind:
98 return RecordTypeIR::class_kind;
99
100 case abi_dump::RecordKind::union_kind:
101 return RecordTypeIR::union_kind;
102
103 default:
104 return RecordTypeIR::struct_kind;
105 }
106 // Should not be reached
107 assert(false);
108 }
109
VTableComponentKindIRToProtobuf(VTableComponentIR::Kind kind)110 inline abi_dump::VTableComponent::Kind VTableComponentKindIRToProtobuf(
111 VTableComponentIR::Kind kind) {
112 switch (kind) {
113 case VTableComponentIR::Kind::VCallOffset:
114 return abi_dump::VTableComponent_Kind_VCallOffset;
115
116 case VTableComponentIR::Kind::VBaseOffset:
117 return abi_dump::VTableComponent_Kind_VBaseOffset;
118
119 case VTableComponentIR::Kind::OffsetToTop:
120 return abi_dump::VTableComponent_Kind_OffsetToTop;
121
122 case VTableComponentIR::Kind::RTTI:
123 return abi_dump::VTableComponent_Kind_RTTI;
124
125 case VTableComponentIR::Kind::FunctionPointer:
126 return abi_dump::VTableComponent_Kind_FunctionPointer;
127
128 case VTableComponentIR::Kind::CompleteDtorPointer:
129 return abi_dump::VTableComponent_Kind_CompleteDtorPointer;
130
131 case VTableComponentIR::Kind::DeletingDtorPointer:
132 return abi_dump::VTableComponent_Kind_DeletingDtorPointer;
133
134 default:
135 return abi_dump::VTableComponent_Kind_UnusedFunctionPointer;
136 }
137 // Should not be reached
138 assert(false);
139 }
140
VTableComponentKindProtobufToIR(abi_dump::VTableComponent_Kind kind)141 inline VTableComponentIR::Kind VTableComponentKindProtobufToIR(
142 abi_dump::VTableComponent_Kind kind) {
143 switch (kind) {
144 case abi_dump::VTableComponent_Kind_VCallOffset:
145 return VTableComponentIR::Kind::VCallOffset;
146
147 case abi_dump::VTableComponent_Kind_VBaseOffset:
148 return VTableComponentIR::Kind::VBaseOffset;
149
150 case abi_dump::VTableComponent_Kind_OffsetToTop:
151 return VTableComponentIR::Kind::OffsetToTop;
152
153 case abi_dump::VTableComponent_Kind_RTTI:
154 return VTableComponentIR::Kind::RTTI;
155
156 case abi_dump::VTableComponent_Kind_FunctionPointer:
157 return VTableComponentIR::Kind::FunctionPointer;
158
159 case abi_dump::VTableComponent_Kind_CompleteDtorPointer:
160 return VTableComponentIR::Kind::CompleteDtorPointer;
161
162 case abi_dump::VTableComponent_Kind_DeletingDtorPointer:
163 return VTableComponentIR::Kind::DeletingDtorPointer;
164
165 default:
166 return VTableComponentIR::Kind::UnusedFunctionPointer;
167 }
168 // Should not be reached
169 assert(false);
170 }
171
172 class IRToProtobufConverter {
173 private:
174 static bool AddTemplateInformation(
175 abi_dump::TemplateInfo *ti, const abi_util::TemplatedArtifactIR *ta);
176
177 static bool AddTypeInfo(
178 abi_dump::BasicNamedAndTypedDecl *type_info, const TypeIR *typep);
179
180 static bool AddRecordFields(
181 abi_dump::RecordType *record_protobuf, const RecordTypeIR *record_ir);
182
183 static bool AddBaseSpecifiers(
184 abi_dump::RecordType *record_protobuf, const RecordTypeIR *record_ir);
185
186 static bool AddVTableLayout(
187 abi_dump::RecordType *record_protobuf, const RecordTypeIR *record_ir);
188
189 static bool AddTagTypeInfo(abi_dump::TagType *tag_type_protobuf,
190 const TagTypeIR *tag_type_ir);
191
192 static bool AddEnumFields(abi_dump::EnumType *enum_protobuf,
193 const EnumTypeIR *enum_ir);
194 public:
195 static abi_dump::EnumType ConvertEnumTypeIR(const EnumTypeIR *enump);
196
197 static abi_dump::RecordType ConvertRecordTypeIR(const RecordTypeIR *recordp);
198
199 static abi_dump::FunctionType ConvertFunctionTypeIR (
200 const FunctionTypeIR *function_typep);
201
202 template <typename CFunctionLikeMessage>
203 static bool AddFunctionParametersAndSetReturnType(
204 CFunctionLikeMessage *function_like_protobuf,
205 const CFunctionLikeIR *cfunction_like_ir);
206
207 template <typename CFunctionLikeMessage>
208 static bool AddFunctionParameters(CFunctionLikeMessage *function_protobuf,
209 const CFunctionLikeIR *cfunction_like_ir);
210
211 static abi_dump::FunctionDecl ConvertFunctionIR(const FunctionIR *functionp);
212
213 static abi_dump::GlobalVarDecl ConvertGlobalVarIR(
214 const GlobalVarIR *global_varp);
215
216 static abi_dump::PointerType ConvertPointerTypeIR(
217 const PointerTypeIR *pointerp);
218
219 static abi_dump::QualifiedType ConvertQualifiedTypeIR(
220 const QualifiedTypeIR *qualtypep);
221
222 static abi_dump::BuiltinType ConvertBuiltinTypeIR(
223 const BuiltinTypeIR *builtin_typep);
224
225 static abi_dump::ArrayType ConvertArrayTypeIR(
226 const ArrayTypeIR *array_typep);
227
228 static abi_dump::LvalueReferenceType ConvertLvalueReferenceTypeIR(
229 const LvalueReferenceTypeIR *lvalue_reference_typep);
230
231 static abi_dump::RvalueReferenceType ConvertRvalueReferenceTypeIR(
232 const RvalueReferenceTypeIR *rvalue_reference_typep);
233
234 static abi_dump::ElfFunction ConvertElfFunctionIR(
235 const ElfFunctionIR *elf_function_ir);
236
237 static abi_dump::ElfObject ConvertElfObjectIR(
238 const ElfObjectIR *elf_object_ir);
239 };
240
241 class IRDiffToProtobufConverter {
242 private:
243 static bool AddTypeInfoDiff(abi_diff::TypeInfoDiff *type_info_diff_protobuf,
244 const TypeDiffIR *type_diff_ir);
245
246 static bool AddVTableLayoutDiff(
247 abi_diff::VTableLayoutDiff *vtable_layout_diff_protobuf,
248 const VTableLayoutDiffIR *vtable_layout_diff_ir);
249
250 static bool AddBaseSpecifierDiffs(
251 abi_diff::CXXBaseSpecifierDiff *base_specifier_diff_protobuf,
252 const CXXBaseSpecifierDiffIR *base_specifier_diff_ir);
253
254 static bool AddRecordFields(
255 abi_diff::RecordTypeDiff *record_diff_protobuf,
256 const std::vector<const RecordFieldIR *> &record_fields_removed_ir,
257 bool removed);
258
259 static bool AddRecordFieldDiffs(
260 abi_diff::RecordTypeDiff *record_diff_protobuf,
261 const std::vector<RecordFieldDiffIR> &record_field_diff_ir);
262
263 static bool AddEnumUnderlyingTypeDiff(
264 abi_diff::UnderlyingTypeDiff *underlying_type_diff_protobuf,
265 const std::pair<std::string, std::string> *underlying_type_diff_ir);
266
267 public:
268 static abi_diff::RecordTypeDiff ConvertRecordTypeDiffIR(
269 const RecordTypeDiffIR *record_type_diffp);
270
271 static abi_diff::EnumTypeDiff ConvertEnumTypeDiffIR(
272 const EnumTypeDiffIR *enum_type_diffp);
273
274 static abi_diff::FunctionDeclDiff ConvertFunctionDiffIR(
275 const FunctionDiffIR *function_diffp);
276
277 static abi_diff::GlobalVarDeclDiff ConvertGlobalVarDiffIR(
278 const GlobalVarDiffIR *global_var_diffp);
279 };
280
281 class ProtobufIRDumper : public IRDumper, public IRToProtobufConverter {
282 private:
283 // Types
284 bool AddRecordTypeIR(const RecordTypeIR *);
285
286 bool AddEnumTypeIR(const EnumTypeIR *);
287
288 bool AddPointerTypeIR(const PointerTypeIR *);
289
290 bool AddQualifiedTypeIR(const QualifiedTypeIR *);
291
292 bool AddLvalueReferenceTypeIR(const LvalueReferenceTypeIR *);
293
294 bool AddRvalueReferenceTypeIR(const RvalueReferenceTypeIR *);
295
296 bool AddArrayTypeIR(const ArrayTypeIR *);
297
298 bool AddBuiltinTypeIR(const BuiltinTypeIR *);
299
300 bool AddFunctionTypeIR(const FunctionTypeIR *function_typep);
301
302 // Functions and global variables.
303 bool AddFunctionIR(const FunctionIR *);
304
305 bool AddGlobalVarIR(const GlobalVarIR *);
306
307 bool AddElfFunctionIR(const ElfFunctionIR *);
308
309 bool AddElfObjectIR(const ElfObjectIR *);
310
311 public:
ProtobufIRDumper(const std::string & dump_path)312 ProtobufIRDumper(const std::string &dump_path)
313 : IRDumper(dump_path), tu_ptr_(new abi_dump::TranslationUnit()) { }
314
315 bool AddLinkableMessageIR(const LinkableMessageIR *) override;
316
317 bool AddElfSymbolMessageIR(const ElfSymbolIR *) override;
318
319 bool Dump() override;
320
~ProtobufIRDumper()321 ~ProtobufIRDumper() override { }
322
323 private:
324 std::unique_ptr<abi_dump::TranslationUnit> tu_ptr_;
325 };
326
327
328 class ProtobufTextFormatToIRReader : public TextFormatToIRReader {
329 public:
330
ProtobufTextFormatToIRReader(const std::set<std::string> * exported_headers)331 ProtobufTextFormatToIRReader(const std::set<std::string> *exported_headers)
332 : TextFormatToIRReader(exported_headers) { }
333
334 bool ReadDump(const std::string &dump_file) override;
335
336 private:
337 void ReadFunctions(const abi_dump::TranslationUnit &tu);
338
339 void ReadGlobalVariables(const abi_dump::TranslationUnit &tu);
340
341 void ReadEnumTypes(const abi_dump::TranslationUnit &tu);
342
343 void ReadRecordTypes(const abi_dump::TranslationUnit &tu);
344
345 void ReadFunctionTypes(const abi_dump::TranslationUnit &tu);
346
347 void ReadPointerTypes(const abi_dump::TranslationUnit &tu);
348
349 void ReadBuiltinTypes(const abi_dump::TranslationUnit &tu);
350
351 void ReadQualifiedTypes(const abi_dump::TranslationUnit &tu);
352
353 void ReadArrayTypes(const abi_dump::TranslationUnit &tu);
354
355 void ReadLvalueReferenceTypes(const abi_dump::TranslationUnit &tu);
356
357 void ReadRvalueReferenceTypes(const abi_dump::TranslationUnit &tu);
358
359 void ReadElfFunctions (const abi_dump::TranslationUnit &tu);
360
361 void ReadElfObjects (const abi_dump::TranslationUnit &tu);
362
363 void ReadTypeInfo(const abi_dump::BasicNamedAndTypedDecl &type_info,
364 TypeIR *typep);
365
366 FunctionIR FunctionProtobufToIR(const abi_dump::FunctionDecl &);
367
368 FunctionTypeIR FunctionTypeProtobufToIR(
369 const abi_dump::FunctionType &function_type_protobuf);
370
371 RecordTypeIR RecordTypeProtobufToIR(
372 const abi_dump::RecordType &record_type_protobuf);
373
374 std::vector<RecordFieldIR> RecordFieldsProtobufToIR(
375 const google::protobuf::RepeatedPtrField<abi_dump::RecordFieldDecl> &rfp);
376
377 std::vector<CXXBaseSpecifierIR> RecordCXXBaseSpecifiersProtobufToIR(
378 const google::protobuf::RepeatedPtrField<abi_dump::CXXBaseSpecifier> &rbs);
379
380 std::vector<EnumFieldIR> EnumFieldsProtobufToIR(
381 const google::protobuf::RepeatedPtrField<abi_dump::EnumFieldDecl> &efp);
382
383 EnumTypeIR EnumTypeProtobufToIR(
384 const abi_dump::EnumType &enum_type_protobuf);
385
386 VTableLayoutIR VTableLayoutProtobufToIR(
387 const abi_dump::VTableLayout &vtable_layout_protobuf);
388
389 TemplateInfoIR TemplateInfoProtobufToIR(
390 const abi_dump::TemplateInfo &template_info_protobuf);
391 };
392
393 class ProtobufIRDiffDumper : public IRDiffDumper {
394 public:
ProtobufIRDiffDumper(const std::string & dump_path)395 ProtobufIRDiffDumper(const std::string &dump_path)
396 : IRDiffDumper(dump_path),
397 diff_tu_(new abi_diff::TranslationUnitDiff()) { }
398
399 bool AddDiffMessageIR(const DiffMessageIR *, const std::string &type_stack,
400 DiffKind diff_kind) override;
401
402 bool AddLinkableMessageIR(const LinkableMessageIR *,
403 DiffKind diff_kind) override;
404
405 bool AddElfSymbolMessageIR(const ElfSymbolIR *, DiffKind diff_kind) override;
406
407 void AddLibNameIR(const std::string &name) override;
408
409 void AddArchIR(const std::string &arch) override;
410
411 void AddCompatibilityStatusIR(CompatibilityStatusIR status) override;
412
413 bool Dump() override;
414
415 CompatibilityStatusIR GetCompatibilityStatusIR() override;
416
~ProtobufIRDiffDumper()417 ~ProtobufIRDiffDumper() override { }
418
419 private:
420 // User defined types.
421 bool AddRecordTypeDiffIR(const RecordTypeDiffIR *,
422 const std::string &type_stack, DiffKind diff_kind);
423
424 bool AddEnumTypeDiffIR(const EnumTypeDiffIR *,
425 const std::string &type_stack, DiffKind diff_kind);
426
427 // Functions and global variables.
428 bool AddFunctionDiffIR(const FunctionDiffIR *,
429 const std::string &type_stack, DiffKind diff_kind);
430
431 bool AddGlobalVarDiffIR(const GlobalVarDiffIR *,
432 const std::string &type_stack, DiffKind diff_kind);
433
434 bool AddLoneRecordTypeDiffIR(const RecordTypeIR *, DiffKind diff_kind);
435
436 bool AddLoneEnumTypeDiffIR(const EnumTypeIR *, DiffKind diff_kind);
437
438 // Functions and global variables.
439 bool AddLoneFunctionDiffIR(const FunctionIR *, DiffKind diff_kind);
440
441 bool AddLoneGlobalVarDiffIR(const GlobalVarIR *, DiffKind diff_kind);
442
443 bool AddElfObjectIR(const ElfObjectIR *elf_object_ir, DiffKind diff_kind);
444
445 bool AddElfFunctionIR(const ElfFunctionIR *elf_function_ir,
446 DiffKind diff_kind);
447
448 protected:
449 std::unique_ptr<abi_diff::TranslationUnitDiff> diff_tu_;
450 };
451
452 } // abi_util
453
454 #endif // IR_PROTOBUF_
455