// Copyright 2018 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef COMPONENTS_ZUCCHINI_DISASSEMBLER_DEX_H_ #define COMPONENTS_ZUCCHINI_DISASSEMBLER_DEX_H_ #include #include #include #include #include #include "components/zucchini/disassembler.h" #include "components/zucchini/image_utils.h" #include "components/zucchini/type_dex.h" namespace zucchini { // For consistency, let "canonical order" of DEX data types be the order defined // in https://source.android.com/devices/tech/dalvik/dex-format "Type Codes" // section. class DisassemblerDex : public Disassembler { public: static constexpr uint16_t kVersion = 1; // Pools follow canonical order. enum ReferencePool : uint8_t { kStringId, kTypeId, kProtoId, kFieldId, kMethodId, // kClassDef, // Unused kCallSiteId, kMethodHandle, kTypeList, kAnnotationSetRefList, kAnnotionSet, kClassData, kCode, kStringData, kAnnotation, kEncodedArray, kAnnotationsDirectory, kCallSite, kNumPools }; // Types are grouped and ordered by target ReferencePool. This is required by // Zucchini-apply, which visits references by type order and sequentially // handles pools in the same order. Type-pool association is established in // MakeReferenceGroups(), and verified by a unit test. enum ReferenceType : uint8_t { kTypeIdToDescriptorStringId, // kStringId kProtoIdToShortyStringId, kFieldIdToNameStringId, kMethodIdToNameStringId, kClassDefToSourceFileStringId, kCodeToStringId16, kCodeToStringId32, kProtoIdToReturnTypeId, // kTypeId kFieldIdToClassTypeId, kFieldIdToTypeId, kMethodIdToClassTypeId, kClassDefToClassTypeId, kClassDefToSuperClassTypeId, kTypeListToTypeId, kCodeToTypeId, kCodeToProtoId, // kProtoId kMethodIdToProtoId, kCodeToFieldId, // kFieldId kMethodHandleToFieldId, kAnnotationsDirectoryToFieldId, kCodeToMethodId, // kMethodId kMethodHandleToMethodId, kAnnotationsDirectoryToMethodId, kAnnotationsDirectoryToParameterMethodId, kCodeToCallSiteId, // kCallSiteId kCodeToMethodHandle, // kMethodHandle kProtoIdToParametersTypeList, // kTypeList kClassDefToInterfacesTypeList, kAnnotationsDirectoryToParameterAnnotationSetRef, // kAnnotationSetRef, kAnnotationSetRefListToAnnotationSet, // kAnnotationSet, kAnnotationsDirectoryToClassAnnotationSet, kAnnotationsDirectoryToFieldAnnotationSet, kAnnotationsDirectoryToMethodAnnotationSet, kClassDefToClassData, // kClassData kCodeToRelCode8, // kCode kCodeToRelCode16, kCodeToRelCode32, kStringIdToStringData, // kStringData kAnnotationSetToAnnotation, // kAnnotation kClassDefToStaticValuesEncodedArray, // kEncodedArrayItem kClassDefToAnnotationDirectory, // kAnnotationsDirectory kCallSiteIdToCallSite, // kCallSite kNumTypes }; DisassemblerDex(); DisassemblerDex(const DisassemblerDex&) = delete; const DisassemblerDex& operator=(const DisassemblerDex&) = delete; ~DisassemblerDex() override; // Applies quick checks to determine if |image| *may* point to the start of an // executable. Returns true on success. static bool QuickDetect(ConstBufferView image); // Disassembler: ExecutableType GetExeType() const override; std::string GetExeTypeString() const override; std::vector MakeReferenceGroups() const override; // Functions that return reference readers. These follow canonical order of // *locations* (unlike targets for ReferenceType). This allows functions with // similar parsing logic to appear togeter. std::unique_ptr MakeReadStringIdToStringData(offset_t lo, offset_t hi); std::unique_ptr MakeReadTypeIdToDescriptorStringId32( offset_t lo, offset_t hi); std::unique_ptr MakeReadProtoIdToShortyStringId32( offset_t lo, offset_t hi); std::unique_ptr MakeReadProtoIdToReturnTypeId32(offset_t lo, offset_t hi); std::unique_ptr MakeReadProtoIdToParametersTypeList( offset_t lo, offset_t hi); std::unique_ptr MakeReadFieldToClassTypeId16(offset_t lo, offset_t hi); std::unique_ptr MakeReadFieldToTypeId16(offset_t lo, offset_t hi); std::unique_ptr MakeReadFieldToNameStringId32(offset_t lo, offset_t hi); std::unique_ptr MakeReadMethodIdToClassTypeId16(offset_t lo, offset_t hi); std::unique_ptr MakeReadMethodIdToProtoId16(offset_t lo, offset_t hi); std::unique_ptr MakeReadMethodIdToNameStringId32( offset_t lo, offset_t hi); std::unique_ptr MakeReadClassDefToClassTypeId32(offset_t lo, offset_t hi); std::unique_ptr MakeReadClassDefToSuperClassTypeId32( offset_t lo, offset_t hi); std::unique_ptr MakeReadClassDefToInterfacesTypeList( offset_t lo, offset_t hi); std::unique_ptr MakeReadClassDefToSourceFileStringId32( offset_t lo, offset_t hi); std::unique_ptr MakeReadClassDefToAnnotationDirectory( offset_t lo, offset_t hi); std::unique_ptr MakeReadClassDefToClassData(offset_t lo, offset_t hi); std::unique_ptr MakeReadClassDefToStaticValuesEncodedArray( offset_t lo, offset_t hi); std::unique_ptr MakeReadCallSiteIdToCallSite32(offset_t lo, offset_t hi); std::unique_ptr MakeReadMethodHandleToFieldId16(offset_t lo, offset_t hi); std::unique_ptr MakeReadMethodHandleToMethodId16( offset_t lo, offset_t hi); std::unique_ptr MakeReadTypeListToTypeId16(offset_t lo, offset_t hi); std::unique_ptr MakeReadAnnotationSetToAnnotation( offset_t lo, offset_t hi); std::unique_ptr MakeReadAnnotationSetRefListToAnnotationSet( offset_t lo, offset_t hi); std::unique_ptr MakeReadAnnotationsDirectoryToClassAnnotationSet(offset_t lo, offset_t hi); std::unique_ptr MakeReadAnnotationsDirectoryToFieldId32( offset_t lo, offset_t hi); std::unique_ptr MakeReadAnnotationsDirectoryToFieldAnnotationSet(offset_t lo, offset_t hi); std::unique_ptr MakeReadAnnotationsDirectoryToMethodId32( offset_t lo, offset_t hi); std::unique_ptr MakeReadAnnotationsDirectoryToMethodAnnotationSet(offset_t lo, offset_t hi); std::unique_ptr MakeReadAnnotationsDirectoryToParameterMethodId32(offset_t lo, offset_t hi); std::unique_ptr MakeReadAnnotationsDirectoryToParameterAnnotationSetRef(offset_t lo, offset_t hi); std::unique_ptr MakeReadCodeToStringId16(offset_t lo, offset_t hi); std::unique_ptr MakeReadCodeToStringId32(offset_t lo, offset_t hi); std::unique_ptr MakeReadCodeToTypeId16(offset_t lo, offset_t hi); std::unique_ptr MakeReadCodeToProtoId16(offset_t lo, offset_t hi); std::unique_ptr MakeReadCodeToFieldId16(offset_t lo, offset_t hi); std::unique_ptr MakeReadCodeToMethodId16(offset_t lo, offset_t hi); std::unique_ptr MakeReadCodeToCallSiteId16(offset_t lo, offset_t hi); std::unique_ptr MakeReadCodeToMethodHandle16(offset_t lo, offset_t hi); std::unique_ptr MakeReadCodeToRelCode8(offset_t lo, offset_t hi); std::unique_ptr MakeReadCodeToRelCode16(offset_t lo, offset_t hi); std::unique_ptr MakeReadCodeToRelCode32(offset_t lo, offset_t hi); // Functions that return reference writers. Different readers may share a // common writer. Therefore these loosely follow canonical order of locations, std::unique_ptr MakeWriteStringId16(MutableBufferView image); std::unique_ptr MakeWriteStringId32(MutableBufferView image); std::unique_ptr MakeWriteTypeId16(MutableBufferView image); std::unique_ptr MakeWriteTypeId32(MutableBufferView image); std::unique_ptr MakeWriteProtoId16(MutableBufferView image); std::unique_ptr MakeWriteFieldId16(MutableBufferView image); std::unique_ptr MakeWriteFieldId32(MutableBufferView image); std::unique_ptr MakeWriteMethodId16(MutableBufferView image); std::unique_ptr MakeWriteMethodId32(MutableBufferView image); std::unique_ptr MakeWriteCallSiteId16( MutableBufferView image); std::unique_ptr MakeWriteMethodHandle16( MutableBufferView image); std::unique_ptr MakeWriteRelCode8(MutableBufferView image); std::unique_ptr MakeWriteRelCode16(MutableBufferView image); std::unique_ptr MakeWriteRelCode32(MutableBufferView image); std::unique_ptr MakeWriteAbs32(MutableBufferView image); private: friend Disassembler; using MapItemMap = std::map; // Disassembler: bool Parse(ConstBufferView image) override; bool ParseHeader(); const dex::HeaderItem* header_ = nullptr; int dex_version_ = 0; MapItemMap map_item_map_ = {}; dex::MapItem string_map_item_ = {}; dex::MapItem type_map_item_ = {}; dex::MapItem proto_map_item_ = {}; dex::MapItem field_map_item_ = {}; dex::MapItem method_map_item_ = {}; dex::MapItem class_def_map_item_ = {}; dex::MapItem call_site_map_item_ = {}; dex::MapItem method_handle_map_item_ = {}; dex::MapItem type_list_map_item_ = {}; dex::MapItem annotation_set_ref_list_map_item_ = {}; dex::MapItem annotation_set_map_item_ = {}; dex::MapItem code_map_item_ = {}; dex::MapItem annotations_directory_map_item_ = {}; // Sorted list of offsets of parsed items in |image_|. std::vector code_item_offsets_; std::vector type_list_offsets_; std::vector annotation_set_ref_list_offsets_; std::vector annotation_set_offsets_; std::vector annotations_directory_item_offsets_; std::vector annotations_directory_item_field_annotation_offsets_; std::vector annotations_directory_item_method_annotation_offsets_; std::vector annotations_directory_item_parameter_annotation_offsets_; }; } // namespace zucchini #endif // COMPONENTS_ZUCCHINI_DISASSEMBLER_DEX_H_