1 /* Return unsigned constant represented by attribute. 2 Copyright (C) 2003-2012, 2014 Red Hat, Inc. 3 This file is part of elfutils. 4 Written by Ulrich Drepper <drepper (at) redhat.com>, 2003. 5 6 This file is free software; you can redistribute it and/or modify 7 it under the terms of either 8 9 * the GNU Lesser General Public License as published by the Free 10 Software Foundation; either version 3 of the License, or (at 11 your option) any later version 12 13 or 14 15 * the GNU General Public License as published by the Free 16 Software Foundation; either version 2 of the License, or (at 17 your option) any later version 18 19 or both in parallel, as here. 20 21 elfutils is distributed in the hope that it will be useful, but 22 WITHOUT ANY WARRANTY; without even the implied warranty of 23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24 General Public License for more details. 25 26 You should have received copies of the GNU General Public License and 27 the GNU Lesser General Public License along with this program. If 28 not, see <http://www.gnu.org/licenses/>. */ 29 30 #ifdef HAVE_CONFIG_H 31 # include <config.h> 32 #endif 33 34 #include <dwarf.h> 35 #include "libdwP.h" 36 37 internal_function unsigned char * 38 __libdw_formptr (Dwarf_Attribute *attr, int sec_index, 39 int err_nodata, unsigned char **endpp, 40 Dwarf_Off *offsetp) 41 { 42 if (attr == NULL) 43 return NULL; 44 45 const Elf_Data *d = attr->cu->dbg->sectiondata[sec_index]; 46 if (unlikely (d == NULL)) 47 { 48 __libdw_seterrno (err_nodata); 49 return NULL; 50 } 51 52 Dwarf_Word offset; 53 if (attr->form == DW_FORM_sec_offset) 54 { 55 if (__libdw_read_offset (attr->cu->dbg, attr->cu->dbg, 56 cu_sec_idx (attr->cu), attr->valp, 57 attr->cu->offset_size, &offset, sec_index, 0)) 58 return NULL; 59 } 60 else if (attr->cu->version > 3) 61 goto invalid; 62 else 63 switch (attr->form) 64 { 65 case DW_FORM_data4: 66 case DW_FORM_data8: 67 if (__libdw_read_offset (attr->cu->dbg, attr->cu->dbg, 68 cu_sec_idx (attr->cu), 69 attr->valp, 70 attr->form == DW_FORM_data4 ? 4 : 8, 71 &offset, sec_index, 0)) 72 return NULL; 73 break; 74 75 default: 76 if (INTUSE(dwarf_formudata) (attr, &offset)) 77 return NULL; 78 }; 79 80 unsigned char *readp = d->d_buf + offset; 81 unsigned char *endp = d->d_buf + d->d_size; 82 if (unlikely (readp >= endp)) 83 { 84 invalid: 85 __libdw_seterrno (DWARF_E_INVALID_DWARF); 86 return NULL; 87 } 88 89 if (endpp != NULL) 90 *endpp = endp; 91 if (offsetp != NULL) 92 *offsetp = offset; 93 return readp; 94 } 95 96 int 97 dwarf_formudata (Dwarf_Attribute *attr, Dwarf_Word *return_uval) 98 { 99 if (attr == NULL) 100 return -1; 101 102 const unsigned char *datap = attr->valp; 103 const unsigned char *endp = attr->cu->endp; 104 105 switch (attr->form) 106 { 107 case DW_FORM_data1: 108 if (datap + 1 > endp) 109 { 110 invalid: 111 __libdw_seterrno (DWARF_E_INVALID_DWARF); 112 return -1; 113 } 114 *return_uval = *attr->valp; 115 break; 116 117 case DW_FORM_data2: 118 if (datap + 2 > endp) 119 goto invalid; 120 *return_uval = read_2ubyte_unaligned (attr->cu->dbg, attr->valp); 121 break; 122 123 case DW_FORM_data4: 124 case DW_FORM_data8: 125 case DW_FORM_sec_offset: 126 /* Before DWARF4 data4 and data8 are pure constants unless the 127 attribute also allows offsets (*ptr classes), since DWARF4 128 they are always just constants (start_scope is special though, 129 since it only could express a rangelist since DWARF4). */ 130 if (attr->form == DW_FORM_sec_offset 131 || (attr->cu->version < 4 && attr->code != DW_AT_start_scope)) 132 { 133 switch (attr->code) 134 { 135 case DW_AT_data_member_location: 136 case DW_AT_frame_base: 137 case DW_AT_location: 138 case DW_AT_return_addr: 139 case DW_AT_segment: 140 case DW_AT_static_link: 141 case DW_AT_string_length: 142 case DW_AT_use_location: 143 case DW_AT_vtable_elem_location: 144 /* loclistptr */ 145 if (__libdw_formptr (attr, IDX_debug_loc, 146 DWARF_E_NO_LOCLIST, NULL, 147 return_uval) == NULL) 148 return -1; 149 break; 150 151 case DW_AT_macro_info: 152 /* macptr into .debug_macinfo */ 153 if (__libdw_formptr (attr, IDX_debug_macinfo, 154 DWARF_E_NO_ENTRY, NULL, 155 return_uval) == NULL) 156 return -1; 157 break; 158 159 case DW_AT_GNU_macros: 160 /* macptr into .debug_macro */ 161 if (__libdw_formptr (attr, IDX_debug_macro, 162 DWARF_E_NO_ENTRY, NULL, 163 return_uval) == NULL) 164 return -1; 165 break; 166 167 case DW_AT_ranges: 168 case DW_AT_start_scope: 169 /* rangelistptr */ 170 if (__libdw_formptr (attr, IDX_debug_ranges, 171 DWARF_E_NO_DEBUG_RANGES, NULL, 172 return_uval) == NULL) 173 return -1; 174 break; 175 176 case DW_AT_stmt_list: 177 /* lineptr */ 178 if (__libdw_formptr (attr, IDX_debug_line, 179 DWARF_E_NO_DEBUG_LINE, NULL, 180 return_uval) == NULL) 181 return -1; 182 break; 183 184 default: 185 /* sec_offset can only be used by one of the above attrs. */ 186 if (attr->form == DW_FORM_sec_offset) 187 { 188 __libdw_seterrno (DWARF_E_INVALID_DWARF); 189 return -1; 190 } 191 192 /* Not one of the special attributes, just a constant. */ 193 if (__libdw_read_address (attr->cu->dbg, cu_sec_idx (attr->cu), 194 attr->valp, 195 attr->form == DW_FORM_data4 ? 4 : 8, 196 return_uval)) 197 return -1; 198 break; 199 } 200 } 201 else 202 { 203 /* We are dealing with a constant data4 or data8. */ 204 if (__libdw_read_address (attr->cu->dbg, cu_sec_idx (attr->cu), 205 attr->valp, 206 attr->form == DW_FORM_data4 ? 4 : 8, 207 return_uval)) 208 return -1; 209 } 210 break; 211 212 case DW_FORM_sdata: 213 if (datap + 1 > endp) 214 goto invalid; 215 get_sleb128 (*return_uval, datap, endp); 216 break; 217 218 case DW_FORM_udata: 219 if (datap + 1 > endp) 220 goto invalid; 221 get_uleb128 (*return_uval, datap, endp); 222 break; 223 224 default: 225 __libdw_seterrno (DWARF_E_NO_CONSTANT); 226 return -1; 227 } 228 229 return 0; 230 } 231 INTDEF(dwarf_formudata) 232