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., 59 Temple Place - Suite 330, Boston MA 02111-1307, 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 53int 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*/ 87int 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*/ 136static 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*/ 170int 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} 300