Branch data Line data Source code
1 : : /* Return address represented by attribute. 2 : : Copyright (C) 2003-2010, 2018 Red Hat, Inc. 3 : : This file is part of elfutils. 4 : : 5 : : This file is free software; you can redistribute it and/or modify 6 : : it under the terms of either 7 : : 8 : : * the GNU Lesser General Public License as published by the Free 9 : : Software Foundation; either version 3 of the License, or (at 10 : : your option) any later version 11 : : 12 : : or 13 : : 14 : : * the GNU General Public License as published by the Free 15 : : Software Foundation; either version 2 of the License, or (at 16 : : your option) any later version 17 : : 18 : : or both in parallel, as here. 19 : : 20 : : elfutils is distributed in the hope that it will be useful, but 21 : : WITHOUT ANY WARRANTY; without even the implied warranty of 22 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 : : General Public License for more details. 24 : : 25 : : You should have received copies of the GNU General Public License and 26 : : the GNU Lesser General Public License along with this program. If 27 : : not, see <http://www.gnu.org/licenses/>. */ 28 : : 29 : : #ifdef HAVE_CONFIG_H 30 : : # include <config.h> 31 : : #endif 32 : : 33 : : #include <dwarf.h> 34 : : #include "libdwP.h" 35 : : 36 : : 37 : : int 38 : 478 : __libdw_addrx (Dwarf_CU *cu, Dwarf_Word idx, Dwarf_Addr *addr) 39 : : { 40 : 478 : Dwarf_Off addr_off = __libdw_cu_addr_base (cu); 41 [ - + ]: 478 : if (addr_off == (Dwarf_Off) -1) 42 : : return -1; 43 : : 44 : 478 : Dwarf *dbg = cu->dbg; 45 [ - + ]: 478 : if (dbg->sectiondata[IDX_debug_addr] == NULL) 46 : : { 47 : 0 : __libdw_seterrno (DWARF_E_NO_DEBUG_ADDR); 48 : 0 : return -1; 49 : : } 50 : : 51 : : /* The section should at least contain room for one address. */ 52 : 478 : int address_size = cu->address_size; 53 [ - + ]: 478 : if (cu->address_size > dbg->sectiondata[IDX_debug_addr]->d_size) 54 : : { 55 : 0 : invalid_offset: 56 : 0 : __libdw_seterrno (DWARF_E_INVALID_OFFSET); 57 : 0 : return -1; 58 : : } 59 : : 60 : 478 : if (addr_off > (dbg->sectiondata[IDX_debug_addr]->d_size 61 [ - + ]: 478 : - address_size)) 62 : 0 : goto invalid_offset; 63 : : 64 : 478 : idx *= address_size; 65 : 478 : if (idx > (dbg->sectiondata[IDX_debug_addr]->d_size 66 [ - + ]: 478 : - address_size - addr_off)) 67 : 0 : goto invalid_offset; 68 : : 69 : 478 : const unsigned char *datap; 70 : 478 : datap = dbg->sectiondata[IDX_debug_addr]->d_buf + addr_off + idx; 71 [ - + ]: 478 : if (address_size == 4) 72 [ # # ]: 0 : *addr = read_4ubyte_unaligned (dbg, datap); 73 : : else 74 [ - + ]: 478 : *addr = read_8ubyte_unaligned (dbg, datap); 75 : : 76 : : return 0; 77 : : } 78 : : 79 : : int 80 : 882067 : dwarf_formaddr (Dwarf_Attribute *attr, Dwarf_Addr *return_addr) 81 : : { 82 [ + + ]: 882067 : if (attr == NULL) 83 : : return -1; 84 : : 85 : 185436 : Dwarf_Word idx; 86 : 185436 : Dwarf_CU *cu = attr->cu; 87 : 185436 : Dwarf *dbg = cu->dbg; 88 : 185436 : const unsigned char *datap = attr->valp; 89 : 185436 : const unsigned char *endp = attr->cu->endp; 90 [ + + - - : 185436 : switch (attr->form) - - + ] 91 : : { 92 : : /* There is one form that just encodes the whole address. */ 93 : 152207 : case DW_FORM_addr: 94 [ - + ]: 152207 : if (__libdw_read_address (dbg, cu_sec_idx (cu), datap, 95 : 152207 : cu->address_size, return_addr)) 96 : : return -1; 97 : : return 0; 98 : : 99 : : /* All others encode an index into the .debug_addr section where 100 : : the address can be found. */ 101 : 158 : case DW_FORM_GNU_addr_index: 102 : : case DW_FORM_addrx: 103 [ - + ]: 158 : if (datap >= endp) 104 : : { 105 : 0 : invalid: 106 : 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF); 107 : 0 : return -1; 108 : : } 109 : 158 : get_uleb128 (idx, datap, endp); 110 : 158 : break; 111 : : 112 : 0 : case DW_FORM_addrx1: 113 [ # # ]: 0 : if (datap >= endp - 1) 114 : 0 : goto invalid; 115 : 0 : idx = *datap; 116 : 0 : break; 117 : : 118 : 0 : case DW_FORM_addrx2: 119 [ # # ]: 0 : if (datap >= endp - 2) 120 : 0 : goto invalid; 121 [ # # ]: 0 : idx = read_2ubyte_unaligned (dbg, datap); 122 : : break; 123 : : 124 : 0 : case DW_FORM_addrx3: 125 [ # # ]: 0 : if (datap >= endp - 3) 126 : 0 : goto invalid; 127 : 0 : idx = read_3ubyte_unaligned (dbg, datap); 128 : 0 : break; 129 : : 130 : 0 : case DW_FORM_addrx4: 131 [ # # ]: 0 : if (datap >= endp - 4) 132 : 0 : goto invalid; 133 [ # # ]: 0 : idx = read_4ubyte_unaligned (dbg, datap); 134 : : break; 135 : : 136 : 33071 : default: 137 : 33071 : __libdw_seterrno (DWARF_E_NO_ADDR); 138 : 33071 : return -1; 139 : : } 140 : : 141 : : /* So we got an index. Lets see if it is valid and we can get the actual 142 : : address. */ 143 [ - + ]: 158 : if (__libdw_addrx (cu, idx, return_addr) != 0) 144 : : return -1; 145 : : 146 : : return 0; 147 : : } 148 : : INTDEF(dwarf_formaddr)