tools/elf4rom/libs/dwarf-20071209/libdwarf/pro_reloc.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 /*#include <elfaccess.h> */
       
    43 #include "pro_incl.h"
       
    44 
       
    45 
       
    46 /*Do initial alloc of newslots slots.
       
    47   Fails only if malloc fails.
       
    48 
       
    49   Supposed to be called before any relocs allocated.
       
    50   Ignored if after any allocated.
       
    51 
       
    52   Part of an optimization, so that for a known 'newslots' 
       
    53   relocations count we can preallocate the right size block.
       
    54   Called from just 2 places.
       
    55 
       
    56   returns DW_DLV_OK or  DW_DLV_ERROR
       
    57 */
       
    58 int
       
    59 _dwarf_pro_pre_alloc_n_reloc_slots(Dwarf_P_Debug dbg,
       
    60 				   int rel_sec_index,
       
    61 				   Dwarf_Unsigned newslots)
       
    62 {
       
    63     unsigned long len;
       
    64     struct Dwarf_P_Relocation_Block_s *data;
       
    65     Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[rel_sec_index];
       
    66     unsigned long slots_in_blk = (unsigned long) newslots;
       
    67     unsigned long rel_rec_size = dbg->de_relocation_record_size;
       
    68 
       
    69     if (prel->pr_first_block)
       
    70 	return DW_DLV_OK;	/* do nothing */
       
    71 
       
    72     len = sizeof(struct Dwarf_P_Relocation_Block_s) +
       
    73 	slots_in_blk * rel_rec_size;
       
    74 
       
    75 
       
    76     data = (struct Dwarf_P_Relocation_Block_s *)
       
    77 	_dwarf_p_get_alloc(dbg, len);
       
    78     if (!data) {
       
    79 	return DW_DLV_ERROR;
       
    80     }
       
    81     data->rb_slots_in_block = slots_in_blk;	/* could use default
       
    82 						   here, as fallback in 
       
    83 						   case our origininal
       
    84 						   estimate wrong. When 
       
    85 						   we call this we
       
    86 						   presumably know what 
       
    87 						   we are doing, so
       
    88 						   keep this count for
       
    89 						   now */
       
    90     data->rb_next_slot_to_use = 0;
       
    91     data->rb_where_to_add_next =
       
    92 	((char *) data) + sizeof(struct Dwarf_P_Relocation_Block_s);
       
    93     data->rb_data = data->rb_where_to_add_next;
       
    94 
       
    95     prel->pr_first_block = data;
       
    96     prel->pr_last_block = data;
       
    97     prel->pr_block_count = 1;
       
    98 
       
    99 
       
   100     return DW_DLV_OK;
       
   101 }
       
   102 
       
   103 
       
   104 /*Do alloc of slots.
       
   105   Fails only if malloc fails.
       
   106 
       
   107   Only allocator used.
       
   108 
       
   109   returns DW_DLV_OK or  DW_DLV_ERROR
       
   110 */
       
   111 int
       
   112 _dwarf_pro_alloc_reloc_slots(Dwarf_P_Debug dbg, int rel_sec_index)
       
   113 {
       
   114     unsigned long len;
       
   115     struct Dwarf_P_Relocation_Block_s *data;
       
   116     Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[rel_sec_index];
       
   117     unsigned long slots_in_blk = prel->pr_slots_per_block_to_alloc;
       
   118     unsigned long rel_rec_size = dbg->de_relocation_record_size;
       
   119 
       
   120     len = sizeof(struct Dwarf_P_Relocation_Block_s) +
       
   121 	slots_in_blk * rel_rec_size;
       
   122 
       
   123     data = (struct Dwarf_P_Relocation_Block_s *)
       
   124 	_dwarf_p_get_alloc(dbg, len);
       
   125     if (!data) {
       
   126 	return DW_DLV_ERROR;
       
   127     }
       
   128 
       
   129     if (prel->pr_first_block) {
       
   130 	prel->pr_last_block->rb_next = data;
       
   131 	prel->pr_last_block = data;
       
   132 	prel->pr_block_count += 1;
       
   133 
       
   134     } else {
       
   135 
       
   136 	prel->pr_first_block = data;
       
   137 	prel->pr_last_block = data;
       
   138 	prel->pr_block_count = 1;
       
   139     }
       
   140 
       
   141     data->rb_slots_in_block = slots_in_blk;
       
   142     data->rb_next_slot_to_use = 0;
       
   143     data->rb_where_to_add_next =
       
   144 	((char *) data) + sizeof(struct Dwarf_P_Relocation_Block_s);
       
   145     data->rb_data = data->rb_where_to_add_next;
       
   146 
       
   147     return DW_DLV_OK;
       
   148 
       
   149 }
       
   150 
       
   151 /*
       
   152 	Reserve a slot. return DW_DLV_OK if succeeds.
       
   153 
       
   154 	Return DW_DLV_ERROR if fails (malloc error).
       
   155 
       
   156 	Use the relrec_to_fill to pass back a pointer to
       
   157 	a slot space to use.
       
   158 */
       
   159 int
       
   160 _dwarf_pro_reloc_get_a_slot(Dwarf_P_Debug dbg,
       
   161 			    int base_sec_index, void **relrec_to_fill)
       
   162 {
       
   163     struct Dwarf_P_Relocation_Block_s *data;
       
   164     Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[base_sec_index];
       
   165     unsigned long rel_rec_size = dbg->de_relocation_record_size;
       
   166 
       
   167     char *ret_addr;
       
   168 
       
   169     data = prel->pr_last_block;
       
   170     if ((data == 0) ||
       
   171 	(data->rb_next_slot_to_use >= data->rb_slots_in_block)) {
       
   172 	int res;
       
   173 
       
   174 	res = _dwarf_pro_alloc_reloc_slots(dbg, base_sec_index);
       
   175 	if (res != DW_DLV_OK) {
       
   176 	    return res;
       
   177 	}
       
   178     }
       
   179 
       
   180     data = prel->pr_last_block;
       
   181     /* now we have an empty slot */
       
   182     ret_addr = data->rb_where_to_add_next;
       
   183 
       
   184     data->rb_where_to_add_next += rel_rec_size;
       
   185     data->rb_next_slot_to_use += 1;
       
   186 
       
   187     prel->pr_reloc_total_count += 1;
       
   188 
       
   189     *relrec_to_fill = (void *) ret_addr;
       
   190 
       
   191     return DW_DLV_OK;
       
   192 
       
   193 }
       
   194 
       
   195 /*
       
   196    On success  returns count of
       
   197    .rel.* sections that are symbolic 
       
   198    thru count_of_relocation_sections.
       
   199 
       
   200    On success, returns DW_DLV_OK.
       
   201 
       
   202    If this is not a 'symbolic' run, returns
       
   203     DW_DLV_NO_ENTRY.
       
   204 
       
   205    No errors are possible.
       
   206 
       
   207 
       
   208 
       
   209 
       
   210 */
       
   211 
       
   212  /*ARGSUSED*/ int
       
   213 dwarf_get_relocation_info_count(Dwarf_P_Debug dbg,
       
   214 				Dwarf_Unsigned *
       
   215 				count_of_relocation_sections,
       
   216 				int *drd_buffer_version,
       
   217 				Dwarf_Error * error)
       
   218 {
       
   219     if (dbg->de_flags & DW_DLC_SYMBOLIC_RELOCATIONS) {
       
   220 	int i;
       
   221 	unsigned int count = 0;
       
   222 
       
   223 	for (i = 0; i < NUM_DEBUG_SECTIONS; ++i) {
       
   224 	    if (dbg->de_reloc_sect[i].pr_reloc_total_count > 0) {
       
   225 		++count;
       
   226 	    }
       
   227 	}
       
   228 	*count_of_relocation_sections = (Dwarf_Unsigned) count;
       
   229 	*drd_buffer_version = DWARF_DRD_BUFFER_VERSION;
       
   230 	return DW_DLV_OK;
       
   231     }
       
   232     return DW_DLV_NO_ENTRY;
       
   233 }
       
   234 
       
   235 int
       
   236 dwarf_get_relocation_info(Dwarf_P_Debug dbg,
       
   237 			  Dwarf_Signed * elf_section_index,
       
   238 			  Dwarf_Signed * elf_section_index_link,
       
   239 			  Dwarf_Unsigned * relocation_buffer_count,
       
   240 			  Dwarf_Relocation_Data * reldata_buffer,
       
   241 			  Dwarf_Error * error)
       
   242 {
       
   243     int next = dbg->de_reloc_next_to_return;
       
   244 
       
   245     if (dbg->de_flags & DW_DLC_SYMBOLIC_RELOCATIONS) {
       
   246 	int i;
       
   247 
       
   248 	for (i = next; i < NUM_DEBUG_SECTIONS; ++i) {
       
   249 	    Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[i];
       
   250 
       
   251 	    if (prel->pr_reloc_total_count > 0) {
       
   252 		dbg->de_reloc_next_to_return = i + 1;
       
   253 
       
   254 
       
   255 		/* ASSERT: prel->.pr_block_count == 1 */
       
   256 
       
   257 		*elf_section_index = prel->pr_sect_num_of_reloc_sect;
       
   258 		*elf_section_index_link = dbg->de_elf_sects[i];
       
   259 		*relocation_buffer_count = prel->pr_reloc_total_count;
       
   260 		*reldata_buffer = (Dwarf_Relocation_Data)
       
   261 		    (prel->pr_first_block->rb_data);
       
   262 		return DW_DLV_OK;
       
   263 	    }
       
   264 	}
       
   265 	DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, DW_DLV_ERROR);
       
   266     }
       
   267     return DW_DLV_NO_ENTRY;
       
   268 }