1 /* 2 3 Copyright (C) 2000 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., 1600 Amphitheatre Pky, 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. 85 When 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 } 269