107dc194Richard Lowe/*
207dc194Richard Lowe
307dc194Richard Lowe  Copyright (C) 2008-2010 David Anderson. All Rights Reserved.
407dc194Richard Lowe
507dc194Richard Lowe  This program is free software; you can redistribute it and/or modify it
607dc194Richard Lowe  under the terms of version 2.1 of the GNU Lesser General Public License
707dc194Richard Lowe  as published by the Free Software Foundation.
807dc194Richard Lowe
907dc194Richard Lowe  This program is distributed in the hope that it would be useful, but
1007dc194Richard Lowe  WITHOUT ANY WARRANTY; without even the implied warranty of
1207dc194Richard Lowe
1307dc194Richard Lowe  Further, this software is distributed without any warranty that it is
1407dc194Richard Lowe  free of the rightful claim of any third person regarding infringement
1507dc194Richard Lowe  or the like.  Any license provided herein, whether implied or
1607dc194Richard Lowe  otherwise, applies only to this software file.  Patent licenses, if
1707dc194Richard Lowe  any, provided herein do not apply to combinations of this program with
1807dc194Richard Lowe  other software, or any other product whatsoever.
1907dc194Richard Lowe
2007dc194Richard Lowe  You should have received a copy of the GNU Lesser General Public
2107dc194Richard Lowe  License along with this program; if not, write the Free Software
2207dc194Richard Lowe  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
2307dc194Richard Lowe  USA.
2407dc194Richard Lowe
2507dc194Richard Lowe  Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
2607dc194Richard Lowe  Mountain View, CA 94043, or:
2707dc194Richard Lowe
2807dc194Richard Lowe  http://www.sgi.com
2907dc194Richard Lowe
3007dc194Richard Lowe  For further information regarding this notice, see:
3107dc194Richard Lowe
3207dc194Richard Lowe  http://oss.sgi.com/projects/GenInfo/NoticeExplan
3307dc194Richard Lowe
3407dc194Richard Lowe*/
3507dc194Richard Lowe/* The address of the Free Software Foundation is
3607dc194Richard Lowe   Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
3707dc194Richard Lowe   Boston, MA 02110-1301, USA.
3807dc194Richard Lowe   SGI has moved from the Crittenden Lane address.
3907dc194Richard Lowe*/
4007dc194Richard Lowe
4107dc194Richard Lowe
4207dc194Richard Lowe
4307dc194Richard Lowe#include "config.h"
4407dc194Richard Lowe#include <stdlib.h>
4507dc194Richard Lowe#include "dwarf_incl.h"
4607dc194Richard Lowe
4707dc194Richard Lowestruct ranges_entry {
4807dc194Richard Lowe   struct ranges_entry *next;
4907dc194Richard Lowe   Dwarf_Ranges cur;
5007dc194Richard Lowe};
5107dc194Richard Lowe
5207dc194Richard Lowe
5307dc194Richard Lowe#define MAX_ADDR ((address_size == 8)?0xffffffffffffffffULL:0xffffffff)
5407dc194Richard Loweint dwarf_get_ranges_a(Dwarf_Debug dbg,
5507dc194Richard Lowe    Dwarf_Off rangesoffset,
5607dc194Richard Lowe    Dwarf_Die die,
5707dc194Richard Lowe    Dwarf_Ranges ** rangesbuf,
5807dc194Richard Lowe    Dwarf_Signed * listlen,
5907dc194Richard Lowe    Dwarf_Unsigned * bytecount,
6007dc194Richard Lowe    Dwarf_Error * error)
6107dc194Richard Lowe{
6207dc194Richard Lowe    Dwarf_Small *rangeptr = 0;
6307dc194Richard Lowe    Dwarf_Small *beginrangeptr = 0;
6407dc194Richard Lowe    Dwarf_Small *section_end = 0;
6507dc194Richard Lowe    unsigned entry_count = 0;
6607dc194Richard Lowe    struct ranges_entry *base = 0;
6707dc194Richard Lowe    struct ranges_entry *last = 0;
6807dc194Richard Lowe    struct ranges_entry *curre = 0;
6907dc194Richard Lowe    Dwarf_Ranges * ranges_data_out = 0;
7007dc194Richard Lowe    unsigned copyindex = 0;
7107dc194Richard Lowe    Dwarf_Half address_size = 0;
7207dc194Richard Lowe    int res = DW_DLV_ERROR;
7307dc194Richard Lowe
7407dc194Richard Lowe    res = _dwarf_load_section(dbg, &dbg->de_debug_ranges,error);
7507dc194Richard Lowe    if (res != DW_DLV_OK) {
7607dc194Richard Lowe        return res;
7707dc194Richard Lowe    }
7807dc194Richard Lowe    if(rangesoffset >= dbg->de_debug_ranges.dss_size) {
7907dc194Richard Lowe        _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OFFSET_BAD);
8007dc194Richard Lowe        return (DW_DLV_ERROR);
8107dc194Richard Lowe
8207dc194Richard Lowe    }
8307dc194Richard Lowe    address_size = _dwarf_get_address_size(dbg, die);
8407dc194Richard Lowe    section_end = dbg->de_debug_ranges.dss_data +
8507dc194Richard Lowe        dbg->de_debug_ranges.dss_size;
8607dc194Richard Lowe    rangeptr = dbg->de_debug_ranges.dss_data + rangesoffset;
8707dc194Richard Lowe    beginrangeptr = rangeptr;
8807dc194Richard Lowe
8907dc194Richard Lowe    for(;;) {
9007dc194Richard Lowe        struct ranges_entry * re = calloc(sizeof(struct ranges_entry),1);
9107dc194Richard Lowe        if(!re) {
9207dc194Richard Lowe            _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OUT_OF_MEM);
9307dc194Richard Lowe            return (DW_DLV_ERROR);
9407dc194Richard Lowe        }
9507dc194Richard Lowe        if(rangeptr  >= section_end) {
9607dc194Richard Lowe            return (DW_DLV_NO_ENTRY);
9707dc194Richard Lowe        }
9807dc194Richard Lowe        if((rangeptr + (2*address_size)) > section_end) {
9907dc194Richard Lowe            _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OFFSET_BAD);
10007dc194Richard Lowe            return (DW_DLV_ERROR);
10107dc194Richard Lowe        }
10207dc194Richard Lowe        entry_count++;
10307dc194Richard Lowe        READ_UNALIGNED(dbg,re->cur.dwr_addr1,
10407dc194Richard Lowe                       Dwarf_Addr, rangeptr,
10507dc194Richard Lowe                       address_size);
10607dc194Richard Lowe        rangeptr +=  address_size;
10707dc194Richard Lowe        READ_UNALIGNED(dbg,re->cur.dwr_addr2 ,
10807dc194Richard Lowe                       Dwarf_Addr, rangeptr,
10907dc194Richard Lowe                       address_size);
11007dc194Richard Lowe        rangeptr +=  address_size;
11107dc194Richard Lowe        if(!base) {
11207dc194Richard Lowe           base = re;
11307dc194Richard Lowe           last = re;
11407dc194Richard Lowe        } else {
11507dc194Richard Lowe           last->next = re;
11607dc194Richard Lowe           last = re;
11707dc194Richard Lowe        }
11807dc194Richard Lowe        if(re->cur.dwr_addr1 == 0 && re->cur.dwr_addr2 == 0) {
11907dc194Richard Lowe            re->cur.dwr_type =  DW_RANGES_END;
12007dc194Richard Lowe            break;
12107dc194Richard Lowe        } else if ( re->cur.dwr_addr1 == MAX_ADDR) {
12207dc194Richard Lowe            re->cur.dwr_type =  DW_RANGES_ADDRESS_SELECTION;
12307dc194Richard Lowe        } else {
12407dc194Richard Lowe            re->cur.dwr_type =  DW_RANGES_ENTRY;
12507dc194Richard Lowe        }
12607dc194Richard Lowe    }
12707dc194Richard Lowe
12807dc194Richard Lowe    ranges_data_out =   (Dwarf_Ranges *)
12907dc194Richard Lowe    _dwarf_get_alloc(dbg,DW_DLA_RANGES,entry_count);
13007dc194Richard Lowe    if(!ranges_data_out) {
13107dc194Richard Lowe            _dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OUT_OF_MEM);
13207dc194Richard Lowe            return (DW_DLV_ERROR);
13307dc194Richard Lowe    }
13407dc194Richard Lowe    curre = base;
13507dc194Richard Lowe    *rangesbuf = ranges_data_out;
13607dc194Richard Lowe    *listlen = entry_count;
13707dc194Richard Lowe    for( copyindex = 0; curre && (copyindex < entry_count);
13807dc194Richard Lowe        ++copyindex,++ranges_data_out) {
13907dc194Richard Lowe
14007dc194Richard Lowe        struct ranges_entry *r = curre;
14107dc194Richard Lowe        *ranges_data_out = curre->cur;
14207dc194Richard Lowe        curre = curre->next;
14307dc194Richard Lowe        free(r);
14407dc194Richard Lowe    }
14507dc194Richard Lowe    /* Callers will often not care about the bytes used. */
14607dc194Richard Lowe    if(bytecount) {
14707dc194Richard Lowe        *bytecount = rangeptr - beginrangeptr;
14807dc194Richard Lowe    }
14907dc194Richard Lowe    return DW_DLV_OK;
15007dc194Richard Lowe}
15107dc194Richard Loweint dwarf_get_ranges(Dwarf_Debug dbg,
15207dc194Richard Lowe    Dwarf_Off rangesoffset,
15307dc194Richard Lowe    Dwarf_Ranges ** rangesbuf,
15407dc194Richard Lowe    Dwarf_Signed * listlen,
15507dc194Richard Lowe    Dwarf_Unsigned * bytecount,
15607dc194Richard Lowe    Dwarf_Error * error)
15707dc194Richard Lowe{
15807dc194Richard Lowe    Dwarf_Die die = 0;
15907dc194Richard Lowe    int res = dwarf_get_ranges_a(dbg,rangesoffset,die,
16007dc194Richard Lowe        rangesbuf,listlen,bytecount,error);
16107dc194Richard Lowe    return res;
16207dc194Richard Lowe}
16307dc194Richard Lowe
16407dc194Richard Lowevoid
16507dc194Richard Lowedwarf_ranges_dealloc(Dwarf_Debug dbg, Dwarf_Ranges * rangesbuf,
16607dc194Richard Lowe    Dwarf_Signed rangecount)
16707dc194Richard Lowe{
16807dc194Richard Lowe    dwarf_dealloc(dbg,rangesbuf, DW_DLA_RANGES);
16907dc194Richard Lowe
17007dc194Richard Lowe}
17107dc194Richard Lowe