pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, const unw_proc_info_t *ctx) { pint_t startAddr = addr; const uint8_t *p = (uint8_t *)addr; pint_t result; if (encoding == DW_EH_PE_omit) return 0; if (encoding == DW_EH_PE_aligned) { addr = (addr + sizeof(pint_t) - 1) & sizeof(pint_t); return getP(addr); } // first get value switch (encoding & 0x0F) { case DW_EH_PE_ptr: result = getP(addr); p += sizeof(pint_t); addr = (pint_t)p; break; case DW_EH_PE_uleb128: result = getULEB128(addr, end); break; case DW_EH_PE_udata2: result = get16(addr); p += 2; addr = (pint_t)p; break; case DW_EH_PE_udata4: result = get32(addr); p += 4; addr = (pint_t)p; break; case DW_EH_PE_udata8: result = get64(addr); p += 8; addr = (pint_t)p; break; case DW_EH_PE_sleb128: result = getSLEB128(addr, end); break; case DW_EH_PE_sdata2: result = (int16_t)get16(addr); p += 2; addr = (pint_t)p; break; case DW_EH_PE_sdata4: result = (int32_t)get32(addr); p += 4; addr = (pint_t)p; break; case DW_EH_PE_sdata8: result = get64(addr); p += 8; addr = (pint_t)p; break; case DW_EH_PE_omit: result = 0; break; default: assert(0 && "unknown pointer encoding"); } // then add relative offset switch (encoding & 0x70) { case DW_EH_PE_absptr: // do nothing break; case DW_EH_PE_pcrel: result += startAddr; break; case DW_EH_PE_textrel: assert(0 && "DW_EH_PE_textrel pointer encoding not supported"); break; case DW_EH_PE_datarel: assert(ctx != NULL && "DW_EH_PE_datarel without context"); if (ctx) result += ctx->data_base; break; case DW_EH_PE_funcrel: assert(ctx != NULL && "DW_EH_PE_funcrel without context"); if (ctx) result += ctx->start_ip; break; case DW_EH_PE_aligned: __builtin_unreachable(); default: assert(0 && "unknown pointer encoding"); break; } if (encoding & DW_EH_PE_indirect) result = getP(result); return result; }
LocalAddressSpace::pint_t LocalAddressSpace::getEncodedP(pint_t& addr, pint_t end, uint8_t encoding) { pint_t startAddr = addr; const uint8_t* p = (uint8_t*)addr; pint_t result; // first get value switch (encoding & 0x0F) { case DW_EH_PE_ptr: result = getP(addr); p += sizeof(pint_t); addr = (pint_t)p; break; case DW_EH_PE_uleb128: result = getULEB128(addr, end); break; case DW_EH_PE_udata2: result = get16(addr); p += 2; addr = (pint_t)p; break; case DW_EH_PE_udata4: result = get32(addr); p += 4; addr = (pint_t)p; break; case DW_EH_PE_udata8: result = get64(addr); p += 8; addr = (pint_t)p; break; case DW_EH_PE_sleb128: result = getSLEB128(addr, end); break; case DW_EH_PE_sdata2: result = (int16_t)get16(addr); p += 2; addr = (pint_t)p; break; case DW_EH_PE_sdata4: result = (int32_t)get32(addr); p += 4; addr = (pint_t)p; break; case DW_EH_PE_sdata8: result = get64(addr); p += 8; addr = (pint_t)p; break; default: ABORT("unknown pointer encoding"); } // then add relative offset switch ( encoding & 0x70 ) { case DW_EH_PE_absptr: // do nothing break; case DW_EH_PE_pcrel: result += startAddr; break; case DW_EH_PE_textrel: ABORT("DW_EH_PE_textrel pointer encoding not supported"); break; case DW_EH_PE_datarel: ABORT("DW_EH_PE_datarel pointer encoding not supported"); break; case DW_EH_PE_funcrel: ABORT("DW_EH_PE_funcrel pointer encoding not supported"); break; case DW_EH_PE_aligned: ABORT("DW_EH_PE_aligned pointer encoding not supported"); break; default: ABORT("unknown pointer encoding"); break; } if ( encoding & DW_EH_PE_indirect ) result = getP(result); return result; }