Blame libdwarf/dwarf_arange.c

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
}