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