xref: /titanic_41/usr/src/tools/ctf/dwarf/common/pro_arange.c (revision 07dc1947c362e187fb955d283b692f8769dd5def)
149d3bc91SRichard Lowe /*
249d3bc91SRichard Lowe 
3*07dc1947SRichard Lowe   Copyright (C) 2000,2004 Silicon Graphics, Inc.  All Rights Reserved.
449d3bc91SRichard Lowe 
549d3bc91SRichard Lowe   This program is free software; you can redistribute it and/or modify it
649d3bc91SRichard Lowe   under the terms of version 2.1 of the GNU Lesser General Public License
749d3bc91SRichard Lowe   as published by the Free Software Foundation.
849d3bc91SRichard Lowe 
949d3bc91SRichard Lowe   This program is distributed in the hope that it would be useful, but
1049d3bc91SRichard Lowe   WITHOUT ANY WARRANTY; without even the implied warranty of
1149d3bc91SRichard Lowe   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1249d3bc91SRichard Lowe 
1349d3bc91SRichard Lowe   Further, this software is distributed without any warranty that it is
1449d3bc91SRichard Lowe   free of the rightful claim of any third person regarding infringement
1549d3bc91SRichard Lowe   or the like.  Any license provided herein, whether implied or
1649d3bc91SRichard Lowe   otherwise, applies only to this software file.  Patent licenses, if
1749d3bc91SRichard Lowe   any, provided herein do not apply to combinations of this program with
1849d3bc91SRichard Lowe   other software, or any other product whatsoever.
1949d3bc91SRichard Lowe 
2049d3bc91SRichard Lowe   You should have received a copy of the GNU Lesser General Public
2149d3bc91SRichard Lowe   License along with this program; if not, write the Free Software
22*07dc1947SRichard Lowe   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
2349d3bc91SRichard Lowe   USA.
2449d3bc91SRichard Lowe 
25*07dc1947SRichard Lowe   Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
2649d3bc91SRichard Lowe   Mountain View, CA 94043, or:
2749d3bc91SRichard Lowe 
2849d3bc91SRichard Lowe   http://www.sgi.com
2949d3bc91SRichard Lowe 
3049d3bc91SRichard Lowe   For further information regarding this notice, see:
3149d3bc91SRichard Lowe 
3249d3bc91SRichard Lowe   http://oss.sgi.com/projects/GenInfo/NoticeExplan
3349d3bc91SRichard Lowe 
3449d3bc91SRichard Lowe */
3549d3bc91SRichard Lowe 
3649d3bc91SRichard Lowe 
3749d3bc91SRichard Lowe 
3849d3bc91SRichard Lowe #include "config.h"
3949d3bc91SRichard Lowe #include "libdwarfdefs.h"
4049d3bc91SRichard Lowe #include <stdio.h>
4149d3bc91SRichard Lowe #include <string.h>
4249d3bc91SRichard Lowe #ifdef HAVE_ELFACCESS_H
4349d3bc91SRichard Lowe #include <elfaccess.h>
4449d3bc91SRichard Lowe #endif
4549d3bc91SRichard Lowe #include "pro_incl.h"
4649d3bc91SRichard Lowe #include "pro_arange.h"
4749d3bc91SRichard Lowe #include "pro_section.h"
4849d3bc91SRichard Lowe #include "pro_reloc.h"
4949d3bc91SRichard Lowe 
5049d3bc91SRichard Lowe 
5149d3bc91SRichard Lowe 
5249d3bc91SRichard Lowe /*
5349d3bc91SRichard Lowe     This function adds another address range
5449d3bc91SRichard Lowe     to the list of address ranges for the
5549d3bc91SRichard Lowe     given Dwarf_P_Debug.  It returns 0 on error,
5649d3bc91SRichard Lowe     and 1 otherwise.
5749d3bc91SRichard Lowe */
5849d3bc91SRichard Lowe Dwarf_Unsigned
dwarf_add_arange(Dwarf_P_Debug dbg,Dwarf_Addr begin_address,Dwarf_Unsigned length,Dwarf_Signed symbol_index,Dwarf_Error * error)5949d3bc91SRichard Lowe dwarf_add_arange(Dwarf_P_Debug dbg,
6049d3bc91SRichard Lowe                  Dwarf_Addr begin_address,
6149d3bc91SRichard Lowe                  Dwarf_Unsigned length,
6249d3bc91SRichard Lowe                  Dwarf_Signed symbol_index, Dwarf_Error * error)
6349d3bc91SRichard Lowe {
6449d3bc91SRichard Lowe     return dwarf_add_arange_b(dbg, begin_address, length, symbol_index,
6549d3bc91SRichard Lowe                               /* end_symbol_index */ 0,
6649d3bc91SRichard Lowe                               /* offset_from_end_sym */ 0,
6749d3bc91SRichard Lowe                               error);
6849d3bc91SRichard Lowe }
6949d3bc91SRichard Lowe 
7049d3bc91SRichard Lowe /*
7149d3bc91SRichard Lowe     This function adds another address range
7249d3bc91SRichard Lowe     to the list of address ranges for the
7349d3bc91SRichard Lowe     given Dwarf_P_Debug.  It returns 0 on error,
7449d3bc91SRichard Lowe     and 1 otherwise.
7549d3bc91SRichard Lowe */
7649d3bc91SRichard Lowe Dwarf_Unsigned
dwarf_add_arange_b(Dwarf_P_Debug dbg,Dwarf_Addr begin_address,Dwarf_Unsigned length,Dwarf_Unsigned symbol_index,Dwarf_Unsigned end_symbol_index,Dwarf_Addr offset_from_end_sym,Dwarf_Error * error)7749d3bc91SRichard Lowe dwarf_add_arange_b(Dwarf_P_Debug dbg,
7849d3bc91SRichard Lowe                    Dwarf_Addr begin_address,
7949d3bc91SRichard Lowe                    Dwarf_Unsigned length,
8049d3bc91SRichard Lowe                    Dwarf_Unsigned symbol_index,
8149d3bc91SRichard Lowe                    Dwarf_Unsigned end_symbol_index,
8249d3bc91SRichard Lowe                    Dwarf_Addr offset_from_end_sym, Dwarf_Error * error)
8349d3bc91SRichard Lowe {
8449d3bc91SRichard Lowe     Dwarf_P_Arange arange;
8549d3bc91SRichard Lowe 
8649d3bc91SRichard Lowe     if (dbg == NULL) {
8749d3bc91SRichard Lowe         _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
8849d3bc91SRichard Lowe         return (0);
8949d3bc91SRichard Lowe     }
9049d3bc91SRichard Lowe 
9149d3bc91SRichard Lowe     arange = (Dwarf_P_Arange)
9249d3bc91SRichard Lowe         _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Arange_s));
9349d3bc91SRichard Lowe     if (arange == NULL) {
9449d3bc91SRichard Lowe         _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
9549d3bc91SRichard Lowe         return (0);
9649d3bc91SRichard Lowe     }
9749d3bc91SRichard Lowe 
9849d3bc91SRichard Lowe     arange->ag_begin_address = begin_address;
9949d3bc91SRichard Lowe     arange->ag_length = length;
10049d3bc91SRichard Lowe     arange->ag_symbol_index = symbol_index;
10149d3bc91SRichard Lowe     arange->ag_end_symbol_index = end_symbol_index;
10249d3bc91SRichard Lowe     arange->ag_end_symbol_offset = offset_from_end_sym;
10349d3bc91SRichard Lowe 
10449d3bc91SRichard Lowe     if (dbg->de_arange == NULL)
10549d3bc91SRichard Lowe         dbg->de_arange = dbg->de_last_arange = arange;
10649d3bc91SRichard Lowe     else {
10749d3bc91SRichard Lowe         dbg->de_last_arange->ag_next = arange;
10849d3bc91SRichard Lowe         dbg->de_last_arange = arange;
10949d3bc91SRichard Lowe     }
11049d3bc91SRichard Lowe     dbg->de_arange_count++;
11149d3bc91SRichard Lowe 
11249d3bc91SRichard Lowe     return (1);
11349d3bc91SRichard Lowe }
11449d3bc91SRichard Lowe 
11549d3bc91SRichard Lowe 
11649d3bc91SRichard Lowe int
_dwarf_transform_arange_to_disk(Dwarf_P_Debug dbg,Dwarf_Error * error)11749d3bc91SRichard Lowe _dwarf_transform_arange_to_disk(Dwarf_P_Debug dbg, Dwarf_Error * error)
11849d3bc91SRichard Lowe {
11949d3bc91SRichard Lowe     /* Total num of bytes in .debug_aranges section. */
12049d3bc91SRichard Lowe     Dwarf_Unsigned arange_num_bytes;
12149d3bc91SRichard Lowe 
12249d3bc91SRichard Lowe     /*
12349d3bc91SRichard Lowe        Adjustment to align the start of the actual address ranges on a
12449d3bc91SRichard Lowe        boundary aligned with twice the address size. */
12549d3bc91SRichard Lowe     Dwarf_Small remainder;
12649d3bc91SRichard Lowe 
12749d3bc91SRichard Lowe     /* Total number of bytes excluding the length field. */
12849d3bc91SRichard Lowe     Dwarf_Unsigned adjusted_length;
12949d3bc91SRichard Lowe 
13049d3bc91SRichard Lowe     /* Points to first byte of .debug_aranges buffer. */
13149d3bc91SRichard Lowe     Dwarf_Small *arange;
13249d3bc91SRichard Lowe 
13349d3bc91SRichard Lowe     /* Fills in the .debug_aranges buffer. */
13449d3bc91SRichard Lowe     Dwarf_Small *arange_ptr;
13549d3bc91SRichard Lowe 
13649d3bc91SRichard Lowe     /* Scans the list of address ranges provided by user. */
13749d3bc91SRichard Lowe     Dwarf_P_Arange given_arange;
13849d3bc91SRichard Lowe 
13949d3bc91SRichard Lowe     /* Used to fill in 0. */
14049d3bc91SRichard Lowe     const Dwarf_Signed big_zero = 0;
14149d3bc91SRichard Lowe 
14249d3bc91SRichard Lowe     int extension_word_size = dbg->de_64bit_extension ? 4 : 0;
14349d3bc91SRichard Lowe     int uword_size = dbg->de_offset_size;
14449d3bc91SRichard Lowe     int upointer_size = dbg->de_pointer_size;
14549d3bc91SRichard Lowe     int res;
14649d3bc91SRichard Lowe 
14749d3bc91SRichard Lowe 
14849d3bc91SRichard Lowe     /* ***** BEGIN CODE ***** */
14949d3bc91SRichard Lowe 
15049d3bc91SRichard Lowe     /* Size of the .debug_aranges section header. */
15149d3bc91SRichard Lowe     arange_num_bytes = extension_word_size + uword_size +       /* Size
15249d3bc91SRichard Lowe                                                                    of
15349d3bc91SRichard Lowe                                                                    length
15449d3bc91SRichard Lowe                                                                    field.
15549d3bc91SRichard Lowe                                                                  */
15649d3bc91SRichard Lowe         sizeof(Dwarf_Half) +    /* Size of version field. */
15749d3bc91SRichard Lowe         uword_size +            /* Size of .debug_info offset. */
15849d3bc91SRichard Lowe         sizeof(Dwarf_Small) +   /* Size of address size field. */
15949d3bc91SRichard Lowe         sizeof(Dwarf_Small);    /* Size of segment size field. */
16049d3bc91SRichard Lowe 
16149d3bc91SRichard Lowe     /*
16249d3bc91SRichard Lowe        Adjust the size so that the set of aranges begins on a boundary
16349d3bc91SRichard Lowe        that aligned with twice the address size.  This is a Libdwarf
16449d3bc91SRichard Lowe        requirement. */
16549d3bc91SRichard Lowe     remainder = arange_num_bytes % (2 * upointer_size);
16649d3bc91SRichard Lowe     if (remainder != 0)
16749d3bc91SRichard Lowe         arange_num_bytes += (2 * upointer_size) - remainder;
16849d3bc91SRichard Lowe 
16949d3bc91SRichard Lowe 
17049d3bc91SRichard Lowe     /* Add the bytes for the actual address ranges. */
17149d3bc91SRichard Lowe     arange_num_bytes += upointer_size * 2 * (dbg->de_arange_count + 1);
17249d3bc91SRichard Lowe 
17349d3bc91SRichard Lowe     GET_CHUNK(dbg, dbg->de_elf_sects[DEBUG_ARANGES],
17449d3bc91SRichard Lowe               arange, (unsigned long) arange_num_bytes, error);
17549d3bc91SRichard Lowe     arange_ptr = arange;
17649d3bc91SRichard Lowe     if (arange == NULL) {
17749d3bc91SRichard Lowe         _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
17849d3bc91SRichard Lowe         return (0);
17949d3bc91SRichard Lowe     }
18049d3bc91SRichard Lowe     if (extension_word_size) {
18149d3bc91SRichard Lowe         Dwarf_Word x = DISTINGUISHED_VALUE;
18249d3bc91SRichard Lowe 
18349d3bc91SRichard Lowe         WRITE_UNALIGNED(dbg, (void *) arange_ptr,
18449d3bc91SRichard Lowe                         (const void *) &x,
18549d3bc91SRichard Lowe                         sizeof(x), extension_word_size);
18649d3bc91SRichard Lowe         arange_ptr += extension_word_size;
18749d3bc91SRichard Lowe     }
18849d3bc91SRichard Lowe 
18949d3bc91SRichard Lowe     /* Write the total length of .debug_aranges section. */
19049d3bc91SRichard Lowe     adjusted_length = arange_num_bytes - uword_size
19149d3bc91SRichard Lowe         - extension_word_size;
19249d3bc91SRichard Lowe     {
19349d3bc91SRichard Lowe         Dwarf_Unsigned du = adjusted_length;
19449d3bc91SRichard Lowe 
19549d3bc91SRichard Lowe         WRITE_UNALIGNED(dbg, (void *) arange_ptr,
19649d3bc91SRichard Lowe                         (const void *) &du, sizeof(du), uword_size);
19749d3bc91SRichard Lowe         arange_ptr += uword_size;
19849d3bc91SRichard Lowe     }
19949d3bc91SRichard Lowe 
20049d3bc91SRichard Lowe     /* Write the version as 2 bytes. */
20149d3bc91SRichard Lowe     {
20249d3bc91SRichard Lowe         Dwarf_Half verstamp = CURRENT_VERSION_STAMP;
20349d3bc91SRichard Lowe 
20449d3bc91SRichard Lowe         WRITE_UNALIGNED(dbg, (void *) arange_ptr,
20549d3bc91SRichard Lowe                         (const void *) &verstamp,
20649d3bc91SRichard Lowe                         sizeof(verstamp), sizeof(Dwarf_Half));
20749d3bc91SRichard Lowe         arange_ptr += sizeof(Dwarf_Half);
20849d3bc91SRichard Lowe     }
20949d3bc91SRichard Lowe 
21049d3bc91SRichard Lowe 
21149d3bc91SRichard Lowe     /* Write the .debug_info offset.  This is always 0. */
21249d3bc91SRichard Lowe     WRITE_UNALIGNED(dbg, (void *) arange_ptr,
21349d3bc91SRichard Lowe                     (const void *) &big_zero,
21449d3bc91SRichard Lowe                     sizeof(big_zero), uword_size);
21549d3bc91SRichard Lowe     arange_ptr += uword_size;
21649d3bc91SRichard Lowe 
21749d3bc91SRichard Lowe     {
21849d3bc91SRichard Lowe         unsigned long count = dbg->de_arange_count + 1;
21949d3bc91SRichard Lowe         int res;
22049d3bc91SRichard Lowe 
22149d3bc91SRichard Lowe         if (dbg->de_reloc_pair) {
22249d3bc91SRichard Lowe             count = (3 * dbg->de_arange_count) + 1;
22349d3bc91SRichard Lowe         }
22449d3bc91SRichard Lowe         /* the following is a small optimization: not needed for
22549d3bc91SRichard Lowe            correctness */
22649d3bc91SRichard Lowe         res = _dwarf_pro_pre_alloc_n_reloc_slots(dbg,
22749d3bc91SRichard Lowe                                                  DEBUG_ARANGES, count);
22849d3bc91SRichard Lowe         if (res != DW_DLV_OK) {
22949d3bc91SRichard Lowe             {
23049d3bc91SRichard Lowe                 _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
23149d3bc91SRichard Lowe                 return (0);
23249d3bc91SRichard Lowe             }
23349d3bc91SRichard Lowe         }
23449d3bc91SRichard Lowe     }
23549d3bc91SRichard Lowe 
23649d3bc91SRichard Lowe     /* reloc for .debug_info */
23749d3bc91SRichard Lowe     res = dbg->de_reloc_name(dbg,
23849d3bc91SRichard Lowe                              DEBUG_ARANGES,
23949d3bc91SRichard Lowe                              extension_word_size +
24049d3bc91SRichard Lowe                              uword_size + sizeof(Dwarf_Half),
24149d3bc91SRichard Lowe                              dbg->de_sect_name_idx[DEBUG_INFO],
24249d3bc91SRichard Lowe                              dwarf_drt_data_reloc, uword_size);
24349d3bc91SRichard Lowe 
24449d3bc91SRichard Lowe     /* Write the size of addresses. */
24549d3bc91SRichard Lowe     *arange_ptr = dbg->de_pointer_size;
24649d3bc91SRichard Lowe     arange_ptr++;
24749d3bc91SRichard Lowe 
24849d3bc91SRichard Lowe     /*
24949d3bc91SRichard Lowe        Write the size of segment addresses. This is zero for MIPS
25049d3bc91SRichard Lowe        architectures. */
25149d3bc91SRichard Lowe     *arange_ptr = 0;
25249d3bc91SRichard Lowe     arange_ptr++;
25349d3bc91SRichard Lowe 
25449d3bc91SRichard Lowe     /*
25549d3bc91SRichard Lowe        Skip over the padding to align the start of the actual address
25649d3bc91SRichard Lowe        ranges to twice the address size. */
25749d3bc91SRichard Lowe     if (remainder != 0)
25849d3bc91SRichard Lowe         arange_ptr += (2 * upointer_size) - remainder;
25949d3bc91SRichard Lowe 
26049d3bc91SRichard Lowe 
26149d3bc91SRichard Lowe 
26249d3bc91SRichard Lowe 
26349d3bc91SRichard Lowe 
26449d3bc91SRichard Lowe     /* The arange address, length are pointer-size fields of the target
26549d3bc91SRichard Lowe        machine. */
26649d3bc91SRichard Lowe     for (given_arange = dbg->de_arange; given_arange != NULL;
26749d3bc91SRichard Lowe          given_arange = given_arange->ag_next) {
26849d3bc91SRichard Lowe 
26949d3bc91SRichard Lowe         /* Write relocation record for beginning of address range. */
270*07dc1947SRichard Lowe         res = dbg->de_reloc_name(dbg, DEBUG_ARANGES, arange_ptr - arange,       /* r_offset
271*07dc1947SRichard Lowe                                                                                  */
27249d3bc91SRichard Lowe                                  (long) given_arange->ag_symbol_index,
27349d3bc91SRichard Lowe                                  dwarf_drt_data_reloc, upointer_size);
27449d3bc91SRichard Lowe         if (res != DW_DLV_OK) {
27549d3bc91SRichard Lowe             {
27649d3bc91SRichard Lowe                 _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
27749d3bc91SRichard Lowe                 return (0);
27849d3bc91SRichard Lowe             }
27949d3bc91SRichard Lowe         }
28049d3bc91SRichard Lowe 
28149d3bc91SRichard Lowe         /* Copy beginning address of range. */
28249d3bc91SRichard Lowe         WRITE_UNALIGNED(dbg, (void *) arange_ptr,
28349d3bc91SRichard Lowe                         (const void *) &given_arange->ag_begin_address,
28449d3bc91SRichard Lowe                         sizeof(given_arange->ag_begin_address),
28549d3bc91SRichard Lowe                         upointer_size);
28649d3bc91SRichard Lowe         arange_ptr += upointer_size;
28749d3bc91SRichard Lowe 
28849d3bc91SRichard Lowe         if (dbg->de_reloc_pair &&
28949d3bc91SRichard Lowe             given_arange->ag_end_symbol_index != 0 &&
29049d3bc91SRichard Lowe             given_arange->ag_length == 0) {
29149d3bc91SRichard Lowe             /* symbolic reloc, need reloc for length What if we really
29249d3bc91SRichard Lowe                know the length? If so, should use the other part of
29349d3bc91SRichard Lowe                'if'. */
29449d3bc91SRichard Lowe             Dwarf_Unsigned val;
29549d3bc91SRichard Lowe 
29649d3bc91SRichard Lowe             res = dbg->de_reloc_pair(dbg, DEBUG_ARANGES, arange_ptr - arange,   /* r_offset
29749d3bc91SRichard Lowe                                                                                  */
29849d3bc91SRichard Lowe                                      given_arange->ag_symbol_index,
29949d3bc91SRichard Lowe                                      given_arange->ag_end_symbol_index,
30049d3bc91SRichard Lowe                                      dwarf_drt_first_of_length_pair,
30149d3bc91SRichard Lowe                                      upointer_size);
30249d3bc91SRichard Lowe             if (res != DW_DLV_OK) {
30349d3bc91SRichard Lowe                 {
30449d3bc91SRichard Lowe                     _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
30549d3bc91SRichard Lowe                     return (0);
30649d3bc91SRichard Lowe                 }
30749d3bc91SRichard Lowe             }
30849d3bc91SRichard Lowe 
30949d3bc91SRichard Lowe             /* arrange pre-calc so assem text can do .word end - begin
31049d3bc91SRichard Lowe                + val (gets val from stream) */
31149d3bc91SRichard Lowe             val = given_arange->ag_end_symbol_offset -
31249d3bc91SRichard Lowe                 given_arange->ag_begin_address;
31349d3bc91SRichard Lowe             WRITE_UNALIGNED(dbg, (void *) arange_ptr,
31449d3bc91SRichard Lowe                             (const void *) &val,
31549d3bc91SRichard Lowe                             sizeof(val), upointer_size);
31649d3bc91SRichard Lowe             arange_ptr += upointer_size;
31749d3bc91SRichard Lowe 
31849d3bc91SRichard Lowe         } else {
31949d3bc91SRichard Lowe             /* plain old length to copy, no relocation at all */
32049d3bc91SRichard Lowe             WRITE_UNALIGNED(dbg, (void *) arange_ptr,
32149d3bc91SRichard Lowe                             (const void *) &given_arange->ag_length,
32249d3bc91SRichard Lowe                             sizeof(given_arange->ag_length),
32349d3bc91SRichard Lowe                             upointer_size);
32449d3bc91SRichard Lowe             arange_ptr += upointer_size;
32549d3bc91SRichard Lowe         }
32649d3bc91SRichard Lowe     }
32749d3bc91SRichard Lowe 
32849d3bc91SRichard Lowe     WRITE_UNALIGNED(dbg, (void *) arange_ptr,
32949d3bc91SRichard Lowe                     (const void *) &big_zero,
33049d3bc91SRichard Lowe                     sizeof(big_zero), upointer_size);
33149d3bc91SRichard Lowe 
33249d3bc91SRichard Lowe     arange_ptr += upointer_size;
33349d3bc91SRichard Lowe     WRITE_UNALIGNED(dbg, (void *) arange_ptr,
33449d3bc91SRichard Lowe                     (const void *) &big_zero,
33549d3bc91SRichard Lowe                     sizeof(big_zero), upointer_size);
33649d3bc91SRichard Lowe     return (int) dbg->de_n_debug_sect;
33749d3bc91SRichard Lowe }
338