132f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm/* libunwind - a platform-independent unwind library 29fac7579ee3261babb6f745c8c1511c24ed88cb4hp.com!davidm Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P. 332f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm Contributed by David Mosberger-Tang <davidm@hpl.hp.com> 432f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 532f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidmThis file is part of libunwind. 632f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 732f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidmPermission is hereby granted, free of charge, to any person obtaining 832f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidma copy of this software and associated documentation files (the 932f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm"Software"), to deal in the Software without restriction, including 1032f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidmwithout limitation the rights to use, copy, modify, merge, publish, 1132f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidmdistribute, sublicense, and/or sell copies of the Software, and to 1232f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidmpermit persons to whom the Software is furnished to do so, subject to 1332f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidmthe following conditions: 1432f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 1532f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidmThe above copyright notice and this permission notice shall be 1632f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidmincluded in all copies or substantial portions of the Software. 1732f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 1832f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidmTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1932f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidmEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2032f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidmMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 2132f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidmNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 2232f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidmLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 2332f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidmOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 2432f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidmWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 2532f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 2632f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm#include "dwarf_i.h" 2732f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 2846b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidmstatic inline int 293842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitzis_cie_id (unw_word_t val, int is_debug_frame) 3046b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm{ 313842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz /* The CIE ID is normally 0xffffffff (for 32-bit ELF) or 323842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz 0xffffffffffffffff (for 64-bit ELF). However, .eh_frame 3346b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm uses 0. */ 343842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz if (is_debug_frame) 35d1c383c5bb03420decf5cf789cf14ab144b0720dChristopher Ferris /* ANDROID support update. */ 36d1c383c5bb03420decf5cf789cf14ab144b0720dChristopher Ferris return (val == (uint32_t) -1 || val == (unw_word_t) (uint64_t) -1); 37d1c383c5bb03420decf5cf789cf14ab144b0720dChristopher Ferris /* End of ANDROID update. */ 383842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz else 393842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz return (val == 0); 4046b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm} 4146b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm 4232f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm/* Note: we don't need to keep track of more than the first four 4332f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm characters of the augmentation string, because we (a) ignore any 4432f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm augmentation string contents once we find an unrecognized character 4532f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm and (b) those characters that we do recognize, can't be 4632f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm repeated. */ 4732f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidmstatic inline int 4846b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidmparse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr, 493842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz const unw_proc_info_t *pi, struct dwarf_cie_info *dci, 503842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz unw_word_t base, void *arg) 5132f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm{ 5232f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm uint8_t version, ch, augstr[5], fde_encoding, handler_encoding; 5346b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm unw_word_t len, cie_end_addr, aug_size; 5432f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm uint32_t u32val; 5532f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm uint64_t u64val; 5632f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm size_t i; 5732f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm int ret; 5832f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm# define STR2(x) #x 5932f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm# define STR(x) STR2(x) 6032f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 619ac7a860d1db4e607c9cb86e70524c17fe0bc087homeip.net!davidm /* Pick appropriate default for FDE-encoding. DWARF spec says 629ac7a860d1db4e607c9cb86e70524c17fe0bc087homeip.net!davidm start-IP (initial_location) and the code-size (address_range) are 639ac7a860d1db4e607c9cb86e70524c17fe0bc087homeip.net!davidm "address-unit sized constants". The `R' augmentation can be used 649ac7a860d1db4e607c9cb86e70524c17fe0bc087homeip.net!davidm to override this, but by default, we pick an address-sized unit 659ac7a860d1db4e607c9cb86e70524c17fe0bc087homeip.net!davidm for fde_encoding. */ 663842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz switch (dwarf_addr_size (as)) 67077322d41429859d924a87cd3c045c64851eb024homeip.net!davidm { 68077322d41429859d924a87cd3c045c64851eb024homeip.net!davidm case 4: fde_encoding = DW_EH_PE_udata4; break; 69077322d41429859d924a87cd3c045c64851eb024homeip.net!davidm case 8: fde_encoding = DW_EH_PE_udata8; break; 70077322d41429859d924a87cd3c045c64851eb024homeip.net!davidm default: fde_encoding = DW_EH_PE_omit; break; 71077322d41429859d924a87cd3c045c64851eb024homeip.net!davidm } 72077322d41429859d924a87cd3c045c64851eb024homeip.net!davidm 7346b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm dci->lsda_encoding = DW_EH_PE_omit; 7446b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm dci->handler = 0; 7532f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 7646b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm if ((ret = dwarf_readu32 (as, a, &addr, &u32val, arg)) < 0) 7732f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm return ret; 7832f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 7932f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm if (u32val != 0xffffffff) 8032f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm { 8132f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm /* the CIE is in the 32-bit DWARF format */ 8232f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm uint32_t cie_id; 833842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz /* DWARF says CIE id should be 0xffffffff, but in .eh_frame, it's 0 */ 843842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz const uint32_t expected_id = (base) ? 0xffffffff : 0; 8532f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 8632f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm len = u32val; 8746b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm cie_end_addr = addr + len; 8846b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm if ((ret = dwarf_readu32 (as, a, &addr, &cie_id, arg)) < 0) 8932f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm return ret; 903842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz if (cie_id != expected_id) 9132f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm { 9232f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm Debug (1, "Unexpected CIE id %x\n", cie_id); 9332f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm return -UNW_EINVAL; 9432f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm } 9532f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm } 9632f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm else 9732f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm { 9832f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm /* the CIE is in the 64-bit DWARF format */ 9932f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm uint64_t cie_id; 1003842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz /* DWARF says CIE id should be 0xffffffffffffffff, but in 1013842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz .eh_frame, it's 0 */ 1023842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz const uint64_t expected_id = (base) ? 0xffffffffffffffffull : 0; 10332f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 10446b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm if ((ret = dwarf_readu64 (as, a, &addr, &u64val, arg)) < 0) 10532f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm return ret; 10632f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm len = u64val; 10746b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm cie_end_addr = addr + len; 10846b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm if ((ret = dwarf_readu64 (as, a, &addr, &cie_id, arg)) < 0) 10932f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm return ret; 1103842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz if (cie_id != expected_id) 11132f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm { 11232f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm Debug (1, "Unexpected CIE id %llx\n", (long long) cie_id); 11332f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm return -UNW_EINVAL; 11432f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm } 11532f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm } 11646b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm dci->cie_instr_end = cie_end_addr; 11732f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 11846b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm if ((ret = dwarf_readu8 (as, a, &addr, &version, arg)) < 0) 11932f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm return ret; 12032f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 121a220bd08dd6659a3a3543825f0e0e19c9a20486bYabin Cui if (version != 1 && version != 3 && version != 4) 12232f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm { 123a220bd08dd6659a3a3543825f0e0e19c9a20486bYabin Cui Debug (1, "Got CIE version %u, expected version 1, 3 or 4\n", version); 12432f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm return -UNW_EBADVERSION; 12532f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm } 12632f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 12732f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm /* read and parse the augmentation string: */ 12832f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm memset (augstr, 0, sizeof (augstr)); 12932f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm for (i = 0;;) 13032f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm { 13146b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm if ((ret = dwarf_readu8 (as, a, &addr, &ch, arg)) < 0) 13232f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm return ret; 13332f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 13432f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm if (!ch) 13532f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm break; /* end of augmentation string */ 13632f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 13732f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm if (i < sizeof (augstr) - 1) 13832f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm augstr[i++] = ch; 13932f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm } 14032f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 141a220bd08dd6659a3a3543825f0e0e19c9a20486bYabin Cui if (version == 4) { 142a220bd08dd6659a3a3543825f0e0e19c9a20486bYabin Cui uint8_t address_size; 143a220bd08dd6659a3a3543825f0e0e19c9a20486bYabin Cui if ((ret = dwarf_readu8(as, a, &addr, &address_size, arg)) < 0) { 144a220bd08dd6659a3a3543825f0e0e19c9a20486bYabin Cui return ret; 145a220bd08dd6659a3a3543825f0e0e19c9a20486bYabin Cui } 146a220bd08dd6659a3a3543825f0e0e19c9a20486bYabin Cui if (address_size != sizeof(unw_word_t)) { 147a220bd08dd6659a3a3543825f0e0e19c9a20486bYabin Cui return -UNW_EBADVERSION; 148a220bd08dd6659a3a3543825f0e0e19c9a20486bYabin Cui } 149a220bd08dd6659a3a3543825f0e0e19c9a20486bYabin Cui uint8_t segment_size; 150a220bd08dd6659a3a3543825f0e0e19c9a20486bYabin Cui if ((ret = dwarf_readu8(as, a, &addr, &segment_size, arg)) < 0) { 151a220bd08dd6659a3a3543825f0e0e19c9a20486bYabin Cui return ret; 152a220bd08dd6659a3a3543825f0e0e19c9a20486bYabin Cui } 153a220bd08dd6659a3a3543825f0e0e19c9a20486bYabin Cui // We don't support non-zero segment size. 154a220bd08dd6659a3a3543825f0e0e19c9a20486bYabin Cui if (segment_size != 0) { 155a220bd08dd6659a3a3543825f0e0e19c9a20486bYabin Cui return -UNW_EBADVERSION; 156a220bd08dd6659a3a3543825f0e0e19c9a20486bYabin Cui } 157a220bd08dd6659a3a3543825f0e0e19c9a20486bYabin Cui } 15846b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm if ((ret = dwarf_read_uleb128 (as, a, &addr, &dci->code_align, arg)) < 0 15946b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm || (ret = dwarf_read_sleb128 (as, a, &addr, &dci->data_align, arg)) < 0) 16032f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm return ret; 16132f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 16232f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm /* Read the return-address column either as a u8 or as a uleb128. */ 16332f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm if (version == 1) 16432f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm { 16546b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm if ((ret = dwarf_readu8 (as, a, &addr, &ch, arg)) < 0) 16632f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm return ret; 16746b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm dci->ret_addr_column = ch; 16832f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm } 16946b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm else if ((ret = dwarf_read_uleb128 (as, a, &addr, &dci->ret_addr_column, 17046b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm arg)) < 0) 17132f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm return ret; 17232f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 1733842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz i = 0; 17432f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm if (augstr[0] == 'z') 17532f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm { 17646b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm dci->sized_augmentation = 1; 17746b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm if ((ret = dwarf_read_uleb128 (as, a, &addr, &aug_size, arg)) < 0) 17832f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm return ret; 1793842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz i++; 18032f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm } 18132f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 1823842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz for (; i < sizeof (augstr) && augstr[i]; ++i) 18332f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm switch (augstr[i]) 18432f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm { 18532f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm case 'L': 18632f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm /* read the LSDA pointer-encoding format. */ 18746b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm if ((ret = dwarf_readu8 (as, a, &addr, &ch, arg)) < 0) 18832f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm return ret; 18946b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm dci->lsda_encoding = ch; 19032f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm break; 19132f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 19232f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm case 'R': 19332f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm /* read the FDE pointer-encoding format. */ 19446b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm if ((ret = dwarf_readu8 (as, a, &addr, &fde_encoding, arg)) < 0) 19532f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm return ret; 19632f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm break; 19732f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 19832f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm case 'P': 19932f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm /* read the personality-routine pointer-encoding format. */ 20046b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm if ((ret = dwarf_readu8 (as, a, &addr, &handler_encoding, arg)) < 0) 20132f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm return ret; 20246b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm if ((ret = dwarf_read_encoded_pointer (as, a, &addr, handler_encoding, 20346b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm pi, &dci->handler, arg)) < 0) 20432f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm return ret; 20532f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm break; 20632f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 20746b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm case 'S': 208dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura /* This is a signal frame. */ 209dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura dci->signal_frame = 1; 210dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura 21146b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm /* Temporarily set it to one so dwarf_parse_fde() knows that 21246b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm it should fetch the actual ABI/TAG pair from the FDE. */ 21346b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm dci->have_abi_marker = 1; 21446b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm break; 21546b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm 21632f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm default: 2173842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz Debug (1, "Unexpected augmentation string `%s'\n", augstr); 21846b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm if (dci->sized_augmentation) 21932f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm /* If we have the size of the augmentation body, we can skip 22032f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm over the parts that we don't understand, so we're OK. */ 2213842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz goto done; 22232f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm else 2233842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz return -UNW_EINVAL; 22432f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm } 2253842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz done: 22646b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm dci->fde_encoding = fde_encoding; 22746b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm dci->cie_instr_start = addr; 228077322d41429859d924a87cd3c045c64851eb024homeip.net!davidm Debug (15, "CIE parsed OK, augmentation = \"%s\", handler=0x%lx\n", 22946b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm augstr, (long) dci->handler); 23032f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm return 0; 23132f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm} 23232f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 2333842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz/* Extract proc-info from the FDE starting at adress ADDR. 2343842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz 2353842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz Pass BASE as zero for eh_frame behaviour, or a pointer to 2363842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz debug_frame base for debug_frame behaviour. */ 23746b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm 23832f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidmHIDDEN int 23946b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidmdwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a, 24046b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm unw_word_t *addrp, unw_proc_info_t *pi, 2413842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz int need_unwind_info, unw_word_t base, 24246b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm void *arg) 24332f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm{ 24432f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm unw_word_t fde_end_addr, cie_addr, cie_offset_addr, aug_end_addr = 0; 24546b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm unw_word_t start_ip, ip_range, aug_size, addr = *addrp; 24646b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm int ret, ip_range_encoding; 24746b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm struct dwarf_cie_info dci; 24832f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm uint64_t u64val; 24932f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm uint32_t u32val; 25032f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 25146b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm Debug (12, "FDE @ 0x%lx\n", (long) addr); 25232f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 25346b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm memset (&dci, 0, sizeof (dci)); 25432f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 25546b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm if ((ret = dwarf_readu32 (as, a, &addr, &u32val, arg)) < 0) 25632f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm return ret; 25732f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 25832f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm if (u32val != 0xffffffff) 25932f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm { 2603842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz int32_t cie_offset; 26132f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 26246b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm /* In some configurations, an FDE with a 0 length indicates the 26346b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm end of the FDE-table. */ 26446b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm if (u32val == 0) 26546b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm return -UNW_ENOINFO; 26646b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm 26732f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm /* the FDE is in the 32-bit DWARF format */ 26832f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 26946b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm *addrp = fde_end_addr = addr + u32val; 27046b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm cie_offset_addr = addr; 27132f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 27246b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm if ((ret = dwarf_reads32 (as, a, &addr, &cie_offset, arg)) < 0) 27332f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm return ret; 27432f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 2753842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz if (is_cie_id (cie_offset, base != 0)) 27646b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm /* ignore CIEs (happens during linear searches) */ 27746b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm return 0; 27846b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm 2793842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz if (base != 0) 2803842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz cie_addr = base + cie_offset; 2813842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz else 2823842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz /* DWARF says that the CIE_pointer in the FDE is a 2833842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz .debug_frame-relative offset, but the GCC-generated .eh_frame 2843842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz sections instead store a "pcrelative" offset, which is just 2853842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz as fine as it's self-contained. */ 2863842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz cie_addr = cie_offset_addr - cie_offset; 28732f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm } 28832f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm else 28932f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm { 2903842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz int64_t cie_offset; 29132f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 29232f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm /* the FDE is in the 64-bit DWARF format */ 29332f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 29446b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm if ((ret = dwarf_readu64 (as, a, &addr, &u64val, arg)) < 0) 29532f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm return ret; 29632f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 29746b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm *addrp = fde_end_addr = addr + u64val; 29846b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm cie_offset_addr = addr; 29932f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 30046b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm if ((ret = dwarf_reads64 (as, a, &addr, &cie_offset, arg)) < 0) 30132f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm return ret; 30232f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 3033842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz if (is_cie_id (cie_offset, base != 0)) 30446b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm /* ignore CIEs (happens during linear searches) */ 30546b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm return 0; 30646b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm 3073842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz if (base != 0) 3083842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz cie_addr = base + cie_offset; 3093842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz else 3103842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz /* DWARF says that the CIE_pointer in the FDE is a 3113842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz .debug_frame-relative offset, but the GCC-generated .eh_frame 3123842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz sections instead store a "pcrelative" offset, which is just 3133842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz as fine as it's self-contained. */ 3143842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz cie_addr = (unw_word_t) ((uint64_t) cie_offset_addr - cie_offset); 31532f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm } 31632f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 317250382c56d2c84fc3976cf8a4c834433bb68990dLassi Tuura Debug (15, "looking for CIE at address %lx\n", (long) cie_addr); 3183842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz 3193842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitz if ((ret = parse_cie (as, a, cie_addr, pi, &dci, base, arg)) < 0) 32032f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm return ret; 32132f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 32232f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm /* IP-range has same encoding as FDE pointers, except that it's 32332f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm always an absolute value: */ 32446b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm ip_range_encoding = dci.fde_encoding & DW_EH_PE_FORMAT_MASK; 32532f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 32646b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm if ((ret = dwarf_read_encoded_pointer (as, a, &addr, dci.fde_encoding, 32732f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm pi, &start_ip, arg)) < 0 32846b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm || (ret = dwarf_read_encoded_pointer (as, a, &addr, ip_range_encoding, 32932f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm pi, &ip_range, arg)) < 0) 33032f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm return ret; 33132f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm pi->start_ip = start_ip; 33232f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm pi->end_ip = start_ip + ip_range; 33346b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm pi->handler = dci.handler; 33432f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 33546b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm if (dci.sized_augmentation) 33632f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm { 33746b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm if ((ret = dwarf_read_uleb128 (as, a, &addr, &aug_size, arg)) < 0) 33832f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm return ret; 33946b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm aug_end_addr = addr + aug_size; 34032f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm } 34132f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 34246b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm if ((ret = dwarf_read_encoded_pointer (as, a, &addr, dci.lsda_encoding, 34332f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm pi, &pi->lsda, arg)) < 0) 34432f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm return ret; 34532f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm 346077322d41429859d924a87cd3c045c64851eb024homeip.net!davidm Debug (15, "FDE covers IP 0x%lx-0x%lx, LSDA=0x%lx\n", 34732f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm (long) pi->start_ip, (long) pi->end_ip, (long) pi->lsda); 34846b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm 34946b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm if (need_unwind_info) 35046b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm { 35146b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm pi->format = UNW_INFO_FORMAT_TABLE; 35246b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm pi->unwind_info_size = sizeof (dci); 35346b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm pi->unwind_info = mempool_alloc (&dwarf_cie_info_pool); 35446b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm if (!pi->unwind_info) 3555ed2da2a403fe091d953183449003c9df861c289Mark Wielaard return -UNW_ENOMEM; 35646b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm 35746b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm if (dci.have_abi_marker) 35846b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm { 35946b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm if ((ret = dwarf_readu16 (as, a, &addr, &dci.abi, arg)) < 0 36046b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm || (ret = dwarf_readu16 (as, a, &addr, &dci.tag, arg)) < 0) 36146b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm return ret; 36246b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm Debug (13, "Found ABI marker = (abi=%u, tag=%u)\n", 36346b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm dci.abi, dci.tag); 36446b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm } 36546b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm 36646b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm if (dci.sized_augmentation) 36746b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm dci.fde_instr_start = aug_end_addr; 36846b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm else 36946b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm dci.fde_instr_start = addr; 37046b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm dci.fde_instr_end = fde_end_addr; 37146b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm 37246b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm memcpy (pi->unwind_info, &dci, sizeof (dci)); 37346b7b8196c7600aaa200e31d01a2b4df7e7760admostang.com!davidm } 37432f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm return 0; 37532f3a1e58f48d6ec811f54dedf74eb4b17ae4e2chomeip.net!davidm} 376