AutorÃa | Ultima modificación | Ver Log |
// Copyright 2019 Google//// 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.#include "Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDataParsing.h"#include "Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h"#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h"#include "Crashlytics/third_party/libunwind/dwarf.h"#include <string.h>#if CLS_DWARF_UNWINDING_SUPPORTEDuint8_t FIRCLSParseUint8AndAdvance(const void** cursor) {uint8_t tmp = **(uint8_t**)cursor;*cursor += sizeof(uint8_t);return tmp;}uint16_t FIRCLSParseUint16AndAdvance(const void** cursor) {uint16_t tmp = **(uint16_t**)cursor;*cursor += sizeof(uint16_t);return tmp;}int16_t FIRCLSParseInt16AndAdvance(const void** cursor) {int16_t tmp = **(int16_t**)cursor;*cursor += sizeof(int16_t);return tmp;}uint32_t FIRCLSParseUint32AndAdvance(const void** cursor) {uint32_t tmp = **(uint32_t**)cursor;*cursor += sizeof(uint32_t);return tmp;}int32_t FIRCLSParseInt32AndAdvance(const void** cursor) {int32_t tmp = **(int32_t**)cursor;*cursor += sizeof(int32_t);return tmp;}uint64_t FIRCLSParseUint64AndAdvance(const void** cursor) {uint64_t tmp = **(uint64_t**)cursor;*cursor += sizeof(uint64_t);return tmp;}int64_t FIRCLSParseInt64AndAdvance(const void** cursor) {int64_t tmp = **(int64_t**)cursor;*cursor += sizeof(int64_t);return tmp;}uintptr_t FIRCLSParsePointerAndAdvance(const void** cursor) {uintptr_t tmp = **(uintptr_t**)cursor;*cursor += sizeof(uintptr_t);return tmp;}// Signed and Unsigned LEB128 decoding algorithms taken from Wikipedia -// http://en.wikipedia.org/wiki/LEB128uint64_t FIRCLSParseULEB128AndAdvance(const void** cursor) {uint64_t result = 0;char shift = 0;for (int i = 0; i < sizeof(uint64_t); ++i) {char byte;byte = **(uint8_t**)cursor;*cursor += 1;result |= ((0x7F & byte) << shift);if ((0x80 & byte) == 0) {break;}shift += 7;}return result;}int64_t FIRCLSParseLEB128AndAdvance(const void** cursor) {uint64_t result = 0;char shift = 0;char size = sizeof(int64_t) * 8;char byte = 0;for (int i = 0; i < sizeof(uint64_t); ++i) {byte = **(uint8_t**)cursor;*cursor += 1;result |= ((0x7F & byte) << shift);shift += 7;/* sign bit of byte is second high order bit (0x40) */if ((0x80 & byte) == 0) {break;}}if ((shift < size) && (0x40 & byte)) {// sign extendresult |= -(1 << shift);}return result;}const char* FIRCLSParseStringAndAdvance(const void** cursor) {const char* string;string = (const char*)(*cursor);// strlen doesn't include the null character, which we need to advance past*cursor += strlen(string) + 1;return string;}uint64_t FIRCLSParseRecordLengthAndAdvance(const void** cursor) {uint64_t length;length = FIRCLSParseUint32AndAdvance(cursor);if (length == DWARF_EXTENDED_LENGTH_FLAG) {length = FIRCLSParseUint64AndAdvance(cursor);}return length;}uintptr_t FIRCLSParseAddressWithEncodingAndAdvance(const void** cursor, uint8_t encoding) {if (encoding == DW_EH_PE_omit) {return 0;}if (!cursor) {return CLS_INVALID_ADDRESS;}if (!*cursor) {return CLS_INVALID_ADDRESS;}intptr_t inputAddr = (intptr_t)*cursor;intptr_t addr;switch (encoding & DW_EH_PE_VALUE_MASK) {case DW_EH_PE_ptr:// 32 or 64 bitsaddr = FIRCLSParsePointerAndAdvance(cursor);break;case DW_EH_PE_uleb128:addr = (intptr_t)FIRCLSParseULEB128AndAdvance(cursor);break;case DW_EH_PE_udata2:addr = FIRCLSParseUint16AndAdvance(cursor);break;case DW_EH_PE_udata4:addr = FIRCLSParseUint32AndAdvance(cursor);break;case DW_EH_PE_udata8:addr = (intptr_t)FIRCLSParseUint64AndAdvance(cursor);break;case DW_EH_PE_sleb128:addr = (intptr_t)FIRCLSParseLEB128AndAdvance(cursor);break;case DW_EH_PE_sdata2:addr = FIRCLSParseInt16AndAdvance(cursor);break;case DW_EH_PE_sdata4:addr = FIRCLSParseInt32AndAdvance(cursor);break;case DW_EH_PE_sdata8:addr = (intptr_t)FIRCLSParseInt64AndAdvance(cursor);break;default:FIRCLSSDKLog("Unhandled: encoding 0x%02x\n", encoding);return CLS_INVALID_ADDRESS;}// and now apply the relative offsetswitch (encoding & DW_EH_PE_RELATIVE_OFFSET_MASK) {case DW_EH_PE_absptr:break;case DW_EH_PE_pcrel:addr += inputAddr;break;default:FIRCLSSDKLog("Unhandled: relative encoding 0x%02x\n", encoding);return CLS_INVALID_ADDRESS;}// Here's a crazy one. It seems this encoding means you actually look up// the value of the address using the result address itselfif (encoding & DW_EH_PE_indirect) {if (!addr) {return CLS_INVALID_ADDRESS;}addr = *(uintptr_t*)addr;}return addr;}#elseINJECT_STRIP_SYMBOL(data_parsing)#endif