mirror of
https://github.com/microsoft/plcrashreporter.git
synced 2026-01-18 04:01:18 +01:00
Adding a parser for DWARF EH LSDA records.
This currently is not async-safe due to the use of std::vector. Once a suitable async-safe data type is available, it should be switched over. Additionally, the use of vector has forced the iOS demo app to link against libstdc++. This seems far from ideal and should be fixed. Issue: PLCR-561
This commit is contained in:
@@ -804,6 +804,18 @@
|
||||
C26022901642FE9B007FC29F /* PLCrashAsyncSymbolicationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C260228F1642FE9B007FC29F /* PLCrashAsyncSymbolicationTests.m */; };
|
||||
C26022911642FE9B007FC29F /* PLCrashAsyncSymbolicationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C260228F1642FE9B007FC29F /* PLCrashAsyncSymbolicationTests.m */; };
|
||||
C26022921642FE9B007FC29F /* PLCrashAsyncSymbolicationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C260228F1642FE9B007FC29F /* PLCrashAsyncSymbolicationTests.m */; };
|
||||
D81ACF0F1AB795D4001590A9 /* PLCrashDwarfLSDATests.mm in Sources */ = {isa = PBXBuildFile; fileRef = D81ACF0E1AB795CE001590A9 /* PLCrashDwarfLSDATests.mm */; };
|
||||
D81ACF101AB795D4001590A9 /* PLCrashDwarfLSDATests.mm in Sources */ = {isa = PBXBuildFile; fileRef = D81ACF0E1AB795CE001590A9 /* PLCrashDwarfLSDATests.mm */; };
|
||||
D81ACF111AB795D5001590A9 /* PLCrashDwarfLSDATests.mm in Sources */ = {isa = PBXBuildFile; fileRef = D81ACF0E1AB795CE001590A9 /* PLCrashDwarfLSDATests.mm */; };
|
||||
D81ACF121AB795FF001590A9 /* PLCrashDwarfLSDA.hpp in Headers */ = {isa = PBXBuildFile; fileRef = D81ACF0D1AB795CE001590A9 /* PLCrashDwarfLSDA.hpp */; };
|
||||
D81ACF131AB79600001590A9 /* PLCrashDwarfLSDA.hpp in Headers */ = {isa = PBXBuildFile; fileRef = D81ACF0D1AB795CE001590A9 /* PLCrashDwarfLSDA.hpp */; };
|
||||
D81ACF141AB79610001590A9 /* PLCrashDwarfLSDA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D81ACF0C1AB795CE001590A9 /* PLCrashDwarfLSDA.cpp */; };
|
||||
D81ACF151AB79611001590A9 /* PLCrashDwarfLSDA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D81ACF0C1AB795CE001590A9 /* PLCrashDwarfLSDA.cpp */; };
|
||||
D81ACF161AB79613001590A9 /* PLCrashDwarfLSDA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D81ACF0C1AB795CE001590A9 /* PLCrashDwarfLSDA.cpp */; };
|
||||
D81ACF171AB79614001590A9 /* PLCrashDwarfLSDA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D81ACF0C1AB795CE001590A9 /* PLCrashDwarfLSDA.cpp */; };
|
||||
D81ACF181AB79614001590A9 /* PLCrashDwarfLSDA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D81ACF0C1AB795CE001590A9 /* PLCrashDwarfLSDA.cpp */; };
|
||||
D81ACF191AB79615001590A9 /* PLCrashDwarfLSDA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D81ACF0C1AB795CE001590A9 /* PLCrashDwarfLSDA.cpp */; };
|
||||
D81ACF1A1AB79616001590A9 /* PLCrashDwarfLSDA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D81ACF0C1AB795CE001590A9 /* PLCrashDwarfLSDA.cpp */; };
|
||||
FCE45210FDD184E397747BE3 /* PLCrashFrameStackUnwind.h in Headers */ = {isa = PBXBuildFile; fileRef = FCE4522F86AC61C08E9DCC17 /* PLCrashFrameStackUnwind.h */; };
|
||||
FCE4550BA74D9DF923CFCD5A /* PLCrashFrameStackUnwind.c in Sources */ = {isa = PBXBuildFile; fileRef = FCE45837C8C773EFFD15C52B /* PLCrashFrameStackUnwind.c */; };
|
||||
FCE4566DF9168DCC484928E1 /* PLCrashFrameStackUnwind.c in Sources */ = {isa = PBXBuildFile; fileRef = FCE45837C8C773EFFD15C52B /* PLCrashFrameStackUnwind.c */; };
|
||||
@@ -1346,6 +1358,9 @@
|
||||
C26022851642FCA6007FC29F /* PLCrashAsyncSymbolication.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = PLCrashAsyncSymbolication.c; sourceTree = "<group>"; };
|
||||
C260228D1642FCAF007FC29F /* PLCrashAsyncSymbolication.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PLCrashAsyncSymbolication.h; sourceTree = "<group>"; };
|
||||
C260228F1642FE9B007FC29F /* PLCrashAsyncSymbolicationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PLCrashAsyncSymbolicationTests.m; sourceTree = "<group>"; };
|
||||
D81ACF0C1AB795CE001590A9 /* PLCrashDwarfLSDA.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PLCrashDwarfLSDA.cpp; sourceTree = "<group>"; };
|
||||
D81ACF0D1AB795CE001590A9 /* PLCrashDwarfLSDA.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = PLCrashDwarfLSDA.hpp; sourceTree = "<group>"; };
|
||||
D81ACF0E1AB795CE001590A9 /* PLCrashDwarfLSDATests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PLCrashDwarfLSDATests.mm; sourceTree = "<group>"; };
|
||||
FCE4522F86AC61C08E9DCC17 /* PLCrashFrameStackUnwind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PLCrashFrameStackUnwind.h; sourceTree = "<group>"; };
|
||||
FCE45837C8C773EFFD15C52B /* PLCrashFrameStackUnwind.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = PLCrashFrameStackUnwind.c; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
@@ -1945,6 +1960,9 @@
|
||||
05E7483D175A384C009B8745 /* Decoding */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D81ACF0D1AB795CE001590A9 /* PLCrashDwarfLSDA.hpp */,
|
||||
D81ACF0C1AB795CE001590A9 /* PLCrashDwarfLSDA.cpp */,
|
||||
D81ACF0E1AB795CE001590A9 /* PLCrashDwarfLSDATests.mm */,
|
||||
05E7486E1760D8AE009B8745 /* PLCrashAsyncDwarfCIE.hpp */,
|
||||
05E748661760D890009B8745 /* PLCrashAsyncDwarfCIE.cpp */,
|
||||
05E748711760DBBE009B8745 /* PLCrashAsyncDwarfCIETests.mm */,
|
||||
@@ -2196,6 +2214,7 @@
|
||||
054627AD11D998BB007891C7 /* PLCrashReportTextFormatter.h in Headers */,
|
||||
054627BD11D99D06007891C7 /* PLCrashReportFormatter.h in Headers */,
|
||||
05771CE313683EDD001DE4B1 /* PLCrashReportMachineInfo.h in Headers */,
|
||||
D81ACF131AB79600001590A9 /* PLCrashDwarfLSDA.hpp in Headers */,
|
||||
05771CE213683ED4001DE4B1 /* PLCrashReportProcessorInfo.h in Headers */,
|
||||
05DEE6491636E642007E99DC /* PLCrashAsyncMObject.h in Headers */,
|
||||
05D8FE5516ACAA81000ED70C /* PLCrashAsyncAllocator.h in Headers */,
|
||||
@@ -2345,6 +2364,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
05CD318B0EE93A90000FDE88 /* CrashReporter.h in Headers */,
|
||||
D81ACF121AB795FF001590A9 /* PLCrashDwarfLSDA.hpp in Headers */,
|
||||
05A04D8C15AB38C10011CFA4 /* PLCrashNamespace.h in Headers */,
|
||||
05A5E28117A82751008A75E5 /* PLCrashMacros.h in Headers */,
|
||||
05CD33A00EE948EB000FDE88 /* PLCrashSignalHandler.h in Headers */,
|
||||
@@ -2904,6 +2924,7 @@
|
||||
05A17DF316DBD0AD00888448 /* PLCrashAsyncThread_x86.c in Sources */,
|
||||
05A17DF816DBD0C200888448 /* PLCrashAsyncThread_arm.c in Sources */,
|
||||
05F3CD6216DD6A3B007911FB /* PLCrashFrameCompactUnwind.c in Sources */,
|
||||
D81ACF1A1AB79616001590A9 /* PLCrashDwarfLSDA.cpp in Sources */,
|
||||
05F3CD7A16DFC744007911FB /* PLCrashAsyncCompactUnwindEncoding.c in Sources */,
|
||||
05E7484F175E5349009B8745 /* PLCrashAsyncDwarfPrimitives.cpp in Sources */,
|
||||
05E748611760D64D009B8745 /* PLCrashAsyncDwarfFDE.cpp in Sources */,
|
||||
@@ -2973,6 +2994,7 @@
|
||||
05A17DF416DBD0AD00888448 /* PLCrashAsyncThread_x86.c in Sources */,
|
||||
05A17DF916DBD0C200888448 /* PLCrashAsyncThread_arm.c in Sources */,
|
||||
05F3CD6316DD6A3B007911FB /* PLCrashFrameCompactUnwind.c in Sources */,
|
||||
D81ACF191AB79615001590A9 /* PLCrashDwarfLSDA.cpp in Sources */,
|
||||
05F3CD7B16DFC744007911FB /* PLCrashAsyncCompactUnwindEncoding.c in Sources */,
|
||||
057DCA18179C613200BDC648 /* PLCrashAsyncDwarfEncoding.cpp in Sources */,
|
||||
05E74850175E5349009B8745 /* PLCrashAsyncDwarfPrimitives.cpp in Sources */,
|
||||
@@ -3037,6 +3059,7 @@
|
||||
052951EF1696A461006EDA8A /* PLCrashLogWriterEncodingTests.proto in Sources */,
|
||||
05D8FE5016ACAA6E000ED70C /* PLCrashAsyncAllocator.c in Sources */,
|
||||
05D8FE5816ACC8CD000ED70C /* PLCrashAsyncAllocatorTests.m in Sources */,
|
||||
D81ACF0F1AB795D4001590A9 /* PLCrashDwarfLSDATests.mm in Sources */,
|
||||
05A533DE16D6ACBF00C5E2B3 /* PLCrashFrameStackUnwindTests.m in Sources */,
|
||||
05A17DB816D7E36400888448 /* PLCrashFrameStackUnwind.c in Sources */,
|
||||
05A17DC916D7F81600888448 /* PLCrashAsyncThread.c in Sources */,
|
||||
@@ -3083,6 +3106,7 @@
|
||||
05507A531784DEE4009D5168 /* unwind_test_x86_frame.S in Sources */,
|
||||
05C5880E1788CAA400BA118D /* unwind_test_x86_frameless.S in Sources */,
|
||||
05C588121788F36800BA118D /* unwind_test_x86_frameless_big.S in Sources */,
|
||||
D81ACF161AB79613001590A9 /* PLCrashDwarfLSDA.cpp in Sources */,
|
||||
05C588161788F3E700BA118D /* unwind_test_x86_unusual.S in Sources */,
|
||||
05C5881A1788F48500BA118D /* unwind_test_x86_disable_compact_frame.S in Sources */,
|
||||
05920D36178B310A001E8975 /* unwind_test_arm.S in Sources */,
|
||||
@@ -3127,6 +3151,7 @@
|
||||
05EB2B1D15B6FE2A0066EB4D /* PLCrashReporterNSErrorTests.m in Sources */,
|
||||
05F76DDF16305A7000A668C7 /* PLCrashAsyncMachOImage.c in Sources */,
|
||||
05F76DDB162F238E00A668C7 /* PLCrashAsyncMachOImageTests.m in Sources */,
|
||||
D81ACF101AB795D4001590A9 /* PLCrashDwarfLSDATests.mm in Sources */,
|
||||
05DEE6441636E62B007E99DC /* PLCrashAsyncMObject.c in Sources */,
|
||||
05DEE64C1636E721007E99DC /* PLCrashAsyncMObjectTests.m in Sources */,
|
||||
C2198DDE1640188C006EB46A /* PLCrashAsyncObjCSection.cpp in Sources */,
|
||||
@@ -3152,6 +3177,7 @@
|
||||
05F3CD8216DFC78D007911FB /* PLCrashAsyncCompactUnwindEncodingTests.m in Sources */,
|
||||
05659DF317456A4000D2EE21 /* PLCrashAsyncDwarfEncodingTests.mm in Sources */,
|
||||
05A17DCA16D7F81600888448 /* PLCrashAsyncThread.c in Sources */,
|
||||
D81ACF171AB79614001590A9 /* PLCrashDwarfLSDA.cpp in Sources */,
|
||||
0518E0A7174BF82500BB47DE /* PLCrashAsyncThread_arm.c in Sources */,
|
||||
0518E0A6174BF82300BB47DE /* PLCrashAsyncThread_x86.c in Sources */,
|
||||
05659DFA174D2E1200D2EE21 /* PLCrashTestCase.m in Sources */,
|
||||
@@ -3242,6 +3268,7 @@
|
||||
052951F11696A461006EDA8A /* PLCrashLogWriterEncodingTests.proto in Sources */,
|
||||
058484AE1804841100A56049 /* unwind_test_arm64_frameless.S in Sources */,
|
||||
05D8FE5216ACAA6E000ED70C /* PLCrashAsyncAllocator.c in Sources */,
|
||||
D81ACF111AB795D5001590A9 /* PLCrashDwarfLSDATests.mm in Sources */,
|
||||
05D8FE5A16ACC8CD000ED70C /* PLCrashAsyncAllocatorTests.m in Sources */,
|
||||
05A533E016D6ACBF00C5E2B3 /* PLCrashFrameStackUnwindTests.m in Sources */,
|
||||
05A17DBA16D7E37100888448 /* PLCrashFrameStackUnwind.c in Sources */,
|
||||
@@ -3288,6 +3315,7 @@
|
||||
05507A511784DA8A009D5168 /* unwind_test_x86_64_unusual.S in Sources */,
|
||||
05507A551784DEE4009D5168 /* unwind_test_x86_frame.S in Sources */,
|
||||
05C588101788CAA400BA118D /* unwind_test_x86_frameless.S in Sources */,
|
||||
D81ACF181AB79614001590A9 /* PLCrashDwarfLSDA.cpp in Sources */,
|
||||
05C588141788F36800BA118D /* unwind_test_x86_frameless_big.S in Sources */,
|
||||
05C588181788F3E700BA118D /* unwind_test_x86_unusual.S in Sources */,
|
||||
05C5881C1788F48500BA118D /* unwind_test_x86_disable_compact_frame.S in Sources */,
|
||||
@@ -3358,6 +3386,7 @@
|
||||
05A17DC516D7F81600888448 /* PLCrashAsyncThread.c in Sources */,
|
||||
05A17DF116DBD0AD00888448 /* PLCrashAsyncThread_x86.c in Sources */,
|
||||
05A17DF616DBD0C200888448 /* PLCrashAsyncThread_arm.c in Sources */,
|
||||
D81ACF151AB79611001590A9 /* PLCrashDwarfLSDA.cpp in Sources */,
|
||||
05F3CD6016DD6A3B007911FB /* PLCrashFrameCompactUnwind.c in Sources */,
|
||||
05F3CD7816DFC744007911FB /* PLCrashAsyncCompactUnwindEncoding.c in Sources */,
|
||||
05E7484D175E5349009B8745 /* PLCrashAsyncDwarfPrimitives.cpp in Sources */,
|
||||
@@ -3436,6 +3465,7 @@
|
||||
05A17DC616D7F81600888448 /* PLCrashAsyncThread.c in Sources */,
|
||||
05A17DF216DBD0AD00888448 /* PLCrashAsyncThread_x86.c in Sources */,
|
||||
05A17DF716DBD0C200888448 /* PLCrashAsyncThread_arm.c in Sources */,
|
||||
D81ACF141AB79610001590A9 /* PLCrashDwarfLSDA.cpp in Sources */,
|
||||
05F3CD6116DD6A3B007911FB /* PLCrashFrameCompactUnwind.c in Sources */,
|
||||
05F3CD7916DFC744007911FB /* PLCrashAsyncCompactUnwindEncoding.c in Sources */,
|
||||
05659DEE17455DED00D2EE21 /* PLCrashAsyncDwarfEncoding.cpp in Sources */,
|
||||
@@ -3669,6 +3699,7 @@
|
||||
Foundation,
|
||||
"-framework",
|
||||
UIKit,
|
||||
"-lstdc++",
|
||||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = iphoneos;
|
||||
@@ -3696,6 +3727,7 @@
|
||||
Foundation,
|
||||
"-framework",
|
||||
UIKit,
|
||||
"-lstdc++",
|
||||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = iphoneos;
|
||||
|
||||
312
Source/PLCrashDwarfLSDA.cpp
Normal file
312
Source/PLCrashDwarfLSDA.cpp
Normal file
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
* Author: Joe Ranieri <joe@alacatialabs.com>
|
||||
*
|
||||
* Copyright (c) 2015 Plausible Labs Cooperative, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "PLCrashDwarfLSDA.hpp"
|
||||
#include "PLCrashAsyncDwarfPrimitives.hpp"
|
||||
|
||||
#if PLCRASH_FEATURE_UNWIND_DWARF
|
||||
|
||||
using namespace plcrash;
|
||||
using namespace plcrash::async;
|
||||
|
||||
/**
|
||||
* Determines how many bytes are required by a given DWARF pointer encoding.
|
||||
*/
|
||||
template <typename machine_ptr>
|
||||
static plcrash_error_t dwarf_encoding_size (uint8_t encoding, uint8_t *size)
|
||||
{
|
||||
if (encoding == DW_EH_PE::DW_EH_PE_omit) {
|
||||
*size = 0;
|
||||
return PLCRASH_ESUCCESS;
|
||||
}
|
||||
|
||||
switch (encoding & 0x0F) {
|
||||
case DW_EH_PE::DW_EH_PE_absptr:
|
||||
*size = sizeof(machine_ptr);
|
||||
return PLCRASH_ESUCCESS;
|
||||
case DW_EH_PE::DW_EH_PE_udata2:
|
||||
*size = sizeof(uint16_t);
|
||||
return PLCRASH_ESUCCESS;
|
||||
case DW_EH_PE::DW_EH_PE_udata4:
|
||||
*size = sizeof(uint32_t);
|
||||
return PLCRASH_ESUCCESS;
|
||||
case DW_EH_PE::DW_EH_PE_udata8:
|
||||
*size = sizeof(uint64_t);
|
||||
return PLCRASH_ESUCCESS;
|
||||
case DW_EH_PE::DW_EH_PE_sdata2:
|
||||
*size = sizeof(int16_t);
|
||||
return PLCRASH_ESUCCESS;
|
||||
case DW_EH_PE::DW_EH_PE_sdata4:
|
||||
*size = sizeof(int32_t);
|
||||
return PLCRASH_ESUCCESS;
|
||||
case DW_EH_PE::DW_EH_PE_sdata8:
|
||||
*size = sizeof(int64_t);
|
||||
return PLCRASH_ESUCCESS;
|
||||
default:
|
||||
return PLCRASH_EINVALID_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes all of the action records associated with a single callsite.
|
||||
*/
|
||||
template <typename machine_ptr>
|
||||
static plcrash_error_t read_action_table (plcrash_async_mobject_t *mobj,
|
||||
pl_vm_address_t first,
|
||||
std::vector<dwarf_lsda_action_record> &result,
|
||||
gnu_ehptr_reader<machine_ptr> *ptr_reader,
|
||||
pl_vm_address_t ttype_base,
|
||||
DW_EH_PE ttype_encoding)
|
||||
{
|
||||
plcrash_error_t err = PLCRASH_ESUCCESS;
|
||||
|
||||
/* All items in the types table have the same encoding and length, allowing
|
||||
* random access into it. */
|
||||
uint8_t ttype_size;
|
||||
if ((err = dwarf_encoding_size<machine_ptr>(ttype_encoding, &ttype_size)) != PLCRASH_ESUCCESS) {
|
||||
PLCF_DEBUG("Invalid ttype_encoding in LSDA: %i", ttype_encoding);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Each action record is a type filter and the relative offset to the next
|
||||
* action record. An offset of zero means there are no more records. */
|
||||
pl_vm_address_t address = first;
|
||||
while (true) {
|
||||
pl_vm_off_t offset = 0;
|
||||
pl_vm_size_t size = 0;
|
||||
|
||||
int64_t filter;
|
||||
if ((err = plcrash_async_dwarf_read_sleb128(mobj, address, offset, &filter, &size)) != PLCRASH_ESUCCESS) {
|
||||
PLCF_DEBUG("Failed to read action record filter");
|
||||
return err;
|
||||
}
|
||||
offset += size;
|
||||
|
||||
int64_t next_offset;
|
||||
if ((err = plcrash_async_dwarf_read_sleb128(mobj, address, offset, &next_offset, &size)) != PLCRASH_ESUCCESS) {
|
||||
PLCF_DEBUG("Failed to read action record offset");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* If the filter is positive, this represents a simple catch. If the
|
||||
* filter is negative, it's an exception specification which can have
|
||||
* an arbitrary number of types. */
|
||||
dwarf_lsda_action_record action;
|
||||
if (filter > 0) {
|
||||
machine_ptr type_info = 0;
|
||||
if ((err = ptr_reader->read(mobj, ttype_base - (filter * ttype_size), 0, ttype_encoding, &type_info, &size)) != PLCRASH_ESUCCESS) {
|
||||
PLCF_DEBUG("Failed to dereference type info (filter = %lli)", filter);
|
||||
return err;
|
||||
}
|
||||
action.kind = DWARF_LSDA_ACTION_KIND_CATCH;
|
||||
action.types.push_back(type_info);
|
||||
} else {
|
||||
/* The exception specification type indexes list is a series of
|
||||
* uleb128s that is terminated by 0. The filter we're given is a
|
||||
* byte offset into the table (not an index). */
|
||||
pl_vm_off_t spec_offset = -filter - 1;
|
||||
action.kind = DWARF_LSDA_ACTION_KIND_EXCEPTION_SPECIFICATION;
|
||||
while (true) {
|
||||
uint64_t filter_index;
|
||||
if ((err = plcrash_async_dwarf_read_uleb128(mobj, ttype_base, spec_offset, &filter_index, &size)) != PLCRASH_ESUCCESS) {
|
||||
PLCF_DEBUG("Failed to read action record filter");
|
||||
return err;
|
||||
}
|
||||
spec_offset += size;
|
||||
|
||||
if (filter_index == 0)
|
||||
break;
|
||||
|
||||
machine_ptr type_info = 0;
|
||||
if ((err = ptr_reader->read(mobj, ttype_base - (filter_index * ttype_size), 0, ttype_encoding, &type_info, &size)) != PLCRASH_ESUCCESS) {
|
||||
PLCF_DEBUG("Failed to dereference type info (filter = %lli)", filter_index);
|
||||
return err;
|
||||
}
|
||||
action.types.push_back(type_info);
|
||||
}
|
||||
}
|
||||
result.push_back(action);
|
||||
|
||||
if (next_offset == 0)
|
||||
break;
|
||||
address = address + offset + next_offset;
|
||||
}
|
||||
|
||||
return PLCRASH_ESUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode LSDA info at target-relative @a address.
|
||||
*
|
||||
* Any resources held by a successfully initialized instance must be freed via
|
||||
* plcrash_async_dwarf_lsda_info_free();
|
||||
*
|
||||
* @param info The LSDA record to be initialized.
|
||||
* @param mobj The memory object containing the LSDA at the start address.
|
||||
* @param byteorder The byte order of the data referenced by @a mobj.
|
||||
* @param address The target-relative address containing the LSDA info to be
|
||||
* decoded.
|
||||
*/
|
||||
template <typename machine_ptr>
|
||||
plcrash_error_t plcrash::dwarf_lsda_info_init (dwarf_lsda_info_t *info,
|
||||
plcrash_async_mobject_t *mobj,
|
||||
const plcrash_async_byteorder_t *byteorder,
|
||||
pl_vm_address_t address)
|
||||
{
|
||||
plcrash_error_t err;
|
||||
pl_vm_size_t size;
|
||||
pl_vm_off_t offset = 0;
|
||||
gnu_ehptr_reader<machine_ptr> ptr_reader(byteorder);
|
||||
|
||||
DW_EH_PE lp_start_encoding = DW_EH_PE_omit;
|
||||
if ((err = plcrash_async_mobject_read_uint8(mobj, address, offset, (uint8_t *)&lp_start_encoding)) != PLCRASH_ESUCCESS) {
|
||||
PLCF_DEBUG("Invalid lp_start_encoding in lsda");
|
||||
return err;
|
||||
}
|
||||
offset += 1;
|
||||
|
||||
if (lp_start_encoding != DW_EH_PE_omit) {
|
||||
machine_ptr ptr = 0;
|
||||
if ((err = ptr_reader.read(mobj, address, offset, lp_start_encoding, &ptr, &size)) != PLCRASH_ESUCCESS) {
|
||||
PLCF_DEBUG("Couldn't read lp_start (encoding %i)", lp_start_encoding);
|
||||
return err;
|
||||
}
|
||||
info->has_lp_start = true;
|
||||
info->lp_start = ptr;
|
||||
offset += size;
|
||||
} else {
|
||||
info->has_lp_start = false;
|
||||
info->lp_start = 0;
|
||||
}
|
||||
|
||||
DW_EH_PE ttype_encoding = DW_EH_PE_omit;
|
||||
if ((err = plcrash_async_mobject_read_uint8(mobj, address, offset, (uint8_t *)&ttype_encoding)) != PLCRASH_ESUCCESS) {
|
||||
PLCF_DEBUG("Couldn't read ttype_encoding");
|
||||
return err;
|
||||
}
|
||||
offset += 1;
|
||||
|
||||
pl_vm_address_t ttype_base = 0;
|
||||
if (ttype_encoding != DW_EH_PE_omit) {
|
||||
uint64_t ttypeOffset = 0;
|
||||
if ((err = plcrash_async_dwarf_read_uleb128(mobj, address, offset, &ttypeOffset, &size)) != PLCRASH_ESUCCESS) {
|
||||
PLCF_DEBUG("Couldn't read ttype_base");
|
||||
return err;
|
||||
}
|
||||
offset += size;
|
||||
ttype_base = address + offset + ttypeOffset;
|
||||
}
|
||||
|
||||
DW_EH_PE call_site_encoding = DW_EH_PE_omit;
|
||||
if ((err = plcrash_async_mobject_read_uint8(mobj, address, offset, (uint8_t *)&call_site_encoding)) != PLCRASH_ESUCCESS) {
|
||||
PLCF_DEBUG("Couldn't read call_site_encoding");
|
||||
return err;
|
||||
}
|
||||
offset += 1;
|
||||
|
||||
uint64_t call_site_table_length = 0;
|
||||
if ((err = plcrash_async_dwarf_read_uleb128(mobj, address, offset, &call_site_table_length, &size)) != PLCRASH_ESUCCESS) {
|
||||
PLCF_DEBUG("Couldn't read call_site_table_length");
|
||||
return err;
|
||||
}
|
||||
offset += size;
|
||||
|
||||
/* After all of that header information is the callsite table, which encodes
|
||||
* what should happen for ranges of code in the function. We do not know
|
||||
* how many items are in it, but we do know its total length. */
|
||||
uint64_t call_site_start = offset;
|
||||
while (offset - call_site_start < call_site_table_length) {
|
||||
dwarf_lsda_callsite_info_t callsite;
|
||||
|
||||
machine_ptr ptr = 0;
|
||||
if ((err = ptr_reader.read(mobj, address, offset, call_site_encoding, &ptr, &size)) != PLCRASH_ESUCCESS) {
|
||||
PLCF_DEBUG("Couldn't read call site's start");
|
||||
return err;
|
||||
}
|
||||
/* Despite what the spec says, this pointer appears to be relative to
|
||||
* the start of the function and not the previous callsite. */
|
||||
callsite.start = ptr;
|
||||
offset += size;
|
||||
|
||||
if ((err = ptr_reader.read(mobj, address, offset, call_site_encoding, &ptr, &size)) != PLCRASH_ESUCCESS) {
|
||||
PLCF_DEBUG("Couldn't read call site's length");
|
||||
return err;
|
||||
}
|
||||
callsite.length = ptr;
|
||||
offset += size;
|
||||
|
||||
if ((err = ptr_reader.read(mobj, address, offset, call_site_encoding, &ptr, &size)) != PLCRASH_ESUCCESS) {
|
||||
PLCF_DEBUG("Couldn't read call site's landing pad offset");
|
||||
return err;
|
||||
}
|
||||
callsite.landing_pad_offset = ptr;
|
||||
offset += size;
|
||||
|
||||
uint8_t action = 0;
|
||||
if ((err = plcrash_async_mobject_read_uint8(mobj, address, offset, &action)) != PLCRASH_ESUCCESS) {
|
||||
PLCF_DEBUG("Couldn't read call site's action");
|
||||
return err;
|
||||
}
|
||||
offset += 1;
|
||||
|
||||
/* The action is a 1-based index into the actions table. If the value is
|
||||
* zero and the landing pad is zero, the range of code is assumed not
|
||||
* to throw. If the value is zero and there is a landing pad, this is
|
||||
* a cleanup. */
|
||||
if (action > 0) {
|
||||
pl_vm_address_t action_table = address + call_site_start + call_site_table_length;
|
||||
err = read_action_table(mobj, action_table + action - 1, callsite.actions, &ptr_reader, ttype_base, ttype_encoding);
|
||||
if (err != PLCRASH_ESUCCESS)
|
||||
return err;
|
||||
}
|
||||
|
||||
info->callsites.push_back(callsite);
|
||||
}
|
||||
|
||||
return PLCRASH_ESUCCESS;
|
||||
}
|
||||
|
||||
void plcrash::dwarf_lsda_info_free (dwarf_lsda_info_t *info)
|
||||
{
|
||||
/* All resources will automatically be freed by the destructor. */
|
||||
}
|
||||
|
||||
namespace plcrash {
|
||||
template
|
||||
plcrash_error_t dwarf_lsda_info_init<uint32_t> (dwarf_lsda_info_t *info,
|
||||
plcrash_async_mobject_t *mobj,
|
||||
const plcrash_async_byteorder_t *byteorder,
|
||||
pl_vm_address_t address);
|
||||
template
|
||||
plcrash_error_t dwarf_lsda_info_init<uint64_t> (dwarf_lsda_info_t *info,
|
||||
plcrash_async_mobject_t *mobj,
|
||||
const plcrash_async_byteorder_t *byteorder,
|
||||
pl_vm_address_t address);
|
||||
}
|
||||
|
||||
#endif /* PLCRASH_FEATURE_UNWIND_DWARF */
|
||||
125
Source/PLCrashDwarfLSDA.hpp
Normal file
125
Source/PLCrashDwarfLSDA.hpp
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Author: Joe Ranieri <joe@alacatialabs.com>
|
||||
*
|
||||
* Copyright (c) 2015 Plausible Labs Cooperative, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef PLCRASH_ASYNC_DWARF_LSDA_H
|
||||
#define PLCRASH_ASYNC_DWARF_LSDA_H
|
||||
|
||||
#include "PLCrashAsync.h"
|
||||
#include "PLCrashAsyncMObject.h"
|
||||
#include "PLCrashAsyncDwarfPrimitives.hpp"
|
||||
#include "PLCrashFeatureConfig.h"
|
||||
#include <vector>
|
||||
|
||||
#if PLCRASH_FEATURE_UNWIND_DWARF
|
||||
|
||||
namespace plcrash {
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @ingroup plcrash_async_dwarf
|
||||
* @{
|
||||
*/
|
||||
|
||||
struct dwarf_lsda_callsite_info;
|
||||
struct dwarf_lsda_action_record;
|
||||
|
||||
/**
|
||||
* A DWARF Language Specific Data Area (LSDA) record. This describes how to
|
||||
* handle exceptions within a function.
|
||||
*/
|
||||
typedef struct dwarf_lsda_info {
|
||||
/** Is the lp_start field present in the LSDA? */
|
||||
bool has_lp_start;
|
||||
/**
|
||||
* The address that all landing pads described by the LSDA are relative to.
|
||||
* If this field is absent, landing pads are relative to the beginning of
|
||||
* the function.
|
||||
*/
|
||||
uintptr_t lp_start;
|
||||
|
||||
std::vector<dwarf_lsda_callsite_info> callsites;
|
||||
} dwarf_lsda_info_t;
|
||||
|
||||
/**
|
||||
* A DWARF exception handling callsite record. This represents a range of code
|
||||
* in a function and describes where to jump if an exception is raised in that
|
||||
* range.
|
||||
*/
|
||||
typedef struct dwarf_lsda_callsite_info {
|
||||
/** The byte offset from the start of the function for this range. */
|
||||
pl_vm_address_t start;
|
||||
/** The number of bytes this range covers. */
|
||||
pl_vm_off_t length;
|
||||
/**
|
||||
* The offset to the landing pad in bytes, measured from the start of the
|
||||
* function or, if specified, the lp_start field in the lsda header.
|
||||
*/
|
||||
pl_vm_off_t landing_pad_offset;
|
||||
/**
|
||||
* A collection of actions that the personality function will use to
|
||||
* dispatch the exception or perform validation.
|
||||
*/
|
||||
std::vector<dwarf_lsda_action_record> actions;
|
||||
} dwarf_lsda_callsite_info_t;
|
||||
|
||||
typedef enum {
|
||||
DWARF_LSDA_ACTION_KIND_CATCH,
|
||||
DWARF_LSDA_ACTION_KIND_EXCEPTION_SPECIFICATION
|
||||
} dwarf_lsda_action_kind_t;
|
||||
|
||||
/**
|
||||
* A DWARF Exception handling action record. This describes either a type that
|
||||
* can be caught or a set of types that is allowed to be thrown.
|
||||
*/
|
||||
typedef struct dwarf_lsda_action_record {
|
||||
dwarf_lsda_action_kind_t kind;
|
||||
/**
|
||||
* The type information that this action matches against. For catch actions,
|
||||
* this is the type that can be caught and will have one item. For
|
||||
* exception specifications, this will be all of the types that the code is
|
||||
* allowed to throw.
|
||||
*/
|
||||
std::vector<pl_vm_address_t> types;
|
||||
} dwarf_lsda_action_record_t;
|
||||
|
||||
template <typename machine_ptr>
|
||||
plcrash_error_t dwarf_lsda_info_init (dwarf_lsda_info_t *info,
|
||||
plcrash_async_mobject_t *mobj,
|
||||
const plcrash_async_byteorder_t *byteorder,
|
||||
pl_vm_address_t address);
|
||||
|
||||
void dwarf_lsda_info_free (dwarf_lsda_info_t *info);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* defined(PLCRASH_ASYNC_DWARF_LSDA_H) */
|
||||
216
Source/PLCrashDwarfLSDATests.mm
Normal file
216
Source/PLCrashDwarfLSDATests.mm
Normal file
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Author: Joe Ranieri <joe@alacatialabs.com>
|
||||
*
|
||||
* Copyright (c) 2015 Plausible Labs Cooperative, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#import "PLCrashTestCase.h"
|
||||
#include "PLCrashDwarfLSDA.hpp"
|
||||
#include "PLCrashFeatureConfig.h"
|
||||
|
||||
#ifdef try
|
||||
#undef try
|
||||
#endif
|
||||
#ifdef catch
|
||||
#undef catch
|
||||
#endif
|
||||
|
||||
#if PLCRASH_FEATURE_UNWIND_DWARF
|
||||
|
||||
using namespace plcrash;
|
||||
using namespace plcrash::async;
|
||||
|
||||
@interface PLCrashAsyncDwarfLSDATests : PLCrashTestCase {
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation PLCrashAsyncDwarfLSDATests
|
||||
|
||||
- (void) setUp {
|
||||
}
|
||||
|
||||
- (void) tearDown {
|
||||
}
|
||||
|
||||
- (void) testSimpleCleanup {
|
||||
static const uint8_t lsda[] = {
|
||||
0xff, // @LPStart Encoding = omit
|
||||
0x9b, // @TType Encoding = indirect pcrel sdata4
|
||||
0x29, // @TType base offset
|
||||
0x03, // Call site Encoding = udata4
|
||||
0x0d, // Call site table length
|
||||
// >> Call Site 1 <<
|
||||
0x00, 0x00, 0x00, 0x00, //
|
||||
0xa2, 0x00, 0x00, 0x00, // Call between Leh_func_begin0 and Ltmp0
|
||||
0x00, 0x00, 0x00, 0x00, // has no landing pad
|
||||
0x00, // On action: cleanup
|
||||
};
|
||||
|
||||
plcrash_async_mobject mobj;
|
||||
plcrash_error_t err = plcrash_async_mobject_init(&mobj, mach_task_self(), (pl_vm_address_t)lsda, sizeof(lsda), true);
|
||||
|
||||
dwarf_lsda_info_t info;
|
||||
err = dwarf_lsda_info_init<uint64_t>(&info, &mobj, &plcrash_async_byteorder_direct, (pl_vm_address_t)lsda);
|
||||
STAssertEquals(err, PLCRASH_ESUCCESS, @"Failed to parse LSDA");
|
||||
|
||||
STAssertEquals(info.has_lp_start, false, @"Incorrect has_lp_start");
|
||||
STAssertEquals(info.callsites.size(), 1, @"Incorrect number of call sites");
|
||||
|
||||
STAssertEquals(info.callsites[0].start, 0x00, @"callsite 1's start is wrong");
|
||||
STAssertEquals(info.callsites[0].length, 0xA2, @"callsite 1's length is wrong");
|
||||
STAssertEquals(info.callsites[0].landing_pad_offset, 0, @"callsite 1's landing pad is wrong");
|
||||
STAssertEquals(info.callsites[0].actions.size(), 0, @"callsite 1 shouldn't have actions");
|
||||
|
||||
dwarf_lsda_info_free(&info);
|
||||
plcrash_async_mobject_free(&mobj);
|
||||
}
|
||||
|
||||
- (void) testExceptionSpecifications {
|
||||
// A simple function with an exception specification.
|
||||
static const uint8_t lsda[] = {
|
||||
0xff, // LPStart Encoding = omit
|
||||
0x9b, // @TType Encoding = indirect pcrel sdata4
|
||||
0x99, 0x80, 0x80, 0x00, // @TType base offset
|
||||
0x03, // Call site Encoding = udata4
|
||||
0x0d, // Call site table length
|
||||
// >> Call Site 1 <<
|
||||
0x08, 0x00, 0x00, 0x00, //
|
||||
0x0c, 0x00, 0x00, 0x00, // Call between Ltmp0 and Ltmp1
|
||||
0x22, 0x00, 0x00, 0x00, // jumps to Ltmp2
|
||||
0x01, // On action: 1
|
||||
// >> Action Record 1 <<
|
||||
0x7f, // Filter TypeInfo -1
|
||||
0x00, // No further actions
|
||||
// >> Catch TypeInfos <<
|
||||
0x0B, 0x00, 0x00, 0x00, // TypeInfo 2
|
||||
0x0F, 0x00, 0x00, 0x00, // TypeInfo 1
|
||||
// >> Filter TypeInfos <<
|
||||
0x01, // FilterInfo -1
|
||||
0x02, // FilterInfo -2
|
||||
0x00,
|
||||
// >> Non-LSDA data <<
|
||||
0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
|
||||
0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
|
||||
};
|
||||
|
||||
plcrash_async_mobject mobj;
|
||||
plcrash_error_t err = plcrash_async_mobject_init(&mobj, mach_task_self(), (pl_vm_address_t)lsda, sizeof(lsda), true);
|
||||
|
||||
dwarf_lsda_info_t info;
|
||||
err = dwarf_lsda_info_init<uint64_t>(&info, &mobj, &plcrash_async_byteorder_direct, (pl_vm_address_t)lsda);
|
||||
STAssertEquals(err, PLCRASH_ESUCCESS, @"Failed to parse LSDA");
|
||||
|
||||
STAssertEquals(info.has_lp_start, false, @"Incorrect has_lp_start");
|
||||
STAssertEquals(info.callsites.size(), 1, @"Incorrect number of call sites");
|
||||
|
||||
STAssertEquals(info.callsites[0].start, 0x08, @"callsite 1's start is wrong");
|
||||
STAssertEquals(info.callsites[0].length, 0x0C, @"callsite 1's length is wrong");
|
||||
STAssertEquals(info.callsites[0].landing_pad_offset, 0x22, @"callsite 1's landing pad is wrong");
|
||||
STAssertEquals(info.callsites[0].actions.size(), 1, @"callsite 1's should have one action");
|
||||
|
||||
STAssertEquals(info.callsites[0].actions[0].kind, DWARF_LSDA_ACTION_KIND_EXCEPTION_SPECIFICATION, @"wrong action kind");
|
||||
STAssertEquals(info.callsites[0].actions[0].types.size(), 2, @"wrong type size");
|
||||
STAssertEquals(info.callsites[0].actions[0].types[0], 0x3F3F3F3F3F3F3F3F, @"wrong type value");
|
||||
STAssertEquals(info.callsites[0].actions[0].types[1], 0x2A2A2A2A2A2A2A2A, @"wrong type value");
|
||||
|
||||
dwarf_lsda_info_free(&info);
|
||||
plcrash_async_mobject_free(&mobj);
|
||||
}
|
||||
|
||||
- (void) testMultipleCatches {
|
||||
// A function with a try block with several catches.
|
||||
static const uint8_t lsda[] = {
|
||||
0xff, // @LPStart Encoding = omit
|
||||
0x9b, // @TType Encoding = indirect pcrel sdata4
|
||||
0xae, 0x80, 0x00, // @TType base offset
|
||||
0x03, // Call site Encoding = udata4
|
||||
0x1a, // Call site table length
|
||||
// >> Call Site 1 <<
|
||||
0x00, 0x00, 0x00, 0x00, //
|
||||
0x1e, 0x00, 0x00, 0x00, // Call between Ltmp0 and Ltmp1
|
||||
0x00, 0x00, 0x00, 0x00, // has no landing pad
|
||||
0x00, // On action: cleanup
|
||||
// >> Call Site 2 <<
|
||||
0x1e, 0x00, 0x00, 0x00, //
|
||||
0x13, 0x00, 0x00, 0x00, // Call between Ltmp0 and Ltmp1
|
||||
0x36, 0x00, 0x00, 0x00, // jumps to Ltmp2
|
||||
0x05, // On action: 3
|
||||
// >> Action Record 1 <<
|
||||
0x01, // Catch TypeInfo 1
|
||||
0x00, // No further actions
|
||||
// >> Action Record 2 <<
|
||||
0x02, // Catch TypeInfo 2
|
||||
0x7d, // Continue to action 1
|
||||
/// >> Action Record 3 <<
|
||||
0x03, // Catch TypeInfo 3
|
||||
0x7d, // Continue to action 2
|
||||
// >> Catch TypeInfos <<
|
||||
0x0C, 0x00, 0x00, 0x00, // TypeInfo 3
|
||||
0x10, 0x00, 0x00, 0x00, // TypeInfo 2
|
||||
0x00, 0x00, 0x00, 0x00, // TypeInfo 1
|
||||
// >> Non-LSDA data <<
|
||||
0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
|
||||
0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
|
||||
};
|
||||
|
||||
plcrash_async_mobject mobj;
|
||||
plcrash_error_t err = plcrash_async_mobject_init(&mobj, mach_task_self(), (pl_vm_address_t)lsda, sizeof(lsda), true);
|
||||
|
||||
dwarf_lsda_info_t info;
|
||||
err = dwarf_lsda_info_init<uint64_t>(&info, &mobj, &plcrash_async_byteorder_direct, (pl_vm_address_t)lsda);
|
||||
STAssertEquals(err, PLCRASH_ESUCCESS, @"Failed to parse LSDA");
|
||||
|
||||
STAssertEquals(info.has_lp_start, false, @"Incorrect has_lp_start");
|
||||
STAssertEquals(info.callsites.size(), 2, @"Incorrect number of call sites");
|
||||
|
||||
STAssertEquals(info.callsites[0].start, 0, @"callsite 1's start is wrong");
|
||||
STAssertEquals(info.callsites[0].length, 0x1e, @"callsite 1's length is wrong");
|
||||
STAssertEquals(info.callsites[0].landing_pad_offset, 0, @"callsite 1's landing pad is wrong");
|
||||
STAssertEquals(info.callsites[0].actions.size(), 0, @"callsite 1's shouldn't have actions");
|
||||
|
||||
STAssertEquals(info.callsites[1].start, 0x1e, @"callsite 2's start is wrong");
|
||||
STAssertEquals(info.callsites[1].length, 0x13, @"callsite 2's length is wrong");
|
||||
STAssertEquals(info.callsites[1].landing_pad_offset, 0x36, @"callsite 2's landing pad is wrong");
|
||||
STAssertEquals(info.callsites[1].actions.size(), 3, @"callsite 2's action count is wrong");
|
||||
|
||||
STAssertEquals(info.callsites[1].actions[0].kind, DWARF_LSDA_ACTION_KIND_CATCH, @"wrong action kind");
|
||||
STAssertEquals(info.callsites[1].actions[0].types.size(), 1, @"wrong type size");
|
||||
STAssertEquals(info.callsites[1].actions[0].types[0], 0x2A2A2A2A2A2A2A2A, @"wrong type value");
|
||||
|
||||
STAssertEquals(info.callsites[1].actions[1].kind, DWARF_LSDA_ACTION_KIND_CATCH, @"wrong action kind");
|
||||
STAssertEquals(info.callsites[1].actions[1].types.size(), 1, @"wrong type size");
|
||||
STAssertEquals(info.callsites[1].actions[1].types[0], 0x3F3F3F3F3F3F3F3F, @"wrong type value");
|
||||
|
||||
STAssertEquals(info.callsites[1].actions[2].kind, DWARF_LSDA_ACTION_KIND_CATCH, @"wrong action kind");
|
||||
STAssertEquals(info.callsites[1].actions[2].types.size(), 1, @"wrong type size");
|
||||
STAssertEquals(info.callsites[1].actions[2].types[0], 0, @"wrong type value");
|
||||
|
||||
dwarf_lsda_info_free(&info);
|
||||
plcrash_async_mobject_free(&mobj);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif /* PLCRASH_FEATURE_UNWIND_DWARF */
|
||||
Reference in New Issue
Block a user