resetting manifest requested domain to floor
[platform/upstream/elfutils.git] / libdw / dwarf_formudata.c
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
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)