|
Packit |
cdaae3 |
/*
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
Copyright (C) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
|
|
Packit |
cdaae3 |
Portions Copyright (C) 2007-2018 David Anderson. All Rights Reserved.
|
|
Packit |
cdaae3 |
Portions Copyright 2012 SN Systems Ltd. All rights reserved.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
This program is free software; you can redistribute it and/or modify it
|
|
Packit |
cdaae3 |
under the terms of version 2.1 of the GNU Lesser General Public License
|
|
Packit |
cdaae3 |
as published by the Free Software Foundation.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
This program is distributed in the hope that it would be useful, but
|
|
Packit |
cdaae3 |
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
cdaae3 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
Further, this software is distributed without any warranty that it is
|
|
Packit |
cdaae3 |
free of the rightful claim of any third person regarding infringement
|
|
Packit |
cdaae3 |
or the like. Any license provided herein, whether implied or
|
|
Packit |
cdaae3 |
otherwise, applies only to this software file. Patent licenses, if
|
|
Packit |
cdaae3 |
any, provided herein do not apply to combinations of this program with
|
|
Packit |
cdaae3 |
other software, or any other product whatsoever.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
You should have received a copy of the GNU Lesser General Public
|
|
Packit |
cdaae3 |
License along with this program; if not, write the Free Software
|
|
Packit |
cdaae3 |
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
|
|
Packit |
cdaae3 |
USA.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
*/
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
#include "config.h"
|
|
Packit |
cdaae3 |
#include "dwarf_incl.h"
|
|
Packit |
cdaae3 |
#include <stdio.h>
|
|
Packit |
cdaae3 |
#include "dwarf_arange.h"
|
|
Packit |
cdaae3 |
#include "dwarf_global.h" /* for _dwarf_fixup_* */
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Common code for two user-visible routines to share.
|
|
Packit |
cdaae3 |
Errors here result in memory leaks, but errors here
|
|
Packit |
cdaae3 |
are serious (making aranges unusable) so we assume
|
|
Packit |
cdaae3 |
callers will not repeat the error often or mind the leaks.
|
|
Packit |
cdaae3 |
*/
|
|
Packit |
cdaae3 |
static int
|
|
Packit |
cdaae3 |
dwarf_get_aranges_list(Dwarf_Debug dbg,
|
|
Packit |
cdaae3 |
Dwarf_Chain * chain_out,
|
|
Packit |
cdaae3 |
Dwarf_Signed * chain_count_out,
|
|
Packit |
cdaae3 |
Dwarf_Error * error)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
/* Sweeps through the arange. */
|
|
Packit |
cdaae3 |
Dwarf_Small *arange_ptr = 0;
|
|
Packit |
cdaae3 |
Dwarf_Small *arange_ptr_start = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Start of arange header. Used for rounding offset of arange_ptr
|
|
Packit |
cdaae3 |
to twice the tuple size. Libdwarf requirement. */
|
|
Packit |
cdaae3 |
Dwarf_Small *header_ptr = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Version of .debug_aranges header. */
|
|
Packit |
cdaae3 |
Dwarf_Half version = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Offset of current set of aranges into .debug_info. */
|
|
Packit |
cdaae3 |
Dwarf_Off info_offset = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Size in bytes of addresses in target. */
|
|
Packit |
cdaae3 |
Dwarf_Small address_size = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Size in bytes of segment offsets in target. */
|
|
Packit |
cdaae3 |
Dwarf_Small segment_size = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Count of total number of aranges. */
|
|
Packit |
cdaae3 |
Dwarf_Signed arange_count = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
Dwarf_Arange arange = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned section_size = 0;
|
|
Packit |
cdaae3 |
Dwarf_Byte_Ptr arange_end_section = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Used to chain Dwarf_Aranges structs. */
|
|
Packit |
cdaae3 |
Dwarf_Chain curr_chain = NULL;
|
|
Packit |
cdaae3 |
Dwarf_Chain prev_chain = NULL;
|
|
Packit |
cdaae3 |
Dwarf_Chain head_chain = NULL;
|
|
Packit |
cdaae3 |
if (!dbg->de_debug_aranges.dss_size) {
|
|
Packit |
cdaae3 |
return (DW_DLV_NO_ENTRY);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
arange_ptr = dbg->de_debug_aranges.dss_data;
|
|
Packit |
cdaae3 |
arange_ptr_start = arange_ptr;
|
|
Packit |
cdaae3 |
section_size = dbg->de_debug_aranges.dss_size;
|
|
Packit |
cdaae3 |
arange_end_section = arange_ptr + section_size;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
do {
|
|
Packit |
cdaae3 |
/* Length of current set of aranges.
|
|
Packit |
cdaae3 |
This is local length, which begins just
|
|
Packit |
cdaae3 |
after the length field itself. */
|
|
Packit |
cdaae3 |
Dwarf_Unsigned area_length = 0;
|
|
Packit |
cdaae3 |
Dwarf_Small remainder = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned range_entry_size = 0;
|
|
Packit |
cdaae3 |
int local_length_size;
|
|
Packit |
cdaae3 |
int local_extension_size = 0;
|
|
Packit |
cdaae3 |
Dwarf_Small *end_this_arange = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
header_ptr = arange_ptr;
|
|
Packit |
cdaae3 |
if (header_ptr >= arange_end_section) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error,DW_DLE_ARANGES_HEADER_ERROR);
|
|
Packit |
cdaae3 |
return DW_DLV_ERROR;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
/* READ_AREA_LENGTH updates arange_ptr for consumed bytes */
|
|
Packit |
cdaae3 |
READ_AREA_LENGTH_CK(dbg, area_length, Dwarf_Unsigned,
|
|
Packit |
cdaae3 |
arange_ptr, local_length_size,
|
|
Packit |
cdaae3 |
local_extension_size,error,
|
|
Packit |
cdaae3 |
section_size,
|
|
Packit |
cdaae3 |
arange_end_section);
|
|
Packit |
cdaae3 |
/* arange_ptr has been incremented appropriately past
|
|
Packit |
cdaae3 |
the length field by READ_AREA_LENGTH. */
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (area_length > dbg->de_debug_aranges.dss_size) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error,DW_DLE_ARANGES_HEADER_ERROR);
|
|
Packit |
cdaae3 |
return DW_DLV_ERROR;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if ((area_length + local_length_size + local_extension_size) >
|
|
Packit |
cdaae3 |
dbg->de_debug_aranges.dss_size) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error, DW_DLE_ARANGES_HEADER_ERROR);
|
|
Packit |
cdaae3 |
return DW_DLV_ERROR;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
end_this_arange = arange_ptr + area_length;
|
|
Packit |
cdaae3 |
if (end_this_arange > arange_end_section) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error,DW_DLE_ARANGES_HEADER_ERROR);
|
|
Packit |
cdaae3 |
return DW_DLV_ERROR;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
READ_UNALIGNED_CK(dbg, version, Dwarf_Half,
|
|
Packit |
cdaae3 |
arange_ptr, sizeof(Dwarf_Half),
|
|
Packit |
cdaae3 |
error,end_this_arange);
|
|
Packit |
cdaae3 |
arange_ptr += sizeof(Dwarf_Half);
|
|
Packit |
cdaae3 |
if (arange_ptr >= end_this_arange) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error, DW_DLE_ARANGES_HEADER_ERROR);
|
|
Packit |
cdaae3 |
return DW_DLV_ERROR;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if (version != DW_ARANGES_VERSION2) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
READ_UNALIGNED_CK(dbg, info_offset, Dwarf_Off,
|
|
Packit |
cdaae3 |
arange_ptr, local_length_size,
|
|
Packit |
cdaae3 |
error,end_this_arange);
|
|
Packit |
cdaae3 |
arange_ptr += local_length_size;
|
|
Packit |
cdaae3 |
if (arange_ptr >= end_this_arange) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error, DW_DLE_ARANGES_HEADER_ERROR);
|
|
Packit |
cdaae3 |
return DW_DLV_ERROR;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
/* This applies to debug_info only, not to debug_types. */
|
|
Packit |
cdaae3 |
if (info_offset >= dbg->de_debug_info.dss_size) {
|
|
Packit |
cdaae3 |
FIX_UP_OFFSET_IRIX_BUG(dbg, info_offset,
|
|
Packit |
cdaae3 |
"arange info offset.a");
|
|
Packit |
cdaae3 |
if (info_offset >= dbg->de_debug_info.dss_size) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error, DW_DLE_ARANGE_OFFSET_BAD);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
address_size = *(Dwarf_Small *) arange_ptr;
|
|
Packit |
cdaae3 |
if (address_size > sizeof(Dwarf_Addr)) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error, DW_DLE_ADDRESS_SIZE_ERROR);
|
|
Packit |
cdaae3 |
return DW_DLV_ERROR;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if (address_size == 0) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error, DW_DLE_ADDRESS_SIZE_ZERO);
|
|
Packit |
cdaae3 |
return DW_DLV_ERROR;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
/* It is not an error if the sizes differ.
|
|
Packit |
cdaae3 |
Unusual, but not an error. */
|
|
Packit |
cdaae3 |
arange_ptr = arange_ptr + sizeof(Dwarf_Small);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* The following deref means we better check the pointer for off-end. */
|
|
Packit |
cdaae3 |
if (arange_ptr >= end_this_arange) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error, DW_DLE_ARANGE_OFFSET_BAD);
|
|
Packit |
cdaae3 |
return DW_DLV_ERROR;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Even DWARF2 had a segment_size field here, meaning
|
|
Packit |
cdaae3 |
size in bytes of a segment descriptor on the target
|
|
Packit |
cdaae3 |
system. */
|
|
Packit |
cdaae3 |
segment_size = *(Dwarf_Small *) arange_ptr;
|
|
Packit |
cdaae3 |
if (segment_size > sizeof(Dwarf_Addr)) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error, DW_DLE_SEGMENT_SIZE_BAD);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
arange_ptr = arange_ptr + sizeof(Dwarf_Small);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Code below will check for == end_this_arange as appropriate. */
|
|
Packit |
cdaae3 |
if (arange_ptr > end_this_arange) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error, DW_DLE_ARANGE_OFFSET_BAD);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
range_entry_size = 2*address_size + segment_size;
|
|
Packit |
cdaae3 |
/* Round arange_ptr offset to next multiple of address_size. */
|
|
Packit |
cdaae3 |
remainder = (Dwarf_Unsigned) (arange_ptr - header_ptr) %
|
|
Packit |
cdaae3 |
(range_entry_size);
|
|
Packit |
cdaae3 |
if (remainder != 0) {
|
|
Packit |
cdaae3 |
arange_ptr = arange_ptr + (2 * address_size) - remainder;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
do {
|
|
Packit |
cdaae3 |
Dwarf_Addr range_address = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned segment_selector = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned range_length = 0;
|
|
Packit |
cdaae3 |
/* For segmented address spaces, the first field to
|
|
Packit |
cdaae3 |
read is a segment selector (new in DWARF4).
|
|
Packit |
cdaae3 |
Surprising since the segment_size was always there
|
|
Packit |
cdaae3 |
in the table header! */
|
|
Packit |
cdaae3 |
if ((version >= 4) && (segment_size != 0)) {
|
|
Packit |
cdaae3 |
READ_UNALIGNED_CK(dbg, segment_selector, Dwarf_Unsigned,
|
|
Packit |
cdaae3 |
arange_ptr, segment_size,
|
|
Packit |
cdaae3 |
error,end_this_arange);
|
|
Packit |
cdaae3 |
arange_ptr += address_size;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
READ_UNALIGNED_CK(dbg, range_address, Dwarf_Addr,
|
|
Packit |
cdaae3 |
arange_ptr, address_size,
|
|
Packit |
cdaae3 |
error,end_this_arange);
|
|
Packit |
cdaae3 |
arange_ptr += address_size;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
READ_UNALIGNED_CK(dbg, range_length, Dwarf_Unsigned,
|
|
Packit |
cdaae3 |
arange_ptr, address_size,
|
|
Packit |
cdaae3 |
error,end_this_arange);
|
|
Packit |
cdaae3 |
arange_ptr += address_size;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
/* We used to suppress all-zero entries, but
|
|
Packit |
cdaae3 |
now we return all aranges entries so we show
|
|
Packit |
cdaae3 |
the entire content. March 31, 2010. */
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
arange = (Dwarf_Arange)
|
|
Packit |
cdaae3 |
_dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1);
|
|
Packit |
cdaae3 |
if (arange == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
arange->ar_segment_selector = segment_selector;
|
|
Packit |
cdaae3 |
arange->ar_segment_selector_size = segment_size;
|
|
Packit |
cdaae3 |
arange->ar_address = range_address;
|
|
Packit |
cdaae3 |
arange->ar_length = range_length;
|
|
Packit |
cdaae3 |
arange->ar_info_offset = info_offset;
|
|
Packit |
cdaae3 |
arange->ar_dbg = dbg;
|
|
Packit |
cdaae3 |
arange_count++;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
curr_chain = (Dwarf_Chain)
|
|
Packit |
cdaae3 |
_dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
|
|
Packit |
cdaae3 |
if (curr_chain == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
curr_chain->ch_item = arange;
|
|
Packit |
cdaae3 |
if (head_chain == NULL)
|
|
Packit |
cdaae3 |
head_chain = prev_chain = curr_chain;
|
|
Packit |
cdaae3 |
else {
|
|
Packit |
cdaae3 |
prev_chain->ch_next = curr_chain;
|
|
Packit |
cdaae3 |
prev_chain = curr_chain;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
/* The current set of ranges is terminated by
|
|
Packit |
cdaae3 |
range_address 0 and range_length 0, but that
|
|
Packit |
cdaae3 |
does not necessarily terminate the ranges for this CU!
|
|
Packit |
cdaae3 |
There can be multiple sets in that DWARF
|
|
Packit |
cdaae3 |
does not explicitly forbid multiple sets.
|
|
Packit |
cdaae3 |
DWARF2,3,4 section 7.20
|
|
Packit |
cdaae3 |
We stop short to avoid overrun of the end of the CU. */
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
} while (end_this_arange >= (arange_ptr + range_entry_size));
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* A compiler could emit some padding bytes here. dwarf2/3
|
|
Packit |
cdaae3 |
(dwarf4 sec 7.20) does not clearly make extra padding
|
|
Packit |
cdaae3 |
bytes illegal. */
|
|
Packit |
cdaae3 |
if (end_this_arange < arange_ptr) {
|
|
Packit |
cdaae3 |
char buf[200];
|
|
Packit |
cdaae3 |
Dwarf_Unsigned pad_count = arange_ptr - end_this_arange;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned offset = arange_ptr - arange_ptr_start;
|
|
Packit |
cdaae3 |
snprintf(buf,sizeof(buf),"DW_DLE_ARANGE_LENGTH_BAD."
|
|
Packit |
cdaae3 |
" 0x%" DW_PR_XZEROS DW_PR_DUx
|
|
Packit |
cdaae3 |
" pad bytes at offset 0x%" DW_PR_XZEROS DW_PR_DUx
|
|
Packit |
cdaae3 |
" in .debug_aranges",
|
|
Packit |
cdaae3 |
pad_count, offset);
|
|
Packit |
cdaae3 |
dwarf_insert_harmless_error(dbg,buf);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
/* For most compilers, arange_ptr == end_this_arange at
|
|
Packit |
cdaae3 |
this point. But not if there were padding bytes */
|
|
Packit |
cdaae3 |
arange_ptr = end_this_arange;
|
|
Packit |
cdaae3 |
} while (arange_ptr < arange_end_section);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (arange_ptr != arange_end_section) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error, DW_DLE_ARANGE_DECODE_ERROR);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
*chain_out = head_chain;
|
|
Packit |
cdaae3 |
*chain_count_out = arange_count;
|
|
Packit |
cdaae3 |
return DW_DLV_OK;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/*
|
|
Packit |
cdaae3 |
This function returns the count of the number of
|
|
Packit |
cdaae3 |
aranges in the .debug_aranges section. It sets
|
|
Packit |
cdaae3 |
aranges to point to a block of Dwarf_Arange's
|
|
Packit |
cdaae3 |
describing the arange's. It returns DW_DLV_ERROR
|
|
Packit |
cdaae3 |
on error.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
Must be identical in most aspects to
|
|
Packit |
cdaae3 |
dwarf_get_aranges_addr_offsets!
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
*/
|
|
Packit |
cdaae3 |
int
|
|
Packit |
cdaae3 |
dwarf_get_aranges(Dwarf_Debug dbg,
|
|
Packit |
cdaae3 |
Dwarf_Arange ** aranges,
|
|
Packit |
cdaae3 |
Dwarf_Signed * returned_count, Dwarf_Error * error)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
/* Count of total number of aranges. */
|
|
Packit |
cdaae3 |
Dwarf_Signed arange_count = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
Dwarf_Arange *arange_block = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Used to chain Dwarf_Aranges structs. */
|
|
Packit |
cdaae3 |
Dwarf_Chain curr_chain = NULL;
|
|
Packit |
cdaae3 |
Dwarf_Chain prev_chain = NULL;
|
|
Packit |
cdaae3 |
Dwarf_Chain head_chain = NULL;
|
|
Packit |
cdaae3 |
Dwarf_Signed i = 0;
|
|
Packit |
cdaae3 |
int res = DW_DLV_ERROR;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* ***** BEGIN CODE ***** */
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (dbg == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_error(NULL, error, DW_DLE_DBG_NULL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
res = _dwarf_load_section(dbg, &dbg->de_debug_aranges, error);
|
|
Packit |
cdaae3 |
if (res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
return res;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
res = dwarf_get_aranges_list(dbg,&head_chain,&arange_count,error);
|
|
Packit |
cdaae3 |
if (res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
return res;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
arange_block = (Dwarf_Arange *)
|
|
Packit |
cdaae3 |
_dwarf_get_alloc(dbg, DW_DLA_LIST, arange_count);
|
|
Packit |
cdaae3 |
if (arange_block == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
curr_chain = head_chain;
|
|
Packit |
cdaae3 |
for (i = 0; i < arange_count; i++) {
|
|
Packit |
cdaae3 |
*(arange_block + i) = curr_chain->ch_item;
|
|
Packit |
cdaae3 |
prev_chain = curr_chain;
|
|
Packit |
cdaae3 |
curr_chain = curr_chain->ch_next;
|
|
Packit |
cdaae3 |
dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
*aranges = arange_block;
|
|
Packit |
cdaae3 |
*returned_count = (arange_count);
|
|
Packit |
cdaae3 |
return DW_DLV_OK;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/*
|
|
Packit |
cdaae3 |
This function returns DW_DLV_OK if it succeeds
|
|
Packit |
cdaae3 |
and DW_DLV_ERR or DW_DLV_OK otherwise.
|
|
Packit |
cdaae3 |
count is set to the number of addresses in the
|
|
Packit |
cdaae3 |
.debug_aranges section.
|
|
Packit |
cdaae3 |
For each address, the corresponding element in
|
|
Packit |
cdaae3 |
an array is set to the address itself(aranges) and
|
|
Packit |
cdaae3 |
the section offset (offsets).
|
|
Packit |
cdaae3 |
Must be identical in most aspects to
|
|
Packit |
cdaae3 |
dwarf_get_aranges!
|
|
Packit |
cdaae3 |
*/
|
|
Packit |
cdaae3 |
int
|
|
Packit |
cdaae3 |
_dwarf_get_aranges_addr_offsets(Dwarf_Debug dbg,
|
|
Packit |
cdaae3 |
Dwarf_Addr ** addrs,
|
|
Packit |
cdaae3 |
Dwarf_Off ** offsets,
|
|
Packit |
cdaae3 |
Dwarf_Signed * count,
|
|
Packit |
cdaae3 |
Dwarf_Error * error)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
Dwarf_Signed i = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* Used to chain Dwarf_Aranges structs. */
|
|
Packit |
cdaae3 |
Dwarf_Chain curr_chain = NULL;
|
|
Packit |
cdaae3 |
Dwarf_Chain prev_chain = NULL;
|
|
Packit |
cdaae3 |
Dwarf_Chain head_chain = NULL;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
Dwarf_Signed arange_count = 0;
|
|
Packit |
cdaae3 |
Dwarf_Addr *arange_addrs = 0;
|
|
Packit |
cdaae3 |
Dwarf_Off *arange_offsets = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
int res = DW_DLV_ERROR;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* ***** BEGIN CODE ***** */
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (error != NULL)
|
|
Packit |
cdaae3 |
*error = NULL;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (dbg == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_error(NULL, error, DW_DLE_DBG_NULL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
res = _dwarf_load_section(dbg, &dbg->de_debug_aranges,error);
|
|
Packit |
cdaae3 |
if (res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
return res;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
res = dwarf_get_aranges_list(dbg,&head_chain,&arange_count,error);
|
|
Packit |
cdaae3 |
if (res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
return res;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
arange_addrs = (Dwarf_Addr *)
|
|
Packit |
cdaae3 |
_dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count);
|
|
Packit |
cdaae3 |
if (arange_addrs == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
arange_offsets = (Dwarf_Off *)
|
|
Packit |
cdaae3 |
_dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count);
|
|
Packit |
cdaae3 |
if (arange_offsets == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
curr_chain = head_chain;
|
|
Packit |
cdaae3 |
for (i = 0; i < arange_count; i++) {
|
|
Packit |
cdaae3 |
Dwarf_Arange ar = curr_chain->ch_item;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
arange_addrs[i] = ar->ar_address;
|
|
Packit |
cdaae3 |
arange_offsets[i] = ar->ar_info_offset;
|
|
Packit |
cdaae3 |
prev_chain = curr_chain;
|
|
Packit |
cdaae3 |
curr_chain = curr_chain->ch_next;
|
|
Packit |
cdaae3 |
dwarf_dealloc(dbg, ar, DW_DLA_ARANGE);
|
|
Packit |
cdaae3 |
dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
*count = arange_count;
|
|
Packit |
cdaae3 |
*offsets = arange_offsets;
|
|
Packit |
cdaae3 |
*addrs = arange_addrs;
|
|
Packit |
cdaae3 |
return (DW_DLV_OK);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/*
|
|
Packit |
cdaae3 |
This function takes a pointer to a block
|
|
Packit |
cdaae3 |
of Dwarf_Arange's, and a count of the
|
|
Packit |
cdaae3 |
length of the block. It checks if the
|
|
Packit |
cdaae3 |
given address is within the range of an
|
|
Packit |
cdaae3 |
address range in the block. If yes, it
|
|
Packit |
cdaae3 |
returns the appropriate Dwarf_Arange.
|
|
Packit |
cdaae3 |
Otherwise, it returns DW_DLV_ERROR.
|
|
Packit |
cdaae3 |
*/
|
|
Packit |
cdaae3 |
int
|
|
Packit |
cdaae3 |
dwarf_get_arange(Dwarf_Arange * aranges,
|
|
Packit |
cdaae3 |
Dwarf_Unsigned arange_count,
|
|
Packit |
cdaae3 |
Dwarf_Addr address,
|
|
Packit |
cdaae3 |
Dwarf_Arange * returned_arange, Dwarf_Error * error)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
Dwarf_Arange curr_arange = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned i = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (aranges == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_error(NULL, error, DW_DLE_ARANGES_NULL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
for (i = 0; i < arange_count; i++) {
|
|
Packit |
cdaae3 |
curr_arange = *(aranges + i);
|
|
Packit |
cdaae3 |
if (address >= curr_arange->ar_address &&
|
|
Packit |
cdaae3 |
address <
|
|
Packit |
cdaae3 |
curr_arange->ar_address + curr_arange->ar_length) {
|
|
Packit |
cdaae3 |
*returned_arange = curr_arange;
|
|
Packit |
cdaae3 |
return (DW_DLV_OK);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
return (DW_DLV_NO_ENTRY);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/*
|
|
Packit |
cdaae3 |
This function takes an Dwarf_Arange,
|
|
Packit |
cdaae3 |
and returns the offset of the first
|
|
Packit |
cdaae3 |
die in the compilation-unit that the
|
|
Packit |
cdaae3 |
arange belongs to. Returns DW_DLV_ERROR
|
|
Packit |
cdaae3 |
on error.
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
For an arange, the cu_die can only be from debug_info,
|
|
Packit |
cdaae3 |
not debug_types, it seems.
|
|
Packit |
cdaae3 |
*/
|
|
Packit |
cdaae3 |
int
|
|
Packit |
cdaae3 |
dwarf_get_cu_die_offset(Dwarf_Arange arange,
|
|
Packit |
cdaae3 |
Dwarf_Off * returned_offset,
|
|
Packit |
cdaae3 |
Dwarf_Error * error)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
Dwarf_Debug dbg = 0;
|
|
Packit |
cdaae3 |
Dwarf_Off offset = 0;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned headerlen = 0;
|
|
Packit |
cdaae3 |
int cres = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (arange == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_error(NULL, error, DW_DLE_ARANGE_NULL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
dbg = arange->ar_dbg;
|
|
Packit |
cdaae3 |
offset = arange->ar_info_offset;
|
|
Packit |
cdaae3 |
/* This applies to debug_info only, not to debug_types. */
|
|
Packit |
cdaae3 |
if (!dbg->de_debug_info.dss_data) {
|
|
Packit |
cdaae3 |
int res = _dwarf_load_debug_info(dbg, error);
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
return res;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
cres = _dwarf_length_of_cu_header(dbg, offset,
|
|
Packit |
cdaae3 |
true, &headerlen,error);
|
|
Packit |
cdaae3 |
if (cres != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
return cres;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
*returned_offset = headerlen + offset;
|
|
Packit |
cdaae3 |
return DW_DLV_OK;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* This function takes an Dwarf_Arange,
|
|
Packit |
cdaae3 |
and returns the offset of the CU header
|
|
Packit |
cdaae3 |
in the compilation-unit that the
|
|
Packit |
cdaae3 |
arange belongs to. Returns DW_DLV_ERROR
|
|
Packit |
cdaae3 |
on error.
|
|
Packit |
cdaae3 |
Ensures .debug_info loaded so
|
|
Packit |
cdaae3 |
the cu_offset is meaningful. */
|
|
Packit |
cdaae3 |
int
|
|
Packit |
cdaae3 |
dwarf_get_arange_cu_header_offset(Dwarf_Arange arange,
|
|
Packit |
cdaae3 |
Dwarf_Off * cu_header_offset_returned,
|
|
Packit |
cdaae3 |
Dwarf_Error * error)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
Dwarf_Debug dbg = 0;
|
|
Packit |
cdaae3 |
if (arange == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_error(NULL, error, DW_DLE_ARANGE_NULL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
dbg = arange->ar_dbg;
|
|
Packit |
cdaae3 |
/* This applies to debug_info only, not to debug_types. */
|
|
Packit |
cdaae3 |
/* Like dwarf_get_arange_info this ensures debug_info loaded:
|
|
Packit |
cdaae3 |
the cu_header is in debug_info and will be used else
|
|
Packit |
cdaae3 |
we would not call dwarf_get_arange_cu_header_offset. */
|
|
Packit |
cdaae3 |
if (!dbg->de_debug_info.dss_data) {
|
|
Packit |
cdaae3 |
int res = _dwarf_load_debug_info(dbg, error);
|
|
Packit |
cdaae3 |
if (res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
return res;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
*cu_header_offset_returned = arange->ar_info_offset;
|
|
Packit |
cdaae3 |
return DW_DLV_OK;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/*
|
|
Packit |
cdaae3 |
This function takes a Dwarf_Arange, and returns
|
|
Packit |
cdaae3 |
true if it is not NULL. It also stores the start
|
|
Packit |
cdaae3 |
address of the range in *start, the length of the
|
|
Packit |
cdaae3 |
range in *length, and the offset of the first die
|
|
Packit |
cdaae3 |
in the compilation-unit in *cu_die_offset. It
|
|
Packit |
cdaae3 |
returns false on error.
|
|
Packit |
cdaae3 |
If cu_die_offset returned ensures .debug_info loaded so
|
|
Packit |
cdaae3 |
the cu_die_offset is meaningful.
|
|
Packit |
cdaae3 |
*/
|
|
Packit |
cdaae3 |
int
|
|
Packit |
cdaae3 |
dwarf_get_arange_info(Dwarf_Arange arange,
|
|
Packit |
cdaae3 |
Dwarf_Addr * start,
|
|
Packit |
cdaae3 |
Dwarf_Unsigned * length,
|
|
Packit |
cdaae3 |
Dwarf_Off * cu_die_offset, Dwarf_Error * error)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
if (arange == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_error(NULL, error, DW_DLE_ARANGE_NULL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (start != NULL)
|
|
Packit |
cdaae3 |
*start = arange->ar_address;
|
|
Packit |
cdaae3 |
if (length != NULL)
|
|
Packit |
cdaae3 |
*length = arange->ar_length;
|
|
Packit |
cdaae3 |
if (cu_die_offset != NULL) {
|
|
Packit |
cdaae3 |
Dwarf_Debug dbg = arange->ar_dbg;
|
|
Packit |
cdaae3 |
Dwarf_Off headerlen = 0;
|
|
Packit |
cdaae3 |
Dwarf_Off offset = arange->ar_info_offset;
|
|
Packit |
cdaae3 |
int cres = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* This applies to debug_info only, not to debug_types. */
|
|
Packit |
cdaae3 |
if (!dbg->de_debug_info.dss_data) {
|
|
Packit |
cdaae3 |
int res = _dwarf_load_debug_info(dbg, error);
|
|
Packit |
cdaae3 |
if (res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
return res;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
cres = _dwarf_length_of_cu_header(dbg, offset,
|
|
Packit |
cdaae3 |
true, &headerlen,error);
|
|
Packit |
cdaae3 |
if (cres != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
return cres;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
*cu_die_offset = headerlen + offset;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
return (DW_DLV_OK);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* New for DWARF4, entries may have segment information.
|
|
Packit |
cdaae3 |
*segment is only meaningful if *segment_entry_size is non-zero. */
|
|
Packit |
cdaae3 |
int
|
|
Packit |
cdaae3 |
dwarf_get_arange_info_b(Dwarf_Arange arange,
|
|
Packit |
cdaae3 |
Dwarf_Unsigned* segment,
|
|
Packit |
cdaae3 |
Dwarf_Unsigned* segment_entry_size,
|
|
Packit |
cdaae3 |
Dwarf_Addr * start,
|
|
Packit |
cdaae3 |
Dwarf_Unsigned* length,
|
|
Packit |
cdaae3 |
Dwarf_Off * cu_die_offset,
|
|
Packit |
cdaae3 |
Dwarf_Error * error)
|
|
Packit |
cdaae3 |
{
|
|
Packit |
cdaae3 |
if (arange == NULL) {
|
|
Packit |
cdaae3 |
_dwarf_error(NULL, error, DW_DLE_ARANGE_NULL);
|
|
Packit |
cdaae3 |
return (DW_DLV_ERROR);
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
if (segment != NULL) {
|
|
Packit |
cdaae3 |
*segment = arange->ar_segment_selector;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if (segment_entry_size != NULL) {
|
|
Packit |
cdaae3 |
*segment_entry_size = arange->ar_segment_selector_size;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
if (start != NULL)
|
|
Packit |
cdaae3 |
*start = arange->ar_address;
|
|
Packit |
cdaae3 |
if (length != NULL)
|
|
Packit |
cdaae3 |
*length = arange->ar_length;
|
|
Packit |
cdaae3 |
if (cu_die_offset != NULL) {
|
|
Packit |
cdaae3 |
Dwarf_Debug dbg = arange->ar_dbg;
|
|
Packit |
cdaae3 |
Dwarf_Off offset = arange->ar_info_offset;
|
|
Packit |
cdaae3 |
Dwarf_Unsigned headerlen = 0;
|
|
Packit |
cdaae3 |
int cres = 0;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
/* This applies to debug_info only, not to debug_types. */
|
|
Packit |
cdaae3 |
if (!dbg->de_debug_info.dss_data) {
|
|
Packit |
cdaae3 |
int res = _dwarf_load_debug_info(dbg, error);
|
|
Packit |
cdaae3 |
if (res != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
return res;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
cres = _dwarf_length_of_cu_header(dbg, offset,
|
|
Packit |
cdaae3 |
true, &headerlen,error);
|
|
Packit |
cdaae3 |
if (cres != DW_DLV_OK) {
|
|
Packit |
cdaae3 |
return cres;
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
*cu_die_offset = offset + headerlen;
|
|
Packit |
cdaae3 |
|
|
Packit |
cdaae3 |
}
|
|
Packit |
cdaae3 |
return (DW_DLV_OK);
|
|
Packit |
cdaae3 |
}
|