From 980b266a84e5ee0179c32729556a9e13e1f7db83 Mon Sep 17 00:00:00 2001 From: IsmailShaheen Date: Wed, 12 Feb 2020 00:00:47 +0200 Subject: [PATCH 01/16] first draft for decoding function --- .gitignore | 2 + abi_v08/mycppabi.cpp | 210 +++++++++++++++++++++++++++---------------- 2 files changed, 136 insertions(+), 76 deletions(-) diff --git a/.gitignore b/.gitignore index ade24f3..a543961 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,5 @@ *.a libcxxabi + +app \ No newline at end of file diff --git a/abi_v08/mycppabi.cpp b/abi_v08/mycppabi.cpp index cd2344d..f0d09a4 100644 --- a/abi_v08/mycppabi.cpp +++ b/abi_v08/mycppabi.cpp @@ -84,7 +84,26 @@ void __cxa_end_catch() * this to avoid a const mess later on; LSDA_ptr refers to readonly and * &LSDA_ptr will be a non-const pointer to a const place in memory */ -typedef const uint8_t* LSDA_ptr; +typedef const _uleb128_t* LSDA_ptr; +typedef _uleb128_t LSDA_line; + +static const unsigned char * +dec_uleb128 (const unsigned char *p, _uleb128_t *val) +{ + unsigned int shift = 0; + unsigned char byte; + _uleb128_t result; + result = 0; + do + { + byte = *p++; + result |= ((_uleb128_t)byte & 0x7f) << shift; + shift += 7; + } + while (byte & 0x80); + *val = result; + return p; +} struct LSDA_Header { /** @@ -92,46 +111,67 @@ struct LSDA_Header { * as many bytes as read */ LSDA_Header(LSDA_ptr *lsda) { - LSDA_ptr read_ptr = *lsda; - - // Copy the LSDA fields - start_encoding = read_ptr[0]; - type_encoding = read_ptr[1]; - type_table_offset = read_ptr[2]; - - // Advance the lsda pointer - *lsda = read_ptr + sizeof(LSDA_Header); + // LSDA_ptr read_ptr = *lsda; + + // // Copy the LSDA fields + // start_encoding = read_ptr[0]; + // type_encoding = read_ptr[1]; + // type_table_offset = read_ptr[2]; + + // // Advance the lsda pointer + // *lsda = read_ptr + sizeof(LSDA_Header); + + // Modified version of read for compatability with decodoing function + const unsigned char *read_ptr = (const unsigned char *)*lsda; + read_ptr = dec_uleb128(read_ptr, &start_encoding); + read_ptr = dec_uleb128(read_ptr, &type_encoding); + read_ptr = dec_uleb128(read_ptr, &type_table_offset); + *lsda = (LSDA_ptr)read_ptr; } - uint8_t start_encoding; - uint8_t type_encoding; + LSDA_line start_encoding; + LSDA_line type_encoding; // This is the offset, from the end of the header, to the types table - uint8_t type_table_offset; + LSDA_line type_table_offset; }; struct LSDA_CS_Header { // Same as other LSDA constructors LSDA_CS_Header(LSDA_ptr *lsda) { - LSDA_ptr read_ptr = *lsda; - encoding = read_ptr[0]; - length = read_ptr[1]; - *lsda = read_ptr + sizeof(LSDA_CS_Header); + // LSDA_ptr read_ptr = *lsda; + // encoding = read_ptr[0]; + // length = read_ptr[1]; + // *lsda = read_ptr + sizeof(LSDA_CS_Header); + + // Modified version of read for compatability with decodoing function + const unsigned char *read_ptr = (const unsigned char *)*lsda; + read_ptr = dec_uleb128(read_ptr, &encoding); + read_ptr = dec_uleb128(read_ptr, &length); + *lsda = (LSDA_ptr)read_ptr; } - uint8_t encoding; - uint8_t length; + LSDA_line encoding; + LSDA_line length; }; struct LSDA_CS { // Same as other LSDA constructors LSDA_CS(LSDA_ptr *lsda) { - LSDA_ptr read_ptr = *lsda; - start = read_ptr[0]; - len = read_ptr[1]; - lp = read_ptr[2]; - action = read_ptr[3]; - *lsda = read_ptr + sizeof(LSDA_CS); + // LSDA_ptr read_ptr = *lsda; + // start = read_ptr[0]; + // len = read_ptr[1]; + // lp = read_ptr[2]; + // action = read_ptr[3]; + // *lsda = read_ptr + sizeof(LSDA_CS); + + // Modified version of read for compatability with decodoing function + const unsigned char *read_ptr = (const unsigned char *)*lsda; + read_ptr = dec_uleb128(read_ptr, &start); + read_ptr = dec_uleb128(read_ptr, &len); + read_ptr = dec_uleb128(read_ptr, &lp); + read_ptr = dec_uleb128(read_ptr, &action); + *lsda = (LSDA_ptr)read_ptr; } LSDA_CS() { } @@ -141,14 +181,14 @@ struct LSDA_CS { // is relative to start // Offset into function from which we could handle a throw - uint8_t start; + LSDA_line start; // Length of the block that might throw - uint8_t len; + LSDA_line len; // Landing pad - uint8_t lp; + LSDA_line lp; // Offset into action table + 1 (0 means no action) // Used to run destructors - uint8_t action; + LSDA_line action; }; /** @@ -251,54 +291,72 @@ _Unwind_Reason_Code __gxx_personality_v0 ( // Go through each call site in this stack frame to check whether // the current exception can be handled here - for(const LSDA_CS *cs = lsda.next_call_site_entry(true); - cs != NULL; - cs = lsda.next_call_site_entry()) + /* + * This loop produces a segmentation fault error due to accesing a wrong memory location + * This happens probably because the LSDA entries are read without proper decoding so until we fix it, it will remain preceded by these nice // + */ + // for(const LSDA_CS *cs = lsda.next_call_site_entry(true); + // cs != NULL; + // cs = lsda.next_call_site_entry()) + // { + // // If there's no landing pad we can't handle this exception + // if (not cs->lp) continue; + + // uintptr_t func_start = _Unwind_GetRegionStart(context); + + // // Calculate the range of the instruction pointer valid for this + // // landing pad; if this LP can handle the current exception then + // // the IP for this stack frame must be in this range + // uintptr_t try_start = func_start + cs->start; + // uintptr_t try_end = func_start + cs->start + cs->len; + + // // Check if this is the correct LP for the current try block + // if (throw_ip < try_start) continue; + // if (throw_ip > try_end) continue; + + // // Get the offset into the action table for this LP + // if (cs->action > 0) + // { + // // cs->action is the offset + 1; that way cs->action == 0 + // // means there is no associated entry in the action table + // const size_t action_offset = cs->action - 1; + // const LSDA_ptr action = lsda.action_tbl_start + action_offset; + + // // For a landing pad with a catch the action table will + // // hold an index to a list of types + // int type_index = action[0]; + + // const void* catch_type_info = lsda.types_table_start[ -1 * type_index ]; + // const std::type_info *catch_ti = (const std::type_info *) catch_type_info; + // printf("%s\n", catch_ti->name()); + // } + + // // We found a landing pad for this exception; resume execution + // int r0 = __builtin_eh_return_data_regno(0); + // int r1 = __builtin_eh_return_data_regno(1); + + // _Unwind_SetGR(context, r0, (uintptr_t)(unwind_exception)); + + // // Note the following code hardcodes the exception type; + // // we'll fix that later on + // _Unwind_SetGR(context, r1, (uintptr_t)(1)); + + // _Unwind_SetIP(context, func_start + cs->lp); + // break; + // } + + //Now this one is a cute little for loop for accessing the Call Site table entries for depugging + int i = 0; + for (const LSDA_CS *cs = lsda.next_call_site_entry(true); + cs != NULL; + cs = lsda.next_call_site_entry()) { - // If there's no landing pad we can't handle this exception - if (not cs->lp) continue; - - uintptr_t func_start = _Unwind_GetRegionStart(context); - - // Calculate the range of the instruction pointer valid for this - // landing pad; if this LP can handle the current exception then - // the IP for this stack frame must be in this range - uintptr_t try_start = func_start + cs->start; - uintptr_t try_end = func_start + cs->start + cs->len; - - // Check if this is the correct LP for the current try block - if (throw_ip < try_start) continue; - if (throw_ip > try_end) continue; - - // Get the offset into the action table for this LP - if (cs->action > 0) - { - // cs->action is the offset + 1; that way cs->action == 0 - // means there is no associated entry in the action table - const size_t action_offset = cs->action - 1; - const LSDA_ptr action = lsda.action_tbl_start + action_offset; - - // For a landing pad with a catch the action table will - // hold an index to a list of types - int type_index = action[0]; - - const void* catch_type_info = lsda.types_table_start[ -1 * type_index ]; - const std::type_info *catch_ti = (const std::type_info *) catch_type_info; - printf("%s\n", catch_ti->name()); - } - - // We found a landing pad for this exception; resume execution - int r0 = __builtin_eh_return_data_regno(0); - int r1 = __builtin_eh_return_data_regno(1); - - _Unwind_SetGR(context, r0, (uintptr_t)(unwind_exception)); - - // Note the following code hardcodes the exception type; - // we'll fix that later on - _Unwind_SetGR(context, r1, (uintptr_t)(1)); - - _Unwind_SetIP(context, func_start + cs->lp); - break; + printf("Found a CS #%i:\n", i); + printf("\tcs_start: %i\n", cs->start); + printf("\tcs_len: %i\n", cs->len); + printf("\tcs_lp: %i\n", cs->lp); + printf("\tcs_action: %i\n", cs->action); + i++; } return _URC_INSTALL_CONTEXT; From 1c73a37c07ba83911777f896111d675182b53bd2 Mon Sep 17 00:00:00 2001 From: IsmailShaheen Date: Wed, 12 Feb 2020 03:09:33 +0200 Subject: [PATCH 02/16] LSDA call site is read correctly with uleb128 decoding --- .gitignore | 7 +++++-- abi_v08/mycppabi.cpp | 27 ++++++++++++++++++++------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index a543961..f5aa7c9 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,9 @@ *.la *.a -libcxxabi +# Assembly files +*.s -app \ No newline at end of file +libcxxabi +app +*log.txt \ No newline at end of file diff --git a/abi_v08/mycppabi.cpp b/abi_v08/mycppabi.cpp index f0d09a4..a09f34f 100644 --- a/abi_v08/mycppabi.cpp +++ b/abi_v08/mycppabi.cpp @@ -123,14 +123,15 @@ struct LSDA_Header { // Modified version of read for compatability with decodoing function const unsigned char *read_ptr = (const unsigned char *)*lsda; - read_ptr = dec_uleb128(read_ptr, &start_encoding); - read_ptr = dec_uleb128(read_ptr, &type_encoding); + start_encoding = read_ptr[0]; + type_encoding = read_ptr[1]; + read_ptr += 2; read_ptr = dec_uleb128(read_ptr, &type_table_offset); *lsda = (LSDA_ptr)read_ptr; } - LSDA_line start_encoding; - LSDA_line type_encoding; + uint8_t start_encoding; + uint8_t type_encoding; // This is the offset, from the end of the header, to the types table LSDA_line type_table_offset; @@ -146,12 +147,13 @@ struct LSDA_CS_Header { // Modified version of read for compatability with decodoing function const unsigned char *read_ptr = (const unsigned char *)*lsda; - read_ptr = dec_uleb128(read_ptr, &encoding); + encoding = read_ptr[0]; + read_ptr += 1; read_ptr = dec_uleb128(read_ptr, &length); *lsda = (LSDA_ptr)read_ptr; } - LSDA_line encoding; + uint8_t encoding; LSDA_line length; }; @@ -233,7 +235,8 @@ struct LSDA cs_table_start(raw_lsda), // Calculate where the end of the LSDA CS table is - cs_table_end(raw_lsda + cs_header.length), + // Pointer Arth. has been changed to accomodate the lareger pointer type + cs_table_end((const LSDA_ptr)((uint8_t*)(raw_lsda) + cs_header.length)), // Get the start of action tables action_tbl_start( cs_table_end ) @@ -345,6 +348,16 @@ _Unwind_Reason_Code __gxx_personality_v0 ( // break; // } + // This is used to print the values inside the headers + printf("LSDA Header:\n"); + printf("\tstart_encoding: %i\n", lsda.header.start_encoding); + printf("\ttype_encoding: %i\n", lsda.header.type_encoding); + printf("\ttype_table_offset: %i\n", lsda.header.type_table_offset); + + printf("LSDA Call Site Header:\n"); + printf("\tencoding: %i\n", lsda.cs_header.encoding); + printf("\tlength: %i\n", lsda.cs_header.length); + //Now this one is a cute little for loop for accessing the Call Site table entries for depugging int i = 0; for (const LSDA_CS *cs = lsda.next_call_site_entry(true); From d0c04cece4c046d75fe639fc8cb6d00fbee3ec2b Mon Sep 17 00:00:00 2001 From: IsmailShaheen Date: Sat, 15 Feb 2020 23:57:16 +0200 Subject: [PATCH 03/16] table type is accessed correctly --- .gitignore | 3 +- abi_v08/mycppabi.cpp | 151 ++++++++++++++++++++++--------------------- 2 files changed, 80 insertions(+), 74 deletions(-) diff --git a/.gitignore b/.gitignore index f5aa7c9..dadc816 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,5 @@ libcxxabi app -*log.txt \ No newline at end of file +*log.txt +.vscode \ No newline at end of file diff --git a/abi_v08/mycppabi.cpp b/abi_v08/mycppabi.cpp index a09f34f..156ab9b 100644 --- a/abi_v08/mycppabi.cpp +++ b/abi_v08/mycppabi.cpp @@ -84,7 +84,7 @@ void __cxa_end_catch() * this to avoid a const mess later on; LSDA_ptr refers to readonly and * &LSDA_ptr will be a non-const pointer to a const place in memory */ -typedef const _uleb128_t* LSDA_ptr; +typedef const uint8_t* LSDA_ptr; typedef _uleb128_t LSDA_line; static const unsigned char * @@ -226,7 +226,8 @@ struct LSDA // Get the start of the types table (it's actually the end of the // table, but since the action index will hold a negative index // for this table we can say it's the beginning - types_table_start( (const void**)(raw_lsda + header.type_table_offset) ), + // modified the pointer size for pointer arthemitics + types_table_start( (const void**)((uint8_t*)raw_lsda + header.type_table_offset) ), // Read the LSDA CS header cs_header(&raw_lsda), @@ -298,80 +299,84 @@ _Unwind_Reason_Code __gxx_personality_v0 ( * This loop produces a segmentation fault error due to accesing a wrong memory location * This happens probably because the LSDA entries are read without proper decoding so until we fix it, it will remain preceded by these nice // */ - // for(const LSDA_CS *cs = lsda.next_call_site_entry(true); - // cs != NULL; - // cs = lsda.next_call_site_entry()) - // { - // // If there's no landing pad we can't handle this exception - // if (not cs->lp) continue; - - // uintptr_t func_start = _Unwind_GetRegionStart(context); - - // // Calculate the range of the instruction pointer valid for this - // // landing pad; if this LP can handle the current exception then - // // the IP for this stack frame must be in this range - // uintptr_t try_start = func_start + cs->start; - // uintptr_t try_end = func_start + cs->start + cs->len; - - // // Check if this is the correct LP for the current try block - // if (throw_ip < try_start) continue; - // if (throw_ip > try_end) continue; - - // // Get the offset into the action table for this LP - // if (cs->action > 0) - // { - // // cs->action is the offset + 1; that way cs->action == 0 - // // means there is no associated entry in the action table - // const size_t action_offset = cs->action - 1; - // const LSDA_ptr action = lsda.action_tbl_start + action_offset; - - // // For a landing pad with a catch the action table will - // // hold an index to a list of types - // int type_index = action[0]; - - // const void* catch_type_info = lsda.types_table_start[ -1 * type_index ]; - // const std::type_info *catch_ti = (const std::type_info *) catch_type_info; - // printf("%s\n", catch_ti->name()); - // } - - // // We found a landing pad for this exception; resume execution - // int r0 = __builtin_eh_return_data_regno(0); - // int r1 = __builtin_eh_return_data_regno(1); - - // _Unwind_SetGR(context, r0, (uintptr_t)(unwind_exception)); - - // // Note the following code hardcodes the exception type; - // // we'll fix that later on - // _Unwind_SetGR(context, r1, (uintptr_t)(1)); - - // _Unwind_SetIP(context, func_start + cs->lp); - // break; - // } - - // This is used to print the values inside the headers - printf("LSDA Header:\n"); - printf("\tstart_encoding: %i\n", lsda.header.start_encoding); - printf("\ttype_encoding: %i\n", lsda.header.type_encoding); - printf("\ttype_table_offset: %i\n", lsda.header.type_table_offset); - - printf("LSDA Call Site Header:\n"); - printf("\tencoding: %i\n", lsda.cs_header.encoding); - printf("\tlength: %i\n", lsda.cs_header.length); - - //Now this one is a cute little for loop for accessing the Call Site table entries for depugging - int i = 0; - for (const LSDA_CS *cs = lsda.next_call_site_entry(true); - cs != NULL; - cs = lsda.next_call_site_entry()) + for(const LSDA_CS *cs = lsda.next_call_site_entry(true); + cs != NULL; + cs = lsda.next_call_site_entry()) { - printf("Found a CS #%i:\n", i); - printf("\tcs_start: %i\n", cs->start); - printf("\tcs_len: %i\n", cs->len); - printf("\tcs_lp: %i\n", cs->lp); - printf("\tcs_action: %i\n", cs->action); - i++; + // If there's no landing pad we can't handle this exception + if (not cs->lp) continue; + + uintptr_t func_start = _Unwind_GetRegionStart(context); + + // Calculate the range of the instruction pointer valid for this + // landing pad; if this LP can handle the current exception then + // the IP for this stack frame must be in this range + uintptr_t try_start = func_start + cs->start; + uintptr_t try_end = func_start + cs->start + cs->len; + + // Check if this is the correct LP for the current try block + if (throw_ip < try_start) continue; + if (throw_ip > try_end) continue; + + // Get the offset into the action table for this LP + if (cs->action > 0) + { + // cs->action is the offset + 1; that way cs->action == 0 + // means there is no associated entry in the action table + const size_t action_offset = cs->action - 1; + const LSDA_ptr action = lsda.action_tbl_start + action_offset; + + // For a landing pad with a catch the action table will + // hold an index to a list of types + // the 4 is the size of the .long data that stores types in ttable + int type_index = 4 * action[0]; + + uint8_t* catch_type_info_byte = (uint8_t*)lsda.types_table_start; + catch_type_info_byte -= type_index; + void** catch_type_info_void = (void**)catch_type_info_byte; + const void* catch_type_info = (const void*)(catch_type_info_void[0]); + const std::type_info *catch_ti = (const std::type_info *) catch_type_info; + //printf("%s\n", catch_ti->name()); + } + + // We found a landing pad for this exception; resume execution + int r0 = __builtin_eh_return_data_regno(0); + int r1 = __builtin_eh_return_data_regno(1); + + _Unwind_SetGR(context, r0, (uintptr_t)(unwind_exception)); + + // Note the following code hardcodes the exception type; + // we'll fix that later on + _Unwind_SetGR(context, r1, (uintptr_t)(1)); + + _Unwind_SetIP(context, func_start + cs->lp); + break; } + // // This is used to print the values inside the headers + // printf("LSDA Header:\n"); + // printf("\tstart_encoding: %i\n", lsda.header.start_encoding); + // printf("\ttype_encoding: %i\n", lsda.header.type_encoding); + // printf("\ttype_table_offset: %i\n", lsda.header.type_table_offset); + + // printf("LSDA Call Site Header:\n"); + // printf("\tencoding: %i\n", lsda.cs_header.encoding); + // printf("\tlength: %i\n", lsda.cs_header.length); + + // //Now this one is a cute little for loop for accessing the Call Site table entries for debugging + // int i = 0; + // for (const LSDA_CS *cs = lsda.next_call_site_entry(true); + // cs != NULL; + // cs = lsda.next_call_site_entry()) + // { + // printf("Found a CS #%i:\n", i); + // printf("\tcs_start: %i\n", cs->start); + // printf("\tcs_len: %i\n", cs->len); + // printf("\tcs_lp: %i\n", cs->lp); + // printf("\tcs_action: %i\n", cs->action); + // i++; + // } + return _URC_INSTALL_CONTEXT; } else { printf("Personality function, error\n"); From 3141127996a1c722fa4bb0152625c31d840af325 Mon Sep 17 00:00:00 2001 From: IsmailShaheen Date: Mon, 17 Feb 2020 16:46:06 +0200 Subject: [PATCH 04/16] abi_v08 fixed! --- abi_v08/mycppabi.cpp | 40 +++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/abi_v08/mycppabi.cpp b/abi_v08/mycppabi.cpp index 156ab9b..6d07ff6 100644 --- a/abi_v08/mycppabi.cpp +++ b/abi_v08/mycppabi.cpp @@ -87,7 +87,7 @@ void __cxa_end_catch() typedef const uint8_t* LSDA_ptr; typedef _uleb128_t LSDA_line; -static const unsigned char * +const unsigned char * dec_uleb128 (const unsigned char *p, _uleb128_t *val) { unsigned int shift = 0; @@ -105,6 +105,32 @@ dec_uleb128 (const unsigned char *p, _uleb128_t *val) return p; } +// This function recieves a pointer to a ttype entry and return the corrisponding type_info +// It's an implementation of three different functions from unwind-pe.h specific to our case and cannot be generalized for different encoding and size +// Handling these differences will be done by accessing different members of the union according to the encoding +const std::type_info * +get_ttype_entry (uint8_t* entry) +{ + union unaligned + { + void *ptr; + unsigned u2 __attribute__ ((mode (HI))); + unsigned u4 __attribute__ ((mode (SI))); + unsigned u8 __attribute__ ((mode (DI))); + signed s2 __attribute__ ((mode (HI))); + signed s4 __attribute__ ((mode (SI))); + signed s8 __attribute__ ((mode (DI))); + } __attribute__((__packed__)); + + const union unaligned *u = (const union unaligned *) entry; + unsigned long result; + result = u->s4 + (unsigned long)u; + entry += 4; + result = *(unsigned long *)result; + const std::type_info *tinfo = reinterpret_cast(result); + return tinfo; +} + struct LSDA_Header { /** * Read the LSDA table into a struct; advances the lsda pointer @@ -331,12 +357,12 @@ _Unwind_Reason_Code __gxx_personality_v0 ( // the 4 is the size of the .long data that stores types in ttable int type_index = 4 * action[0]; - uint8_t* catch_type_info_byte = (uint8_t*)lsda.types_table_start; - catch_type_info_byte -= type_index; - void** catch_type_info_void = (void**)catch_type_info_byte; - const void* catch_type_info = (const void*)(catch_type_info_void[0]); - const std::type_info *catch_ti = (const std::type_info *) catch_type_info; - //printf("%s\n", catch_ti->name()); + uint8_t* catch_type_info = (uint8_t*)lsda.types_table_start; + catch_type_info -= type_index; + // void** catch_type_info_void = (void**)catch_type_info_byte; + // const void* catch_type_info = (const void*)(catch_type_info_void[0]); + const std::type_info *catch_ti = get_ttype_entry(catch_type_info); + printf("%s\n", catch_ti->name()); } // We found a landing pad for this exception; resume execution From 4aa611d5e87a14538bc70dd4771bde1282b13181 Mon Sep 17 00:00:00 2001 From: IsmailShaheen Date: Sat, 22 Feb 2020 02:21:01 +0200 Subject: [PATCH 05/16] simplified get_ttype_entry method --- abi_v08/mycppabi.cpp | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/abi_v08/mycppabi.cpp b/abi_v08/mycppabi.cpp index 6d07ff6..4837897 100644 --- a/abi_v08/mycppabi.cpp +++ b/abi_v08/mycppabi.cpp @@ -107,26 +107,16 @@ dec_uleb128 (const unsigned char *p, _uleb128_t *val) // This function recieves a pointer to a ttype entry and return the corrisponding type_info // It's an implementation of three different functions from unwind-pe.h specific to our case and cannot be generalized for different encoding and size -// Handling these differences will be done by accessing different members of the union according to the encoding const std::type_info * get_ttype_entry (uint8_t* entry) { - union unaligned - { - void *ptr; - unsigned u2 __attribute__ ((mode (HI))); - unsigned u4 __attribute__ ((mode (SI))); - unsigned u8 __attribute__ ((mode (DI))); - signed s2 __attribute__ ((mode (HI))); - signed s4 __attribute__ ((mode (SI))); - signed s8 __attribute__ ((mode (DI))); - } __attribute__((__packed__)); - - const union unaligned *u = (const union unaligned *) entry; + const int32_t *u = (const int32_t *) entry; unsigned long result; - result = u->s4 + (unsigned long)u; + + result = *u + (unsigned long)u; entry += 4; result = *(unsigned long *)result; + const std::type_info *tinfo = reinterpret_cast(result); return tinfo; } From f265e965787a006dd8b55572eb8e85700f602cb7 Mon Sep 17 00:00:00 2001 From: IsmailShaheen Date: Tue, 25 Feb 2020 17:17:54 +0200 Subject: [PATCH 06/16] dec_uleb128 changed for compatibility --- abi_v08/mycppabi.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/abi_v08/mycppabi.cpp b/abi_v08/mycppabi.cpp index 4837897..3cbf4b2 100644 --- a/abi_v08/mycppabi.cpp +++ b/abi_v08/mycppabi.cpp @@ -88,7 +88,7 @@ typedef const uint8_t* LSDA_ptr; typedef _uleb128_t LSDA_line; const unsigned char * -dec_uleb128 (const unsigned char *p, _uleb128_t *val) +read_uleb128 (const unsigned char *p, _uleb128_t *val) { unsigned int shift = 0; unsigned char byte; @@ -142,7 +142,7 @@ struct LSDA_Header { start_encoding = read_ptr[0]; type_encoding = read_ptr[1]; read_ptr += 2; - read_ptr = dec_uleb128(read_ptr, &type_table_offset); + read_ptr = read_uleb128(read_ptr, &type_table_offset); *lsda = (LSDA_ptr)read_ptr; } @@ -165,7 +165,7 @@ struct LSDA_CS_Header { const unsigned char *read_ptr = (const unsigned char *)*lsda; encoding = read_ptr[0]; read_ptr += 1; - read_ptr = dec_uleb128(read_ptr, &length); + read_ptr = read_uleb128(read_ptr, &length); *lsda = (LSDA_ptr)read_ptr; } @@ -185,10 +185,10 @@ struct LSDA_CS { // Modified version of read for compatability with decodoing function const unsigned char *read_ptr = (const unsigned char *)*lsda; - read_ptr = dec_uleb128(read_ptr, &start); - read_ptr = dec_uleb128(read_ptr, &len); - read_ptr = dec_uleb128(read_ptr, &lp); - read_ptr = dec_uleb128(read_ptr, &action); + read_ptr = read_uleb128(read_ptr, &start); + read_ptr = read_uleb128(read_ptr, &len); + read_ptr = read_uleb128(read_ptr, &lp); + read_ptr = read_uleb128(read_ptr, &action); *lsda = (LSDA_ptr)read_ptr; } From ba1dc8451c5de7c09e6ae16c01c45db008edb135 Mon Sep 17 00:00:00 2001 From: amroadel Date: Tue, 25 Feb 2020 17:22:30 +0200 Subject: [PATCH 07/16] explaining read_uleb128 --- abi_v08/mycppabi.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/abi_v08/mycppabi.cpp b/abi_v08/mycppabi.cpp index 6d07ff6..66dd686 100644 --- a/abi_v08/mycppabi.cpp +++ b/abi_v08/mycppabi.cpp @@ -87,6 +87,8 @@ void __cxa_end_catch() typedef const uint8_t* LSDA_ptr; typedef _uleb128_t LSDA_line; + +//This function receives a pointer the first byte to be decoded and the address of where to put the decoded value. const unsigned char * dec_uleb128 (const unsigned char *p, _uleb128_t *val) { @@ -96,10 +98,12 @@ dec_uleb128 (const unsigned char *p, _uleb128_t *val) result = 0; do { - byte = *p++; + byte = *p++; + // Shifting the byte to the left and propagating the new byte to it (if there's any) result |= ((_uleb128_t)byte & 0x7f) << shift; shift += 7; } + // if the 8th bit is 1, this means that there still another byte to be concatinated to the current byte (if zero, then decoding is done) while (byte & 0x80); *val = result; return p; From cd0f3a58b8bd38d9ff2030cd581ab8f496650eef Mon Sep 17 00:00:00 2001 From: IsmailShaheen Date: Fri, 28 Feb 2020 15:46:11 +0200 Subject: [PATCH 08/16] bug fixed in v09 __cxa_throw --- abi_v09/mycppabi.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/abi_v09/mycppabi.cpp b/abi_v09/mycppabi.cpp index a57cc03..d8fff01 100644 --- a/abi_v09/mycppabi.cpp +++ b/abi_v09/mycppabi.cpp @@ -54,7 +54,9 @@ void __cxa_throw(void* thrown_exception, { printf("__cxa_throw called\n"); - __cxa_exception *header = ((__cxa_exception *) thrown_exception - 1); + __cxa_exception *header = ((__cxa_exception *) thrown_exception); + const char* nm = tinfo->name(); + printf("%s\n", nm); // We need to save the type info in the exception header _Unwind_ will // receive, otherwise we won't be able to know it when unwinding From 10d26e266f93f60a567eceb548a45dd430483fd9 Mon Sep 17 00:00:00 2001 From: IsmailShaheen Date: Fri, 28 Feb 2020 17:16:53 +0200 Subject: [PATCH 09/16] v09 works --- abi_v09/mycppabi.cpp | 91 +++++++++++++++++++++++++++++++------------- 1 file changed, 64 insertions(+), 27 deletions(-) diff --git a/abi_v09/mycppabi.cpp b/abi_v09/mycppabi.cpp index d8fff01..5e84e1b 100644 --- a/abi_v09/mycppabi.cpp +++ b/abi_v09/mycppabi.cpp @@ -91,6 +91,44 @@ void __cxa_end_catch() * &LSDA_ptr will be a non-const pointer to a const place in memory */ typedef const uint8_t* LSDA_ptr; +typedef _uleb128_t LSDA_line; + +//This function receives a pointer the first byte to be decoded and the address of where to put the decoded value. +const unsigned char * +read_uleb128 (const unsigned char *p, _uleb128_t *val) +{ + unsigned int shift = 0; + unsigned char byte; + _uleb128_t result; + result = 0; + do + { + byte = *p++; + // Shifting the byte to the left and propagating the new byte to it (if there's any) + result |= ((_uleb128_t)byte & 0x7f) << shift; + shift += 7; + } + // if the 8th bit is 1, this means that there still another byte to be concatinated to the current byte (if zero, then decoding is done) + while (byte & 0x80); + *val = result; + return p; +} + +// This function recieves a pointer to a ttype entry and return the corrisponding type_info +// It's an implementation of three different functions from unwind-pe.h specific to our case and cannot be generalized for different encoding and size +const std::type_info * +get_ttype_entry (uint8_t* entry) +{ + const int32_t *u = (const int32_t *) entry; + unsigned long result; + + result = *u + (unsigned long)u; + entry += 4; + result = *(unsigned long *)result; + + const std::type_info *tinfo = reinterpret_cast(result); + return tinfo; +} struct LSDA_Header { /** @@ -98,46 +136,44 @@ struct LSDA_Header { * as many bytes as read */ LSDA_Header(LSDA_ptr *lsda) { - LSDA_ptr read_ptr = *lsda; - - // Copy the LSDA fields + const unsigned char *read_ptr = (const unsigned char *)*lsda; start_encoding = read_ptr[0]; type_encoding = read_ptr[1]; - type_table_offset = read_ptr[2]; - - // Advance the lsda pointer - *lsda = read_ptr + sizeof(LSDA_Header); + read_ptr += 2; + read_ptr = read_uleb128(read_ptr, &type_table_offset); + *lsda = (LSDA_ptr)read_ptr; } uint8_t start_encoding; uint8_t type_encoding; // This is the offset, from the end of the header, to the types table - uint8_t type_table_offset; + LSDA_line type_table_offset; }; struct LSDA_CS_Header { // Same as other LSDA constructors LSDA_CS_Header(LSDA_ptr *lsda) { - LSDA_ptr read_ptr = *lsda; + const unsigned char *read_ptr = (const unsigned char *)*lsda; encoding = read_ptr[0]; - length = read_ptr[1]; - *lsda = read_ptr + sizeof(LSDA_CS_Header); + read_ptr += 1; + read_ptr = read_uleb128(read_ptr, &length); + *lsda = (LSDA_ptr)read_ptr; } uint8_t encoding; - uint8_t length; + LSDA_line length; }; struct LSDA_CS { // Same as other LSDA constructors LSDA_CS(LSDA_ptr *lsda) { - LSDA_ptr read_ptr = *lsda; - start = read_ptr[0]; - len = read_ptr[1]; - lp = read_ptr[2]; - action = read_ptr[3]; - *lsda = read_ptr + sizeof(LSDA_CS); + const unsigned char *read_ptr = (const unsigned char *)*lsda; + read_ptr = read_uleb128(read_ptr, &start); + read_ptr = read_uleb128(read_ptr, &len); + read_ptr = read_uleb128(read_ptr, &lp); + read_ptr = read_uleb128(read_ptr, &action); + *lsda = (LSDA_ptr)read_ptr; } LSDA_CS() { } @@ -147,14 +183,14 @@ struct LSDA_CS { // is relative to start // Offset into function from which we could handle a throw - uint8_t start; + LSDA_line start; // Length of the block that might throw - uint8_t len; + LSDA_line len; // Landing pad - uint8_t lp; + LSDA_line lp; // Offset into action table + 1 (0 means no action) // Used to run destructors - uint8_t action; + LSDA_line action; }; /** @@ -190,7 +226,7 @@ struct LSDA // Get the start of the types table (it's actually the end of the // table, but since the action index will hold a negative index // for this table we can say it's the beginning - types_table_start( (const void**)(raw_lsda + header.type_table_offset) ), + types_table_start( (const void**)((uint8_t*)raw_lsda + header.type_table_offset) ), // Read the LSDA CS header cs_header(&raw_lsda), @@ -199,7 +235,7 @@ struct LSDA cs_table_start(raw_lsda), // Calculate where the end of the LSDA CS table is - cs_table_end(raw_lsda + cs_header.length), + cs_table_end((const LSDA_ptr)((uint8_t*)(raw_lsda) + cs_header.length)), // Get the start of action tables action_tbl_start( cs_table_end ) @@ -286,11 +322,12 @@ _Unwind_Reason_Code __gxx_personality_v0 ( // For a landing pad with a catch the action table will // hold an index to a list of types - int type_index = action[0]; + int type_index = 4 * action[0]; // Get the type of the exception we can handle - const void* catch_type_info = lsda.types_table_start[ -1 * type_index ]; - const std::type_info *catch_ti = (const std::type_info *) catch_type_info; + uint8_t* catch_type_info = (uint8_t*)lsda.types_table_start; + catch_type_info -= type_index; + const std::type_info *catch_ti = get_ttype_entry(catch_type_info); // Get the type of the original exception being thrown __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; From 73fb2387ae9b2ea017fa0f2ec1e7efb794d7015d Mon Sep 17 00:00:00 2001 From: IsmailShaheen Date: Fri, 28 Feb 2020 17:34:10 +0200 Subject: [PATCH 10/16] v10 works --- abi_v10/mycppabi.cpp | 93 +++++++++++++++++++++++++++++++------------- 1 file changed, 65 insertions(+), 28 deletions(-) diff --git a/abi_v10/mycppabi.cpp b/abi_v10/mycppabi.cpp index f3e2392..28fe81e 100644 --- a/abi_v10/mycppabi.cpp +++ b/abi_v10/mycppabi.cpp @@ -54,7 +54,7 @@ void __cxa_throw(void* thrown_exception, { printf("__cxa_throw called\n"); - __cxa_exception *header = ((__cxa_exception *) thrown_exception - 1); + __cxa_exception *header = ((__cxa_exception *) thrown_exception); // We need to save the type info in the exception header _Unwind_ will // receive, otherwise we won't be able to know it when unwinding @@ -89,6 +89,44 @@ void __cxa_end_catch() * &LSDA_ptr will be a non-const pointer to a const place in memory */ typedef const uint8_t* LSDA_ptr; +typedef _uleb128_t LSDA_line; + +//This function receives a pointer the first byte to be decoded and the address of where to put the decoded value. +const unsigned char * +read_uleb128 (const unsigned char *p, _uleb128_t *val) +{ + unsigned int shift = 0; + unsigned char byte; + _uleb128_t result; + result = 0; + do + { + byte = *p++; + // Shifting the byte to the left and propagating the new byte to it (if there's any) + result |= ((_uleb128_t)byte & 0x7f) << shift; + shift += 7; + } + // if the 8th bit is 1, this means that there still another byte to be concatinated to the current byte (if zero, then decoding is done) + while (byte & 0x80); + *val = result; + return p; +} + +// This function recieves a pointer to a ttype entry and return the corrisponding type_info +// It's an implementation of three different functions from unwind-pe.h specific to our case and cannot be generalized for different encoding and size +const std::type_info * +get_ttype_entry (uint8_t* entry) +{ + const int32_t *u = (const int32_t *) entry; + unsigned long result; + + result = *u + (unsigned long)u; + entry += 4; + result = *(unsigned long *)result; + + const std::type_info *tinfo = reinterpret_cast(result); + return tinfo; +} struct LSDA_Header { /** @@ -96,46 +134,44 @@ struct LSDA_Header { * as many bytes as read */ LSDA_Header(LSDA_ptr *lsda) { - LSDA_ptr read_ptr = *lsda; - - // Copy the LSDA fields + const unsigned char *read_ptr = (const unsigned char *)*lsda; start_encoding = read_ptr[0]; type_encoding = read_ptr[1]; - type_table_offset = read_ptr[2]; - - // Advance the lsda pointer - *lsda = read_ptr + sizeof(LSDA_Header); + read_ptr += 2; + read_ptr = read_uleb128(read_ptr, &type_table_offset); + *lsda = (LSDA_ptr)read_ptr; } uint8_t start_encoding; uint8_t type_encoding; // This is the offset, from the end of the header, to the types table - uint8_t type_table_offset; + LSDA_line type_table_offset; }; struct LSDA_CS_Header { // Same as other LSDA constructors LSDA_CS_Header(LSDA_ptr *lsda) { - LSDA_ptr read_ptr = *lsda; + const unsigned char *read_ptr = (const unsigned char *)*lsda; encoding = read_ptr[0]; - length = read_ptr[1]; - *lsda = read_ptr + sizeof(LSDA_CS_Header); + read_ptr += 1; + read_ptr = read_uleb128(read_ptr, &length); + *lsda = (LSDA_ptr)read_ptr; } uint8_t encoding; - uint8_t length; + LSDA_line length; }; struct LSDA_CS { // Same as other LSDA constructors LSDA_CS(LSDA_ptr *lsda) { - LSDA_ptr read_ptr = *lsda; - start = read_ptr[0]; - len = read_ptr[1]; - lp = read_ptr[2]; - action = read_ptr[3]; - *lsda = read_ptr + sizeof(LSDA_CS); + const unsigned char *read_ptr = (const unsigned char *)*lsda; + read_ptr = read_uleb128(read_ptr, &start); + read_ptr = read_uleb128(read_ptr, &len); + read_ptr = read_uleb128(read_ptr, &lp); + read_ptr = read_uleb128(read_ptr, &action); + *lsda = (LSDA_ptr)read_ptr; } LSDA_CS() { } @@ -145,14 +181,14 @@ struct LSDA_CS { // is relative to start // Offset into function from which we could handle a throw - uint8_t start; + LSDA_line start; // Length of the block that might throw - uint8_t len; + LSDA_line len; // Landing pad - uint8_t lp; + LSDA_line lp; // Offset into action table + 1 (0 means no action) // Used to run destructors - uint8_t action; + LSDA_line action; }; /** @@ -188,7 +224,7 @@ struct LSDA // Get the start of the types table (it's actually the end of the // table, but since the action index will hold a negative index // for this table we can say it's the beginning - types_table_start( (const void**)(raw_lsda + header.type_table_offset) ), + types_table_start( (const void**)((uint8_t*)raw_lsda + header.type_table_offset) ), // Read the LSDA CS header cs_header(&raw_lsda), @@ -197,7 +233,7 @@ struct LSDA cs_table_start(raw_lsda), // Calculate where the end of the LSDA CS table is - cs_table_end(raw_lsda + cs_header.length), + cs_table_end((const LSDA_ptr)((uint8_t*)(raw_lsda) + cs_header.length)), // Get the start of action tables action_tbl_start( cs_table_end ) @@ -279,11 +315,12 @@ _Unwind_Reason_Code __gxx_personality_v0 ( // For a landing pad with a catch the action table will // hold an index to a list of types - int type_index = action[0]; + int type_index = 4 * action[0]; // Get the type of the exception we can handle - const void* catch_type_info = lsda.types_table_start[ -1 * type_index ]; - const std::type_info *catch_ti = (const std::type_info *) catch_type_info; + uint8_t* catch_type_info = (uint8_t*)lsda.types_table_start; + catch_type_info -= type_index; + const std::type_info *catch_ti = get_ttype_entry(catch_type_info); // Get the type of the original exception being thrown __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; From 6dcebc1d4231acbf7c440b1dae7360b1f90c3722 Mon Sep 17 00:00:00 2001 From: IsmailShaheen Date: Sat, 29 Feb 2020 02:42:32 +0200 Subject: [PATCH 11/16] v11 works --- abi_v11/mycppabi.cpp | 91 +++++++++++++++++++++++++++++++------------- 1 file changed, 64 insertions(+), 27 deletions(-) diff --git a/abi_v11/mycppabi.cpp b/abi_v11/mycppabi.cpp index 60acf1e..c09c9bb 100644 --- a/abi_v11/mycppabi.cpp +++ b/abi_v11/mycppabi.cpp @@ -51,7 +51,7 @@ void __cxa_throw(void* thrown_exception, std::type_info *tinfo, void (*dest)(void*)) { - __cxa_exception *header = ((__cxa_exception *) thrown_exception - 1); + __cxa_exception *header = ((__cxa_exception *) thrown_exception); // We need to save the type info in the exception header _Unwind_ will // receive, otherwise we won't be able to know it when unwinding @@ -108,6 +108,44 @@ int readSLEB128(const uint8_t* data) * &LSDA_ptr will be a non-const pointer to a const place in memory */ typedef const uint8_t* LSDA_ptr; +typedef _uleb128_t LSDA_line; + +//This function receives a pointer the first byte to be decoded and the address of where to put the decoded value. +const unsigned char * +read_uleb128 (const unsigned char *p, _uleb128_t *val) +{ + unsigned int shift = 0; + unsigned char byte; + _uleb128_t result; + result = 0; + do + { + byte = *p++; + // Shifting the byte to the left and propagating the new byte to it (if there's any) + result |= ((_uleb128_t)byte & 0x7f) << shift; + shift += 7; + } + // if the 8th bit is 1, this means that there still another byte to be concatinated to the current byte (if zero, then decoding is done) + while (byte & 0x80); + *val = result; + return p; +} + +// This function recieves a pointer to a ttype entry and return the corrisponding type_info +// It's an implementation of three different functions from unwind-pe.h specific to our case and cannot be generalized for different encoding and size +const std::type_info * +get_ttype_entry (const uint8_t* entry) +{ + const int32_t *u = (const int32_t *) entry; + unsigned long result; + + result = *u + (unsigned long)u; + entry += 4; + result = *(unsigned long *)result; + + const std::type_info *tinfo = reinterpret_cast(result); + return tinfo; +} struct LSDA_Header { /** @@ -115,46 +153,44 @@ struct LSDA_Header { * as many bytes as read */ LSDA_Header(LSDA_ptr *lsda) { - LSDA_ptr read_ptr = *lsda; - - // Copy the LSDA fields + const unsigned char *read_ptr = (const unsigned char *)*lsda; start_encoding = read_ptr[0]; type_encoding = read_ptr[1]; - type_table_offset = read_ptr[2]; - - // Advance the lsda pointer - *lsda = read_ptr + sizeof(LSDA_Header); + read_ptr += 2; + read_ptr = read_uleb128(read_ptr, &type_table_offset); + *lsda = (LSDA_ptr)read_ptr; } uint8_t start_encoding; uint8_t type_encoding; // This is the offset, from the end of the header, to the types table - uint8_t type_table_offset; + LSDA_line type_table_offset; }; struct Call_Site_Header { // Same as other LSDA constructors Call_Site_Header(LSDA_ptr *lsda) { - LSDA_ptr read_ptr = *lsda; + const unsigned char *read_ptr = (const unsigned char *)*lsda; encoding = read_ptr[0]; - length = read_ptr[1]; - *lsda = read_ptr + sizeof(Call_Site_Header); + read_ptr += 1; + read_ptr = read_uleb128(read_ptr, &length); + *lsda = (LSDA_ptr)read_ptr; } uint8_t encoding; - uint8_t length; + LSDA_line length; }; struct Call_Site { // Same as other LSDA constructors Call_Site(LSDA_ptr *lsda) { - LSDA_ptr read_ptr = *lsda; - start = read_ptr[0]; - len = read_ptr[1]; - lp = read_ptr[2]; - action = read_ptr[3]; - *lsda = read_ptr + sizeof(Call_Site); + const unsigned char *read_ptr = (const unsigned char *)*lsda; + read_ptr = read_uleb128(read_ptr, &start); + read_ptr = read_uleb128(read_ptr, &len); + read_ptr = read_uleb128(read_ptr, &lp); + read_ptr = read_uleb128(read_ptr, &action); + *lsda = (LSDA_ptr)read_ptr; } Call_Site() { } @@ -164,14 +200,14 @@ struct Call_Site { // is relative to start // Offset into function from which we could handle a throw - uint8_t start; + LSDA_line start; // Length of the block that might throw - uint8_t len; + LSDA_line len; // Landing pad - uint8_t lp; + LSDA_line lp; // Offset into action table + 1 (0 means no action) // Used to run destructors - uint8_t action; + LSDA_line action; bool has_landing_pad() const { return lp; } @@ -231,7 +267,7 @@ struct LSDA // Get the start of the types table (it's actually the end of the // table, but since the action index will hold a negative index // for this table we can say it's the beginning - types_table_start( (const void**)(raw_lsda + header.type_table_offset) ), + types_table_start( (const void**)((uint8_t*)raw_lsda + header.type_table_offset) ), // Read the LSDA CS header cs_header(&raw_lsda), @@ -240,7 +276,7 @@ struct LSDA cs_table_start(raw_lsda), // Calculate where the end of the LSDA CS table is - cs_table_end(raw_lsda + cs_header.length), + cs_table_end((const LSDA_ptr)((uint8_t*)(raw_lsda) + cs_header.length)), // Get the start of action tables action_tbl_start( cs_table_end ) @@ -352,8 +388,9 @@ struct LSDA { // The index starts at the end of the types table int idx = -1 * action->type_index; - const void* catch_type_info = this->types_table_start[idx]; - return (const std::type_info *) catch_type_info; + const uint8_t* catch_type_info = ((const uint8_t*)this->types_table_start) + (idx * 4); + //return 0; + return get_ttype_entry(catch_type_info);; } }; From ea02768227a1c4987fc06ee81f3e83dbc8d2ec01 Mon Sep 17 00:00:00 2001 From: IsmailShaheen Date: Sat, 29 Feb 2020 02:51:59 +0200 Subject: [PATCH 12/16] v12 works --- abi_v12/mycppabi.cpp | 91 +++++++++++++++++++++++++++++++------------- 1 file changed, 64 insertions(+), 27 deletions(-) diff --git a/abi_v12/mycppabi.cpp b/abi_v12/mycppabi.cpp index 8b4d643..ef4b7b7 100644 --- a/abi_v12/mycppabi.cpp +++ b/abi_v12/mycppabi.cpp @@ -51,7 +51,7 @@ void __cxa_throw(void* thrown_exception, std::type_info *tinfo, void (*dest)(void*)) { - __cxa_exception *header = ((__cxa_exception *) thrown_exception - 1); + __cxa_exception *header = ((__cxa_exception *) thrown_exception); // We need to save the type info in the exception header _Unwind_ will // receive, otherwise we won't be able to know it when unwinding @@ -108,6 +108,44 @@ int readSLEB128(const uint8_t* data) * &LSDA_ptr will be a non-const pointer to a const place in memory */ typedef const uint8_t* LSDA_ptr; +typedef _uleb128_t LSDA_line; + +//This function receives a pointer the first byte to be decoded and the address of where to put the decoded value. +const unsigned char * +read_uleb128 (const unsigned char *p, _uleb128_t *val) +{ + unsigned int shift = 0; + unsigned char byte; + _uleb128_t result; + result = 0; + do + { + byte = *p++; + // Shifting the byte to the left and propagating the new byte to it (if there's any) + result |= ((_uleb128_t)byte & 0x7f) << shift; + shift += 7; + } + // if the 8th bit is 1, this means that there still another byte to be concatinated to the current byte (if zero, then decoding is done) + while (byte & 0x80); + *val = result; + return p; +} + +// This function recieves a pointer to a ttype entry and return the corrisponding type_info +// It's an implementation of three different functions from unwind-pe.h specific to our case and cannot be generalized for different encoding and size +const std::type_info * +get_ttype_entry (const uint8_t* entry) +{ + const int32_t *u = (const int32_t *) entry; + unsigned long result; + + result = *u + (unsigned long)u; + entry += 4; + result = *(unsigned long *)result; + + const std::type_info *tinfo = reinterpret_cast(result); + return tinfo; +} struct LSDA_Header { /** @@ -115,46 +153,44 @@ struct LSDA_Header { * as many bytes as read */ LSDA_Header(LSDA_ptr *lsda) { - LSDA_ptr read_ptr = *lsda; - - // Copy the LSDA fields + const unsigned char *read_ptr = (const unsigned char *)*lsda; start_encoding = read_ptr[0]; type_encoding = read_ptr[1]; - type_table_offset = read_ptr[2]; - - // Advance the lsda pointer - *lsda = read_ptr + sizeof(LSDA_Header); + read_ptr += 2; + read_ptr = read_uleb128(read_ptr, &type_table_offset); + *lsda = (LSDA_ptr)read_ptr; } uint8_t start_encoding; uint8_t type_encoding; // This is the offset, from the end of the header, to the types table - uint8_t type_table_offset; + LSDA_line type_table_offset; }; struct Call_Site_Header { // Same as other LSDA constructors Call_Site_Header(LSDA_ptr *lsda) { - LSDA_ptr read_ptr = *lsda; + const unsigned char *read_ptr = (const unsigned char *)*lsda; encoding = read_ptr[0]; - length = read_ptr[1]; - *lsda = read_ptr + sizeof(Call_Site_Header); + read_ptr += 1; + read_ptr = read_uleb128(read_ptr, &length); + *lsda = (LSDA_ptr)read_ptr; } uint8_t encoding; - uint8_t length; + LSDA_line length; }; struct Call_Site { // Same as other LSDA constructors Call_Site(LSDA_ptr *lsda) { - LSDA_ptr read_ptr = *lsda; - start = read_ptr[0]; - len = read_ptr[1]; - lp = read_ptr[2]; - action = read_ptr[3]; - *lsda = read_ptr + sizeof(Call_Site); + const unsigned char *read_ptr = (const unsigned char *)*lsda; + read_ptr = read_uleb128(read_ptr, &start); + read_ptr = read_uleb128(read_ptr, &len); + read_ptr = read_uleb128(read_ptr, &lp); + read_ptr = read_uleb128(read_ptr, &action); + *lsda = (LSDA_ptr)read_ptr; } Call_Site() { } @@ -164,14 +200,14 @@ struct Call_Site { // is relative to start // Offset into function from which we could handle a throw - uint8_t start; + LSDA_line start; // Length of the block that might throw - uint8_t len; + LSDA_line len; // Landing pad - uint8_t lp; + LSDA_line lp; // Offset into action table + 1 (0 means no action) // Used to run destructors - uint8_t action; + LSDA_line action; bool has_landing_pad() const { return lp; } @@ -231,7 +267,7 @@ struct LSDA // Get the start of the types table (it's actually the end of the // table, but since the action index will hold a negative index // for this table we can say it's the beginning - types_table_start( (const void**)(raw_lsda + header.type_table_offset) ), + types_table_start( (const void**)((uint8_t*)raw_lsda + header.type_table_offset) ), // Read the LSDA CS header cs_header(&raw_lsda), @@ -240,7 +276,7 @@ struct LSDA cs_table_start(raw_lsda), // Calculate where the end of the LSDA CS table is - cs_table_end(raw_lsda + cs_header.length), + cs_table_end((const LSDA_ptr)((uint8_t*)(raw_lsda) + cs_header.length)), // Get the start of action tables action_tbl_start( cs_table_end ) @@ -352,8 +388,9 @@ struct LSDA { // The index starts at the end of the types table int idx = -1 * action->type_index; - const void* catch_type_info = this->types_table_start[idx]; - return (const std::type_info *) catch_type_info; + const uint8_t* catch_type_info = ((const uint8_t*)this->types_table_start) + (idx * 4); + //return 0; + return get_ttype_entry(catch_type_info);; } }; From 347e1fa4f7a05740e4c4014123bf7189a0744d0b Mon Sep 17 00:00:00 2001 From: IsmailShaheen Date: Sat, 29 Feb 2020 03:56:27 +0200 Subject: [PATCH 13/16] catch all fixed --- abi_v12/mycppabi.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/abi_v12/mycppabi.cpp b/abi_v12/mycppabi.cpp index ef4b7b7..ff584f1 100644 --- a/abi_v12/mycppabi.cpp +++ b/abi_v12/mycppabi.cpp @@ -139,6 +139,9 @@ get_ttype_entry (const uint8_t* entry) const int32_t *u = (const int32_t *) entry; unsigned long result; + if (*u == 0) + return NULL; + result = *u + (unsigned long)u; entry += 4; result = *(unsigned long *)result; @@ -494,7 +497,7 @@ _Unwind_Reason_Code __gxx_personality_v0 ( // Get the types this action can handle const std::type_info *catch_type = lsda.get_type_for(action); - if (can_handle(catch_type, thrown_exception_type)) + if (can_handle(thrown_exception_type, catch_type)) // order reversed in original { // If we are on search phase, tell _Unwind_ we can handle this one if (actions & _UA_SEARCH_PHASE) return _URC_HANDLER_FOUND; From eab0e8e3a7829dcec4a5f67d738103011f97d25d Mon Sep 17 00:00:00 2001 From: IsmailShaheen Date: Tue, 3 Mar 2020 15:29:18 +0200 Subject: [PATCH 14/16] commenting --- abi_v08/mycppabi.cpp | 6 ++++-- abi_v09/mycppabi.cpp | 4 +++- abi_v10/mycppabi.cpp | 4 +++- abi_v11/mycppabi.cpp | 4 +++- abi_v12/mycppabi.cpp | 7 +++---- 5 files changed, 16 insertions(+), 9 deletions(-) diff --git a/abi_v08/mycppabi.cpp b/abi_v08/mycppabi.cpp index dec5a90..e4c0314 100644 --- a/abi_v08/mycppabi.cpp +++ b/abi_v08/mycppabi.cpp @@ -114,13 +114,15 @@ read_uleb128 (const unsigned char *p, _uleb128_t *val) const std::type_info * get_ttype_entry (uint8_t* entry) { + // Get a pointer to the value of the address inside entry const int32_t *u = (const int32_t *) entry; unsigned long result; + // The final address will be the value stored plus the address of the value (pc relative addressing) result = *u + (unsigned long)u; - entry += 4; result = *(unsigned long *)result; + // Type cast it into a valid type_info const std::type_info *tinfo = reinterpret_cast(result); return tinfo; } @@ -128,7 +130,7 @@ get_ttype_entry (uint8_t* entry) struct LSDA_Header { /** * Read the LSDA table into a struct; advances the lsda pointer - * as many bytes as read + * as many bytes as read. The commented code is the old one and will be deletedin later version */ LSDA_Header(LSDA_ptr *lsda) { // LSDA_ptr read_ptr = *lsda; diff --git a/abi_v09/mycppabi.cpp b/abi_v09/mycppabi.cpp index 5e84e1b..db1d1a8 100644 --- a/abi_v09/mycppabi.cpp +++ b/abi_v09/mycppabi.cpp @@ -119,13 +119,15 @@ read_uleb128 (const unsigned char *p, _uleb128_t *val) const std::type_info * get_ttype_entry (uint8_t* entry) { + // Get a pointer to the value of the address inside entry const int32_t *u = (const int32_t *) entry; unsigned long result; + // The final address will be the value stored plus the address of the value (pc relative addressing) result = *u + (unsigned long)u; - entry += 4; result = *(unsigned long *)result; + // Type cast it into a valid type_info const std::type_info *tinfo = reinterpret_cast(result); return tinfo; } diff --git a/abi_v10/mycppabi.cpp b/abi_v10/mycppabi.cpp index 28fe81e..aa8d6b0 100644 --- a/abi_v10/mycppabi.cpp +++ b/abi_v10/mycppabi.cpp @@ -117,13 +117,15 @@ read_uleb128 (const unsigned char *p, _uleb128_t *val) const std::type_info * get_ttype_entry (uint8_t* entry) { + // Get a pointer to the value of the address inside entry const int32_t *u = (const int32_t *) entry; unsigned long result; + // The final address will be the value stored plus the address of the value (pc relative addressing) result = *u + (unsigned long)u; - entry += 4; result = *(unsigned long *)result; + // Type cast it into a valid type_info const std::type_info *tinfo = reinterpret_cast(result); return tinfo; } diff --git a/abi_v11/mycppabi.cpp b/abi_v11/mycppabi.cpp index c09c9bb..39f2e12 100644 --- a/abi_v11/mycppabi.cpp +++ b/abi_v11/mycppabi.cpp @@ -136,13 +136,15 @@ read_uleb128 (const unsigned char *p, _uleb128_t *val) const std::type_info * get_ttype_entry (const uint8_t* entry) { + // Get a pointer to the value of the address inside entry const int32_t *u = (const int32_t *) entry; unsigned long result; + // The final address will be the value stored plus the address of the value (pc relative addressing) result = *u + (unsigned long)u; - entry += 4; result = *(unsigned long *)result; + // Type cast it into a valid type_info const std::type_info *tinfo = reinterpret_cast(result); return tinfo; } diff --git a/abi_v12/mycppabi.cpp b/abi_v12/mycppabi.cpp index ff584f1..c580d3a 100644 --- a/abi_v12/mycppabi.cpp +++ b/abi_v12/mycppabi.cpp @@ -136,16 +136,15 @@ read_uleb128 (const unsigned char *p, _uleb128_t *val) const std::type_info * get_ttype_entry (const uint8_t* entry) { + // Get a pointer to the value of the address inside entry const int32_t *u = (const int32_t *) entry; unsigned long result; - if (*u == 0) - return NULL; - + // The final address will be the value stored plus the address of the value (pc relative addressing) result = *u + (unsigned long)u; - entry += 4; result = *(unsigned long *)result; + // Type cast it into a valid type_info const std::type_info *tinfo = reinterpret_cast(result); return tinfo; } From ab84f280cc7a12d370d5e52fc0f34ae7306b732a Mon Sep 17 00:00:00 2001 From: IsmailShaheen Date: Fri, 6 Mar 2020 16:12:32 +0200 Subject: [PATCH 15/16] ready for review --- debugging.txt | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 debugging.txt diff --git a/debugging.txt b/debugging.txt new file mode 100644 index 0000000..5d687da --- /dev/null +++ b/debugging.txt @@ -0,0 +1,46 @@ +### ULEB128 encoding +As mentioned in the blog (prior knowledge of the source code from the blog until v08 is required), the personality function iterates through the LSDA call site table (LSDACS) entries in search for a proper handler. the entries are encoded in ULEB128 formate (for god knows why) and one of the assumptions that sadly wasn't true is that the values will be small enough so that their encoded value will be the same as the original (check [ULEB128 encoding](https://en.wikipedia.org/wiki/LEB128) for more info about the encoding process). The values stored represent relative addresses for possible handlers and while the assumption holds true for this case on a 32 bit machine, the longer machine code in a 64 bit resulted in a higher value for the relative addresses ultimately exceeding 127 (which is the maximum value that has the same encoding as its original) and as result the value read directly from the call site table wasn't the ones we needed and we had to proberly decode them. To solve this issue, a simple decoding function 'read_uleb128' was implemented and called each time a uleb128 entry was accessed. The result is, we can now access all the entries (with the correct values) in the lsda table, but it's never too easy. We still had the segmentation fault error, and the reason this time was another architicture dependant issue. +### Void* size +After finding the correct handler from the call site table, the next step is accessing its related entry in the action table (and we can do this without a problem). The problem happens when we try jumping to the needed entry in the type table (basic understanding of the exception handling flow is required). Entries in type table are of type long and hold addresses to the needed data types (of type 'type_info') to check the thrown exception type. '.long' data type in x86 assembly (mostly anywhere actually) have a size of 4 bytes. The original source code iterated the table with the help of a simple void pointer and some pointer arthematics. ++1-ing a void pointer simply adds its size ('sizeof(void*)' which is 4 byte for 32 bit architicture) to the address contained in the pointer and this is how we access subsequent entries in the table, so far so good. Now when we go to a 64 bit machine, the size of the void* increases to 8 bytes but the entries are still spaced at 4 byte (because the .long size doesn't change with the architicture) and what happens is a troublsome out of bounds case. by modifying the mechanism of iteration (modifying the pointer size) we were able to access the correct address value. Now you would think that by jumping to this address we can have our required 'type_info', little did we know it wasn't that simple. +### Table type entries encoding +In one of the earlier version when we first started reading the lsda, we came across a '.byte' entry that we ignored assuming that it holds unnecessary information about the encoding of the type table. Well, this seamingly innocent single byte value should be masked with 3 different values to get the appropriate size, encoding, and relative address base. Now the size and encoding were not a problem (well we already solved the size issue and the size directives made it clear that this is a 4 byte value). The relative address base on the other hand was wrongfully ignored. It was assumed in the blog that the adress was an absolute address to a location in the assembly code (it was actually if you try it in the same environment). It turns out it's a pc-relative address (relative to the location of the current entry to be exact) after tracing the eh-personality of the libsupc++ library on an 64 bit machine. In order to get the correct address, just add the value found in the type table to the address of the value in the table (this was implemented in 'get_ttype_entry'). And there you have it, v08 now finally works on an x86_64 machine. We were hoping that propagating the changes to v12 would solve everything, but '__cxa_throw' function had another say in the matter. +### __cxa_throw 'thrown_exception' parameter +If you jump all the way up to cxa_throw you will notice that there is a weird -1 (in the old version at least). This -1 moves the '\*header' up by the size of '__cxa_exception'. The only logical reason you would need to do this is if the pointer '\*thrown_exception' that is passed to the function was pointing to the end of the struct and not the begining, but who decides where the pointer is? Well, it's '__cxa_allocate' but in our version it's normally pointing to the begining of the buffer that would be casted later on to a '__cxa_exception' type. So, all that we need is to remove the -1 and all will be good, right? Well actually this indeed solved the problem this time, but (there is always a but) the allocate method in gcc/libsupc++ responsible for exception handling sends the pointer at the end for some reason, so it's a good idea to follow it just in case some unwind function expects the '\*thrown_exception' to point at the end. Get the -1 back and make allocate point to the end of the buffer. And there you have it, your minimal working exception handling ABI. +____ +### TTBase_encoding break down +The info stored in @TTBase_encoding can be obtained by applying different masks + +To get the size of the encoded value mask it with 0x07 +|Mask Result |Size | +|-------------|---------------| +|0x00 |sizeof(void*) | +|0x02 |2 bytes | +|0x03 |4 bytes | +|0x04 |8 bytes | + +To get the encoding and data type mask it with 0x0f +|Mask Result |Type | +|-------------|-------------------| +|0x00 |void* | +|0x01 |uleb128 | +|0x09 |sleb128 | +|0x02 |unsigned 2 bytes | +|0x03 |unsigned 4 bytes | +|0x04 |unsigned 8 bytes | +|0x0a |signed 2 bytes | +|0x0b |signed 4 bytes | +|0x0c |signed 8 bytes | + +There is a special treatment if the value of @TTBase_encoding is 0x50 (if it's of reference aligned) + +To get the base of the relative address mask it with 0x70 +|Mask Result |Reference | +|-------------|-------------------| +|0x00 |absolute ptr | +|0x10 |pc relative | +|0x50 |aligned* | +|0x20 |text relative | +|0x30 |data relative | +|0x40 |function relative | + +*aligned is still unknown and for know is deemed unnecessary \ No newline at end of file From 0de7d23aa1604879ddc755b28ec72354f5221cdd Mon Sep 17 00:00:00 2001 From: Ismail Shaheen <30374605+IsmailShaheen@users.noreply.github.com> Date: Fri, 6 Mar 2020 16:14:54 +0200 Subject: [PATCH 16/16] typos --- debugging.txt => debugging.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename debugging.txt => debugging.md (99%) diff --git a/debugging.txt b/debugging.md similarity index 99% rename from debugging.txt rename to debugging.md index 5d687da..a42e0d3 100644 --- a/debugging.txt +++ b/debugging.md @@ -43,4 +43,4 @@ To get the base of the relative address mask it with 0x70 |0x30 |data relative | |0x40 |function relative | -*aligned is still unknown and for know is deemed unnecessary \ No newline at end of file +*aligned is still unknown and for know is deemed unnecessary