1 /* 2 Copyright (C) 2017-2018 David Anderson. All Rights Reserved. 3 4 This program is free software; you can redistribute it 5 and/or modify it under the terms of version 2.1 of the 6 GNU Lesser General Public License as published by the Free 7 Software Foundation. 8 9 This program is distributed in the hope that it would be 10 useful, but WITHOUT ANY WARRANTY; without even the implied 11 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 12 PURPOSE. 13 14 Further, this software is distributed without any warranty 15 that it is free of the rightful claim of any third person 16 regarding infringement or the like. Any license provided 17 herein, whether implied or otherwise, applies only to this 18 software file. Patent licenses, if any, provided herein 19 do not apply to combinations of this program with other 20 software, or any other product whatsoever. 21 22 You should have received a copy of the GNU Lesser General 23 Public License along with this program; if not, write the 24 Free Software Foundation, Inc., 51 Franklin Street - Fifth 25 Floor, Boston MA 02110-1301, USA. 26 27 */ 28 29 #include "config.h" 30 #include <stdio.h> 31 #ifdef HAVE_STDLIB_H 32 #include <stdlib.h> 33 #endif /* HAVE_STDLIB_H */ 34 #ifdef HAVE_STDINT_H 35 #include <stdint.h> /* For uintptr_t */ 36 #endif /* HAVE_STDINT_H */ 37 #include "dwarf_incl.h" 38 #include "dwarf_error.h" 39 #include "dwarf_tsearch.h" 40 41 #define TRUE 1 42 #define FALSE 0 43 44 #define HASHSEARCH 45 46 /* It has not escaped our attention that the section-group 47 tsearch hash table could 48 be replaced by a simple array with space for each possible 49 section number, each element being the group number. 50 This would be much simpler than what follows here. */ 51 52 /* Each section number can appear in at most one record in the hash 53 because each section belongs in only one group. 54 Each group number appears as often as appropriate. */ 55 56 struct Dwarf_Group_Map_Entry_s { 57 unsigned gm_key; /* section number */ 58 unsigned gm_group_number; /* What group number is. */ 59 60 /* The name is from static storage or from elf, 61 so there is nothing to free on record delete. */ 62 const char * gm_section_name; 63 }; 64 65 static void * 66 grp_make_entry(unsigned section, unsigned group,const char *name) 67 { 68 struct Dwarf_Group_Map_Entry_s *e = 0; 69 e = calloc(1,sizeof(struct Dwarf_Group_Map_Entry_s)); 70 if(e) { 71 e->gm_key = section; 72 e->gm_group_number = group; 73 e->gm_section_name = name; 74 } 75 return e; 76 } 77 78 79 static DW_TSHASHTYPE 80 grp_data_hashfunc(const void *keyp) 81 { 82 const struct Dwarf_Group_Map_Entry_s * enp = keyp; 83 DW_TSHASHTYPE hashv = 0; 84 85 hashv = enp->gm_key; 86 return hashv; 87 } 88 89 static int 90 grp_compare_function(const void *l, const void *r) 91 { 92 const struct Dwarf_Group_Map_Entry_s * lp = l; 93 const struct Dwarf_Group_Map_Entry_s * rp = r; 94 95 if (lp->gm_key < rp->gm_key) { 96 return -1; 97 } 98 if (lp->gm_key > rp->gm_key) { 99 return 1; 100 } 101 102 /* match. */ 103 return 0; 104 } 105 106 static void 107 _dwarf_grp_destroy_free_node(void*nodep) 108 { 109 struct Dwarf_Group_Map_Entry_s * enp = nodep; 110 free(enp); 111 return; 112 } 113 114 int 115 _dwarf_insert_in_group_map(Dwarf_Debug dbg, 116 unsigned groupnum, 117 unsigned section_index, 118 const char *name, 119 Dwarf_Error * error) 120 { 121 struct Dwarf_Group_Data_s *grp = &dbg->de_groupnumbers; 122 123 void *entry2 = 0; 124 struct Dwarf_Group_Map_Entry_s * entry3 = 0; 125 126 if (!grp->gd_map) { 127 /* Number of sections is a kind of decent guess 128 as to how much space would be useful. */ 129 dwarf_initialize_search_hash(&grp->gd_map, 130 grp_data_hashfunc,grp->gd_number_of_sections); 131 if (!grp->gd_map) { 132 /* It's really an error I suppose. */ 133 return DW_DLV_NO_ENTRY; 134 } 135 } 136 entry3 = grp_make_entry(section_index,groupnum,name); 137 if (!entry3) { 138 _dwarf_error(dbg, error, DW_DLE_GROUP_MAP_ALLOC); 139 return DW_DLV_ERROR; 140 } 141 entry2 = dwarf_tsearch(entry3,&grp->gd_map,grp_compare_function); 142 if (!entry2) { 143 free(entry3); 144 _dwarf_error(dbg, error, DW_DLE_GROUP_MAP_ALLOC); 145 return DW_DLV_ERROR; 146 } else { 147 struct Dwarf_Group_Map_Entry_s *re = 0; 148 re = *(struct Dwarf_Group_Map_Entry_s **)entry2; 149 if (re != entry3) { 150 free(entry3); 151 _dwarf_error(dbg, error, DW_DLE_GROUP_MAP_DUPLICATE); 152 return DW_DLV_ERROR; 153 } else { 154 ++grp->gd_map_entry_count; 155 /* OK. Added. Fall thru */ 156 } 157 } 158 return DW_DLV_OK; 159 } 160 161 int 162 _dwarf_section_get_target_group_from_map(Dwarf_Debug dbg, 163 unsigned obj_section_index, 164 unsigned * groupnumber_out, 165 UNUSEDARG Dwarf_Error * error) 166 { 167 struct Dwarf_Group_Map_Entry_s entry; 168 struct Dwarf_Group_Map_Entry_s *entry2; 169 struct Dwarf_Group_Data_s *grp = &dbg->de_groupnumbers; 170 171 if (!grp->gd_map) { 172 return DW_DLV_NO_ENTRY; 173 } 174 entry.gm_key = obj_section_index; 175 entry.gm_group_number = 0; /* FAKE */ 176 entry.gm_section_name = ""; /* FAKE */ 177 178 entry2 = dwarf_tfind(&entry, &grp->gd_map,grp_compare_function); 179 if (entry2) { 180 struct Dwarf_Group_Map_Entry_s *e2 = 181 *(struct Dwarf_Group_Map_Entry_s **)entry2;; 182 *groupnumber_out = e2->gm_group_number; 183 return DW_DLV_OK; 184 } 185 return DW_DLV_NO_ENTRY; 186 } 187 188 189 190 191 /* New May 2017. So users can find out what groups (dwo or COMDAT) 192 are in the object and how much to allocate so one can get the 193 group-section map data. */ 194 int dwarf_sec_group_sizes(Dwarf_Debug dbg, 195 Dwarf_Unsigned * section_count_out, 196 Dwarf_Unsigned * group_count_out, 197 Dwarf_Unsigned * selected_group_out, 198 Dwarf_Unsigned * map_entry_count_out, 199 UNUSEDARG Dwarf_Error * error) 200 { 201 struct Dwarf_Group_Data_s *grp = &dbg->de_groupnumbers; 202 203 *section_count_out = grp->gd_number_of_sections; 204 *group_count_out = grp->gd_number_of_groups; 205 *selected_group_out = dbg->de_groupnumber; 206 *map_entry_count_out = grp->gd_map_entry_count; 207 return DW_DLV_OK; 208 } 209 210 211 static Dwarf_Unsigned map_reccount = 0; 212 static struct temp_map_struc_s { 213 Dwarf_Unsigned section; 214 Dwarf_Unsigned group; 215 const char *name; 216 } *temp_map_data; 217 218 219 static void 220 grp_walk_map(const void *nodep, 221 const DW_VISIT which, 222 UNUSEDARG const int depth) 223 { 224 struct Dwarf_Group_Map_Entry_s *re = 0; 225 226 re = *(struct Dwarf_Group_Map_Entry_s **)nodep; 227 if (which == dwarf_postorder || which == dwarf_endorder) { 228 return; 229 } 230 temp_map_data[map_reccount].group = re->gm_group_number; 231 temp_map_data[map_reccount].section = re->gm_key; 232 temp_map_data[map_reccount].name = re->gm_section_name; 233 map_reccount += 1; 234 } 235 236 /* Looks better sorted by group then sec num. */ 237 static int 238 map_sort_compar(const void*l, const void*r) 239 { 240 struct temp_map_struc_s *lv = (struct temp_map_struc_s *)l; 241 struct temp_map_struc_s *rv = (struct temp_map_struc_s *)r; 242 243 if (lv->group < rv->group) { 244 return -1; 245 } 246 if (lv->group > rv->group) { 247 return 1; 248 } 249 if (lv->section < rv->section) { 250 return -1; 251 } 252 if (lv->section > rv->section) { 253 return 1; 254 } 255 /* Should never get here! */ 256 return 0; 257 258 } 259 260 /* New May 2017. Reveals the map between group numbers 261 and section numbers. 262 Caller must allocate the arrays with space for 'map_entry_count' 263 values and this function fills in the array entries. 264 Output ordered by group number and section number. 265 */ 266 int dwarf_sec_group_map(Dwarf_Debug dbg, 267 Dwarf_Unsigned map_entry_count, 268 Dwarf_Unsigned * group_numbers_array, 269 Dwarf_Unsigned * sec_numbers_array, 270 const char ** sec_names_array, 271 Dwarf_Error * error) 272 { 273 Dwarf_Unsigned i = 0; 274 struct Dwarf_Group_Data_s *grp = 0; 275 276 if(temp_map_data) { 277 _dwarf_error(dbg,error,DW_DLE_GROUP_INTERNAL_ERROR); 278 return DW_DLV_ERROR; 279 } 280 map_reccount = 0; 281 grp = &dbg->de_groupnumbers; 282 if (map_entry_count < grp->gd_map_entry_count) { 283 _dwarf_error(dbg,error,DW_DLE_GROUP_COUNT_ERROR); 284 return DW_DLV_ERROR; 285 } 286 temp_map_data = calloc(map_entry_count,sizeof(struct temp_map_struc_s)); 287 if(!temp_map_data) { 288 _dwarf_error(dbg,error,DW_DLE_GROUP_MAP_ALLOC); 289 return DW_DLV_ERROR; 290 } 291 dwarf_twalk(grp->gd_map,grp_walk_map); 292 if (map_reccount != grp->gd_map_entry_count) { 293 /* Impossible. */ 294 _dwarf_error(dbg,error,DW_DLE_GROUP_INTERNAL_ERROR); 295 return DW_DLV_ERROR; 296 } 297 298 qsort(temp_map_data,map_reccount,sizeof(struct temp_map_struc_s), 299 map_sort_compar); 300 for (i =0 ; i < map_reccount; ++i) { 301 sec_numbers_array[i] = temp_map_data[i].section; 302 group_numbers_array[i] = temp_map_data[i].group; 303 sec_names_array[i] = temp_map_data[i].name; 304 } 305 free(temp_map_data); 306 map_reccount = 0; 307 temp_map_data = 0; 308 return DW_DLV_OK; 309 } 310 311 static const char *dwo_secnames[] = { 312 ".debug_info.dwo", 313 ".debug_types.dwo", 314 ".debug_abbrev.dwo", 315 ".debug_line.dwo", 316 ".debug_loc.dwo", 317 ".debug_str.dwo", 318 ".debug_loclists.dwo", 319 ".debug_rnglists.dwo", 320 ".debug_str_offsets.dwo", 321 ".debug_macro.dwo", 322 ".debug_cu_index", 323 ".debug_tu_index", 324 0 }; 325 326 /* Assumption: dwo sections are never in a COMDAT group 327 (groupnumber >2) 328 and by definition here are never group 1. 329 Assumption: the map of COMDAT groups (not necessarily all 330 sections, but at least all COMDAT) is complete. */ 331 int 332 _dwarf_dwo_groupnumber_given_name( 333 const char *name, 334 unsigned *grpnum_out) 335 { 336 const char **s = 0; 337 338 for (s = dwo_secnames; *s; s++) { 339 if(!strcmp(name,*s)) { 340 *grpnum_out = DW_GROUPNUMBER_DWO; 341 return DW_DLV_OK; 342 } 343 } 344 return DW_DLV_NO_ENTRY; 345 } 346 347 static unsigned target_group = 0; 348 static int found_name_in_group = 0; 349 const char *lookfor_name = 0; 350 351 static void 352 grp_walk_for_name(const void *nodep, 353 const DW_VISIT which, 354 UNUSEDARG const int depth) 355 { 356 struct Dwarf_Group_Map_Entry_s *re = 0; 357 358 re = *(struct Dwarf_Group_Map_Entry_s **)nodep; 359 if (which == dwarf_postorder || which == dwarf_endorder) { 360 return; 361 } 362 if (re->gm_group_number == target_group) { 363 if(!strcmp(lookfor_name,re->gm_section_name)) { 364 found_name_in_group = TRUE; 365 } 366 } 367 } 368 369 370 /* returns TRUE or FALSE */ 371 int 372 _dwarf_section_in_group_by_name(Dwarf_Debug dbg, 373 const char * scn_name, 374 unsigned groupnum) 375 { 376 struct Dwarf_Group_Data_s *grp = 0; 377 378 grp = &dbg->de_groupnumbers; 379 found_name_in_group = FALSE; 380 target_group = groupnum; 381 lookfor_name = scn_name; 382 dwarf_twalk(grp->gd_map,grp_walk_for_name); 383 return found_name_in_group; 384 } 385 386 void 387 _dwarf_destroy_group_map(Dwarf_Debug dbg) 388 { 389 dwarf_tdestroy(dbg->de_groupnumbers.gd_map,_dwarf_grp_destroy_free_node); 390 dbg->de_groupnumbers.gd_map = 0; 391 } 392