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