Branch data Line data Source code
1 : : /* Find CU for given offset.
2 : : Copyright (C) 2003-2010 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 <assert.h>
35 : : #include <search.h>
36 : : #include "libdwP.h"
37 : :
38 : : static int
39 : 736216 : findcu_cb (const void *arg1, const void *arg2)
40 : : {
41 : 736216 : struct Dwarf_CU *cu1 = (struct Dwarf_CU *) arg1;
42 : 736216 : struct Dwarf_CU *cu2 = (struct Dwarf_CU *) arg2;
43 : :
44 : : /* Find out which of the two arguments is the search value. It has
45 : : end offset 0. */
46 [ + + ]: 736216 : if (cu1->end == 0)
47 : : {
48 [ + + ]: 578066 : if (cu1->start < cu2->start)
49 : : return -1;
50 [ + + ]: 385828 : if (cu1->start >= cu2->end)
51 : : return 1;
52 : : }
53 : : else
54 : : {
55 [ - + ]: 158150 : if (cu2->start < cu1->start)
56 : : return 1;
57 [ # # ]: 0 : if (cu2->start >= cu1->end)
58 : : return -1;
59 : : }
60 : :
61 : 736216 : return 0;
62 : : }
63 : :
64 : : struct Dwarf_CU *
65 : : internal_function
66 : 19152 : __libdw_intern_next_unit (dbg, debug_types)
67 : : Dwarf *dbg;
68 : : bool debug_types;
69 : : {
70 : 19152 : Dwarf_Off *const offsetp
71 [ + + ]: 19152 : = debug_types ? &dbg->next_tu_offset : &dbg->next_cu_offset;
72 [ + + ]: 19152 : void **tree = debug_types ? &dbg->tu_tree : &dbg->cu_tree;
73 : :
74 : 19152 : Dwarf_Off oldoff = *offsetp;
75 : : uint16_t version;
76 : : uint8_t address_size;
77 : : uint8_t offset_size;
78 : : Dwarf_Off abbrev_offset;
79 : 19152 : uint64_t type_sig8 = 0;
80 : 19152 : Dwarf_Off type_offset = 0;
81 : :
82 [ + + ][ + + ]: 19152 : if (INTUSE(dwarf_next_unit) (dbg, oldoff, offsetp, NULL,
[ + - ]
83 : : &version, &abbrev_offset,
84 : : &address_size, &offset_size,
85 : : debug_types ? &type_sig8 : NULL,
86 : : debug_types ? &type_offset : NULL) != 0)
87 : : /* No more entries. */
88 : : return NULL;
89 : :
90 : : /* We only know how to handle the DWARF version 2 through 4 formats. */
91 [ + - ][ - + ]: 19152 : if (unlikely (version < 2) || unlikely (version > 4))
92 : : {
93 : 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
94 : : return NULL;
95 : : }
96 : :
97 : : /* Create an entry for this CU. */
98 [ + + ]: 19152 : struct Dwarf_CU *newp = libdw_typed_alloc (dbg, struct Dwarf_CU);
99 : :
100 : 19152 : newp->dbg = dbg;
101 : 19152 : newp->start = oldoff;
102 : 19152 : newp->end = *offsetp;
103 : 19152 : newp->address_size = address_size;
104 : 19152 : newp->offset_size = offset_size;
105 : 19152 : newp->version = version;
106 : 19152 : newp->type_sig8 = type_sig8;
107 : 19152 : newp->type_offset = type_offset;
108 : 19152 : Dwarf_Abbrev_Hash_init (&newp->abbrev_hash, 41);
109 : 19152 : newp->orig_abbrev_offset = newp->last_abbrev_offset = abbrev_offset;
110 : 19152 : newp->lines = NULL;
111 : 19152 : newp->locs = NULL;
112 : :
113 : : /* Add the new entry to the search tree. */
114 [ - + ]: 19152 : if (tsearch (newp, tree, findcu_cb) == NULL)
115 : : {
116 : : /* Something went wrong. Undo the operation. */
117 : 0 : *offsetp = oldoff;
118 : 19152 : __libdw_seterrno (DWARF_E_NOMEM);
119 : : return NULL;
120 : : }
121 : :
122 : : return newp;
123 : : }
124 : :
125 : : struct Dwarf_CU *
126 : 90452 : __libdw_findcu (dbg, start, debug_types)
127 : : Dwarf *dbg;
128 : : Dwarf_Off start;
129 : : bool debug_types;
130 : : {
131 [ + + ]: 90452 : void **tree = debug_types ? &dbg->tu_tree : &dbg->cu_tree;
132 : 90452 : Dwarf_Off *next_offset
133 [ + + ]: 90452 : = debug_types ? &dbg->next_tu_offset : &dbg->next_cu_offset;
134 : :
135 : : /* Maybe we already know that CU. */
136 : 90452 : struct Dwarf_CU fake = { .start = start, .end = 0 };
137 : 90452 : struct Dwarf_CU **found = tfind (&fake, tree, findcu_cb);
138 [ + + ]: 90452 : if (found != NULL)
139 : 71303 : return *found;
140 : :
141 [ - + ]: 19149 : if (start < *next_offset)
142 : : {
143 : 19149 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
144 : : return NULL;
145 : : }
146 : :
147 : : /* No. Then read more CUs. */
148 : : while (1)
149 : : {
150 : 19151 : struct Dwarf_CU *newp = __libdw_intern_next_unit (dbg, debug_types);
151 [ + - ]: 19151 : if (newp == NULL)
152 : : return NULL;
153 : :
154 : : /* Is this the one we are looking for? */
155 [ + + ]: 90454 : if (start < *next_offset)
156 : : // XXX Match exact offset.
157 : : return newp;
158 : : }
159 : : /* NOTREACHED */
160 : : }
|