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