#include "config.h"
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#include "dwarf_incl.h"
#include "dwarf_error.h"
#include "dwarf_tsearch.h"
#define TRUE 1
#define FALSE 0
#define HASHSEARCH
struct Dwarf_Group_Map_Entry_s {
unsigned gm_key;
unsigned gm_group_number;
const char * gm_section_name;
};
static void *
grp_make_entry(unsigned section, unsigned group,const char *name)
{
struct Dwarf_Group_Map_Entry_s *e = 0;
e = calloc(1,sizeof(struct Dwarf_Group_Map_Entry_s));
if(e) {
e->gm_key = section;
e->gm_group_number = group;
e->gm_section_name = name;
}
return e;
}
static DW_TSHASHTYPE
grp_data_hashfunc(const void *keyp)
{
const struct Dwarf_Group_Map_Entry_s * enp = keyp;
DW_TSHASHTYPE hashv = 0;
hashv = enp->gm_key;
return hashv;
}
static int
grp_compare_function(const void *l, const void *r)
{
const struct Dwarf_Group_Map_Entry_s * lp = l;
const struct Dwarf_Group_Map_Entry_s * rp = r;
if (lp->gm_key < rp->gm_key) {
return -1;
}
if (lp->gm_key > rp->gm_key) {
return 1;
}
return 0;
}
static void
_dwarf_grp_destroy_free_node(void*nodep)
{
struct Dwarf_Group_Map_Entry_s * enp = nodep;
free(enp);
return;
}
int
_dwarf_insert_in_group_map(Dwarf_Debug dbg,
unsigned groupnum,
unsigned section_index,
const char *name,
Dwarf_Error * error)
{
struct Dwarf_Group_Data_s *grp = &dbg->de_groupnumbers;
void *entry2 = 0;
struct Dwarf_Group_Map_Entry_s * entry3 = 0;
if (!grp->gd_map) {
dwarf_initialize_search_hash(&grp->gd_map,
grp_data_hashfunc,grp->gd_number_of_sections);
if (!grp->gd_map) {
return DW_DLV_NO_ENTRY;
}
}
entry3 = grp_make_entry(section_index,groupnum,name);
if (!entry3) {
_dwarf_error(dbg, error, DW_DLE_GROUP_MAP_ALLOC);
return DW_DLV_ERROR;
}
entry2 = dwarf_tsearch(entry3,&grp->gd_map,grp_compare_function);
if (!entry2) {
free(entry3);
_dwarf_error(dbg, error, DW_DLE_GROUP_MAP_ALLOC);
return DW_DLV_ERROR;
} else {
struct Dwarf_Group_Map_Entry_s *re = 0;
re = *(struct Dwarf_Group_Map_Entry_s **)entry2;
if (re != entry3) {
free(entry3);
_dwarf_error(dbg, error, DW_DLE_GROUP_MAP_DUPLICATE);
return DW_DLV_ERROR;
} else {
++grp->gd_map_entry_count;
}
}
return DW_DLV_OK;
}
int
_dwarf_section_get_target_group_from_map(Dwarf_Debug dbg,
unsigned obj_section_index,
unsigned * groupnumber_out,
UNUSEDARG Dwarf_Error * error)
{
struct Dwarf_Group_Map_Entry_s entry;
struct Dwarf_Group_Map_Entry_s *entry2;
struct Dwarf_Group_Data_s *grp = &dbg->de_groupnumbers;
if (!grp->gd_map) {
return DW_DLV_NO_ENTRY;
}
entry.gm_key = obj_section_index;
entry.gm_group_number = 0;
entry.gm_section_name = "";
entry2 = dwarf_tfind(&entry, &grp->gd_map,grp_compare_function);
if (entry2) {
struct Dwarf_Group_Map_Entry_s *e2 =
*(struct Dwarf_Group_Map_Entry_s **)entry2;;
*groupnumber_out = e2->gm_group_number;
return DW_DLV_OK;
}
return DW_DLV_NO_ENTRY;
}
int dwarf_sec_group_sizes(Dwarf_Debug dbg,
Dwarf_Unsigned * section_count_out,
Dwarf_Unsigned * group_count_out,
Dwarf_Unsigned * selected_group_out,
Dwarf_Unsigned * map_entry_count_out,
UNUSEDARG Dwarf_Error * error)
{
struct Dwarf_Group_Data_s *grp = &dbg->de_groupnumbers;
*section_count_out = grp->gd_number_of_sections;
*group_count_out = grp->gd_number_of_groups;
*selected_group_out = dbg->de_groupnumber;
*map_entry_count_out = grp->gd_map_entry_count;
return DW_DLV_OK;
}
static Dwarf_Unsigned map_reccount = 0;
static struct temp_map_struc_s {
Dwarf_Unsigned section;
Dwarf_Unsigned group;
const char *name;
} *temp_map_data;
static void
grp_walk_map(const void *nodep,
const DW_VISIT which,
UNUSEDARG const int depth)
{
struct Dwarf_Group_Map_Entry_s *re = 0;
re = *(struct Dwarf_Group_Map_Entry_s **)nodep;
if (which == dwarf_postorder || which == dwarf_endorder) {
return;
}
temp_map_data[map_reccount].group = re->gm_group_number;
temp_map_data[map_reccount].section = re->gm_key;
temp_map_data[map_reccount].name = re->gm_section_name;
map_reccount += 1;
}
static int
map_sort_compar(const void*l, const void*r)
{
struct temp_map_struc_s *lv = (struct temp_map_struc_s *)l;
struct temp_map_struc_s *rv = (struct temp_map_struc_s *)r;
if (lv->group < rv->group) {
return -1;
}
if (lv->group > rv->group) {
return 1;
}
if (lv->section < rv->section) {
return -1;
}
if (lv->section > rv->section) {
return 1;
}
return 0;
}
int dwarf_sec_group_map(Dwarf_Debug dbg,
Dwarf_Unsigned map_entry_count,
Dwarf_Unsigned * group_numbers_array,
Dwarf_Unsigned * sec_numbers_array,
const char ** sec_names_array,
Dwarf_Error * error)
{
Dwarf_Unsigned i = 0;
struct Dwarf_Group_Data_s *grp = 0;
if(temp_map_data) {
_dwarf_error(dbg,error,DW_DLE_GROUP_INTERNAL_ERROR);
return DW_DLV_ERROR;
}
map_reccount = 0;
grp = &dbg->de_groupnumbers;
if (map_entry_count < grp->gd_map_entry_count) {
_dwarf_error(dbg,error,DW_DLE_GROUP_COUNT_ERROR);
return DW_DLV_ERROR;
}
temp_map_data = calloc(map_entry_count,sizeof(struct temp_map_struc_s));
if(!temp_map_data) {
_dwarf_error(dbg,error,DW_DLE_GROUP_MAP_ALLOC);
return DW_DLV_ERROR;
}
dwarf_twalk(grp->gd_map,grp_walk_map);
if (map_reccount != grp->gd_map_entry_count) {
_dwarf_error(dbg,error,DW_DLE_GROUP_INTERNAL_ERROR);
return DW_DLV_ERROR;
}
qsort(temp_map_data,map_reccount,sizeof(struct temp_map_struc_s),
map_sort_compar);
for (i =0 ; i < map_reccount; ++i) {
sec_numbers_array[i] = temp_map_data[i].section;
group_numbers_array[i] = temp_map_data[i].group;
sec_names_array[i] = temp_map_data[i].name;
}
free(temp_map_data);
map_reccount = 0;
temp_map_data = 0;
return DW_DLV_OK;
}
static const char *dwo_secnames[] = {
".debug_info.dwo",
".debug_types.dwo",
".debug_abbrev.dwo",
".debug_line.dwo",
".debug_loc.dwo",
".debug_str.dwo",
".debug_loclists.dwo",
".debug_rnglists.dwo",
".debug_str_offsets.dwo",
".debug_macro.dwo",
".debug_cu_index",
".debug_tu_index",
0 };
int
_dwarf_dwo_groupnumber_given_name(
const char *name,
unsigned *grpnum_out)
{
const char **s = 0;
for (s = dwo_secnames; *s; s++) {
if(!strcmp(name,*s)) {
*grpnum_out = DW_GROUPNUMBER_DWO;
return DW_DLV_OK;
}
}
return DW_DLV_NO_ENTRY;
}
static unsigned target_group = 0;
static int found_name_in_group = 0;
const char *lookfor_name = 0;
static void
grp_walk_for_name(const void *nodep,
const DW_VISIT which,
UNUSEDARG const int depth)
{
struct Dwarf_Group_Map_Entry_s *re = 0;
re = *(struct Dwarf_Group_Map_Entry_s **)nodep;
if (which == dwarf_postorder || which == dwarf_endorder) {
return;
}
if (re->gm_group_number == target_group) {
if(!strcmp(lookfor_name,re->gm_section_name)) {
found_name_in_group = TRUE;
}
}
}
int
_dwarf_section_in_group_by_name(Dwarf_Debug dbg,
const char * scn_name,
unsigned groupnum)
{
struct Dwarf_Group_Data_s *grp = 0;
grp = &dbg->de_groupnumbers;
found_name_in_group = FALSE;
target_group = groupnum;
lookfor_name = scn_name;
dwarf_twalk(grp->gd_map,grp_walk_for_name);
return found_name_in_group;
}
void
_dwarf_destroy_group_map(Dwarf_Debug dbg)
{
dwarf_tdestroy(dbg->de_groupnumbers.gd_map,_dwarf_grp_destroy_free_node);
dbg->de_groupnumbers.gd_map = 0;
}