#include "config.h"
#include "dwarf_incl.h"
#include <stdio.h>
#include "dwarf_global.h"
#ifdef __sgi
void
_dwarf_fix_up_offset_irix(Dwarf_Debug dbg,
Dwarf_Unsigned * varp, char *caller_site_name)
{
Dwarf_Unsigned var = *varp;
#define UPPER33 0xffffffff80000000LL
#define LOWER32 0xffffffffLL
if ((var & UPPER33) == UPPER33) {
var &= LOWER32;
*varp = var;
}
#undef UPPER33
#undef LOWER32
return;
}
#endif
int
dwarf_get_globals(Dwarf_Debug dbg,
Dwarf_Global ** globals,
Dwarf_Signed * return_count, Dwarf_Error * error)
{
int res;
res =
_dwarf_load_section(dbg,
dbg->de_debug_pubnames_index,
&dbg->de_debug_pubnames, error);
if (res != DW_DLV_OK) {
return res;
}
return _dwarf_internal_get_pubnames_like_data(dbg,
dbg->
de_debug_pubnames,
dbg->
de_debug_pubnames_size,
globals, return_count,
error,
DW_DLA_GLOBAL_CONTEXT,
DW_DLA_GLOBAL,
DW_DLE_PUBNAMES_LENGTH_BAD,
DW_DLE_PUBNAMES_VERSION_ERROR);
}
void
dwarf_globals_dealloc(Dwarf_Debug dbg, Dwarf_Global * dwgl,
Dwarf_Signed count)
{
_dwarf_internal_globals_dealloc(dbg, dwgl,
count,
DW_DLA_GLOBAL_CONTEXT,
DW_DLA_GLOBAL, DW_DLA_LIST);
return;
}
void
_dwarf_internal_globals_dealloc(Dwarf_Debug dbg, Dwarf_Global * dwgl,
Dwarf_Signed count,
int context_code,
int global_code, int list_code)
{
Dwarf_Signed i;
struct Dwarf_Global_Context_s *gcp = 0;
struct Dwarf_Global_Context_s *lastgcp = 0;
for (i = 0; i < count; i++) {
Dwarf_Global dgb = dwgl[i];
gcp = dgb->gl_context;
if (lastgcp != gcp) {
lastgcp = gcp;
dwarf_dealloc(dbg, gcp, context_code);
}
dwarf_dealloc(dbg, dgb, global_code);
}
dwarf_dealloc(dbg, dwgl, list_code);
return;
}
int
_dwarf_internal_get_pubnames_like_data(Dwarf_Debug dbg,
Dwarf_Small * section_data_ptr,
Dwarf_Unsigned section_length,
Dwarf_Global ** globals,
Dwarf_Signed * return_count,
Dwarf_Error * error,
int context_code,
int global_code,
int length_err_num,
int version_err_num)
{
Dwarf_Small *pubnames_like_ptr;
Dwarf_Global_Context pubnames_context;
Dwarf_Half version;
Dwarf_Off die_offset_in_cu;
Dwarf_Unsigned global_count = 0;
Dwarf_Global global;
Dwarf_Chain curr_chain, prev_chain, head_chain = NULL;
Dwarf_Global *ret_globals;
Dwarf_Unsigned i;
if (dbg == NULL) {
_dwarf_error(NULL, error, DW_DLE_DBG_NULL);
return (DW_DLV_ERROR);
}
if (!dbg->de_debug_info) {
int res = _dwarf_load_debug_info(dbg, error);
if (res != DW_DLV_OK) {
return res;
}
}
if (section_data_ptr == NULL) {
return (DW_DLV_NO_ENTRY);
}
pubnames_like_ptr = section_data_ptr;
do {
Dwarf_Unsigned length;
int local_extension_size;
int local_length_size;
Dwarf_Small *pubnames_ptr_past_end_cu = 0;
pubnames_context = (Dwarf_Global_Context)
_dwarf_get_alloc(dbg, context_code, 1);
if (pubnames_context == NULL) {
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
return (DW_DLV_ERROR);
}
READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned,
pubnames_like_ptr, local_length_size,
local_extension_size);
pubnames_context->pu_length_size = local_length_size;
pubnames_context->pu_extension_size = local_extension_size;
pubnames_context->pu_dbg = dbg;
pubnames_ptr_past_end_cu = pubnames_like_ptr + length;
READ_UNALIGNED(dbg, version, Dwarf_Half,
pubnames_like_ptr, sizeof(Dwarf_Half));
pubnames_like_ptr += sizeof(Dwarf_Half);
if (version != CURRENT_VERSION_STAMP) {
_dwarf_error(dbg, error, version_err_num);
return (DW_DLV_ERROR);
}
READ_UNALIGNED(dbg, pubnames_context->pu_offset_of_cu_header,
Dwarf_Off, pubnames_like_ptr,
pubnames_context->pu_length_size);
pubnames_like_ptr += pubnames_context->pu_length_size;
FIX_UP_OFFSET_IRIX_BUG(dbg,
pubnames_context->pu_offset_of_cu_header,
"pubnames cu header offset");
READ_UNALIGNED(dbg, pubnames_context->pu_info_length,
Dwarf_Unsigned, pubnames_like_ptr,
pubnames_context->pu_length_size);
pubnames_like_ptr += pubnames_context->pu_length_size;
if (pubnames_like_ptr > (section_data_ptr + section_length)) {
_dwarf_error(dbg, error, length_err_num);
return (DW_DLV_ERROR);
}
READ_UNALIGNED(dbg, die_offset_in_cu, Dwarf_Off,
pubnames_like_ptr,
pubnames_context->pu_length_size);
pubnames_like_ptr += pubnames_context->pu_length_size;
FIX_UP_OFFSET_IRIX_BUG(dbg,
die_offset_in_cu, "offset of die in cu");
while (die_offset_in_cu != 0) {
global =
(Dwarf_Global) _dwarf_get_alloc(dbg, global_code, 1);
if (global == NULL) {
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
return (DW_DLV_ERROR);
}
global_count++;
global->gl_context = pubnames_context;
global->gl_named_die_offset_within_cu = die_offset_in_cu;
global->gl_name = pubnames_like_ptr;
pubnames_like_ptr = pubnames_like_ptr +
strlen((char *) pubnames_like_ptr) + 1;
curr_chain =
(Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
if (curr_chain == NULL) {
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
return (DW_DLV_ERROR);
}
curr_chain->ch_item = (Dwarf_Global) global;
if (head_chain == NULL)
head_chain = prev_chain = curr_chain;
else {
prev_chain->ch_next = curr_chain;
prev_chain = curr_chain;
}
READ_UNALIGNED(dbg, die_offset_in_cu, Dwarf_Off,
pubnames_like_ptr,
pubnames_context->pu_length_size);
pubnames_like_ptr += pubnames_context->pu_length_size;
FIX_UP_OFFSET_IRIX_BUG(dbg,
die_offset_in_cu,
"offset of next die in cu");
if (pubnames_like_ptr > (section_data_ptr + section_length)) {
_dwarf_error(dbg, error, length_err_num);
return (DW_DLV_ERROR);
}
}
if (pubnames_like_ptr > pubnames_ptr_past_end_cu) {
_dwarf_error(dbg, error, length_err_num);
return (DW_DLV_ERROR);
}
pubnames_like_ptr = pubnames_ptr_past_end_cu;
} while (pubnames_like_ptr < (section_data_ptr + section_length));
ret_globals = (Dwarf_Global *)
_dwarf_get_alloc(dbg, DW_DLA_LIST, global_count);
if (ret_globals == NULL) {
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
return (DW_DLV_ERROR);
}
curr_chain = head_chain;
for (i = 0; i < global_count; i++) {
*(ret_globals + i) = curr_chain->ch_item;
prev_chain = curr_chain;
curr_chain = curr_chain->ch_next;
dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
}
*globals = ret_globals;
*return_count = (Dwarf_Signed) global_count;
return DW_DLV_OK;
}
int
dwarf_globname(Dwarf_Global glob, char **ret_name, Dwarf_Error * error)
{
if (glob == NULL) {
_dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
return (DW_DLV_ERROR);
}
*ret_name = (char *) (glob->gl_name);
return DW_DLV_OK;
}
int
dwarf_global_die_offset(Dwarf_Global global,
Dwarf_Off * ret_off, Dwarf_Error * error)
{
if (global == NULL) {
_dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
return (DW_DLV_ERROR);
}
if (global->gl_context == NULL) {
_dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
return (DW_DLV_ERROR);
}
*ret_off = (global->gl_named_die_offset_within_cu +
global->gl_context->pu_offset_of_cu_header);
return DW_DLV_OK;
}
int
dwarf_global_cu_offset(Dwarf_Global global,
Dwarf_Off * cu_header_offset,
Dwarf_Error * error)
{
Dwarf_Global_Context con;
if (global == NULL) {
_dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
return (DW_DLV_ERROR);
}
con = global->gl_context;
if (con == NULL) {
_dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
return (DW_DLV_ERROR);
}
*cu_header_offset = con->pu_offset_of_cu_header;
return DW_DLV_OK;
}
int
dwarf_global_name_offsets(Dwarf_Global global,
char **ret_name,
Dwarf_Off * die_offset,
Dwarf_Off * cu_die_offset,
Dwarf_Error * error)
{
Dwarf_Global_Context con;
Dwarf_Debug dbg;
Dwarf_Off off;
if (global == NULL) {
_dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
return (DW_DLV_ERROR);
}
con = global->gl_context;
if (con == NULL) {
_dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
return (DW_DLV_ERROR);
}
off = con->pu_offset_of_cu_header;
#define MIN_CU_HDR_SIZE 10
dbg = con->pu_dbg;
if (dbg == NULL) {
_dwarf_error(NULL, error, DW_DLE_DBG_NULL);
return (DW_DLV_ERROR);
}
if (dbg->de_debug_info_size &&
((off + MIN_CU_HDR_SIZE) >= dbg->de_debug_info_size)) {
_dwarf_error(NULL, error, DW_DLE_OFFSET_BAD);
return (DW_DLV_ERROR);
}
#undef MIN_CU_HDR_SIZE
if (die_offset != NULL) {
*die_offset = global->gl_named_die_offset_within_cu + off;
}
*ret_name = (char *) global->gl_name;
if (cu_die_offset != NULL) {
int res = _dwarf_load_debug_info(dbg, error);
if (res != DW_DLV_OK) {
return res;
}
if ((off + 10) >= dbg->de_debug_info_size) {
_dwarf_error(NULL, error, DW_DLE_OFFSET_BAD);
return (DW_DLV_ERROR);
}
*cu_die_offset = off + _dwarf_length_of_cu_header(dbg, off);
}
return DW_DLV_OK;
}
int
dwarf_get_cu_die_offset_given_cu_header_offset(Dwarf_Debug dbg,
Dwarf_Off
in_cu_header_offset,
Dwarf_Off *
out_cu_die_offset,
Dwarf_Error * err)
{
Dwarf_Off len =
_dwarf_length_of_cu_header(dbg, in_cu_header_offset);
Dwarf_Off newoff = in_cu_header_offset + len;
*out_cu_die_offset = newoff;
return DW_DLV_OK;
}