1 /*
2
3 Copyright (C) 2015-2015 David Anderson. All Rights Reserved.
4
5 This program is free software; you can redistribute it
6 and/or modify it under the terms of version 2.1 of the
7 GNU Lesser General Public License as published by the Free
8 Software Foundation.
9
10 This program is distributed in the hope that it would be
11 useful, but WITHOUT ANY WARRANTY; without even the implied
12 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 PURPOSE.
14
15 Further, this software is distributed without any warranty
16 that it is free of the rightful claim of any third person
17 regarding infringement or the like. Any license provided
18 herein, whether implied or otherwise, applies only to this
19 software file. Patent licenses, if any, provided herein
20 do not apply to combinations of this program with other
21 software, or any other product whatsoever.
22
23 You should have received a copy of the GNU Lesser General
24 Public License along with this program; if not, write the
25 Free Software Foundation, Inc., 51 Franklin Street - Fifth
26 Floor, Boston MA 02110-1301, USA.
27
28 */
29
30 #include "config.h"
31 #include "dwarf_incl.h"
32 #ifdef HAVE_STDLIB_H
33 #include <stdlib.h> /* for free(). */
34 #endif /* HAVE_STDLIB_H */
35 #ifdef HAVE_MALLOC_H
36 /* Useful include for some Windows compilers. */
37 #include <malloc.h>
38 #endif /* HAVE_MALLOC_H */
39 #include <stdio.h> /* For debugging. */
40 #ifdef HAVE_STDINT_H
41 #include <stdint.h> /* For uintptr_t */
42 #endif /* HAVE_STDINT_H */
43 #include "dwarf_tsearch.h"
44 #include "dwarf_tied_decls.h"
45
46 #define TRUE 1
47 #define FALSE 0
48
49
50 void
_dwarf_dumpsig(const char * msg,Dwarf_Sig8 * sig,int lineno)51 _dwarf_dumpsig(const char *msg, Dwarf_Sig8 *sig,int lineno)
52 {
53 const char *sigv = 0;
54 unsigned u = 0;
55
56 printf("%s 0x",msg);
57 sigv = &sig->signature[0];
58 for (u = 0; u < 8; u++) {
59 printf("%02x",0xff&sigv[u]);
60 }
61 printf(" line %d\n",lineno);
62 }
63
64 void *
_dwarf_tied_make_entry(Dwarf_Sig8 * key,Dwarf_CU_Context val)65 _dwarf_tied_make_entry(Dwarf_Sig8 *key, Dwarf_CU_Context val)
66 {
67 struct Dwarf_Tied_Entry_s *e = 0;
68 e = calloc(1,sizeof(struct Dwarf_Tied_Entry_s));
69 if(e) {
70 e->dt_key = *key;
71 e->dt_context = val;
72 }
73 return e;
74 }
75
76
77 /* Tied data Key is Dwarf_Sig8.
78 A hash needed because we are using a hash search
79 here. Would not be needed for the other tree searchs
80 like balanced trees.. */
81 DW_TSHASHTYPE
_dwarf_tied_data_hashfunc(const void * keyp)82 _dwarf_tied_data_hashfunc(const void *keyp)
83 {
84 const struct Dwarf_Tied_Entry_s * enp = keyp;
85 DW_TSHASHTYPE hashv = 0;
86 /* Just take some of the 8 bytes of the signature. */
87 memcpy(&hashv,enp->dt_key.signature,sizeof(hashv));
88 return hashv;
89 }
90
91 int
_dwarf_tied_compare_function(const void * l,const void * r)92 _dwarf_tied_compare_function(const void *l, const void *r)
93 {
94 const struct Dwarf_Tied_Entry_s * lp = l;
95 const struct Dwarf_Tied_Entry_s * rp = r;
96 const char *lcp = (const char *)&lp->dt_key.signature;
97 const char *rcp = (const char *)&rp->dt_key.signature;
98 const char *lcpend = lcp + sizeof(Dwarf_Sig8);
99
100 for(; lcp < lcpend; ++lcp,++rcp) {
101 if (*lcp < *rcp) {
102 return -1;
103 } else if (*lcp > *rcp) {
104 return 1;
105 }
106 }
107 /* match. */
108 return 0;
109 }
110
111
112 void
_dwarf_tied_destroy_free_node(void * nodep)113 _dwarf_tied_destroy_free_node(void*nodep)
114 {
115 struct Dwarf_Tied_Entry_s * enp = nodep;
116 free(enp);
117 return;
118 }
119
120
121 /* This presumes only we are reading the debug_info
122 CUs from tieddbg. That is a reasonable
123 requirement, one hopes.
124 Currently it reads all the tied CUs at once, unless
125 there is an error..
126 */
127 int
_dwarf_loop_reading_debug_info_for_cu(Dwarf_Debug tieddbg,Dwarf_Sig8 sig,Dwarf_Error * error)128 _dwarf_loop_reading_debug_info_for_cu(
129 Dwarf_Debug tieddbg,
130 Dwarf_Sig8 sig,
131 Dwarf_Error *error)
132 {
133 unsigned loop_count = 0;
134 /* We will not find tied signatures
135 for .debug_addr (or line tables) in .debug_types.
136 it seems. Those signatures point from
137 'normal' to 'dwo/dwp' (DWARF4) */
138 int is_info = TRUE;
139 Dwarf_CU_Context startingcontext = 0;
140 Dwarf_Unsigned next_cu_offset = 0;
141
142 startingcontext = tieddbg->de_info_reading.de_cu_context;
143
144 if (startingcontext) {
145 next_cu_offset =
146 startingcontext->cc_debug_offset +
147 startingcontext->cc_length +
148 startingcontext->cc_length_size +
149 startingcontext->cc_extension_size;
150 }
151
152 for (;;++loop_count) {
153 int sres = DW_DLV_OK;
154 Dwarf_Half cu_type = 0;
155 Dwarf_CU_Context latestcontext = 0;
156 Dwarf_Unsigned cu_header_length = 0;
157 Dwarf_Unsigned abbrev_offset = 0;
158 Dwarf_Half version_stamp = 0;
159 Dwarf_Half address_size = 0;
160 Dwarf_Half extension_size = 0;
161 Dwarf_Half length_size = 0;
162 Dwarf_Sig8 signature;
163 Dwarf_Bool has_signature = FALSE;
164 Dwarf_Unsigned typeoffset = 0;
165
166
167 memset(&signature,0,sizeof(signature));
168 sres = _dwarf_next_cu_header_internal(tieddbg,
169 is_info,
170 &cu_header_length, &version_stamp,
171 &abbrev_offset, &address_size,
172 &length_size,&extension_size,
173 &signature, &has_signature,
174 &typeoffset,
175 &next_cu_offset,
176 &cu_type, error);
177 if (sres == DW_DLV_NO_ENTRY) {
178 break;
179 }
180
181 latestcontext = tieddbg->de_info_reading.de_cu_context;
182
183 if (has_signature) {
184 void *retval = 0;
185 Dwarf_Sig8 consign =
186 latestcontext->cc_signature;
187 void *entry =
188 _dwarf_tied_make_entry(&consign,latestcontext);
189
190 if (!entry) {
191 return DW_DLV_NO_ENTRY;
192 }
193 /* Insert this signature and context. */
194 retval = dwarf_tsearch(entry,
195 &tieddbg->de_tied_data.td_tied_search,
196 _dwarf_tied_compare_function);
197 if (!retval) {
198 /* FAILED might be out of memory.*/
199 return DW_DLV_NO_ENTRY;
200 }
201 #if 0 /* FIXME: do this? Not? */
202 /* This could be a compiler error. But
203 let us not decide? FIXME */
204 if (!latestcontext->cc_addr_base_present) {
205 }
206 #endif
207 if (!_dwarf_tied_compare_function(&sig,&consign) ) {
208 /* Identical. We found the matching CU. */
209 return DW_DLV_OK;
210 }
211 }
212 }
213 /* Apparently we never found the sig we are looking for.
214 Pretend ok. Caller will check for success. */
215 return DW_DLV_OK;
216 }
217
218
219 /* If out of memory just return DW_DLV_NO_ENTRY.
220 */
221 int
_dwarf_search_for_signature(Dwarf_Debug tieddbg,Dwarf_Sig8 sig,Dwarf_CU_Context * context_out,Dwarf_Error * error)222 _dwarf_search_for_signature(Dwarf_Debug tieddbg,
223 Dwarf_Sig8 sig,
224 Dwarf_CU_Context *context_out,
225 Dwarf_Error *error)
226 {
227
228 void *entry2 = 0;
229 struct Dwarf_Tied_Entry_s entry;
230 struct Dwarf_Tied_Data_s * tied = &tieddbg->de_tied_data;
231 int res = 0;
232
233 if (!tied->td_tied_search) {
234 dwarf_initialize_search_hash(&tied->td_tied_search,
235 _dwarf_tied_data_hashfunc,0);
236 if (!tied->td_tied_search) {
237 return DW_DLV_NO_ENTRY;
238 }
239 }
240 entry.dt_key = sig;
241 entry.dt_context = 0;
242 entry2 = dwarf_tfind(&entry,
243 &tied->td_tied_search,
244 _dwarf_tied_compare_function);
245 if (entry2) {
246 struct Dwarf_Tied_Entry_s *e2 =
247 *(struct Dwarf_Tied_Entry_s **)entry2;
248 *context_out = e2->dt_context;
249 return DW_DLV_OK;
250 }
251
252 /* We assume the caller is NOT doing
253 info section read operations
254 on the tieddbg. */
255 res = _dwarf_loop_reading_debug_info_for_cu(
256 tieddbg,sig,error);
257 if (res == DW_DLV_ERROR) {
258 return res;
259 }
260 entry2 = dwarf_tfind(&entry,
261 &tied->td_tied_search,
262 _dwarf_tied_compare_function);
263 if (entry2) {
264 struct Dwarf_Tied_Entry_s *e2 =
265 *(struct Dwarf_Tied_Entry_s **)entry2;
266 *context_out = e2->dt_context;
267 return DW_DLV_OK;
268 }
269 return DW_DLV_NO_ENTRY;
270 }
271