Line data Source code
1 : /* Helper functions for form handling.
2 : Copyright (C) 2003-2009, 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 <string.h>
36 :
37 : #include "libdwP.h"
38 :
39 :
40 : size_t
41 : internal_function
42 49556671 : __libdw_form_val_compute_len (struct Dwarf_CU *cu, unsigned int form,
43 : const unsigned char *valp)
44 : {
45 49556671 : const unsigned char *startp = valp;
46 49556671 : const unsigned char *endp = cu->endp;
47 : Dwarf_Word u128;
48 : size_t result;
49 :
50 : /* NB: This doesn't cover constant form lengths, which are
51 : already handled by the inlined __libdw_form_val_len. */
52 49556671 : switch (form)
53 : {
54 : case DW_FORM_addr:
55 9605450 : result = cu->address_size;
56 9605450 : break;
57 :
58 : case DW_FORM_ref_addr:
59 58122 : result = cu->version == 2 ? cu->address_size : cu->offset_size;
60 58122 : break;
61 :
62 : case DW_FORM_strp:
63 : case DW_FORM_strp_sup:
64 : case DW_FORM_line_strp:
65 : case DW_FORM_sec_offset:
66 : case DW_FORM_GNU_ref_alt:
67 : case DW_FORM_GNU_strp_alt:
68 25720657 : result = cu->offset_size;
69 25720657 : break;
70 :
71 : case DW_FORM_block1:
72 3229 : if (unlikely ((size_t) (endp - startp) < 1))
73 : goto invalid;
74 3229 : result = *valp + 1;
75 3229 : break;
76 :
77 : case DW_FORM_block2:
78 3 : if (unlikely ((size_t) (endp - startp) < 2))
79 : goto invalid;
80 3 : result = read_2ubyte_unaligned (cu->dbg, valp) + 2;
81 3 : break;
82 :
83 : case DW_FORM_block4:
84 0 : if (unlikely ((size_t) (endp - startp) < 4))
85 : goto invalid;
86 0 : result = read_4ubyte_unaligned (cu->dbg, valp) + 4;
87 0 : break;
88 :
89 : case DW_FORM_block:
90 : case DW_FORM_exprloc:
91 10869322 : get_uleb128 (u128, valp, endp);
92 10869322 : result = u128 + (valp - startp);
93 10869322 : break;
94 :
95 : case DW_FORM_string:
96 : {
97 2159513 : const unsigned char *endstrp = memchr (valp, '\0',
98 2159513 : (size_t) (endp - startp));
99 2159513 : if (unlikely (endstrp == NULL))
100 : goto invalid;
101 2159513 : result = (size_t) (endstrp - startp) + 1;
102 2159513 : break;
103 : }
104 :
105 : case DW_FORM_sdata:
106 : case DW_FORM_udata:
107 : case DW_FORM_ref_udata:
108 : case DW_FORM_addrx:
109 : case DW_FORM_loclistx:
110 : case DW_FORM_rnglistx:
111 : case DW_FORM_strx:
112 : case DW_FORM_GNU_addr_index:
113 : case DW_FORM_GNU_str_index:
114 1140375 : get_uleb128 (u128, valp, endp);
115 1140375 : result = valp - startp;
116 1140375 : break;
117 :
118 : case DW_FORM_indirect:
119 0 : get_uleb128 (u128, valp, endp);
120 : // XXX Is this really correct?
121 0 : result = __libdw_form_val_len (cu, u128, valp);
122 0 : if (result != (size_t) -1)
123 0 : result += valp - startp;
124 : else
125 : return (size_t) -1;
126 0 : break;
127 :
128 : default:
129 : goto invalid;
130 : }
131 :
132 49556671 : if (unlikely (result > (size_t) (endp - startp)))
133 : {
134 : invalid:
135 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
136 0 : result = (size_t) -1;
137 : }
138 :
139 49556671 : return result;
140 : }
|