• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_dumper.h"
16  
17  #include "repr/protobuf/abi_dump.h"
18  #include "repr/protobuf/api.h"
19  
20  #include <fstream>
21  #include <memory>
22  
23  #include <llvm/Support/raw_ostream.h>
24  
25  #include <google/protobuf/io/zero_copy_stream_impl.h>
26  #include <google/protobuf/text_format.h>
27  
28  
29  namespace header_checker {
30  namespace repr {
31  
32  
AddTemplateInformation(abi_dump::TemplateInfo * ti,const TemplatedArtifactIR * ta)33  bool IRToProtobufConverter::AddTemplateInformation(
34      abi_dump::TemplateInfo *ti, const TemplatedArtifactIR *ta) {
35    for (auto &&template_element : ta->GetTemplateElements()) {
36      abi_dump::TemplateElement *added_element = ti->add_elements();
37      if (!added_element) {
38        llvm::errs() << "Failed to add template element\n";
39        return false;
40      }
41      added_element->set_referenced_type(template_element.GetReferencedType());
42    }
43    return true;
44  }
45  
AddTypeInfo(abi_dump::BasicNamedAndTypedDecl * type_info,const TypeIR * typep)46  bool IRToProtobufConverter::AddTypeInfo(
47      abi_dump::BasicNamedAndTypedDecl *type_info, const TypeIR *typep) {
48    if (!type_info || !typep) {
49      llvm::errs() << "Typeinfo not valid\n";
50      return false;
51    }
52    type_info->set_linker_set_key(typep->GetLinkerSetKey());
53    type_info->set_source_file(typep->GetSourceFile());
54    type_info->set_name(typep->GetName());
55    type_info->set_size(typep->GetSize());
56    type_info->set_alignment(typep->GetAlignment());
57    type_info->set_referenced_type(typep->GetReferencedType());
58    type_info->set_self_type(typep->GetSelfType());
59    return true;
60  }
61  
AddRecordFields(abi_dump::RecordType * record_protobuf,const RecordTypeIR * record_ir)62  bool IRToProtobufConverter::AddRecordFields(
63      abi_dump::RecordType *record_protobuf,
64      const RecordTypeIR *record_ir) {
65    // Iterate through the fields and create corresponding ones for the protobuf
66    // record
67    for (auto &&field_ir : record_ir->GetFields()) {
68      abi_dump::RecordFieldDecl *added_field = record_protobuf->add_fields();
69      if (!added_field) {
70        llvm::errs() << "Couldn't add record field\n";
71      }
72      SetIRToProtobufRecordField(added_field, &field_ir);
73    }
74    return true;
75  }
76  
AddBaseSpecifiers(abi_dump::RecordType * record_protobuf,const RecordTypeIR * record_ir)77  bool IRToProtobufConverter::AddBaseSpecifiers(
78      abi_dump::RecordType *record_protobuf, const RecordTypeIR *record_ir) {
79    for (auto &&base_ir : record_ir->GetBases()) {
80      abi_dump::CXXBaseSpecifier *added_base =
81          record_protobuf->add_base_specifiers();
82      if (!SetIRToProtobufBaseSpecifier(added_base, base_ir)) {
83        return false;
84      }
85    }
86    return true;
87  }
88  
AddVTableLayout(abi_dump::RecordType * record_protobuf,const RecordTypeIR * record_ir)89  bool IRToProtobufConverter::AddVTableLayout(
90      abi_dump::RecordType *record_protobuf,
91      const RecordTypeIR *record_ir) {
92    // If there are no entries in the vtable, just return.
93    if (record_ir->GetVTableNumEntries() == 0) {
94      return true;
95    }
96    const VTableLayoutIR &vtable_layout_ir = record_ir->GetVTableLayout();
97    abi_dump::VTableLayout *vtable_layout_protobuf =
98        record_protobuf->mutable_vtable_layout();
99    if (!SetIRToProtobufVTableLayout(vtable_layout_protobuf, vtable_layout_ir)) {
100      return false;
101    }
102    return true;
103  }
104  
AddTagTypeInfo(abi_dump::TagType * tag_type_protobuf,const TagTypeIR * tag_type_ir)105  bool IRToProtobufConverter::AddTagTypeInfo(
106      abi_dump::TagType *tag_type_protobuf,
107      const TagTypeIR *tag_type_ir) {
108    if (!tag_type_protobuf || !tag_type_ir) {
109      return false;
110    }
111    tag_type_protobuf->set_unique_id(tag_type_ir->GetUniqueId());
112    return true;
113  }
114  
ConvertRecordTypeIR(const RecordTypeIR * recordp)115  abi_dump::RecordType IRToProtobufConverter::ConvertRecordTypeIR(
116      const RecordTypeIR *recordp) {
117    abi_dump::RecordType added_record_type;
118    added_record_type.set_access(AccessIRToProtobuf(recordp->GetAccess()));
119    added_record_type.set_record_kind(
120        RecordKindIRToProtobuf(recordp->GetRecordKind()));
121    if (recordp->IsAnonymous()) {
122      added_record_type.set_is_anonymous(true);
123    }
124    if (!AddTypeInfo(added_record_type.mutable_type_info(), recordp) ||
125        !AddRecordFields(&added_record_type, recordp) ||
126        !AddBaseSpecifiers(&added_record_type, recordp) ||
127        !AddVTableLayout(&added_record_type, recordp) ||
128        !AddTagTypeInfo(added_record_type.mutable_tag_info(), recordp) ||
129        !(recordp->GetTemplateElements().size() ?
130          AddTemplateInformation(added_record_type.mutable_template_info(),
131                                 recordp) : true)) {
132      llvm::errs() << "Template information could not be added\n";
133      ::exit(1);
134    }
135    return added_record_type;
136  }
137  
138  
ConvertElfObjectIR(const ElfObjectIR * elf_object_ir)139  abi_dump::ElfObject IRToProtobufConverter::ConvertElfObjectIR(
140      const ElfObjectIR *elf_object_ir) {
141    abi_dump::ElfObject elf_object_protobuf;
142    elf_object_protobuf.set_name(elf_object_ir->GetName());
143    return elf_object_protobuf;
144  }
145  
ConvertElfFunctionIR(const ElfFunctionIR * elf_function_ir)146  abi_dump::ElfFunction IRToProtobufConverter::ConvertElfFunctionIR(
147      const ElfFunctionIR *elf_function_ir) {
148    abi_dump::ElfFunction elf_function_protobuf;
149    elf_function_protobuf.set_name(elf_function_ir->GetName());
150    return elf_function_protobuf;
151  }
152  
153  template <typename CFunctionLikeMessage>
AddFunctionParametersAndSetReturnType(CFunctionLikeMessage * function_like_protobuf,const CFunctionLikeIR * cfunction_like_ir)154  bool IRToProtobufConverter::AddFunctionParametersAndSetReturnType(
155      CFunctionLikeMessage *function_like_protobuf,
156      const CFunctionLikeIR *cfunction_like_ir) {
157    function_like_protobuf->set_return_type(cfunction_like_ir->GetReturnType());
158    return AddFunctionParameters(function_like_protobuf, cfunction_like_ir);
159  }
160  
161  template <typename CFunctionLikeMessage>
AddFunctionParameters(CFunctionLikeMessage * function_like_protobuf,const CFunctionLikeIR * cfunction_like_ir)162  bool IRToProtobufConverter::AddFunctionParameters(
163      CFunctionLikeMessage *function_like_protobuf,
164      const CFunctionLikeIR *cfunction_like_ir) {
165    for (auto &&parameter : cfunction_like_ir->GetParameters()) {
166      abi_dump::ParamDecl *added_parameter =
167          function_like_protobuf->add_parameters();
168      if (!added_parameter) {
169        return false;
170      }
171      added_parameter->set_referenced_type(
172          parameter.GetReferencedType());
173      added_parameter->set_default_arg(parameter.GetIsDefault());
174      added_parameter->set_is_this_ptr(parameter.GetIsThisPtr());
175    }
176    return true;
177  }
178  
ConvertFunctionTypeIR(const FunctionTypeIR * function_typep)179  abi_dump::FunctionType IRToProtobufConverter::ConvertFunctionTypeIR (
180      const FunctionTypeIR *function_typep) {
181    abi_dump::FunctionType added_function_type;
182    if (!AddTypeInfo(added_function_type.mutable_type_info(), function_typep) ||
183        !AddFunctionParametersAndSetReturnType(&added_function_type,
184                                               function_typep)) {
185      llvm::errs() << "Could not convert FunctionTypeIR to protobuf\n";
186      ::exit(1);
187    }
188    return added_function_type;
189  }
190  
ConvertFunctionIR(const FunctionIR * functionp)191  abi_dump::FunctionDecl IRToProtobufConverter::ConvertFunctionIR(
192      const FunctionIR *functionp) {
193    abi_dump::FunctionDecl added_function;
194    added_function.set_access(AccessIRToProtobuf(functionp->GetAccess()));
195    added_function.set_linker_set_key(functionp->GetLinkerSetKey());
196    added_function.set_source_file(functionp->GetSourceFile());
197    added_function.set_function_name(functionp->GetName());
198    if (!AddFunctionParametersAndSetReturnType(&added_function, functionp) ||
199        !(functionp->GetTemplateElements().size() ?
200        AddTemplateInformation(added_function.mutable_template_info(), functionp)
201        : true)) {
202      llvm::errs() << "Template information could not be added\n";
203      ::exit(1);
204    }
205    return added_function;
206  }
207  
AddEnumFields(abi_dump::EnumType * enum_protobuf,const EnumTypeIR * enum_ir)208  bool IRToProtobufConverter::AddEnumFields(abi_dump::EnumType *enum_protobuf,
209                                            const EnumTypeIR *enum_ir) {
210    for (auto &&field : enum_ir->GetFields()) {
211      abi_dump::EnumFieldDecl *enum_fieldp = enum_protobuf->add_enum_fields();
212      if (!SetIRToProtobufEnumField(enum_fieldp, &field)) {
213        return false;
214      }
215    }
216    return true;
217  }
218  
219  
ConvertEnumTypeIR(const EnumTypeIR * enump)220  abi_dump::EnumType IRToProtobufConverter::ConvertEnumTypeIR(
221      const EnumTypeIR *enump) {
222    abi_dump::EnumType added_enum_type;
223    added_enum_type.set_access(AccessIRToProtobuf(enump->GetAccess()));
224    added_enum_type.set_underlying_type(enump->GetUnderlyingType());
225    if (!AddTypeInfo(added_enum_type.mutable_type_info(), enump) ||
226        !AddEnumFields(&added_enum_type, enump) ||
227        !AddTagTypeInfo(added_enum_type.mutable_tag_info(), enump)) {
228      llvm::errs() << "EnumTypeIR could not be converted\n";
229      ::exit(1);
230    }
231    return added_enum_type;
232  }
233  
ConvertGlobalVarIR(const GlobalVarIR * global_varp)234  abi_dump::GlobalVarDecl IRToProtobufConverter::ConvertGlobalVarIR(
235      const GlobalVarIR *global_varp) {
236    abi_dump::GlobalVarDecl added_global_var;
237    added_global_var.set_referenced_type(global_varp->GetReferencedType());
238    added_global_var.set_source_file(global_varp->GetSourceFile());
239    added_global_var.set_name(global_varp->GetName());
240    added_global_var.set_linker_set_key(global_varp->GetLinkerSetKey());
241    added_global_var.set_access(
242        AccessIRToProtobuf(global_varp->GetAccess()));
243    return added_global_var;
244  }
245  
ConvertPointerTypeIR(const PointerTypeIR * pointerp)246  abi_dump::PointerType IRToProtobufConverter::ConvertPointerTypeIR(
247      const PointerTypeIR *pointerp) {
248    abi_dump::PointerType added_pointer_type;
249    if (!AddTypeInfo(added_pointer_type.mutable_type_info(), pointerp)) {
250      llvm::errs() << "PointerTypeIR could not be converted\n";
251      ::exit(1);
252    }
253    return added_pointer_type;
254  }
255  
ConvertQualifiedTypeIR(const QualifiedTypeIR * qualtypep)256  abi_dump::QualifiedType IRToProtobufConverter::ConvertQualifiedTypeIR(
257      const QualifiedTypeIR *qualtypep) {
258    abi_dump::QualifiedType added_qualified_type;
259    if (!AddTypeInfo(added_qualified_type.mutable_type_info(), qualtypep)) {
260      llvm::errs() << "QualifiedTypeIR could not be converted\n";
261      ::exit(1);
262    }
263    added_qualified_type.set_is_const(qualtypep->IsConst());
264    added_qualified_type.set_is_volatile(qualtypep->IsVolatile());
265    added_qualified_type.set_is_restricted(qualtypep->IsRestricted());
266    return added_qualified_type;
267  }
268  
ConvertBuiltinTypeIR(const BuiltinTypeIR * builtin_typep)269  abi_dump::BuiltinType IRToProtobufConverter::ConvertBuiltinTypeIR(
270      const BuiltinTypeIR *builtin_typep) {
271    abi_dump::BuiltinType added_builtin_type;
272    added_builtin_type.set_is_unsigned(builtin_typep->IsUnsigned());
273    added_builtin_type.set_is_integral(builtin_typep->IsIntegralType());
274    if (!AddTypeInfo(added_builtin_type.mutable_type_info(), builtin_typep)) {
275      llvm::errs() << "BuiltinTypeIR could not be converted\n";
276      ::exit(1);
277    }
278    return added_builtin_type;
279  }
280  
ConvertArrayTypeIR(const ArrayTypeIR * array_typep)281  abi_dump::ArrayType IRToProtobufConverter::ConvertArrayTypeIR(
282      const ArrayTypeIR *array_typep) {
283    abi_dump::ArrayType added_array_type;
284    if (!AddTypeInfo(added_array_type.mutable_type_info(), array_typep)) {
285      llvm::errs() << "ArrayTypeIR could not be converted\n";
286      ::exit(1);
287    }
288    return added_array_type;
289  }
290  
291  abi_dump::LvalueReferenceType
ConvertLvalueReferenceTypeIR(const LvalueReferenceTypeIR * lvalue_reference_typep)292  IRToProtobufConverter::ConvertLvalueReferenceTypeIR(
293      const LvalueReferenceTypeIR *lvalue_reference_typep) {
294    abi_dump::LvalueReferenceType added_lvalue_reference_type;
295    if (!AddTypeInfo(added_lvalue_reference_type.mutable_type_info(),
296                     lvalue_reference_typep)) {
297      llvm::errs() << "LvalueReferenceTypeIR could not be converted\n";
298      ::exit(1);
299    }
300    return added_lvalue_reference_type;
301  }
302  
303  abi_dump::RvalueReferenceType
ConvertRvalueReferenceTypeIR(const RvalueReferenceTypeIR * rvalue_reference_typep)304  IRToProtobufConverter::ConvertRvalueReferenceTypeIR(
305      const RvalueReferenceTypeIR *rvalue_reference_typep) {
306    abi_dump::RvalueReferenceType added_rvalue_reference_type;
307    if (!AddTypeInfo(added_rvalue_reference_type.mutable_type_info(),
308                     rvalue_reference_typep)) {
309      llvm::errs() << "RvalueReferenceTypeIR could not be converted\n";
310      ::exit(1);
311    }
312    return added_rvalue_reference_type;
313  }
314  
AddLinkableMessageIR(const LinkableMessageIR * lm)315  bool ProtobufIRDumper::AddLinkableMessageIR (const LinkableMessageIR *lm) {
316    // No RTTI
317    switch (lm->GetKind()) {
318      case RecordTypeKind:
319        return AddRecordTypeIR(static_cast<const RecordTypeIR *>(lm));
320      case EnumTypeKind:
321        return AddEnumTypeIR(static_cast<const EnumTypeIR *>(lm));
322      case PointerTypeKind:
323        return AddPointerTypeIR(static_cast<const PointerTypeIR *>(lm));
324      case QualifiedTypeKind:
325        return AddQualifiedTypeIR(static_cast<const QualifiedTypeIR *>(lm));
326      case ArrayTypeKind:
327        return AddArrayTypeIR(static_cast<const ArrayTypeIR *>(lm));
328      case LvalueReferenceTypeKind:
329        return AddLvalueReferenceTypeIR(
330            static_cast<const LvalueReferenceTypeIR *>(lm));
331      case RvalueReferenceTypeKind:
332        return AddRvalueReferenceTypeIR(
333            static_cast<const RvalueReferenceTypeIR*>(lm));
334      case BuiltinTypeKind:
335        return AddBuiltinTypeIR(static_cast<const BuiltinTypeIR*>(lm));
336      case FunctionTypeKind:
337        return AddFunctionTypeIR(static_cast<const FunctionTypeIR*>(lm));
338      case GlobalVarKind:
339        return AddGlobalVarIR(static_cast<const GlobalVarIR*>(lm));
340      case FunctionKind:
341        return AddFunctionIR(static_cast<const FunctionIR*>(lm));
342    }
343    return false;
344  }
345  
AddElfFunctionIR(const ElfFunctionIR * elf_function)346  bool ProtobufIRDumper::AddElfFunctionIR(const ElfFunctionIR *elf_function) {
347    abi_dump::ElfFunction *added_elf_function = tu_ptr_->add_elf_functions();
348    if (!added_elf_function) {
349      return false;
350    }
351    added_elf_function->set_name(elf_function->GetName());
352    added_elf_function->set_binding(
353        ElfSymbolBindingIRToProtobuf(elf_function->GetBinding()));
354    return true;
355  }
356  
AddElfObjectIR(const ElfObjectIR * elf_object)357  bool ProtobufIRDumper::AddElfObjectIR(const ElfObjectIR *elf_object) {
358    abi_dump::ElfObject *added_elf_object = tu_ptr_->add_elf_objects();
359    if (!added_elf_object) {
360      return false;
361    }
362    added_elf_object->set_name(elf_object->GetName());
363    added_elf_object->set_binding(
364        ElfSymbolBindingIRToProtobuf(elf_object->GetBinding()));
365    return true;
366  }
367  
AddElfSymbolMessageIR(const ElfSymbolIR * em)368  bool ProtobufIRDumper::AddElfSymbolMessageIR(const ElfSymbolIR *em) {
369    switch (em->GetKind()) {
370      case ElfSymbolIR::ElfFunctionKind:
371        return AddElfFunctionIR(static_cast<const ElfFunctionIR *>(em));
372      case ElfSymbolIR::ElfObjectKind:
373        return AddElfObjectIR(static_cast<const ElfObjectIR *>(em));
374    }
375    return false;
376  }
377  
AddRecordTypeIR(const RecordTypeIR * recordp)378  bool ProtobufIRDumper::AddRecordTypeIR(const RecordTypeIR *recordp) {
379    abi_dump::RecordType *added_record_type = tu_ptr_->add_record_types();
380    if (!added_record_type) {
381      return false;
382    }
383    *added_record_type = ConvertRecordTypeIR(recordp);
384    return true;
385  }
386  
AddFunctionTypeIR(const FunctionTypeIR * function_typep)387  bool ProtobufIRDumper::AddFunctionTypeIR(const FunctionTypeIR *function_typep) {
388    abi_dump::FunctionType *added_function_type = tu_ptr_->add_function_types();
389    if (!added_function_type) {
390      return false;
391    }
392    *added_function_type = ConvertFunctionTypeIR(function_typep);
393    return true;
394  }
395  
AddFunctionIR(const FunctionIR * functionp)396  bool ProtobufIRDumper::AddFunctionIR(const FunctionIR *functionp) {
397    abi_dump::FunctionDecl *added_function = tu_ptr_->add_functions();
398    if (!added_function) {
399      return false;
400    }
401    *added_function = ConvertFunctionIR(functionp);
402    return true;
403  }
404  
AddEnumTypeIR(const EnumTypeIR * enump)405  bool ProtobufIRDumper::AddEnumTypeIR(const EnumTypeIR *enump) {
406    abi_dump::EnumType *added_enum_type = tu_ptr_->add_enum_types();
407    if (!added_enum_type) {
408      return false;
409    }
410    *added_enum_type = ConvertEnumTypeIR(enump);
411    return true;
412  }
413  
AddGlobalVarIR(const GlobalVarIR * global_varp)414  bool ProtobufIRDumper::AddGlobalVarIR(const GlobalVarIR *global_varp) {
415    abi_dump::GlobalVarDecl *added_global_var = tu_ptr_->add_global_vars();
416    if (!added_global_var) {
417      return false;
418    }
419    *added_global_var = ConvertGlobalVarIR(global_varp);
420    return true;
421  }
422  
AddPointerTypeIR(const PointerTypeIR * pointerp)423  bool ProtobufIRDumper::AddPointerTypeIR(const PointerTypeIR *pointerp) {
424    abi_dump::PointerType *added_pointer_type = tu_ptr_->add_pointer_types();
425    if (!added_pointer_type) {
426      return false;
427    }
428    *added_pointer_type = ConvertPointerTypeIR(pointerp);
429    return true;
430  }
431  
AddQualifiedTypeIR(const QualifiedTypeIR * qualtypep)432  bool ProtobufIRDumper::AddQualifiedTypeIR(const QualifiedTypeIR *qualtypep) {
433    abi_dump::QualifiedType *added_qualified_type =
434        tu_ptr_->add_qualified_types();
435    if (!added_qualified_type) {
436      return false;
437    }
438    *added_qualified_type = ConvertQualifiedTypeIR(qualtypep);
439    return true;
440  }
441  
AddBuiltinTypeIR(const BuiltinTypeIR * builtin_typep)442  bool ProtobufIRDumper::AddBuiltinTypeIR(const BuiltinTypeIR *builtin_typep) {
443    abi_dump::BuiltinType *added_builtin_type =
444        tu_ptr_->add_builtin_types();
445    if (!added_builtin_type) {
446      return false;
447    }
448    *added_builtin_type = ConvertBuiltinTypeIR(builtin_typep);
449    return true;
450  }
451  
AddArrayTypeIR(const ArrayTypeIR * array_typep)452  bool ProtobufIRDumper::AddArrayTypeIR(const ArrayTypeIR *array_typep) {
453    abi_dump::ArrayType *added_array_type =
454        tu_ptr_->add_array_types();
455    if (!added_array_type) {
456      return false;
457    }
458    *added_array_type = ConvertArrayTypeIR(array_typep);
459    return true;
460  }
461  
AddLvalueReferenceTypeIR(const LvalueReferenceTypeIR * lvalue_reference_typep)462  bool ProtobufIRDumper::AddLvalueReferenceTypeIR(
463      const LvalueReferenceTypeIR *lvalue_reference_typep) {
464    abi_dump::LvalueReferenceType *added_lvalue_reference_type =
465        tu_ptr_->add_lvalue_reference_types();
466    if (!added_lvalue_reference_type) {
467      return false;
468    }
469    *added_lvalue_reference_type =
470        ConvertLvalueReferenceTypeIR(lvalue_reference_typep);
471    return true;
472  }
473  
AddRvalueReferenceTypeIR(const RvalueReferenceTypeIR * rvalue_reference_typep)474  bool ProtobufIRDumper::AddRvalueReferenceTypeIR(
475      const RvalueReferenceTypeIR *rvalue_reference_typep) {
476    abi_dump::RvalueReferenceType *added_rvalue_reference_type =
477        tu_ptr_->add_rvalue_reference_types();
478    if (!added_rvalue_reference_type) {
479      return false;
480    }
481    *added_rvalue_reference_type =
482        ConvertRvalueReferenceTypeIR(rvalue_reference_typep);
483    return true;
484  }
485  
Dump(const ModuleIR & module)486  bool ProtobufIRDumper::Dump(const ModuleIR &module) {
487    GOOGLE_PROTOBUF_VERIFY_VERSION;
488    DumpModule(module);
489    assert( tu_ptr_.get() != nullptr);
490    std::ofstream text_output(dump_path_);
491    google::protobuf::io::OstreamOutputStream text_os(&text_output);
492    return google::protobuf::TextFormat::Print(*tu_ptr_.get(), &text_os);
493  }
494  
CreateProtobufIRDumper(const std::string & dump_path)495  std::unique_ptr<IRDumper> CreateProtobufIRDumper(const std::string &dump_path) {
496    return std::make_unique<ProtobufIRDumper>(dump_path);
497  }
498  
499  
500  }  // namespace repr
501  }  // namespace header_checker
502