149d3bc9Richard Lowe/*
249d3bc9Richard Lowe
307dc194Richard Lowe  Copyright (C) 2000,2004 Silicon Graphics, Inc.  All Rights Reserved.
449d3bc9Richard Lowe
549d3bc9Richard Lowe  This program is free software; you can redistribute it and/or modify it
649d3bc9Richard Lowe  under the terms of version 2.1 of the GNU Lesser General Public License
749d3bc9Richard Lowe  as published by the Free Software Foundation.
849d3bc9Richard Lowe
949d3bc9Richard Lowe  This program is distributed in the hope that it would be useful, but
1049d3bc9Richard Lowe  WITHOUT ANY WARRANTY; without even the implied warranty of
1149d3bc9Richard Lowe  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1249d3bc9Richard Lowe
1349d3bc9Richard Lowe  Further, this software is distributed without any warranty that it is
1449d3bc9Richard Lowe  free of the rightful claim of any third person regarding infringement
1549d3bc9Richard Lowe  or the like.  Any license provided herein, whether implied or
1649d3bc9Richard Lowe  otherwise, applies only to this software file.  Patent licenses, if
1749d3bc9Richard Lowe  any, provided herein do not apply to combinations of this program with
1849d3bc9Richard Lowe  other software, or any other product whatsoever.
1949d3bc9Richard Lowe
2049d3bc9Richard Lowe  You should have received a copy of the GNU Lesser General Public
2149d3bc9Richard 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,
2349d3bc9Richard Lowe  USA.
2449d3bc9Richard Lowe
2507dc194Richard Lowe  Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
2649d3bc9Richard Lowe  Mountain View, CA 94043, or:
2749d3bc9Richard Lowe
2849d3bc9Richard Lowe  http://www.sgi.com
2949d3bc9Richard Lowe
3049d3bc9Richard Lowe  For further information regarding this notice, see:
3149d3bc9Richard Lowe
3249d3bc9Richard Lowe  http://oss.sgi.com/projects/GenInfo/NoticeExplan
3349d3bc9Richard Lowe
3449d3bc9Richard Lowe*/
3549d3bc9Richard Lowe
3649d3bc9Richard Lowe
3749d3bc9Richard Lowe
3849d3bc9Richard Lowe#include "config.h"
3949d3bc9Richard Lowe#include "libdwarfdefs.h"
4049d3bc9Richard Lowe#include <stdio.h>
4149d3bc9Richard Lowe#include <string.h>
4249d3bc9Richard Lowe#ifdef HAVE_ELFACCESS_H
4349d3bc9Richard Lowe#include <elfaccess.h>
4449d3bc9Richard Lowe#endif
4549d3bc9Richard Lowe#include "pro_incl.h"
4649d3bc9Richard Lowe#include "pro_arange.h"
4749d3bc9Richard Lowe#include "pro_section.h"
4849d3bc9Richard Lowe#include "pro_reloc.h"
4949d3bc9Richard Lowe
5049d3bc9Richard Lowe
5149d3bc9Richard Lowe
5249d3bc9Richard Lowe/*
5349d3bc9Richard Lowe    This function adds another address range
5449d3bc9Richard Lowe    to the list of address ranges for the
5549d3bc9Richard Lowe    given Dwarf_P_Debug.  It returns 0 on error,
5649d3bc9Richard Lowe    and 1 otherwise.
5749d3bc9Richard Lowe*/
5849d3bc9Richard LoweDwarf_Unsigned
5949d3bc9Richard Lowedwarf_add_arange(Dwarf_P_Debug dbg,
6007dc194Richard Lowe                 Dwarf_Addr begin_address,
6107dc194Richard Lowe                 Dwarf_Unsigned length,
6207dc194Richard Lowe                 Dwarf_Signed symbol_index, Dwarf_Error * error)
6349d3bc9Richard Lowe{
6449d3bc9Richard Lowe    return dwarf_add_arange_b(dbg, begin_address, length, symbol_index,
6507dc194Richard Lowe                              /* end_symbol_index */ 0,
6607dc194Richard Lowe                              /* offset_from_end_sym */ 0,
6707dc194Richard Lowe                              error);
6849d3bc9Richard Lowe}
6949d3bc9Richard Lowe
7049d3bc9Richard Lowe/*
7149d3bc9Richard Lowe    This function adds another address range
7249d3bc9Richard Lowe    to the list of address ranges for the
7349d3bc9Richard Lowe    given Dwarf_P_Debug.  It returns 0 on error,
7449d3bc9Richard Lowe    and 1 otherwise.
7549d3bc9Richard Lowe*/
7649d3bc9Richard LoweDwarf_Unsigned
7749d3bc9Richard Lowedwarf_add_arange_b(Dwarf_P_Debug dbg,
7807dc194Richard Lowe                   Dwarf_Addr begin_address,
7907dc194Richard Lowe                   Dwarf_Unsigned length,
8007dc194Richard Lowe                   Dwarf_Unsigned symbol_index,
8107dc194Richard Lowe                   Dwarf_Unsigned end_symbol_index,
8207dc194Richard Lowe                   Dwarf_Addr offset_from_end_sym, Dwarf_Error * error)
8349d3bc9Richard Lowe{
8449d3bc9Richard Lowe    Dwarf_P_Arange arange;
8549d3bc9Richard Lowe
8649d3bc9Richard Lowe    if (dbg == NULL) {
8707dc194Richard Lowe        _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
8807dc194Richard Lowe        return (0);
8949d3bc9Richard Lowe    }
9049d3bc9Richard Lowe
9149d3bc9Richard Lowe    arange = (Dwarf_P_Arange)
9207dc194Richard Lowe        _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Arange_s));
9349d3bc9Richard Lowe    if (arange == NULL) {
9407dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
9507dc194Richard Lowe        return (0);
9649d3bc9Richard Lowe    }
9749d3bc9Richard Lowe
9849d3bc9Richard Lowe    arange->ag_begin_address = begin_address;
9949d3bc9Richard Lowe    arange->ag_length = length;
10049d3bc9Richard Lowe    arange->ag_symbol_index = symbol_index;
10149d3bc9Richard Lowe    arange->ag_end_symbol_index = end_symbol_index;
10249d3bc9Richard Lowe    arange->ag_end_symbol_offset = offset_from_end_sym;
10349d3bc9Richard Lowe
10449d3bc9Richard Lowe    if (dbg->de_arange == NULL)
10507dc194Richard Lowe        dbg->de_arange = dbg->de_last_arange = arange;
10649d3bc9Richard Lowe    else {
10707dc194Richard Lowe        dbg->de_last_arange->ag_next = arange;
10807dc194Richard Lowe        dbg->de_last_arange = arange;
10949d3bc9Richard Lowe    }
11049d3bc9Richard Lowe    dbg->de_arange_count++;
11149d3bc9Richard Lowe
11249d3bc9Richard Lowe    return (1);
11349d3bc9Richard Lowe}
11449d3bc9Richard Lowe
11549d3bc9Richard Lowe
11649d3bc9Richard Loweint
11749d3bc9Richard Lowe_dwarf_transform_arange_to_disk(Dwarf_P_Debug dbg, Dwarf_Error * error)
11849d3bc9Richard Lowe{
11949d3bc9Richard Lowe    /* Total num of bytes in .debug_aranges section. */
12049d3bc9Richard Lowe    Dwarf_Unsigned arange_num_bytes;
12149d3bc9Richard Lowe
12249d3bc9Richard Lowe    /*
12349d3bc9Richard Lowe       Adjustment to align the start of the actual address ranges on a
12449d3bc9Richard Lowe       boundary aligned with twice the address size. */
12549d3bc9Richard Lowe    Dwarf_Small remainder;
12649d3bc9Richard Lowe
12749d3bc9Richard Lowe    /* Total number of bytes excluding the length field. */
12849d3bc9Richard Lowe    Dwarf_Unsigned adjusted_length;
12949d3bc9Richard Lowe
13049d3bc9Richard Lowe    /* Points to first byte of .debug_aranges buffer. */
13149d3bc9Richard Lowe    Dwarf_Small *arange;
13249d3bc9Richard Lowe
13349d3bc9Richard Lowe    /* Fills in the .debug_aranges buffer. */
13449d3bc9Richard Lowe    Dwarf_Small *arange_ptr;
13549d3bc9Richard Lowe
13649d3bc9Richard Lowe    /* Scans the list of address ranges provided by user. */
13749d3bc9Richard Lowe    Dwarf_P_Arange given_arange;
13849d3bc9Richard Lowe
13949d3bc9Richard Lowe    /* Used to fill in 0. */
14049d3bc9Richard Lowe    const Dwarf_Signed big_zero = 0;
14149d3bc9Richard Lowe
14249d3bc9Richard Lowe    int extension_word_size = dbg->de_64bit_extension ? 4 : 0;
14349d3bc9Richard Lowe    int uword_size = dbg->de_offset_size;
14449d3bc9Richard Lowe    int upointer_size = dbg->de_pointer_size;
14549d3bc9Richard Lowe    int res;
14649d3bc9Richard Lowe
14749d3bc9Richard Lowe
14849d3bc9Richard Lowe    /* ***** BEGIN CODE ***** */
14949d3bc9Richard Lowe
15049d3bc9Richard Lowe    /* Size of the .debug_aranges section header. */
15107dc194Richard Lowe    arange_num_bytes = extension_word_size + uword_size +       /* Size
15207dc194Richard Lowe                                                                   of
15307dc194Richard Lowe                                                                   length
15407dc194Richard Lowe                                                                   field.
15507dc194Richard Lowe                                                                 */
15607dc194Richard Lowe        sizeof(Dwarf_Half) +    /* Size of version field. */
15707dc194Richard Lowe        uword_size +            /* Size of .debug_info offset. */
15807dc194Richard Lowe        sizeof(Dwarf_Small) +   /* Size of address size field. */
15907dc194Richard Lowe        sizeof(Dwarf_Small);    /* Size of segment size field. */
16049d3bc9Richard Lowe
16149d3bc9Richard Lowe    /*
16249d3bc9Richard Lowe       Adjust the size so that the set of aranges begins on a boundary
16349d3bc9Richard Lowe       that aligned with twice the address size.  This is a Libdwarf
16449d3bc9Richard Lowe       requirement. */
16549d3bc9Richard Lowe    remainder = arange_num_bytes % (2 * upointer_size);
16649d3bc9Richard Lowe    if (remainder != 0)
16707dc194Richard Lowe        arange_num_bytes += (2 * upointer_size) - remainder;
16849d3bc9Richard Lowe
16949d3bc9Richard Lowe
17049d3bc9Richard Lowe    /* Add the bytes for the actual address ranges. */
17149d3bc9Richard Lowe    arange_num_bytes += upointer_size * 2 * (dbg->de_arange_count + 1);
17249d3bc9Richard Lowe
17349d3bc9Richard Lowe    GET_CHUNK(dbg, dbg->de_elf_sects[DEBUG_ARANGES],
17407dc194Richard Lowe              arange, (unsigned long) arange_num_bytes, error);
17549d3bc9Richard Lowe    arange_ptr = arange;
17649d3bc9Richard Lowe    if (arange == NULL) {
17707dc194Richard Lowe        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
17807dc194Richard Lowe        return (0);
17949d3bc9Richard Lowe    }
18049d3bc9Richard Lowe    if (extension_word_size) {
18107dc194Richard Lowe        Dwarf_Word x = DISTINGUISHED_VALUE;
18249d3bc9Richard Lowe
18307dc194Richard Lowe        WRITE_UNALIGNED(dbg, (void *) arange_ptr,
18407dc194Richard Lowe                        (const void *) &x,
18507dc194Richard Lowe                        sizeof(x), extension_word_size);
18607dc194Richard Lowe        arange_ptr += extension_word_size;
18749d3bc9Richard Lowe    }
18849d3bc9Richard Lowe
18949d3bc9Richard Lowe    /* Write the total length of .debug_aranges section. */
19049d3bc9Richard Lowe    adjusted_length = arange_num_bytes - uword_size
19107dc194Richard Lowe        - extension_word_size;
19249d3bc9Richard Lowe    {
19307dc194Richard Lowe        Dwarf_Unsigned du = adjusted_length;
19449d3bc9Richard Lowe
19507dc194Richard Lowe        WRITE_UNALIGNED(dbg, (void *) arange_ptr,
19607dc194Richard Lowe                        (const void *) &du, sizeof(du), uword_size);
19707dc194Richard Lowe        arange_ptr += uword_size;
19849d3bc9Richard Lowe    }
19949d3bc9Richard Lowe
20049d3bc9Richard Lowe    /* Write the version as 2 bytes. */
20149d3bc9Richard Lowe    {
20207dc194Richard Lowe        Dwarf_Half verstamp = CURRENT_VERSION_STAMP;
20349d3bc9Richard Lowe
20407dc194Richard Lowe        WRITE_UNALIGNED(dbg, (void *) arange_ptr,
20507dc194Richard Lowe                        (const void *) &verstamp,
20607dc194Richard Lowe                        sizeof(verstamp), sizeof(Dwarf_Half));
20707dc194Richard Lowe        arange_ptr += sizeof(Dwarf_Half);
20849d3bc9Richard Lowe    }
20949d3bc9Richard Lowe
21049d3bc9Richard Lowe
21149d3bc9Richard Lowe    /* Write the .debug_info offset.  This is always 0. */
21249d3bc9Richard Lowe    WRITE_UNALIGNED(dbg, (void *) arange_ptr,
21307dc194Richard Lowe                    (const void *) &big_zero,
21407dc194Richard Lowe                    sizeof(big_zero), uword_size);
21549d3bc9Richard Lowe    arange_ptr += uword_size;
21649d3bc9Richard Lowe
21749d3bc9Richard Lowe    {
21807dc194Richard Lowe        unsigned long count = dbg->de_arange_count + 1;
21907dc194Richard Lowe        int res;
22007dc194Richard Lowe
22107dc194Richard Lowe        if (dbg->de_reloc_pair) {
22207dc194Richard Lowe            count = (3 * dbg->de_arange_count) + 1;
22307dc194Richard Lowe        }
22407dc194Richard Lowe        /* the following is a small optimization: not needed for
22507dc194Richard Lowe           correctness */
22607dc194Richard Lowe        res = _dwarf_pro_pre_alloc_n_reloc_slots(dbg,
22707dc194Richard Lowe                                                 DEBUG_ARANGES, count);
22807dc194Richard Lowe        if (res != DW_DLV_OK) {
22907dc194Richard Lowe            {
23007dc194Richard Lowe                _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
23107dc194Richard Lowe                return (0);
23207dc194Richard Lowe            }
23307dc194Richard Lowe        }
23449d3bc9Richard Lowe    }
23549d3bc9Richard Lowe
23649d3bc9Richard Lowe    /* reloc for .debug_info */
23749d3bc9Richard Lowe    res = dbg->de_reloc_name(dbg,
23807dc194Richard Lowe                             DEBUG_ARANGES,
23907dc194Richard Lowe                             extension_word_size +
24007dc194Richard Lowe                             uword_size + sizeof(Dwarf_Half),
24107dc194Richard Lowe                             dbg->de_sect_name_idx[DEBUG_INFO],
24207dc194Richard Lowe                             dwarf_drt_data_reloc, uword_size);
24349d3bc9Richard Lowe
24449d3bc9Richard Lowe    /* Write the size of addresses. */
24549d3bc9Richard Lowe    *arange_ptr = dbg->de_pointer_size;
24649d3bc9Richard Lowe    arange_ptr++;
24749d3bc9Richard Lowe
24849d3bc9Richard Lowe    /*
24949d3bc9Richard Lowe       Write the size of segment addresses. This is zero for MIPS
25049d3bc9Richard Lowe       architectures. */
25149d3bc9Richard Lowe    *arange_ptr = 0;
25249d3bc9Richard Lowe    arange_ptr++;
25349d3bc9Richard Lowe
25449d3bc9Richard Lowe    /*
25549d3bc9Richard Lowe       Skip over the padding to align the start of the actual address
25649d3bc9Richard Lowe       ranges to twice the address size. */
25749d3bc9Richard Lowe    if (remainder != 0)
25807dc194Richard Lowe        arange_ptr += (2 * upointer_size) - remainder;
25949d3bc9Richard Lowe
26049d3bc9Richard Lowe
26149d3bc9Richard Lowe
26249d3bc9Richard Lowe
26349d3bc9Richard Lowe
26449d3bc9Richard Lowe    /* The arange address, length are pointer-size fields of the target
26549d3bc9Richard Lowe       machine. */
26649d3bc9Richard Lowe    for (given_arange = dbg->de_arange; given_arange != NULL;
26707dc194Richard Lowe         given_arange = given_arange->ag_next) {
26807dc194Richard Lowe
26907dc194Richard Lowe        /* Write relocation record for beginning of address range. */
27007dc194Richard Lowe        res = dbg->de_reloc_name(dbg, DEBUG_ARANGES, arange_ptr - arange,       /* r_offset
27107dc194Richard Lowe                                                                                 */
27207dc194Richard Lowe                                 (long) given_arange->ag_symbol_index,
27307dc194Richard Lowe                                 dwarf_drt_data_reloc, upointer_size);
27407dc194Richard Lowe        if (res != DW_DLV_OK) {
27507dc194Richard Lowe            {
27607dc194Richard Lowe                _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
27707dc194Richard Lowe                return (0);
27807dc194Richard Lowe            }
27907dc194Richard Lowe        }
28007dc194Richard Lowe
28107dc194Richard Lowe        /* Copy beginning address of range. */
28207dc194Richard Lowe        WRITE_UNALIGNED(dbg, (void *) arange_ptr,
28307dc194Richard Lowe                        (const void *) &given_arange->ag_begin_address,
28407dc194Richard Lowe                        sizeof(given_arange->ag_begin_address),
28507dc194Richard Lowe                        upointer_size);
28607dc194Richard Lowe        arange_ptr += upointer_size;
28707dc194Richard Lowe
28807dc194Richard Lowe        if (dbg->de_reloc_pair &&
28907dc194Richard Lowe            given_arange->ag_end_symbol_index != 0 &&
29007dc194Richard Lowe            given_arange->ag_length == 0) {
29107dc194Richard Lowe            /* symbolic reloc, need reloc for length What if we really
29207dc194Richard Lowe               know the length? If so, should use the other part of
29307dc194Richard Lowe               'if'. */
29407dc194Richard Lowe            Dwarf_Unsigned val;
29507dc194Richard Lowe
29607dc194Richard Lowe            res = dbg->de_reloc_pair(dbg, DEBUG_ARANGES, arange_ptr - arange,   /* r_offset
29707dc194Richard Lowe                                                                                 */
29807dc194Richard Lowe                                     given_arange->ag_symbol_index,
29907dc194Richard Lowe                                     given_arange->ag_end_symbol_index,
30007dc194Richard Lowe                                     dwarf_drt_first_of_length_pair,
30107dc194Richard Lowe                                     upointer_size);
30207dc194Richard Lowe            if (res != DW_DLV_OK) {
30307dc194Richard Lowe                {
30407dc194Richard Lowe                    _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
30507dc194Richard Lowe                    return (0);
30607dc194Richard Lowe                }
30707dc194Richard Lowe            }
30807dc194Richard Lowe
30907dc194Richard Lowe            /* arrange pre-calc so assem text can do .word end - begin
31007dc194Richard Lowe               + val (gets val from stream) */
31107dc194Richard Lowe            val = given_arange->ag_end_symbol_offset -
31207dc194Richard Lowe                given_arange->ag_begin_address;
31307dc194Richard Lowe            WRITE_UNALIGNED(dbg, (void *) arange_ptr,
31407dc194Richard Lowe                            (const void *) &val,
31507dc194Richard Lowe                            sizeof(val), upointer_size);
31607dc194Richard Lowe            arange_ptr += upointer_size;
31707dc194Richard Lowe
31807dc194Richard Lowe        } else {
31907dc194Richard Lowe            /* plain old length to copy, no relocation at all */
32007dc194Richard Lowe            WRITE_UNALIGNED(dbg, (void *) arange_ptr,
32107dc194Richard Lowe                            (const void *) &given_arange->ag_length,
32207dc194Richard Lowe                            sizeof(given_arange->ag_length),
32307dc194Richard Lowe                            upointer_size);
32407dc194Richard Lowe            arange_ptr += upointer_size;
32507dc194Richard Lowe        }
32649d3bc9Richard Lowe    }
32749d3bc9Richard Lowe
32849d3bc9Richard Lowe    WRITE_UNALIGNED(dbg, (void *) arange_ptr,
32907dc194Richard Lowe                    (const void *) &big_zero,
33007dc194Richard Lowe                    sizeof(big_zero), upointer_size);
33149d3bc9Richard Lowe
33249d3bc9Richard Lowe    arange_ptr += upointer_size;
33349d3bc9Richard Lowe    WRITE_UNALIGNED(dbg, (void *) arange_ptr,
33407dc194Richard Lowe                    (const void *) &big_zero,
33507dc194Richard Lowe                    sizeof(big_zero), upointer_size);
33649d3bc9Richard Lowe    return (int) dbg->de_n_debug_sect;
33749d3bc9Richard Lowe}
338