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@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 37internal_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 96int 97dwarf_formudata (attr, return_uval) 98 Dwarf_Attribute *attr; 99 Dwarf_Word *return_uval; 100{ 101 if (attr == NULL) 102 return -1; 103 104 const unsigned char *datap = attr->valp; 105 const unsigned char *endp = attr->cu->endp; 106 107 switch (attr->form) 108 { 109 case DW_FORM_data1: 110 if (datap + 1 > endp) 111 { 112 invalid: 113 __libdw_seterrno (DWARF_E_INVALID_DWARF); 114 return -1; 115 } 116 *return_uval = *attr->valp; 117 break; 118 119 case DW_FORM_data2: 120 if (datap + 2 > endp) 121 goto invalid; 122 *return_uval = read_2ubyte_unaligned (attr->cu->dbg, attr->valp); 123 break; 124 125 case DW_FORM_data4: 126 case DW_FORM_data8: 127 case DW_FORM_sec_offset: 128 /* Before DWARF4 data4 and data8 are pure constants unless the 129 attribute also allows offsets (*ptr classes), since DWARF4 130 they are always just constants (start_scope is special though, 131 since it only could express a rangelist since DWARF4). */ 132 if (attr->form == DW_FORM_sec_offset 133 || (attr->cu->version < 4 && attr->code != DW_AT_start_scope)) 134 { 135 switch (attr->code) 136 { 137 case DW_AT_data_member_location: 138 case DW_AT_frame_base: 139 case DW_AT_location: 140 case DW_AT_return_addr: 141 case DW_AT_segment: 142 case DW_AT_static_link: 143 case DW_AT_string_length: 144 case DW_AT_use_location: 145 case DW_AT_vtable_elem_location: 146 /* loclistptr */ 147 if (__libdw_formptr (attr, IDX_debug_loc, 148 DWARF_E_NO_LOCLIST, NULL, 149 return_uval) == NULL) 150 return -1; 151 break; 152 153 case DW_AT_macro_info: 154 /* macptr into .debug_macinfo */ 155 if (__libdw_formptr (attr, IDX_debug_macinfo, 156 DWARF_E_NO_ENTRY, NULL, 157 return_uval) == NULL) 158 return -1; 159 break; 160 161 case DW_AT_GNU_macros: 162 /* macptr into .debug_macro */ 163 if (__libdw_formptr (attr, IDX_debug_macro, 164 DWARF_E_NO_ENTRY, NULL, 165 return_uval) == NULL) 166 return -1; 167 break; 168 169 case DW_AT_ranges: 170 case DW_AT_start_scope: 171 /* rangelistptr */ 172 if (__libdw_formptr (attr, IDX_debug_ranges, 173 DWARF_E_NO_DEBUG_RANGES, NULL, 174 return_uval) == NULL) 175 return -1; 176 break; 177 178 case DW_AT_stmt_list: 179 /* lineptr */ 180 if (__libdw_formptr (attr, IDX_debug_line, 181 DWARF_E_NO_DEBUG_LINE, NULL, 182 return_uval) == NULL) 183 return -1; 184 break; 185 186 default: 187 /* sec_offset can only be used by one of the above attrs. */ 188 if (attr->form == DW_FORM_sec_offset) 189 { 190 __libdw_seterrno (DWARF_E_INVALID_DWARF); 191 return -1; 192 } 193 194 /* Not one of the special attributes, just a constant. */ 195 if (__libdw_read_address (attr->cu->dbg, cu_sec_idx (attr->cu), 196 attr->valp, 197 attr->form == DW_FORM_data4 ? 4 : 8, 198 return_uval)) 199 return -1; 200 break; 201 } 202 } 203 else 204 { 205 /* We are dealing with a constant data4 or data8. */ 206 if (__libdw_read_address (attr->cu->dbg, cu_sec_idx (attr->cu), 207 attr->valp, 208 attr->form == DW_FORM_data4 ? 4 : 8, 209 return_uval)) 210 return -1; 211 } 212 break; 213 214 case DW_FORM_sdata: 215 if (datap + 1 > endp) 216 goto invalid; 217 get_sleb128 (*return_uval, datap, endp); 218 break; 219 220 case DW_FORM_udata: 221 if (datap + 1 > endp) 222 goto invalid; 223 get_uleb128 (*return_uval, datap, endp); 224 break; 225 226 default: 227 __libdw_seterrno (DWARF_E_NO_CONSTANT); 228 return -1; 229 } 230 231 return 0; 232} 233INTDEF(dwarf_formudata) 234