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 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 * 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 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 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 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 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 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