// Copyright 2014 The Crashpad Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef CRASHPAD_SNAPSHOT_MAC_PROCESS_TYPES_H_ #define CRASHPAD_SNAPSHOT_MAC_PROCESS_TYPES_H_ #include #include #include #include #include #include "snapshot/mac/process_reader_mac.h" namespace crashpad { namespace process_types { namespace internal { // Some structure definitions have tail padding when built in a 64-bit // environment, but will have less (or no) tail padding in a 32-bit environment. // These structure’s apparent sizes will differ between these two environments, // which is incorrect. Use this “Nothing” type to place an “end” marker after // all of the real members of such structures, and use offsetof(type, end) to // compute their actual sizes. using Nothing = char[0]; // Some structure definitions differ in 32-bit and 64-bit environments by having // additional “reserved” padding fields present only in the 64-bit environment. // These Reserved*_*Only* types allow the process_types system to replicate // these structures more precisely. using Reserved32_32Only32 = uint32_t; using Reserved32_32Only64 = Nothing; using Reserved32_64Only32 = Nothing; using Reserved32_64Only64 = uint32_t; using Reserved64_64Only32 = Nothing; using Reserved64_64Only64 = uint64_t; } // namespace internal } // namespace process_types } // namespace crashpad #include "snapshot/mac/process_types/traits.h" // Creates the traits type crashpad::process_types::internal::TraitsGeneric. DECLARE_PROCESS_TYPE_TRAITS_CLASS(Generic, 64) #undef DECLARE_PROCESS_TYPE_TRAITS_CLASS // Declare the crashpad::process_types::struct_name structs. These are the // user-visible generic structs that callers will interact with. They read data // from 32-bit or 64-bit processes by using the specific internal templatized // structs below. #define PROCESS_TYPE_STRUCT_DECLARE 1 #define PROCESS_TYPE_STRUCT_BEGIN(struct_name) \ namespace crashpad { \ namespace process_types { \ struct struct_name { \ public: \ using Long = internal::TraitsGeneric::Long; \ using ULong = internal::TraitsGeneric::ULong; \ using Pointer = internal::TraitsGeneric::Pointer; \ using IntPtr = internal::TraitsGeneric::IntPtr; \ using UIntPtr = internal::TraitsGeneric::UIntPtr; \ using Reserved32_32Only = internal::TraitsGeneric::Reserved32_32Only; \ using Reserved32_64Only = internal::TraitsGeneric::Reserved32_64Only; \ using Reserved64_64Only = internal::TraitsGeneric::Reserved64_64Only; \ using Nothing = internal::TraitsGeneric::Nothing; \ \ /* Initializes an object with data read from |process_reader| at \ * |address|, properly genericized. */ \ bool Read(ProcessReaderMac* process_reader, mach_vm_address_t address) { \ return ReadInto(process_reader, address, this); \ } \ \ /* Reads |count| objects from |process_reader| beginning at |address|, and \ * genericizes the objects. The caller must provide storage for |count| \ * objects in |generic|. */ \ static bool ReadArrayInto(ProcessReaderMac* process_reader, \ mach_vm_address_t address, \ size_t count, \ struct_name* generic); \ \ /* Returns the size of the object that was read. This is the size of the \ * storage in the process that the data is read from, and is not the same \ * as the size of the generic struct. For versioned and sized structures, \ * the size of the full structure is returned. */ \ size_t Size() const { return size_; } \ \ /* Similar to Size(), but computes the expected size of a structure based \ * on the process’ bitness. This can be used prior to reading any data \ * from a process. For versioned and sized structures, \ * ExpectedSizeForVersion() and MinimumSize() may also be useful. */ \ static size_t ExpectedSize(ProcessReaderMac* process_reader); #define PROCESS_TYPE_STRUCT_MEMBER(member_type, member_name, ...) \ member_type member_name __VA_ARGS__; #define PROCESS_TYPE_STRUCT_VERSIONED(struct_name, version_field) \ /* Similar to ExpectedSize(), but computes the expected size of a \ * structure based on the process’ bitness and a custom value, such as a \ * structure version number. This can be used prior to reading any data \ * from a process. */ \ static size_t ExpectedSizeForVersion( \ ProcessReaderMac* process_reader, \ decltype(struct_name::version_field) version); #define PROCESS_TYPE_STRUCT_SIZED(struct_name, size_field) \ /* Similar to ExpectedSize(), but computes the minimum size of a \ * structure based on the process’ bitness, typically including enough of \ * a structure to contain its size field. This can be used prior to \ * reading any data from a process. */ \ static size_t MinimumSize(ProcessReaderMac* process_reader); #define PROCESS_TYPE_STRUCT_END(struct_name) \ private: \ /* The static form of Read(). Populates the struct at |generic|. */ \ static bool ReadInto(ProcessReaderMac* process_reader, \ mach_vm_address_t address, \ struct_name* generic); \ \ template \ static bool ReadIntoInternal(ProcessReaderMac* process_reader, \ mach_vm_address_t address, \ struct_name* generic); \ template \ static bool ReadArrayIntoInternal(ProcessReaderMac* process_reader, \ mach_vm_address_t address, \ size_t count, \ struct_name* generic); \ size_t size_; \ } \ ; \ } /* namespace process_types */ \ } /* namespace crashpad */ #include "snapshot/mac/process_types/all.proctype" #undef PROCESS_TYPE_STRUCT_BEGIN #undef PROCESS_TYPE_STRUCT_MEMBER #undef PROCESS_TYPE_STRUCT_VERSIONED #undef PROCESS_TYPE_STRUCT_SIZED #undef PROCESS_TYPE_STRUCT_END #undef PROCESS_TYPE_STRUCT_DECLARE // Declare the templatized crashpad::process_types::internal::struct_name<> // structs. These are the 32-bit and 64-bit specific structs that describe the // layout of objects in another process. This is repeated instead of being // shared with the generic declaration above because both the generic and // templatized specific structs need all of the struct members declared. // // GenericizeInto() translates a struct from the representation used in the // remote process into the generic form. #define PROCESS_TYPE_STRUCT_DECLARE_INTERNAL 1 #define PROCESS_TYPE_STRUCT_BEGIN(struct_name) \ namespace crashpad { \ namespace process_types { \ namespace internal { \ template \ struct struct_name { \ public: \ using Long = typename Traits::Long; \ using ULong = typename Traits::ULong; \ using Pointer = typename Traits::Pointer; \ using IntPtr = typename Traits::IntPtr; \ using UIntPtr = typename Traits::UIntPtr; \ using Reserved32_32Only = typename Traits::Reserved32_32Only; \ using Reserved32_64Only = typename Traits::Reserved32_64Only; \ using Reserved64_64Only = typename Traits::Reserved64_64Only; \ using Nothing = typename Traits::Nothing; \ \ /* Read(), ReadArrayInto(), and Size() are as in the generic user-visible \ * struct above. */ \ bool Read(ProcessReaderMac* process_reader, mach_vm_address_t address) { \ return ReadInto(process_reader, address, this); \ } \ static bool ReadArrayInto(ProcessReaderMac* process_reader, \ mach_vm_address_t address, \ size_t count, \ struct_name* specific); \ static size_t Size() { return sizeof(struct_name); } \ \ /* Translates a struct from the representation used in the remote process \ * into the generic form. */ \ void GenericizeInto(process_types::struct_name* generic, \ size_t* specific_size); #define PROCESS_TYPE_STRUCT_MEMBER(member_type, member_name, ...) \ member_type member_name __VA_ARGS__; #define PROCESS_TYPE_STRUCT_VERSIONED(struct_name, version_field) \ /* ExpectedSizeForVersion() is as in the generic user-visible struct \ * above. */ \ static size_t ExpectedSizeForVersion( \ decltype(struct_name::version_field) version); #define PROCESS_TYPE_STRUCT_SIZED(struct_name, size_field) \ /* MinimumSize() is as in the generic user-visible struct above. */ \ static size_t MinimumSize(); #define PROCESS_TYPE_STRUCT_END(struct_name) \ private: \ /* ReadInto() is as in the generic user-visible struct above. */ \ static bool ReadInto(ProcessReaderMac* process_reader, \ mach_vm_address_t address, \ struct_name* specific); \ } \ ; \ } /* namespace internal */ \ } /* namespace process_types */ \ } /* namespace crashpad */ #include "snapshot/mac/process_types/all.proctype" #undef PROCESS_TYPE_STRUCT_BEGIN #undef PROCESS_TYPE_STRUCT_MEMBER #undef PROCESS_TYPE_STRUCT_VERSIONED #undef PROCESS_TYPE_STRUCT_SIZED #undef PROCESS_TYPE_STRUCT_END #undef PROCESS_TYPE_STRUCT_DECLARE_INTERNAL #endif // CRASHPAD_SNAPSHOT_MAC_PROCESS_TYPES_H_