1 /* 2 3 Copyright (C) 2000,2001,2004 Silicon Graphics, Inc. All Rights Reserved. 4 Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved. 5 Portions Copyright 2008-2010 David Anderson, Inc. All rights reserved. 6 7 This program is free software; you can redistribute it and/or modify it 8 under the terms of version 2.1 of the GNU Lesser General Public License 9 as published by the Free Software Foundation. 10 11 This program is distributed in the hope that it would be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 14 15 Further, this software is distributed without any warranty that it is 16 free of the rightful claim of any third person regarding infringement 17 or the like. Any license provided herein, whether implied or 18 otherwise, applies only to this software file. Patent licenses, if 19 any, provided herein do not apply to combinations of this program with 20 other software, or any other product whatsoever. 21 22 You should have received a copy of the GNU Lesser General Public 23 License along with this program; if not, write the Free Software 24 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, 25 USA. 26 27 Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, 28 Mountain View, CA 94043, or: 29 30 http://www.sgi.com 31 32 For further information regarding this notice, see: 33 34 http://oss.sgi.com/projects/GenInfo/NoticeExplan 35 36 */ 37 38 39 40 #include "config.h" 41 #include "libdwarfdefs.h" 42 #include <stdio.h> 43 #include <string.h> 44 #ifdef HAVE_ELFACCESS_H 45 #include <elfaccess.h> 46 #else 47 /* Set r_info as defined by ELF generic ABI */ 48 #define Set_REL32_info(r,s,t) ((r).r_info = ELF32_R_INFO(s,t)) 49 #define Set_REL64_info(r,s,t) ((r).r_info = ELF64_R_INFO(s,t)) 50 #endif 51 #include "pro_incl.h" 52 #include "pro_section.h" 53 #include "pro_reloc.h" 54 #include "pro_reloc_stream.h" 55 56 /* 57 Return DW_DLV_ERROR on malloc error or reltarget_length error. 58 Return DW_DLV_OK otherwise 59 60 61 62 */ 63 /*ARGSUSED*/ int 64 _dwarf_pro_reloc_name_stream64(Dwarf_P_Debug dbg, 65 int base_sec_index, 66 Dwarf_Unsigned offset, /* r_offset of reloc */ 67 Dwarf_Unsigned symidx, 68 enum Dwarf_Rel_Type type, 69 int reltarget_length) 70 { 71 #if HAVE_ELF64_GETEHDR 72 REL64 *elf64_reloc = 0; 73 void *relrec_to_fill = 0; 74 int res = 0; 75 int rel_type = 0; 76 77 res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index, 78 &relrec_to_fill); 79 if (res != DW_DLV_OK) 80 return res; 81 82 83 if (type == dwarf_drt_data_reloc) { 84 if (reltarget_length == dbg->de_offset_size) { 85 rel_type = dbg->de_offset_reloc; 86 } else if (reltarget_length == dbg->de_pointer_size) { 87 rel_type = dbg->de_ptr_reloc; 88 } else { 89 return DW_DLV_ERROR; 90 } 91 } else if (type == dwarf_drt_segment_rel) { 92 rel_type = dbg->de_exc_reloc; 93 } else { 94 /* We are in trouble: improper use of stream relocations. 95 Someone else will diagnose */ 96 rel_type = 0; 97 } 98 99 elf64_reloc = (REL64 *)relrec_to_fill; 100 elf64_reloc->r_offset = offset; 101 Set_REL64_info(*elf64_reloc, symidx, rel_type); 102 return DW_DLV_OK; 103 #else /* !HAVE_ELF64_GETEHDR */ 104 return DW_DLV_ERROR; 105 #endif /* #if HAVE_ELF64_GETEHDR */ 106 } 107 108 /* 109 Return DW_DLV_ERROR on malloc error or reltarget_length error. 110 Return DW_DLV_OK otherwise 111 a binary reloc: 32bit ABI 112 */ 113 int 114 _dwarf_pro_reloc_name_stream32(Dwarf_P_Debug dbg, int base_sec_index, 115 Dwarf_Unsigned offset, /* r_offset of reloc */ 116 Dwarf_Unsigned symidx, 117 enum Dwarf_Rel_Type type, 118 int reltarget_length) 119 { 120 REL32 *elf32_reloc = 0; 121 void *relrec_to_fill = 0; 122 int res = 0; 123 int rel_type = 0; 124 125 res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index, 126 &relrec_to_fill); 127 if (res != DW_DLV_OK) 128 return res; 129 if (type == dwarf_drt_data_reloc) { 130 if (reltarget_length == dbg->de_offset_size) { 131 rel_type = dbg->de_offset_reloc; 132 } else if (reltarget_length == dbg->de_pointer_size) { 133 rel_type = dbg->de_ptr_reloc; 134 } else { 135 return DW_DLV_ERROR; 136 } 137 } else if (type == dwarf_drt_segment_rel) { 138 rel_type = dbg->de_exc_reloc; 139 } else { 140 /* We are in trouble: improper use of stream relocations. 141 Someone else will diagnose */ 142 rel_type = 0; 143 } 144 145 elf32_reloc = (REL32*)relrec_to_fill; 146 elf32_reloc->r_offset = (Elf32_Addr) offset; 147 Set_REL32_info(*elf32_reloc, (Dwarf_Word) symidx, rel_type); 148 return DW_DLV_OK; 149 150 /* get a slot, fill in the slot entry */ 151 } 152 153 154 155 /* 156 Return DW_DLV_OK. 157 Never can really do anything: lengths cannot 158 be represented as end-start in a stream. 159 160 */ 161 /*ARGSUSED*/ int 162 _dwarf_pro_reloc_length_stream(Dwarf_P_Debug dbg, 163 int base_sec_index, 164 Dwarf_Unsigned offset, /* r_offset of reloc */ 165 Dwarf_Unsigned start_symidx, 166 Dwarf_Unsigned end_symidx, 167 enum Dwarf_Rel_Type type, 168 int reltarget_length) 169 { 170 /* get a slot, fill in the slot entry */ 171 return DW_DLV_OK; 172 } 173 174 175 /* 176 Ensure each stream is a single buffer and 177 add that single buffer to the set of stream buffers. 178 179 By creating a new buffer and copying if necessary. 180 181 Free the input set of buffers if we consolidate. 182 Return -1 on error (malloc failure) 183 184 185 Return DW_DLV_OK on success. Any other return indicates 186 malloc failed. 187 188 */ 189 int 190 _dwarf_stream_relocs_to_disk(Dwarf_P_Debug dbg, 191 Dwarf_Signed * new_sec_count) 192 { 193 unsigned long total_size = 0; 194 Dwarf_Small *data = 0; 195 int sec_index = 0; 196 unsigned long i = 0; 197 Dwarf_Error err = 0; 198 Dwarf_Error *error = &err; 199 200 Dwarf_Signed sec_count = 0; 201 202 Dwarf_P_Per_Reloc_Sect p_reloc = &dbg->de_reloc_sect[0]; 203 204 for (i = 0; i < NUM_DEBUG_SECTIONS; ++i, ++p_reloc) { 205 unsigned long ct = p_reloc->pr_reloc_total_count; 206 unsigned len = 0; 207 struct Dwarf_P_Relocation_Block_s *p_blk = 0; 208 struct Dwarf_P_Relocation_Block_s *p_blk_last = 0; 209 Dwarf_P_Per_Reloc_Sect prb = 0; 210 211 if (ct == 0) { 212 continue; 213 } 214 prb = &dbg->de_reloc_sect[i]; 215 len = dbg->de_relocation_record_size; 216 ++sec_count; 217 218 total_size = ct * len; 219 sec_index = prb->pr_sect_num_of_reloc_sect; 220 if (sec_index == 0) { 221 /* Call de_callback_func or de_callback_func_b, getting 222 section number of reloc section. */ 223 int rel_section_index = 0; 224 Dwarf_Unsigned name_idx = 0; 225 int int_name = 0; 226 int err = 0; 227 228 if (dbg->de_callback_func_b) { 229 rel_section_index = 230 dbg->de_callback_func_b(_dwarf_rel_section_names[i], 231 /* size */ 232 dbg->de_relocation_record_size, 233 /* type */ SHT_REL, 234 /* flags */ 0, 235 /* link to symtab, which we cannot 236 know */ 0, 237 /* info == link to sec rels apply to 238 */ 239 dbg->de_elf_sects[i], 240 &name_idx, &err); 241 } else { 242 rel_section_index = 243 dbg->de_callback_func(_dwarf_rel_section_names[i], 244 /* size */ 245 dbg->de_relocation_record_size, 246 /* type */ SHT_REL, 247 /* flags */ 0, 248 /* link to symtab, which we cannot 249 know */ 0, 250 /* info == link to sec rels apply to */ 251 dbg->de_elf_sects[i], &int_name, &err); 252 name_idx = int_name; 253 } 254 if (rel_section_index == -1) { 255 { 256 _dwarf_p_error(dbg, error, DW_DLE_ELF_SECT_ERR); 257 return (DW_DLV_ERROR); 258 } 259 260 } 261 prb->pr_sect_num_of_reloc_sect = rel_section_index; 262 sec_index = rel_section_index; 263 } 264 GET_CHUNK(dbg, sec_index, data, total_size, &err); 265 p_blk = p_reloc->pr_first_block; 266 267 /* following loop executes at least once. Effects the 268 consolidation to a single block or, if already a single 269 block, simply copies to the output buffer. And frees the 270 input block. The new block is in the de_debug_sects list. */ 271 while (p_blk) { 272 273 unsigned long len = 274 p_blk->rb_where_to_add_next - p_blk->rb_data; 275 276 memcpy(data, p_blk->rb_data, len); 277 278 279 data += len; 280 281 p_blk_last = p_blk; 282 p_blk = p_blk->rb_next; 283 284 _dwarf_p_dealloc(dbg, (Dwarf_Small *) p_blk_last); 285 } 286 /* ASSERT: sum of len copied == total_size */ 287 288 /* 289 We have copied the input, now drop the pointers to it. For 290 debugging, leave the other data untouched. */ 291 p_reloc->pr_first_block = 0; 292 p_reloc->pr_last_block = 0; 293 } 294 295 *new_sec_count = sec_count; 296 return DW_DLV_OK; 297 } 298