Branch data 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 : 56503534 : __libdw_form_val_compute_len (struct Dwarf_CU *cu, unsigned int form,
43 : : const unsigned char *valp)
44 : : {
45 : 56503534 : const unsigned char *startp = valp;
46 : 56503534 : const unsigned char *endp = cu->endp;
47 : 56503534 : Dwarf_Word u128;
48 : 56503534 : 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 [ + + + + : 56503534 : switch (form)
- - + + +
- - ]
53 : : {
54 : 7303898 : case DW_FORM_addr:
55 : 7303898 : result = cu->address_size;
56 : 7303898 : break;
57 : :
58 : 452 : case DW_FORM_ref_addr:
59 [ - + ]: 452 : result = cu->version == 2 ? cu->address_size : cu->offset_size;
60 : : break;
61 : :
62 : 40439100 : 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 : 40439100 : result = cu->offset_size;
69 : 40439100 : break;
70 : :
71 : 7624 : case DW_FORM_block1:
72 [ - + ]: 7624 : if (unlikely ((size_t) (endp - startp) < 1))
73 : 0 : goto invalid;
74 : 7624 : result = *valp + 1;
75 : 7624 : break;
76 : :
77 : 0 : case DW_FORM_block2:
78 [ # # ]: 0 : if (unlikely ((size_t) (endp - startp) < 2))
79 : 0 : goto invalid;
80 [ # # ]: 0 : result = read_2ubyte_unaligned (cu->dbg, valp) + 2;
81 : : break;
82 : :
83 : 0 : case DW_FORM_block4:
84 [ # # ]: 0 : if (unlikely ((size_t) (endp - startp) < 4))
85 : 0 : goto invalid;
86 [ # # ]: 0 : result = read_4ubyte_unaligned (cu->dbg, valp) + 4;
87 : : break;
88 : :
89 : 5939740 : case DW_FORM_block:
90 : : case DW_FORM_exprloc:
91 [ - + ]: 5939740 : if (valp >= endp)
92 : 0 : goto invalid;
93 : 5939740 : get_uleb128 (u128, valp, endp);
94 : 5939740 : result = u128 + (valp - startp);
95 : 5939740 : break;
96 : :
97 : 1866022 : case DW_FORM_string:
98 : : {
99 : 1866022 : const unsigned char *endstrp = memchr (valp, '\0',
100 : 1866022 : (size_t) (endp - startp));
101 [ - + ]: 1866022 : if (unlikely (endstrp == NULL))
102 : 0 : goto invalid;
103 : 1866022 : result = (size_t) (endstrp - startp) + 1;
104 : 1866022 : break;
105 : : }
106 : :
107 : 946698 : case DW_FORM_sdata:
108 : : case DW_FORM_udata:
109 : : case DW_FORM_ref_udata:
110 : : case DW_FORM_addrx:
111 : : case DW_FORM_loclistx:
112 : : case DW_FORM_rnglistx:
113 : : case DW_FORM_strx:
114 : : case DW_FORM_GNU_addr_index:
115 : : case DW_FORM_GNU_str_index:
116 [ - + ]: 946698 : if (valp >= endp)
117 : 0 : goto invalid;
118 : 946698 : get_uleb128 (u128, valp, endp);
119 : 946698 : result = valp - startp;
120 : 946698 : break;
121 : :
122 : 0 : case DW_FORM_indirect:
123 : : /* The amount of data to skip in the DIE is the size of the actual
124 : : FORM data (which is __libdw_form_val_len) plus the size of the
125 : : uleb128 encoding that FORM (which is valp - startp). */
126 [ # # ]: 0 : if (valp >= endp)
127 : 0 : goto invalid;
128 : 0 : get_uleb128 (u128, valp, endp);
129 [ # # ]: 0 : if (*valp == DW_FORM_indirect || *valp == DW_FORM_implicit_const)
130 : : return (size_t) -1;
131 : 0 : result = __libdw_form_val_len (cu, u128, valp);
132 [ # # ]: 0 : if (result != (size_t) -1)
133 : 0 : result += valp - startp;
134 : : else
135 : : return (size_t) -1;
136 : 0 : break;
137 : :
138 : 0 : default:
139 : 0 : goto invalid;
140 : : }
141 : :
142 [ - + ]: 56503534 : if (unlikely (result > (size_t) (endp - startp)))
143 : : {
144 : 0 : invalid:
145 : 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
146 : 0 : result = (size_t) -1;
147 : : }
148 : :
149 : : return result;
150 : : }
|