tools/elf4rom/libs/dwarf-20071209/libdwarf/pro_arange.c
changeset 34 92d87f2e53c2
equal deleted inserted replaced
33:1af5c1be89f8 34:92d87f2e53c2
       
     1 /*
       
     2 
       
     3   Copyright (C) 2000,2004 Silicon Graphics, Inc.  All Rights Reserved.
       
     4 
       
     5   This program is free software; you can redistribute it and/or modify it
       
     6   under the terms of version 2.1 of the GNU Lesser General Public License 
       
     7   as published by the Free Software Foundation.
       
     8 
       
     9   This program is distributed in the hope that it would be useful, but
       
    10   WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
       
    12 
       
    13   Further, this software is distributed without any warranty that it is
       
    14   free of the rightful claim of any third person regarding infringement 
       
    15   or the like.  Any license provided herein, whether implied or 
       
    16   otherwise, applies only to this software file.  Patent licenses, if
       
    17   any, provided herein do not apply to combinations of this program with 
       
    18   other software, or any other product whatsoever.  
       
    19 
       
    20   You should have received a copy of the GNU Lesser General Public 
       
    21   License along with this program; if not, write the Free Software 
       
    22   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
       
    23   USA.
       
    24 
       
    25   Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
       
    26   Mountain View, CA 94043, or:
       
    27 
       
    28   http://www.sgi.com
       
    29 
       
    30   For further information regarding this notice, see:
       
    31 
       
    32   http://oss.sgi.com/projects/GenInfo/NoticeExplan
       
    33 
       
    34 */
       
    35 
       
    36 
       
    37 
       
    38 #include "config.h"
       
    39 #include "libdwarfdefs.h"
       
    40 #include <stdio.h>
       
    41 #include <string.h>
       
    42 #ifdef HAVE_ELFACCESS_H
       
    43 #include <elfaccess.h>
       
    44 #endif
       
    45 #include "pro_incl.h"
       
    46 #include "pro_arange.h"
       
    47 #include "pro_section.h"
       
    48 #include "pro_reloc.h"
       
    49 
       
    50 
       
    51 
       
    52 /*
       
    53     This function adds another address range 
       
    54     to the list of address ranges for the
       
    55     given Dwarf_P_Debug.  It returns 0 on error,
       
    56     and 1 otherwise.
       
    57 */
       
    58 Dwarf_Unsigned
       
    59 dwarf_add_arange(Dwarf_P_Debug dbg,
       
    60 		 Dwarf_Addr begin_address,
       
    61 		 Dwarf_Unsigned length,
       
    62 		 Dwarf_Signed symbol_index, Dwarf_Error * error)
       
    63 {
       
    64     return dwarf_add_arange_b(dbg, begin_address, length, symbol_index,
       
    65 			      /* end_symbol_index */ 0,
       
    66 			      /* offset_from_end_sym */ 0,
       
    67 			      error);
       
    68 }
       
    69 
       
    70 /*
       
    71     This function adds another address range 
       
    72     to the list of address ranges for the
       
    73     given Dwarf_P_Debug.  It returns 0 on error,
       
    74     and 1 otherwise.
       
    75 */
       
    76 Dwarf_Unsigned
       
    77 dwarf_add_arange_b(Dwarf_P_Debug dbg,
       
    78 		   Dwarf_Addr begin_address,
       
    79 		   Dwarf_Unsigned length,
       
    80 		   Dwarf_Unsigned symbol_index,
       
    81 		   Dwarf_Unsigned end_symbol_index,
       
    82 		   Dwarf_Addr offset_from_end_sym, Dwarf_Error * error)
       
    83 {
       
    84     Dwarf_P_Arange arange;
       
    85 
       
    86     if (dbg == NULL) {
       
    87 	_dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
       
    88 	return (0);
       
    89     }
       
    90 
       
    91     arange = (Dwarf_P_Arange)
       
    92 	_dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Arange_s));
       
    93     if (arange == NULL) {
       
    94 	_dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
       
    95 	return (0);
       
    96     }
       
    97 
       
    98     arange->ag_begin_address = begin_address;
       
    99     arange->ag_length = length;
       
   100     arange->ag_symbol_index = symbol_index;
       
   101     arange->ag_end_symbol_index = end_symbol_index;
       
   102     arange->ag_end_symbol_offset = offset_from_end_sym;
       
   103 
       
   104     if (dbg->de_arange == NULL)
       
   105 	dbg->de_arange = dbg->de_last_arange = arange;
       
   106     else {
       
   107 	dbg->de_last_arange->ag_next = arange;
       
   108 	dbg->de_last_arange = arange;
       
   109     }
       
   110     dbg->de_arange_count++;
       
   111 
       
   112     return (1);
       
   113 }
       
   114 
       
   115 
       
   116 int
       
   117 _dwarf_transform_arange_to_disk(Dwarf_P_Debug dbg, Dwarf_Error * error)
       
   118 {
       
   119     /* Total num of bytes in .debug_aranges section. */
       
   120     Dwarf_Unsigned arange_num_bytes;
       
   121 
       
   122     /* 
       
   123        Adjustment to align the start of the actual address ranges on a
       
   124        boundary aligned with twice the address size. */
       
   125     Dwarf_Small remainder;
       
   126 
       
   127     /* Total number of bytes excluding the length field. */
       
   128     Dwarf_Unsigned adjusted_length;
       
   129 
       
   130     /* Points to first byte of .debug_aranges buffer. */
       
   131     Dwarf_Small *arange;
       
   132 
       
   133     /* Fills in the .debug_aranges buffer. */
       
   134     Dwarf_Small *arange_ptr;
       
   135 
       
   136     /* Scans the list of address ranges provided by user. */
       
   137     Dwarf_P_Arange given_arange;
       
   138 
       
   139     /* Used to fill in 0. */
       
   140     const Dwarf_Signed big_zero = 0;
       
   141 
       
   142     int extension_word_size = dbg->de_64bit_extension ? 4 : 0;
       
   143     int uword_size = dbg->de_offset_size;
       
   144     int upointer_size = dbg->de_pointer_size;
       
   145     int res;
       
   146 
       
   147 
       
   148     /* ***** BEGIN CODE ***** */
       
   149 
       
   150     /* Size of the .debug_aranges section header. */
       
   151     arange_num_bytes = extension_word_size + uword_size +	/* Size 
       
   152 								   of
       
   153 								   length 
       
   154 								   field. 
       
   155 								 */
       
   156 	sizeof(Dwarf_Half) +	/* Size of version field. */
       
   157 	uword_size +		/* Size of .debug_info offset. */
       
   158 	sizeof(Dwarf_Small) +	/* Size of address size field. */
       
   159 	sizeof(Dwarf_Small);	/* Size of segment size field. */
       
   160 
       
   161     /* 
       
   162        Adjust the size so that the set of aranges begins on a boundary
       
   163        that aligned with twice the address size.  This is a Libdwarf
       
   164        requirement. */
       
   165     remainder = arange_num_bytes % (2 * upointer_size);
       
   166     if (remainder != 0)
       
   167 	arange_num_bytes += (2 * upointer_size) - remainder;
       
   168 
       
   169 
       
   170     /* Add the bytes for the actual address ranges. */
       
   171     arange_num_bytes += upointer_size * 2 * (dbg->de_arange_count + 1);
       
   172 
       
   173     GET_CHUNK(dbg, dbg->de_elf_sects[DEBUG_ARANGES],
       
   174 	      arange, (unsigned long) arange_num_bytes, error);
       
   175     arange_ptr = arange;
       
   176     if (arange == NULL) {
       
   177 	_dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
       
   178 	return (0);
       
   179     }
       
   180     if (extension_word_size) {
       
   181 	Dwarf_Word x = DISTINGUISHED_VALUE;
       
   182 
       
   183 	WRITE_UNALIGNED(dbg, (void *) arange_ptr,
       
   184 			(const void *) &x,
       
   185 			sizeof(x), extension_word_size);
       
   186 	arange_ptr += extension_word_size;
       
   187     }
       
   188 
       
   189     /* Write the total length of .debug_aranges section. */
       
   190     adjusted_length = arange_num_bytes - uword_size
       
   191 	- extension_word_size;
       
   192     {
       
   193 	Dwarf_Unsigned du = adjusted_length;
       
   194 
       
   195 	WRITE_UNALIGNED(dbg, (void *) arange_ptr,
       
   196 			(const void *) &du, sizeof(du), uword_size);
       
   197 	arange_ptr += uword_size;
       
   198     }
       
   199 
       
   200     /* Write the version as 2 bytes. */
       
   201     {
       
   202 	Dwarf_Half verstamp = CURRENT_VERSION_STAMP;
       
   203 
       
   204 	WRITE_UNALIGNED(dbg, (void *) arange_ptr,
       
   205 			(const void *) &verstamp,
       
   206 			sizeof(verstamp), sizeof(Dwarf_Half));
       
   207 	arange_ptr += sizeof(Dwarf_Half);
       
   208     }
       
   209 
       
   210 
       
   211     /* Write the .debug_info offset.  This is always 0. */
       
   212     WRITE_UNALIGNED(dbg, (void *) arange_ptr,
       
   213 		    (const void *) &big_zero,
       
   214 		    sizeof(big_zero), uword_size);
       
   215     arange_ptr += uword_size;
       
   216 
       
   217     {
       
   218 	unsigned long count = dbg->de_arange_count + 1;
       
   219 	int res;
       
   220 
       
   221 	if (dbg->de_reloc_pair) {
       
   222 	    count = (3 * dbg->de_arange_count) + 1;
       
   223 	}
       
   224 	/* the following is a small optimization: not needed for
       
   225 	   correctness */
       
   226 	res = _dwarf_pro_pre_alloc_n_reloc_slots(dbg,
       
   227 						 DEBUG_ARANGES, count);
       
   228 	if (res != DW_DLV_OK) {
       
   229 	    {
       
   230 		_dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
       
   231 		return (0);
       
   232 	    }
       
   233 	}
       
   234     }
       
   235 
       
   236     /* reloc for .debug_info */
       
   237     res = dbg->de_reloc_name(dbg,
       
   238 			     DEBUG_ARANGES,
       
   239 			     extension_word_size +
       
   240 			     uword_size + sizeof(Dwarf_Half),
       
   241 			     dbg->de_sect_name_idx[DEBUG_INFO],
       
   242 			     dwarf_drt_data_reloc, uword_size);
       
   243 
       
   244     /* Write the size of addresses. */
       
   245     *arange_ptr = dbg->de_pointer_size;
       
   246     arange_ptr++;
       
   247 
       
   248     /* 
       
   249        Write the size of segment addresses. This is zero for MIPS
       
   250        architectures. */
       
   251     *arange_ptr = 0;
       
   252     arange_ptr++;
       
   253 
       
   254     /* 
       
   255        Skip over the padding to align the start of the actual address
       
   256        ranges to twice the address size. */
       
   257     if (remainder != 0)
       
   258 	arange_ptr += (2 * upointer_size) - remainder;
       
   259 
       
   260 
       
   261 
       
   262 
       
   263 
       
   264     /* The arange address, length are pointer-size fields of the target 
       
   265        machine. */
       
   266     for (given_arange = dbg->de_arange; given_arange != NULL;
       
   267 	 given_arange = given_arange->ag_next) {
       
   268 
       
   269 	/* Write relocation record for beginning of address range. */
       
   270 	res = dbg->de_reloc_name(dbg, DEBUG_ARANGES, arange_ptr - arange,	/* r_offset 
       
   271 										 */
       
   272 				 (long) given_arange->ag_symbol_index,
       
   273 				 dwarf_drt_data_reloc, upointer_size);
       
   274 	if (res != DW_DLV_OK) {
       
   275 	    {
       
   276 		_dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
       
   277 		return (0);
       
   278 	    }
       
   279 	}
       
   280 
       
   281 	/* Copy beginning address of range. */
       
   282 	WRITE_UNALIGNED(dbg, (void *) arange_ptr,
       
   283 			(const void *) &given_arange->ag_begin_address,
       
   284 			sizeof(given_arange->ag_begin_address),
       
   285 			upointer_size);
       
   286 	arange_ptr += upointer_size;
       
   287 
       
   288 	if (dbg->de_reloc_pair &&
       
   289 	    given_arange->ag_end_symbol_index != 0 &&
       
   290 	    given_arange->ag_length == 0) {
       
   291 	    /* symbolic reloc, need reloc for length What if we really
       
   292 	       know the length? If so, should use the other part of
       
   293 	       'if'. */
       
   294 	    Dwarf_Unsigned val;
       
   295 
       
   296 	    res = dbg->de_reloc_pair(dbg, DEBUG_ARANGES, arange_ptr - arange,	/* r_offset 
       
   297 										 */
       
   298 				     given_arange->ag_symbol_index,
       
   299 				     given_arange->ag_end_symbol_index,
       
   300 				     dwarf_drt_first_of_length_pair,
       
   301 				     upointer_size);
       
   302 	    if (res != DW_DLV_OK) {
       
   303 		{
       
   304 		    _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
       
   305 		    return (0);
       
   306 		}
       
   307 	    }
       
   308 
       
   309 	    /* arrange pre-calc so assem text can do .word end - begin
       
   310 	       + val (gets val from stream) */
       
   311 	    val = given_arange->ag_end_symbol_offset -
       
   312 		given_arange->ag_begin_address;
       
   313 	    WRITE_UNALIGNED(dbg, (void *) arange_ptr,
       
   314 			    (const void *) &val,
       
   315 			    sizeof(val), upointer_size);
       
   316 	    arange_ptr += upointer_size;
       
   317 
       
   318 	} else {
       
   319 	    /* plain old length to copy, no relocation at all */
       
   320 	    WRITE_UNALIGNED(dbg, (void *) arange_ptr,
       
   321 			    (const void *) &given_arange->ag_length,
       
   322 			    sizeof(given_arange->ag_length),
       
   323 			    upointer_size);
       
   324 	    arange_ptr += upointer_size;
       
   325 	}
       
   326     }
       
   327 
       
   328     WRITE_UNALIGNED(dbg, (void *) arange_ptr,
       
   329 		    (const void *) &big_zero,
       
   330 		    sizeof(big_zero), upointer_size);
       
   331 
       
   332     arange_ptr += upointer_size;
       
   333     WRITE_UNALIGNED(dbg, (void *) arange_ptr,
       
   334 		    (const void *) &big_zero,
       
   335 		    sizeof(big_zero), upointer_size);
       
   336     return (int) dbg->de_n_debug_sect;
       
   337 }