#include "config.h"
#include "dwarf_incl.h"
#include <stdio.h>
#include "dwarf_arange.h"
#include "dwarf_global.h"
int
dwarf_get_aranges(Dwarf_Debug dbg,
Dwarf_Arange ** aranges,
Dwarf_Signed * returned_count, Dwarf_Error * error)
{
Dwarf_Small *arange_ptr;
Dwarf_Small *header_ptr;
Dwarf_Half version;
Dwarf_Off info_offset;
Dwarf_Small address_size;
Dwarf_Small segment_size;
Dwarf_Small remainder;
Dwarf_Unsigned arange_count = 0;
Dwarf_Addr range_address;
Dwarf_Unsigned range_length;
Dwarf_Arange arange, *arange_block;
Dwarf_Unsigned i;
Dwarf_Chain curr_chain, prev_chain, head_chain = NULL;
int res;
if (dbg == NULL) {
_dwarf_error(NULL, error, DW_DLE_DBG_NULL);
return (DW_DLV_ERROR);
}
res =
_dwarf_load_section(dbg,
dbg->de_debug_aranges_index,
&dbg->de_debug_aranges, error);
if (res != DW_DLV_OK) {
return res;
}
arange_ptr = dbg->de_debug_aranges;
do {
Dwarf_Unsigned length;
Dwarf_Small *arange_ptr_past_end = 0;
int local_length_size;
int local_extension_size;
header_ptr = arange_ptr;
READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned,
arange_ptr, local_length_size,
local_extension_size);
arange_ptr_past_end = arange_ptr + length;
READ_UNALIGNED(dbg, version, Dwarf_Half,
arange_ptr, sizeof(Dwarf_Half));
arange_ptr += sizeof(Dwarf_Half);
length = length - sizeof(Dwarf_Half);
if (version != CURRENT_VERSION_STAMP) {
_dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR);
return (DW_DLV_ERROR);
}
READ_UNALIGNED(dbg, info_offset, Dwarf_Off,
arange_ptr, local_length_size);
arange_ptr += local_length_size;
length = length - local_length_size;
if (info_offset >= dbg->de_debug_info_size) {
FIX_UP_OFFSET_IRIX_BUG(dbg, info_offset,
"arange info offset.a");
if (info_offset >= dbg->de_debug_info_size) {
_dwarf_error(dbg, error, DW_DLE_ARANGE_OFFSET_BAD);
return (DW_DLV_ERROR);
}
}
address_size = *(Dwarf_Small *) arange_ptr;
if (address_size != dbg->de_pointer_size) {
_dwarf_error(dbg, error, DW_DLE_BADBITC);
return (DW_DLV_ERROR);
}
arange_ptr = arange_ptr + sizeof(Dwarf_Small);
length = length - sizeof(Dwarf_Small);
segment_size = *(Dwarf_Small *) arange_ptr;
arange_ptr = arange_ptr + sizeof(Dwarf_Small);
length = length - sizeof(Dwarf_Small);
if (segment_size != 0) {
_dwarf_error(dbg, error, DW_DLE_SEGMENT_SIZE_BAD);
return (DW_DLV_ERROR);
}
remainder = (Dwarf_Unsigned) (arange_ptr - header_ptr) %
(2 * address_size);
if (remainder != 0) {
arange_ptr = arange_ptr + (2 * address_size) - remainder;
length = length - ((2 * address_size) - remainder);
}
do {
READ_UNALIGNED(dbg, range_address, Dwarf_Addr,
arange_ptr, address_size);
arange_ptr += address_size;
length = length - address_size;
READ_UNALIGNED(dbg, range_length, Dwarf_Unsigned,
arange_ptr, address_size);
arange_ptr += address_size;
length = length - address_size;
if (range_address != 0 || range_length != 0) {
arange = (Dwarf_Arange)
_dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1);
if (arange == NULL) {
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
return (DW_DLV_ERROR);
}
arange->ar_address = range_address;
arange->ar_length = range_length;
arange->ar_info_offset = info_offset;
arange->ar_dbg = dbg;
arange_count++;
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 = arange;
if (head_chain == NULL)
head_chain = prev_chain = curr_chain;
else {
prev_chain->ch_next = curr_chain;
prev_chain = curr_chain;
}
}
} while (range_address != 0 || range_length != 0);
if (arange_ptr_past_end < arange_ptr) {
_dwarf_error(dbg, error, DW_DLE_ARANGE_LENGTH_BAD);
return (DW_DLV_ERROR);
}
arange_ptr = arange_ptr_past_end;
} while (arange_ptr <
dbg->de_debug_aranges + dbg->de_debug_aranges_size);
if (arange_ptr !=
dbg->de_debug_aranges + dbg->de_debug_aranges_size) {
_dwarf_error(dbg, error, DW_DLE_ARANGE_DECODE_ERROR);
return (DW_DLV_ERROR);
}
arange_block = (Dwarf_Arange *)
_dwarf_get_alloc(dbg, DW_DLA_LIST, arange_count);
if (arange_block == NULL) {
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
return (DW_DLV_ERROR);
}
curr_chain = head_chain;
for (i = 0; i < arange_count; i++) {
*(arange_block + i) = curr_chain->ch_item;
prev_chain = curr_chain;
curr_chain = curr_chain->ch_next;
dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
}
*aranges = arange_block;
*returned_count = (arange_count);
return DW_DLV_OK;
}
int
_dwarf_get_aranges_addr_offsets(Dwarf_Debug dbg,
Dwarf_Addr ** addrs,
Dwarf_Off ** offsets,
Dwarf_Signed * count,
Dwarf_Error * error)
{
Dwarf_Small *arange_ptr;
Dwarf_Small *arange_start_ptr;
Dwarf_Small *header_ptr;
Dwarf_Unsigned length;
Dwarf_Half version;
Dwarf_Off info_offset;
Dwarf_Small address_size;
Dwarf_Small segment_size;
Dwarf_Small remainder;
Dwarf_Unsigned arange_count = 0;
Dwarf_Addr range_address;
Dwarf_Unsigned range_length;
Dwarf_Arange arange;
Dwarf_Unsigned i;
Dwarf_Chain curr_chain, prev_chain, head_chain = NULL;
Dwarf_Addr *arange_addrs;
Dwarf_Off *arange_offsets;
int res;
if (error != NULL)
*error = NULL;
if (dbg == NULL) {
_dwarf_error(NULL, error, DW_DLE_DBG_NULL);
return (DW_DLV_ERROR);
}
res =
_dwarf_load_section(dbg,
dbg->de_debug_aranges_index,
&dbg->de_debug_aranges, error);
if (res != DW_DLV_OK) {
return res;
}
arange_ptr = dbg->de_debug_aranges;
do {
int local_length_size;
int local_extension_size;
header_ptr = arange_ptr;
READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned,
arange_ptr, local_length_size,
local_extension_size);
READ_UNALIGNED(dbg, version, Dwarf_Half,
arange_ptr, sizeof(Dwarf_Half));
arange_ptr += sizeof(Dwarf_Half);
length = length - sizeof(Dwarf_Half);
if (version != CURRENT_VERSION_STAMP) {
_dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR);
return (DW_DLV_ERROR);
}
READ_UNALIGNED(dbg, info_offset, Dwarf_Off,
arange_ptr, local_length_size);
arange_ptr += local_length_size;
length = length - local_length_size;
if (info_offset >= dbg->de_debug_info_size) {
FIX_UP_OFFSET_IRIX_BUG(dbg, info_offset,
"arange info offset.b");
if (info_offset >= dbg->de_debug_info_size) {
_dwarf_error(dbg, error, DW_DLE_ARANGE_OFFSET_BAD);
return (DW_DLV_ERROR);
}
}
address_size = *(Dwarf_Small *) arange_ptr;
arange_ptr = arange_ptr + sizeof(Dwarf_Small);
length = length - sizeof(Dwarf_Small);
segment_size = *(Dwarf_Small *) arange_ptr;
arange_ptr = arange_ptr + sizeof(Dwarf_Small);
length = length - sizeof(Dwarf_Small);
if (segment_size != 0) {
_dwarf_error(dbg, error, DW_DLE_SEGMENT_SIZE_BAD);
return (DW_DLV_ERROR);
}
remainder = (Dwarf_Unsigned) (arange_ptr - header_ptr) %
(2 * address_size);
if (remainder != 0) {
arange_ptr = arange_ptr + (2 * address_size) - remainder;
length = length - ((2 * address_size) - remainder);
}
do {
arange_start_ptr = arange_ptr;
READ_UNALIGNED(dbg, range_address, Dwarf_Addr,
arange_ptr, dbg->de_pointer_size);
arange_ptr += dbg->de_pointer_size;
length = length - dbg->de_pointer_size;
READ_UNALIGNED(dbg, range_length, Dwarf_Unsigned,
arange_ptr, local_length_size);
arange_ptr += local_length_size;
length = length - local_length_size;
if (range_address != 0 || range_length != 0) {
arange = (Dwarf_Arange)
_dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1);
if (arange == NULL) {
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
return (DW_DLV_ERROR);
}
arange->ar_address = range_address;
arange->ar_length = range_length;
arange->ar_info_offset =
arange_start_ptr - dbg->de_debug_aranges;
arange->ar_dbg = dbg;
arange_count++;
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 = arange;
if (head_chain == NULL)
head_chain = prev_chain = curr_chain;
else {
prev_chain->ch_next = curr_chain;
prev_chain = curr_chain;
}
}
} while (range_address != 0 || range_length != 0);
if (length != 0) {
_dwarf_error(dbg, error, DW_DLE_ARANGE_LENGTH_BAD);
return (DW_DLV_ERROR);
}
} while (arange_ptr <
dbg->de_debug_aranges + dbg->de_debug_aranges_size);
if (arange_ptr !=
dbg->de_debug_aranges + dbg->de_debug_aranges_size) {
_dwarf_error(dbg, error, DW_DLE_ARANGE_DECODE_ERROR);
return (DW_DLV_ERROR);
}
arange_addrs = (Dwarf_Addr *)
_dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count);
if (arange_addrs == NULL) {
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
return (DW_DLV_ERROR);
}
arange_offsets = (Dwarf_Off *)
_dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count);
if (arange_offsets == NULL) {
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
return (DW_DLV_ERROR);
}
curr_chain = head_chain;
for (i = 0; i < arange_count; i++) {
Dwarf_Arange ar = curr_chain->ch_item;
arange_addrs[i] = ar->ar_address;
arange_offsets[i] = ar->ar_info_offset;
prev_chain = curr_chain;
curr_chain = curr_chain->ch_next;
dwarf_dealloc(dbg, ar, DW_DLA_ARANGE);
dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
}
*count = arange_count;
*offsets = arange_offsets;
*addrs = arange_addrs;
return (DW_DLV_OK);
}
int
dwarf_get_arange(Dwarf_Arange * aranges,
Dwarf_Unsigned arange_count,
Dwarf_Addr address,
Dwarf_Arange * returned_arange, Dwarf_Error * error)
{
Dwarf_Arange curr_arange;
Dwarf_Unsigned i;
if (aranges == NULL) {
_dwarf_error(NULL, error, DW_DLE_ARANGES_NULL);
return (DW_DLV_ERROR);
}
for (i = 0; i < arange_count; i++) {
curr_arange = *(aranges + i);
if (address >= curr_arange->ar_address &&
address <
curr_arange->ar_address + curr_arange->ar_length) {
*returned_arange = curr_arange;
return (DW_DLV_OK);
}
}
return (DW_DLV_NO_ENTRY);
}
int
dwarf_get_cu_die_offset(Dwarf_Arange arange,
Dwarf_Off * returned_offset,
Dwarf_Error * error)
{
Dwarf_Debug dbg;
Dwarf_Off offset;
if (arange == NULL) {
_dwarf_error(NULL, error, DW_DLE_ARANGE_NULL);
return (DW_DLV_ERROR);
}
dbg = arange->ar_dbg;
offset = arange->ar_info_offset;
if (!dbg->de_debug_info) {
int res = _dwarf_load_debug_info(dbg, error);
if (res != DW_DLV_OK) {
return res;
}
}
*returned_offset = offset + _dwarf_length_of_cu_header(dbg, offset);
return DW_DLV_OK;
}
int
dwarf_get_arange_cu_header_offset(Dwarf_Arange arange,
Dwarf_Off * cu_header_offset_returned,
Dwarf_Error * error)
{
if (arange == NULL) {
_dwarf_error(NULL, error, DW_DLE_ARANGE_NULL);
return (DW_DLV_ERROR);
}
*cu_header_offset_returned = arange->ar_info_offset;
return DW_DLV_OK;
}
int
dwarf_get_arange_info(Dwarf_Arange arange,
Dwarf_Addr * start,
Dwarf_Unsigned * length,
Dwarf_Off * cu_die_offset, Dwarf_Error * error)
{
if (arange == NULL) {
_dwarf_error(NULL, error, DW_DLE_ARANGE_NULL);
return (DW_DLV_ERROR);
}
if (start != NULL)
*start = arange->ar_address;
if (length != NULL)
*length = arange->ar_length;
if (cu_die_offset != NULL) {
Dwarf_Debug dbg = arange->ar_dbg;
Dwarf_Off offset = arange->ar_info_offset;
if (!dbg->de_debug_info) {
int res = _dwarf_load_debug_info(dbg, error);
if (res != DW_DLV_OK) {
return res;
}
}
*cu_die_offset =
offset + _dwarf_length_of_cu_header(dbg, offset);
}
return (DW_DLV_OK);
}