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 : 27293402 : __libdw_form_val_compute_len (struct Dwarf_CU *cu, unsigned int form,
43 : : const unsigned char *valp)
44 : : {
45 : 27293402 : const unsigned char *startp = valp;
46 : 27293402 : const unsigned char *endp = cu->endp;
47 : 27293402 : Dwarf_Word u128;
48 : 27293402 : 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 [ + + + + : 27293402 : switch (form)
- - + + +
- - ]
53 : : {
54 : 3614903 : case DW_FORM_addr:
55 : 3614903 : result = cu->address_size;
56 : 3614903 : break;
57 : :
58 : 87 : case DW_FORM_ref_addr:
59 [ - + ]: 87 : result = cu->version == 2 ? cu->address_size : cu->offset_size;
60 : : break;
61 : :
62 : 20305369 : 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 : 20305369 : result = cu->offset_size;
69 : 20305369 : break;
70 : :
71 : 3341 : case DW_FORM_block1:
72 [ + - ]: 3341 : if (unlikely ((size_t) (endp - startp) < 1))
73 : : goto invalid;
74 : 3341 : result = *valp + 1;
75 : 3341 : break;
76 : :
77 : 0 : case DW_FORM_block2:
78 [ # # ]: 0 : if (unlikely ((size_t) (endp - startp) < 2))
79 : : 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 : : goto invalid;
86 [ # # ]: 0 : result = read_4ubyte_unaligned (cu->dbg, valp) + 4;
87 : : break;
88 : :
89 : 2481478 : case DW_FORM_block:
90 : : case DW_FORM_exprloc:
91 : 2481478 : get_uleb128 (u128, valp, endp);
92 : 2481478 : result = u128 + (valp - startp);
93 : 2481478 : break;
94 : :
95 : 839494 : case DW_FORM_string:
96 : : {
97 : 1678988 : const unsigned char *endstrp = memchr (valp, '\0',
98 : 839494 : (size_t) (endp - startp));
99 [ + - ]: 839494 : if (unlikely (endstrp == NULL))
100 : : goto invalid;
101 : 839494 : result = (size_t) (endstrp - startp) + 1;
102 : 839494 : break;
103 : : }
104 : :
105 : 48730 : 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 : 48730 : get_uleb128 (u128, valp, endp);
115 : 48730 : result = valp - startp;
116 : 48730 : break;
117 : :
118 : 0 : 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 [ - + ]: 27293402 : if (unlikely (result > (size_t) (endp - startp)))
133 : : {
134 : 0 : invalid:
135 : 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
136 : 0 : result = (size_t) -1;
137 : : }
138 : :
139 : : return result;
140 : : }
|