tools/elf4rom/libs/dwarf-20071209/libdwarf/pro_reloc_symbolic.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 #include "pro_section.h"
       
    45 #include "pro_reloc.h"
       
    46 #include "pro_reloc_symbolic.h"
       
    47 
       
    48 /*
       
    49 	Return DW_DLV_ERROR on malloc error.
       
    50 	Return DW_DLV_OK otherwise
       
    51 */
       
    52 
       
    53 int
       
    54 _dwarf_pro_reloc_name_symbolic(Dwarf_P_Debug dbg, int base_sec_index, Dwarf_Unsigned offset,	/* r_offset 
       
    55 												   of 
       
    56 												   reloc 
       
    57 												 */
       
    58 			       Dwarf_Unsigned symidx,
       
    59 			       enum Dwarf_Rel_Type type,
       
    60 			       int reltarget_length)
       
    61 {
       
    62     /* get a slot, fill in the slot entry */
       
    63     void *relrec_to_fill;
       
    64     int res;
       
    65     struct Dwarf_Relocation_Data_s *slotp;
       
    66 
       
    67     res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index,
       
    68 				      &relrec_to_fill);
       
    69     if (res != DW_DLV_OK)
       
    70 	return res;
       
    71 
       
    72     slotp = (struct Dwarf_Relocation_Data_s *) relrec_to_fill;
       
    73     slotp->drd_type = type;
       
    74     slotp->drd_length = reltarget_length;
       
    75     slotp->drd_offset = offset;
       
    76     slotp->drd_symbol_index = symidx;
       
    77     return DW_DLV_OK;
       
    78 
       
    79 }
       
    80 
       
    81 
       
    82 
       
    83 /*
       
    84 	Return DW_DLV_ERROR on malloc error.
       
    85 	Return DW_DLV_OK otherwise
       
    86 */
       
    87 int
       
    88 _dwarf_pro_reloc_length_symbolic(Dwarf_P_Debug dbg, int base_sec_index, Dwarf_Unsigned offset,	/* r_offset 
       
    89 												   of 
       
    90 												   reloc 
       
    91 												 */
       
    92 				 Dwarf_Unsigned start_symidx,
       
    93 				 Dwarf_Unsigned end_symidx,
       
    94 				 enum Dwarf_Rel_Type type,
       
    95 				 int reltarget_length)
       
    96 {
       
    97     /* get a slot, fill in the slot entry */
       
    98     void *relrec_to_fill;
       
    99     int res;
       
   100     struct Dwarf_Relocation_Data_s *slotp1;
       
   101     struct Dwarf_Relocation_Data_s *slotp2;
       
   102 
       
   103 
       
   104 
       
   105     res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index,
       
   106 				      &relrec_to_fill);
       
   107     if (res != DW_DLV_OK)
       
   108 	return res;
       
   109     slotp1 = (struct Dwarf_Relocation_Data_s *) relrec_to_fill;
       
   110     res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index,
       
   111 				      &relrec_to_fill);
       
   112     if (res != DW_DLV_OK)
       
   113 	return res;
       
   114     slotp2 = (struct Dwarf_Relocation_Data_s *) relrec_to_fill;
       
   115 
       
   116     /* ASSERT: type == dwarf_drt_first_of_length_type_pair */
       
   117     slotp1->drd_type = type;
       
   118     slotp1->drd_length = reltarget_length;
       
   119     slotp1->drd_offset = offset;
       
   120     slotp1->drd_symbol_index = start_symidx;
       
   121 
       
   122     slotp2->drd_type = dwarf_drt_second_of_length_pair;
       
   123     slotp2->drd_length = reltarget_length;
       
   124     slotp2->drd_offset = offset;
       
   125     slotp2->drd_symbol_index = end_symidx;
       
   126 
       
   127     return DW_DLV_OK;
       
   128 }
       
   129 
       
   130 /*
       
   131    Reset whatever fields of Dwarf_P_Per_Reloc_Sect_s
       
   132    we must to allow adding a fresh new single
       
   133    block easily (block consolidation use only).
       
   134 
       
   135 */
       
   136 static void
       
   137 _dwarf_reset_reloc_sect_info(struct Dwarf_P_Per_Reloc_Sect_s *pblk,
       
   138 			     unsigned long ct)
       
   139 {
       
   140 
       
   141 
       
   142     /* do not zero pr_sect_num_of_reloc_sect */
       
   143 
       
   144     pblk->pr_reloc_total_count = 0;
       
   145     pblk->pr_first_block = 0;
       
   146     pblk->pr_last_block = 0;
       
   147     pblk->pr_block_count = 0;
       
   148     pblk->pr_slots_per_block_to_alloc = ct;
       
   149 }
       
   150 
       
   151 /*
       
   152         Ensure each stream is a single buffer and
       
   153         add that single buffer to the set of stream buffers.
       
   154 
       
   155 	By creating a new buffer and copying if necessary.
       
   156 	(If > 1 block, reduce to 1 block)
       
   157 
       
   158         Free the input set of buffers if we consolidate.
       
   159 
       
   160 	We pass back *new_sec_count as zero because we
       
   161         are not creating normal sections for a .o, but
       
   162 	symbolic relocations, separately counted.
       
   163 
       
   164         Return -1 on error (malloc failure)
       
   165 
       
   166 
       
   167         Return DW_DLV_OK on success. Any other return indicates 
       
   168 	malloc failed.
       
   169 */
       
   170 int
       
   171 _dwarf_symbolic_relocs_to_disk(Dwarf_P_Debug dbg,
       
   172 			       Dwarf_Signed * new_sec_count)
       
   173 {
       
   174     /* unsigned long total_size =0; */
       
   175     Dwarf_Small *data;
       
   176     int sec_index;
       
   177     int res;
       
   178     unsigned long i;
       
   179     Dwarf_Error error;
       
   180 
       
   181     Dwarf_Signed sec_count = 0;
       
   182 
       
   183     Dwarf_P_Per_Reloc_Sect p_reloc = &dbg->de_reloc_sect[0];
       
   184 
       
   185     for (i = 0; i < NUM_DEBUG_SECTIONS; ++i, ++p_reloc) {
       
   186 
       
   187 	unsigned long ct = p_reloc->pr_reloc_total_count;
       
   188 	struct Dwarf_P_Relocation_Block_s *p_blk;
       
   189 	struct Dwarf_P_Relocation_Block_s *p_blk_last;
       
   190 
       
   191 	/* int len */
       
   192 	int err;
       
   193 
       
   194 
       
   195 	if (ct == 0) {
       
   196 	    continue;
       
   197 	}
       
   198 
       
   199 	/* len = dbg->de_relocation_record_size; */
       
   200 	++sec_count;
       
   201 
       
   202 	/* total_size = ct *len; */
       
   203 	sec_index = p_reloc->pr_sect_num_of_reloc_sect;
       
   204 	if (sec_index == 0) {
       
   205 	    /* call de_func or de_func_b, getting section number of
       
   206 	       reloc sec */
       
   207 	    int rel_section_index;
       
   208 	    int int_name;
       
   209 	    Dwarf_Unsigned name_idx;
       
   210 
       
   211 	    /* 
       
   212 	       This is a bit of a fake, as we do not really have true
       
   213 	       elf sections at all. Just the data such might contain.
       
   214 	       But this lets the caller eventually link things
       
   215 	       together: without this call we would not know what rel
       
   216 	       data goes with what section when we are asked for the
       
   217 	       real arrays. */
       
   218 
       
   219 	    if (dbg->de_func_b) {
       
   220 		rel_section_index =
       
   221 		    dbg->de_func_b(_dwarf_rel_section_names[i],
       
   222 				   dbg->de_relocation_record_size,
       
   223 				   /* type */ SHT_REL,
       
   224 				   /* flags */ 0,
       
   225 				   /* link to symtab, which we cannot
       
   226 				      know */ SHN_UNDEF,
       
   227 				   /* sec rels apply to */
       
   228 				   dbg->de_elf_sects[i],
       
   229 				   &name_idx, &err);
       
   230 	    } else {
       
   231 		rel_section_index =
       
   232 		    dbg->de_func(_dwarf_rel_section_names[i],
       
   233 				 dbg->de_relocation_record_size,
       
   234 				 /* type */ SHT_REL,
       
   235 				 /* flags */ 0,
       
   236 				 /* link to symtab, which we cannot
       
   237 				    know */ SHN_UNDEF,
       
   238 				 /* sec rels apply to, in elf, sh_info */
       
   239 				 dbg->de_elf_sects[i], &int_name, &err);
       
   240 		name_idx = int_name;
       
   241 	    }
       
   242 	    if (rel_section_index == -1) {
       
   243 		{
       
   244 		    _dwarf_p_error(dbg, &error, DW_DLE_ELF_SECT_ERR);
       
   245 		    return (DW_DLV_ERROR);
       
   246 		}
       
   247 	    }
       
   248 	    p_reloc->pr_sect_num_of_reloc_sect = rel_section_index;
       
   249 	    sec_index = rel_section_index;
       
   250 	}
       
   251 
       
   252 	p_blk = p_reloc->pr_first_block;
       
   253 
       
   254 	if (p_reloc->pr_block_count > 1) {
       
   255 	    struct Dwarf_P_Relocation_Block_s *new_blk;
       
   256 
       
   257 	    /* HACK , not normal interfaces, trashing p_reloc current
       
   258 	       contents! */
       
   259 	    _dwarf_reset_reloc_sect_info(p_reloc, ct);
       
   260 
       
   261 	    /* Creating new single block for all 'ct' entries */
       
   262 	    res = _dwarf_pro_pre_alloc_n_reloc_slots(dbg, (int) i, ct);
       
   263 
       
   264 
       
   265 	    if (res != DW_DLV_OK) {
       
   266 		return res;
       
   267 	    }
       
   268 	    new_blk = p_reloc->pr_first_block;
       
   269 
       
   270 	    data = (Dwarf_Small *) new_blk->rb_data;
       
   271 
       
   272 	    /* The following loop does the consolidation to a single
       
   273 	       block and frees the input block(s). */
       
   274 	    do {
       
   275 
       
   276 		unsigned long len =
       
   277 		    p_blk->rb_where_to_add_next - p_blk->rb_data;
       
   278 
       
   279 		memcpy(data, p_blk->rb_data, len);
       
   280 		data += len;
       
   281 
       
   282 		p_blk_last = p_blk;
       
   283 		p_blk = p_blk->rb_next;
       
   284 
       
   285 		_dwarf_p_dealloc(dbg, (Dwarf_Small *) p_blk_last);
       
   286 	    } while (p_blk);
       
   287 	    /* ASSERT: sum of len copied == total_size */
       
   288 	    new_blk->rb_next_slot_to_use = ct;
       
   289 	    new_blk->rb_where_to_add_next = (char *) data;
       
   290 	    p_reloc->pr_reloc_total_count = ct;
       
   291 
       
   292 	    /* have now created a single block, but no change in slots
       
   293 	       used (pr_reloc_total_count) */
       
   294 	}
       
   295     }
       
   296 
       
   297     *new_sec_count = 0;
       
   298     return DW_DLV_OK;
       
   299 }