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