COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0(int version, _Unwind_Action actions, uint64_t exceptionClass, struct _Unwind_Exception* exceptionObject, struct _Unwind_Context *context) #endif { /* Since C does not have catch clauses, there is nothing to do during */ /* phase 1 (the search phase). */ if ( actions & _UA_SEARCH_PHASE ) return _URC_CONTINUE_UNWIND; /* There is nothing to do if there is no LSDA for this frame. */ const uint8_t* lsda = (uint8_t*)_Unwind_GetLanguageSpecificData(context); if ( lsda == (uint8_t*) 0 ) return _URC_CONTINUE_UNWIND; uintptr_t pc = _Unwind_GetIP(context)-1; uintptr_t funcStart = _Unwind_GetRegionStart(context); uintptr_t pcOffset = pc - funcStart; /* Parse LSDA header. */ uint8_t lpStartEncoding = *lsda++; if (lpStartEncoding != DW_EH_PE_omit) { readEncodedPointer(&lsda, lpStartEncoding); } uint8_t ttypeEncoding = *lsda++; if (ttypeEncoding != DW_EH_PE_omit) { readULEB128(&lsda); } /* Walk call-site table looking for range that includes current PC. */ uint8_t callSiteEncoding = *lsda++; uint32_t callSiteTableLength = readULEB128(&lsda); const uint8_t* callSiteTableStart = lsda; const uint8_t* callSiteTableEnd = callSiteTableStart + callSiteTableLength; const uint8_t* p=callSiteTableStart; while (p < callSiteTableEnd) { uintptr_t start = readEncodedPointer(&p, callSiteEncoding); uintptr_t length = readEncodedPointer(&p, callSiteEncoding); uintptr_t landingPad = readEncodedPointer(&p, callSiteEncoding); readULEB128(&p); /* action value not used for C code */ if ( landingPad == 0 ) continue; /* no landing pad for this entry */ if ( (start <= pcOffset) && (pcOffset < (start+length)) ) { /* Found landing pad for the PC. * Set Instruction Pointer to so we re-enter function * at landing pad. The landing pad is created by the compiler * to take two parameters in registers. */ _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), (uintptr_t)exceptionObject); _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), 0); _Unwind_SetIP(context, (funcStart + landingPad)); return _URC_INSTALL_CONTEXT; } } /* No landing pad found, continue unwinding. */ return _URC_CONTINUE_UNWIND; }
/* This is checking a thrown exception type, excpType, against a possibly empty list of catchType's which make up an exception spec. An exception spec acts like a catch handler, but in reverse. This "catch handler" will catch an excpType if and only if none of the catchType's in the list will catch a excpType. If any catchType in the list can catch an excpType, then this exception spec does not catch the excpType. */ static bool exception_spec_can_catch(int64_t specIndex, const uint8_t* classInfo, uint8_t ttypeEncoding, const __shim_type_info* excpType, void* adjustedPtr, _Unwind_Exception* unwind_exception) { if (classInfo == 0) { // this should not happen. Indicates corrupted eh_table. call_terminate(false, unwind_exception); } // specIndex is negative of 1-based byte offset into classInfo; specIndex = -specIndex; --specIndex; const uint8_t* temp = classInfo + specIndex; // If any type in the spec list can catch excpType, return false, else return true // adjustments to adjustedPtr are ignored. while (true) { uint64_t ttypeIndex = readULEB128(&temp); if (ttypeIndex == 0) break; const __shim_type_info* catchType = get_shim_type_info(ttypeIndex, classInfo, ttypeEncoding, true, unwind_exception); void* tempPtr = adjustedPtr; if (catchType->can_catch(excpType, tempPtr)) return false; } return true; }
void __cxa_call_unexpected(void* arg) { _Unwind_Exception* unwind_exception = static_cast<_Unwind_Exception*>(arg); if (unwind_exception == 0) call_terminate(false, unwind_exception); __cxa_begin_catch(unwind_exception); bool native_old_exception = (reinterpret_cast<uint64_t>(unwind_exception->exception_class) & get_vendor_and_language) == (kOurExceptionClass & get_vendor_and_language); std::unexpected_handler u_handler; std::terminate_handler t_handler; __cxa_exception* old_exception_header = 0; int64_t ttypeIndex; const uint8_t* lsda; if (native_old_exception) { old_exception_header = (__cxa_exception*)(unwind_exception+1) - 1; t_handler = old_exception_header->terminateHandler; u_handler = old_exception_header->unexpectedHandler; // If std::__unexpected(u_handler) rethrows the same exception, // these values get overwritten by the rethrow. So save them now: #ifndef __ARM_EABI_UNWINDER__ ttypeIndex = old_exception_header->handlerSwitchValue; lsda = old_exception_header->languageSpecificData; #endif } else { t_handler = std::get_terminate(); u_handler = std::get_unexpected(); } try { std::__unexpected(u_handler); } catch (...) { // If the old exception is foreign, then all we can do is terminate. // We have no way to recover the needed old exception spec. There's // no way to pass that information here. And the personality routine // can't call us directly and do anything but terminate() if we throw // from here. if (native_old_exception) { // Have: // old_exception_header->languageSpecificData // old_exception_header->actionRecord // Need // const uint8_t* classInfo // uint8_t ttypeEncoding uint8_t lpStartEncoding = *lsda++; const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding); (void)lpStart; // purposefully unused. Just needed to increment lsda. uint8_t ttypeEncoding = *lsda++; if (ttypeEncoding == DW_EH_PE_omit) std::__terminate(t_handler); uintptr_t classInfoOffset = readULEB128(&lsda); const uint8_t* classInfo = lsda + classInfoOffset; // Is this new exception catchable by the exception spec at ttypeIndex? // The answer is obviously yes if the new and old exceptions are the same exception // If no // throw; __cxa_eh_globals* globals = __cxa_get_globals_fast(); __cxa_exception* new_exception_header = globals->caughtExceptions; if (new_exception_header == 0) // This shouldn't be able to happen! std::__terminate(t_handler); bool native_new_exception = (reinterpret_cast<uint64_t>(new_exception_header->unwindHeader.exception_class) & get_vendor_and_language) == (kOurExceptionClass & get_vendor_and_language); void* adjustedPtr; if (native_new_exception && (new_exception_header != old_exception_header)) { const __shim_type_info* excpType = static_cast<const __shim_type_info*>(new_exception_header->exceptionType); adjustedPtr = reinterpret_cast<uint64_t>(new_exception_header->unwindHeader.exception_class) == kOurDependentExceptionClass ? ((__cxa_dependent_exception*)new_exception_header)->primaryException : new_exception_header + 1; if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding, excpType, adjustedPtr, unwind_exception)) { // We need to __cxa_end_catch, but for the old exception, // not the new one. This is a little tricky ... // Disguise new_exception_header as a rethrown exception, but // don't actually rethrow it. This means you can temporarily // end the catch clause enclosing new_exception_header without // __cxa_end_catch destroying new_exception_header. new_exception_header->handlerCount = -new_exception_header->handlerCount; globals->uncaughtExceptions += 1; // Call __cxa_end_catch for new_exception_header __cxa_end_catch(); // Call __cxa_end_catch for old_exception_header __cxa_end_catch(); // Renter this catch clause with new_exception_header __cxa_begin_catch(&new_exception_header->unwindHeader); // Rethrow new_exception_header throw; } } // Will a std::bad_exception be catchable by the exception spec at // ttypeIndex? // If no // throw std::bad_exception(); const __shim_type_info* excpType = static_cast<const __shim_type_info*>(&typeid(std::bad_exception)); std::bad_exception be; adjustedPtr = &be; if (!exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding, excpType, adjustedPtr, unwind_exception)) { // We need to __cxa_end_catch for both the old exception and the // new exception. Technically we should do it in that order. // But it is expedient to do it in the opposite order: // Call __cxa_end_catch for new_exception_header __cxa_end_catch(); // Throw std::bad_exception will __cxa_end_catch for // old_exception_header throw be; } } } std::__terminate(t_handler); }
static void scan_eh_tab(scan_results& results, _Unwind_Action actions, bool native_exception, _Unwind_Exception* unwind_exception, _Unwind_Context* context) { // Initialize results to found nothing but an error results.ttypeIndex = 0; results.actionRecord = 0; results.languageSpecificData = 0; results.landingPad = 0; results.adjustedPtr = 0; results.reason = _URC_FATAL_PHASE1_ERROR; // Check for consistent actions if (actions & _UA_SEARCH_PHASE) { // Do Phase 1 if (actions & (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME | _UA_FORCE_UNWIND)) { // None of these flags should be set during Phase 1 // Client error results.reason = _URC_FATAL_PHASE1_ERROR; return; } } else if (actions & _UA_CLEANUP_PHASE) { if ((actions & _UA_HANDLER_FRAME) && (actions & _UA_FORCE_UNWIND)) { // _UA_HANDLER_FRAME should only be set if phase 1 found a handler. // If _UA_FORCE_UNWIND is set, phase 1 shouldn't have happened. // Client error results.reason = _URC_FATAL_PHASE2_ERROR; return; } } else // Neither _UA_SEARCH_PHASE nor _UA_CLEANUP_PHASE is set { // One of these should be set. // Client error results.reason = _URC_FATAL_PHASE1_ERROR; return; } // Start scan by getting exception table address const uint8_t* lsda = (const uint8_t*)_Unwind_GetLanguageSpecificData(context); if (lsda == 0) { // There is no exception table results.reason = _URC_CONTINUE_UNWIND; return; } results.languageSpecificData = lsda; // Get the current instruction pointer and offset it before next // instruction in the current frame which threw the exception. uintptr_t ip = _Unwind_GetIP(context) - 1; // Get beginning current frame's code (as defined by the // emitted dwarf code) uintptr_t funcStart = _Unwind_GetRegionStart(context); #if __arm__ if (ip == uintptr_t(-1)) { // no action results.reason = _URC_CONTINUE_UNWIND; return; } else if (ip == 0) call_terminate(native_exception, unwind_exception); // ip is 1-based index into call site table #else // __arm__ uintptr_t ipOffset = ip - funcStart; #endif // __arm__ const uint8_t* classInfo = NULL; // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding // dwarf emission // Parse LSDA header. uint8_t lpStartEncoding = *lsda++; const uint8_t* lpStart = (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding); if (lpStart == 0) lpStart = (const uint8_t*)funcStart; uint8_t ttypeEncoding = *lsda++; if (ttypeEncoding != DW_EH_PE_omit) { // Calculate type info locations in emitted dwarf code which // were flagged by type info arguments to llvm.eh.selector // intrinsic uintptr_t classInfoOffset = readULEB128(&lsda); classInfo = lsda + classInfoOffset; } // Walk call-site table looking for range that // includes current PC. uint8_t callSiteEncoding = *lsda++; #if __arm__ (void)callSiteEncoding; // On arm callSiteEncoding is never used #endif uint32_t callSiteTableLength = static_cast<uint32_t>(readULEB128(&lsda)); const uint8_t* callSiteTableStart = lsda; const uint8_t* callSiteTableEnd = callSiteTableStart + callSiteTableLength; const uint8_t* actionTableStart = callSiteTableEnd; const uint8_t* callSitePtr = callSiteTableStart; while (callSitePtr < callSiteTableEnd) { // There is one entry per call site. #if !__arm__ // The call sites are non-overlapping in [start, start+length) // The call sites are ordered in increasing value of start uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding); uintptr_t length = readEncodedPointer(&callSitePtr, callSiteEncoding); uintptr_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding); uintptr_t actionEntry = readULEB128(&callSitePtr); if ((start <= ipOffset) && (ipOffset < (start + length))) #else // __arm__ // ip is 1-based index into this table uintptr_t landingPad = readULEB128(&callSitePtr); uintptr_t actionEntry = readULEB128(&callSitePtr); if (--ip == 0) #endif // __arm__ { // Found the call site containing ip. #if !__arm__ if (landingPad == 0) { // No handler here results.reason = _URC_CONTINUE_UNWIND; return; } landingPad = (uintptr_t)lpStart + landingPad; #else // __arm__ ++landingPad; #endif // __arm__ if (actionEntry == 0) { // Found a cleanup // If this is a type 1 or type 2 search, there are no handlers // If this is a type 3 search, you want to install the cleanup. if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME)) { results.ttypeIndex = 0; // Redundant but clarifying results.landingPad = landingPad; results.reason = _URC_HANDLER_FOUND; return; } // No handler here results.reason = _URC_CONTINUE_UNWIND; return; } // Convert 1-based byte offset into const uint8_t* action = actionTableStart + (actionEntry - 1); // Scan action entries until you find a matching handler, cleanup, or the end of action list while (true) { const uint8_t* actionRecord = action; int64_t ttypeIndex = readSLEB128(&action); if (ttypeIndex > 0) { // Found a catch, does it actually catch? // First check for catch (...) const __shim_type_info* catchType = get_shim_type_info(static_cast<uint64_t>(ttypeIndex), classInfo, ttypeEncoding, native_exception, unwind_exception); if (catchType == 0) { // Found catch (...) catches everything, including foreign exceptions // If this is a type 1 search save state and return _URC_HANDLER_FOUND // If this is a type 2 search save state and return _URC_HANDLER_FOUND // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1! // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME)) { // Save state and return _URC_HANDLER_FOUND results.ttypeIndex = ttypeIndex; results.actionRecord = actionRecord; results.landingPad = landingPad; results.adjustedPtr = get_thrown_object_ptr(unwind_exception); results.reason = _URC_HANDLER_FOUND; return; } else if (!(actions & _UA_FORCE_UNWIND)) { // It looks like the exception table has changed // on us. Likely stack corruption! call_terminate(native_exception, unwind_exception); } } // Else this is a catch (T) clause and will never // catch a foreign exception else if (native_exception) { __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; void* adjustedPtr = get_thrown_object_ptr(unwind_exception); const __shim_type_info* excpType = static_cast<const __shim_type_info*>(exception_header->exceptionType); if (adjustedPtr == 0 || excpType == 0) { // Something very bad happened call_terminate(native_exception, unwind_exception); } if (catchType->can_catch(excpType, adjustedPtr)) { // Found a matching handler // If this is a type 1 search save state and return _URC_HANDLER_FOUND // If this is a type 3 search and !_UA_FORCE_UNWIND, we should have found this in phase 1! // If this is a type 3 search and _UA_FORCE_UNWIND, ignore handler and continue scan if (actions & _UA_SEARCH_PHASE) { // Save state and return _URC_HANDLER_FOUND results.ttypeIndex = ttypeIndex; results.actionRecord = actionRecord; results.landingPad = landingPad; results.adjustedPtr = adjustedPtr; results.reason = _URC_HANDLER_FOUND; return; } else if (!(actions & _UA_FORCE_UNWIND)) { // It looks like the exception table has changed // on us. Likely stack corruption! call_terminate(native_exception, unwind_exception); } } } // Scan next action ... } else if (ttypeIndex < 0) { // Found an exception spec. If this is a foreign exception, // it is always caught. if (native_exception) { // Does the exception spec catch this native exception? __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; void* adjustedPtr = get_thrown_object_ptr(unwind_exception); const __shim_type_info* excpType = static_cast<const __shim_type_info*>(exception_header->exceptionType); if (adjustedPtr == 0 || excpType == 0) { // Something very bad happened call_terminate(native_exception, unwind_exception); } if (exception_spec_can_catch(ttypeIndex, classInfo, ttypeEncoding, excpType, adjustedPtr, unwind_exception)) { // native exception caught by exception spec // If this is a type 1 search, save state and return _URC_HANDLER_FOUND // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1! // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan if (actions & _UA_SEARCH_PHASE) { // Save state and return _URC_HANDLER_FOUND results.ttypeIndex = ttypeIndex; results.actionRecord = actionRecord; results.landingPad = landingPad; results.adjustedPtr = adjustedPtr; results.reason = _URC_HANDLER_FOUND; return; } else if (!(actions & _UA_FORCE_UNWIND)) { // It looks like the exception table has changed // on us. Likely stack corruption! call_terminate(native_exception, unwind_exception); } } } else { // foreign exception caught by exception spec // If this is a type 1 search, save state and return _URC_HANDLER_FOUND // If this is a type 2 search, save state and return _URC_HANDLER_FOUND // If this is a type 3 search !_UA_FORCE_UNWIND, we should have found this in phase 1! // If this is a type 3 search _UA_FORCE_UNWIND, ignore handler and continue scan if ((actions & _UA_SEARCH_PHASE) || (actions & _UA_HANDLER_FRAME)) { // Save state and return _URC_HANDLER_FOUND results.ttypeIndex = ttypeIndex; results.actionRecord = actionRecord; results.landingPad = landingPad; results.adjustedPtr = get_thrown_object_ptr(unwind_exception); results.reason = _URC_HANDLER_FOUND; return; } else if (!(actions & _UA_FORCE_UNWIND)) { // It looks like the exception table has changed // on us. Likely stack corruption! call_terminate(native_exception, unwind_exception); } } // Scan next action ... } else // ttypeIndex == 0 { // Found a cleanup // If this is a type 1 search, ignore it and continue scan // If this is a type 2 search, ignore it and continue scan // If this is a type 3 search, save state and return _URC_HANDLER_FOUND if ((actions & _UA_CLEANUP_PHASE) && !(actions & _UA_HANDLER_FRAME)) { // Save state and return _URC_HANDLER_FOUND results.ttypeIndex = ttypeIndex; results.actionRecord = actionRecord; results.landingPad = landingPad; results.adjustedPtr = get_thrown_object_ptr(unwind_exception); results.reason = _URC_HANDLER_FOUND; return; } } const uint8_t* temp = action; int64_t actionOffset = readSLEB128(&temp); if (actionOffset == 0) { // End of action list, no matching handler or cleanup found results.reason = _URC_CONTINUE_UNWIND; return; } // Go to next action action += actionOffset; } // there is no break out of this loop, only return } #if !__arm__ else if (ipOffset < start) { // There is no call site for this ip // Something bad has happened. We should never get here. // Possible stack corruption. call_terminate(native_exception, unwind_exception); } #endif // !__arm__ } // there might be some tricky cases which break out of this loop // It is possible that no eh table entry specify how to handle // this exception. By spec, terminate it immediately. call_terminate(native_exception, unwind_exception); }
/// Read a pointer encoded value and advance pointer /// See Variable Length Data in: /// @link http://dwarfstd.org/Dwarf3.pdf @unlink /// @param data reference variable holding memory pointer to decode from /// @param encoding dwarf encoding type /// @returns decoded value static uintptr_t readEncodedPointer(const uint8_t** data, uint8_t encoding) { uintptr_t result = 0; if (encoding == DW_EH_PE_omit) return result; const uint8_t* p = *data; // first get value switch (encoding & 0x0F) { case DW_EH_PE_absptr: result = *((uintptr_t*)p); p += sizeof(uintptr_t); break; case DW_EH_PE_uleb128: result = readULEB128(&p); break; case DW_EH_PE_sleb128: result = static_cast<uintptr_t>(readSLEB128(&p)); break; case DW_EH_PE_udata2: result = *((uint16_t*)p); p += sizeof(uint16_t); break; case DW_EH_PE_udata4: result = *((uint32_t*)p); p += sizeof(uint32_t); break; case DW_EH_PE_udata8: result = static_cast<uintptr_t>(*((uint64_t*)p)); p += sizeof(uint64_t); break; case DW_EH_PE_sdata2: result = static_cast<uintptr_t>(*((int16_t*)p)); p += sizeof(int16_t); break; case DW_EH_PE_sdata4: result = static_cast<uintptr_t>(*((int32_t*)p)); p += sizeof(int32_t); break; case DW_EH_PE_sdata8: result = static_cast<uintptr_t>(*((int64_t*)p)); p += sizeof(int64_t); break; default: // not supported abort(); break; } // then add relative offset switch (encoding & 0x70) { case DW_EH_PE_absptr: // do nothing break; case DW_EH_PE_pcrel: if (result) result += (uintptr_t)(*data); break; case DW_EH_PE_textrel: case DW_EH_PE_datarel: case DW_EH_PE_funcrel: case DW_EH_PE_aligned: default: // not supported abort(); break; } // then apply indirection if (result && (encoding & DW_EH_PE_indirect)) result = *((uintptr_t*)result); *data = p; return result; }
/* read a pointer encoded value and advance pointer */ static uintptr_t readEncodedPointer(const uint8_t** data, uint8_t encoding) { const uint8_t* p = *data; uintptr_t result = 0; if (encoding == DW_EH_PE_omit) return 0; /* first get value */ switch (encoding & 0x0F) { case DW_EH_PE_absptr: result = *((const uintptr_t*) p); p += sizeof(uintptr_t); break; case DW_EH_PE_uleb128: result = readULEB128(&p); break; case DW_EH_PE_udata2: result = *((const uint16_t*) p); p += sizeof(uint16_t); break; case DW_EH_PE_udata4: result = *((const uint32_t*) p); p += sizeof(uint32_t); break; case DW_EH_PE_udata8: result = *((const uint64_t*) p); p += sizeof(uint64_t); break; case DW_EH_PE_sdata2: result = *((const int16_t*) p); p += sizeof(int16_t); break; case DW_EH_PE_sdata4: result = *((const int32_t*) p); p += sizeof(int32_t); break; case DW_EH_PE_sdata8: result = *((const int64_t*) p); p += sizeof(int64_t); break; case DW_EH_PE_sleb128: default: /* not supported */ abort(); break; } /* then add relative offset */ switch (encoding & 0x70) { case DW_EH_PE_absptr: /* do nothing */ break; case DW_EH_PE_pcrel: result += (uintptr_t)(*data); break; case DW_EH_PE_textrel: case DW_EH_PE_datarel: case DW_EH_PE_funcrel: case DW_EH_PE_aligned: default: /* not supported */ abort(); break; } /* then apply indirection */ if (encoding & DW_EH_PE_indirect) { result = *((const uintptr_t*) result); } *data = p; return result; }
void MergeFile::copyFormTo( MergeFile& out, dr_section sect, uint_32& off, uint_32 form, uint_8 addrSize ) //----------------------------------------------------------------------- { uint_32 num; char * buffer; uint_32 bufLen; uint_8 buf8[ 8 ]; switch( form ) { /* do all simple numeric forms */ case DW_FORM_addr: case DW_FORM_flag: case DW_FORM_data1: case DW_FORM_ref1: case DW_FORM_data2: case DW_FORM_ref2: case DW_FORM_data4: case DW_FORM_ref4: case DW_FORM_sdata: case DW_FORM_udata: case DW_FORM_ref_udata: case DW_FORM_ref_addr: num = readForm( sect, off, form, addrSize ); out.writeForm( form, num, addrSize ); break; case DW_FORM_block1: bufLen = readByte( sect, off ); out.writeByte( (uint_8) bufLen ); if( bufLen ) { buffer = new char[ bufLen ]; readBlock( sect, off, buffer, bufLen ); out.writeBlock( buffer, bufLen ); delete [] buffer; } break; case DW_FORM_block2: bufLen = readWord( sect, off ); out.writeWord( (uint_16) bufLen ); if( bufLen ) { buffer = new char[ bufLen ]; readBlock( sect, off, buffer, bufLen ); out.writeBlock( buffer, bufLen ); delete [] buffer; } break; case DW_FORM_block4: bufLen = readDWord( sect, off ); out.writeDWord( bufLen ); if( bufLen ) { buffer = new char[ bufLen ]; readBlock( sect, off, buffer, bufLen ); out.writeBlock( buffer, bufLen ); delete [] buffer; } break; case DW_FORM_block: bufLen = readULEB128( sect, off ); if( bufLen ) { buffer = new char[ bufLen ]; readBlock( sect, off, buffer, bufLen ); out.writeBlock( buffer, bufLen ); delete [] buffer; } break; case DW_FORM_data8: readBlock( sect, off, buf8, 8 ); out.writeBlock( buf8, 8 ); break; case DW_FORM_string: do { num = readByte( sect, off ); out.writeByte( (uint_8) num ); } while( num != 0 ); break; case DW_FORM_indirect: num = readULEB128( sect, off ); out.writeULEB128( num ); copyFormTo( out, sect, off, num, addrSize ); break; default: #if DEBUG printf( "ACK -- form %#x\n", form ); #endif InternalAssert( 0 ); } }
void MergeFile::skipForm( dr_section sect, uint_32& off, uint_32 form, uint_8 addrSize ) //--------------------------------------------------------------------- { uint_32 value; switch( form ) { case DW_FORM_addr: off += addrSize; break; case DW_FORM_block1: off += readByte( sect, off ); break; case DW_FORM_block2: off += readWord( sect, off ); break; case DW_FORM_block4: off += readDWord( sect, off ); break; case DW_FORM_block: value = readULEB128( sect, off ); off += value; break; case DW_FORM_flag: case DW_FORM_data1: case DW_FORM_ref1: off += 1; break; case DW_FORM_data2: case DW_FORM_ref2: off += 2; break; case DW_FORM_ref_addr: // NYI: non-standard behaviour for form_ref case DW_FORM_data4: case DW_FORM_ref4: off += 4; break; case DW_FORM_data8: off += 8; break; case DW_FORM_sdata: readSLEB128( sect, off ); break; case DW_FORM_udata: case DW_FORM_ref_udata: readULEB128( sect, off ); break; case DW_FORM_string: while( readByte( sect, off ) != 0 ); break; case DW_FORM_indirect: value = readULEB128( sect, off ); skipForm( sect, off, value, addrSize ); break; default: #if DEBUG printf( "ACK -- form %#x\n", form ); #endif InternalAssert( 0 ); } }