1/* 2 3 Copyright (C) 2000,2001,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#ifdef HAVE_ELFACCESS_H 43#include <elfaccess.h> 44#else 45/* Set r_info as defined by ELF generic ABI */ 46#define Set_REL32_info(r,s,t) ((r).r_info = ELF32_R_INFO(s,t)) 47#define Set_REL64_info(r,s,t) ((r).r_info = ELF64_R_INFO(s,t)) 48#endif 49#include "pro_incl.h" 50#include "pro_section.h" 51#include "pro_reloc.h" 52#include "pro_reloc_stream.h" 53 54/* 55 Return DW_DLV_ERROR on malloc error or reltarget_length error. 56 Return DW_DLV_OK otherwise 57 58 59 60*/ 61 /*ARGSUSED*/ int 62_dwarf_pro_reloc_name_stream64(Dwarf_P_Debug dbg, int base_sec_index, Dwarf_Unsigned offset, /* r_offset 63 of 64 reloc 65 */ 66 Dwarf_Unsigned symidx, 67 enum Dwarf_Rel_Type type, 68 int reltarget_length) 69{ 70#if HAVE_ELF64_GETEHDR 71 Elf64_Rel *elf64_reloc; 72 void *relrec_to_fill; 73 int res; 74 int rel_type; 75 76 res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index, 77 &relrec_to_fill); 78 if (res != DW_DLV_OK) 79 return res; 80 81 82 if (type == dwarf_drt_data_reloc) { 83 if (reltarget_length == dbg->de_offset_size) { 84 rel_type = dbg->de_offset_reloc; 85 } else if (reltarget_length == dbg->de_pointer_size) { 86 rel_type = dbg->de_ptr_reloc; 87 } else { 88 return DW_DLV_ERROR; 89 } 90 } else if (type == dwarf_drt_segment_rel) { 91 rel_type = dbg->de_exc_reloc; 92 } else { 93 /* We are in trouble: improper use of stream relocations. 94 Someone else will diagnose */ 95 rel_type = 0; 96 } 97 98 elf64_reloc = (Elf64_Rel *) relrec_to_fill; 99 elf64_reloc->r_offset = offset; 100 Set_REL64_info(*elf64_reloc, symidx, rel_type); 101 return DW_DLV_OK; 102#else /* !HAVE_ELF64_GETEHDR */ 103 return DW_DLV_ERROR; 104#endif /* #if HAVE_ELF64_GETEHDR */ 105} 106 107/* 108 Return DW_DLV_ERROR on malloc error or reltarget_length error. 109 Return DW_DLV_OK otherwise 110 a binary reloc: 32bit ABI 111*/ 112int 113_dwarf_pro_reloc_name_stream32(Dwarf_P_Debug dbg, int base_sec_index, Dwarf_Unsigned offset, /* r_offset 114 of 115 reloc 116 */ 117 Dwarf_Unsigned symidx, 118 enum Dwarf_Rel_Type type, 119 int reltarget_length) 120{ 121 Elf32_Rel *elf32_reloc; 122 void *relrec_to_fill; 123 int res; 124 int rel_type; 125 126 res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index, 127 &relrec_to_fill); 128 if (res != DW_DLV_OK) 129 return res; 130 if (type == dwarf_drt_data_reloc) { 131 if (reltarget_length == dbg->de_offset_size) { 132 rel_type = dbg->de_offset_reloc; 133 } else if (reltarget_length == dbg->de_pointer_size) { 134 rel_type = dbg->de_ptr_reloc; 135 } else { 136 return DW_DLV_ERROR; 137 } 138 } else if (type == dwarf_drt_segment_rel) { 139 rel_type = dbg->de_exc_reloc; 140 } else { 141 /* We are in trouble: improper use of stream relocations. 142 Someone else will diagnose */ 143 rel_type = 0; 144 } 145 146 elf32_reloc = (Elf32_Rel *) relrec_to_fill; 147 elf32_reloc->r_offset = (Elf32_Addr) offset; 148 Set_REL32_info(*elf32_reloc, (Dwarf_Word) symidx, rel_type); 149 return DW_DLV_OK; 150 151 /* get a slot, fill in the slot entry */ 152} 153 154 155 156/* 157 Return DW_DLV_OK. 158 Never can really do anything: lengths cannot 159 be represented as end-start in a stream. 160 161*/ 162 /*ARGSUSED*/ int 163_dwarf_pro_reloc_length_stream(Dwarf_P_Debug dbg, int base_sec_index, Dwarf_Unsigned offset, /* r_offset 164 of 165 reloc 166 */ 167 Dwarf_Unsigned start_symidx, 168 Dwarf_Unsigned end_symidx, 169 enum Dwarf_Rel_Type type, 170 int reltarget_length) 171{ 172 /* get a slot, fill in the slot entry */ 173 return DW_DLV_OK; 174} 175 176 177/* 178 Ensure each stream is a single buffer and 179 add that single buffer to the set of stream buffers. 180 181 By creating a new buffer and copying if necessary. 182 183 Free the input set of buffers if we consolidate. 184 Return -1 on error (malloc failure) 185 186 187 Return DW_DLV_OK on success. Any other return indicates 188 malloc failed. 189 190*/ 191int 192_dwarf_stream_relocs_to_disk(Dwarf_P_Debug dbg, 193 Dwarf_Signed * new_sec_count) 194{ 195 unsigned long total_size = 0; 196 Dwarf_Small *data; 197 int sec_index; 198 unsigned long i; 199 Dwarf_Error err; 200 Dwarf_Error *error = &err; 201 202 Dwarf_Signed sec_count = 0; 203 204 Dwarf_P_Per_Reloc_Sect p_reloc = &dbg->de_reloc_sect[0]; 205 206 for (i = 0; i < NUM_DEBUG_SECTIONS; ++i, ++p_reloc) { 207 unsigned long ct = p_reloc->pr_reloc_total_count; 208 unsigned len; 209 struct Dwarf_P_Relocation_Block_s *p_blk; 210 struct Dwarf_P_Relocation_Block_s *p_blk_last; 211 Dwarf_P_Per_Reloc_Sect prb; 212 213 if (ct == 0) { 214 continue; 215 } 216 prb = &dbg->de_reloc_sect[i]; 217 len = dbg->de_relocation_record_size; 218 ++sec_count; 219 220 total_size = ct * len; 221 sec_index = prb->pr_sect_num_of_reloc_sect; 222 if (sec_index == 0) { 223 /* call de_func or de_func_b, getting section number of 224 reloc sec */ 225 int rel_section_index; 226 Dwarf_Unsigned name_idx; 227 int int_name; 228 int err; 229 230 if (dbg->de_func_b) { 231 rel_section_index = 232 dbg->de_func_b(_dwarf_rel_section_names[i], 233 /* size */ 234 dbg->de_relocation_record_size, 235 /* type */ SHT_REL, 236 /* flags */ 0, 237 /* link to symtab, which we cannot 238 know */ 0, 239 /* info == link to sec rels apply to 240 */ 241 dbg->de_elf_sects[i], 242 &name_idx, &err); 243 } else { 244 rel_section_index = 245 dbg->de_func(_dwarf_rel_section_names[i], 246 /* size */ 247 dbg->de_relocation_record_size, 248 /* type */ SHT_REL, 249 /* flags */ 0, 250 /* link to symtab, which we cannot 251 know */ 0, 252 /* info == link to sec rels apply to */ 253 dbg->de_elf_sects[i], &int_name, &err); 254 name_idx = int_name; 255 } 256 if (rel_section_index == -1) { 257 { 258 _dwarf_p_error(dbg, error, DW_DLE_ELF_SECT_ERR); 259 return (DW_DLV_ERROR); 260 } 261 262 } 263 prb->pr_sect_num_of_reloc_sect = rel_section_index; 264 sec_index = rel_section_index; 265 } 266 GET_CHUNK(dbg, sec_index, data, total_size, &err); 267 p_blk = p_reloc->pr_first_block; 268 269 /* following loop executes at least once. Effects the 270 consolidation to a single block or, if already a single 271 block, simply copies to the output buffer. And frees the 272 input block. The new block is in the de_debug_sects list. */ 273 while (p_blk) { 274 275 unsigned long len = 276 p_blk->rb_where_to_add_next - p_blk->rb_data; 277 278 memcpy(data, p_blk->rb_data, len); 279 280 281 data += len; 282 283 p_blk_last = p_blk; 284 p_blk = p_blk->rb_next; 285 286 _dwarf_p_dealloc(dbg, (Dwarf_Small *) p_blk_last); 287 } 288 /* ASSERT: sum of len copied == total_size */ 289 290 /* 291 We have copied the input, now drop the pointers to it. For 292 debugging, leave the other data untouched. */ 293 p_reloc->pr_first_block = 0; 294 p_reloc->pr_last_block = 0; 295 } 296 297 *new_sec_count = sec_count; 298 return DW_DLV_OK; 299} 300