1*7fd79137SRobert Mustacchi /* 2*7fd79137SRobert Mustacchi 3*7fd79137SRobert Mustacchi Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved. 4*7fd79137SRobert Mustacchi Portions Copyright 2008-2010 David Anderson, Inc. All rights reserved. 5*7fd79137SRobert Mustacchi 6*7fd79137SRobert Mustacchi This program is free software; you can redistribute it and/or modify it 7*7fd79137SRobert Mustacchi under the terms of version 2.1 of the GNU Lesser General Public License 8*7fd79137SRobert Mustacchi as published by the Free Software Foundation. 9*7fd79137SRobert Mustacchi 10*7fd79137SRobert Mustacchi This program is distributed in the hope that it would be useful, but 11*7fd79137SRobert Mustacchi WITHOUT ANY WARRANTY; without even the implied warranty of 12*7fd79137SRobert Mustacchi MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 13*7fd79137SRobert Mustacchi 14*7fd79137SRobert Mustacchi Further, this software is distributed without any warranty that it is 15*7fd79137SRobert Mustacchi free of the rightful claim of any third person regarding infringement 16*7fd79137SRobert Mustacchi or the like. Any license provided herein, whether implied or 17*7fd79137SRobert Mustacchi otherwise, applies only to this software file. Patent licenses, if 18*7fd79137SRobert Mustacchi any, provided herein do not apply to combinations of this program with 19*7fd79137SRobert Mustacchi other software, or any other product whatsoever. 20*7fd79137SRobert Mustacchi 21*7fd79137SRobert Mustacchi You should have received a copy of the GNU Lesser General Public 22*7fd79137SRobert Mustacchi License along with this program; if not, write the Free Software 23*7fd79137SRobert Mustacchi Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, 24*7fd79137SRobert Mustacchi USA. 25*7fd79137SRobert Mustacchi 26*7fd79137SRobert Mustacchi Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, 27*7fd79137SRobert Mustacchi Mountain View, CA 94043, or: 28*7fd79137SRobert Mustacchi 29*7fd79137SRobert Mustacchi http://www.sgi.com 30*7fd79137SRobert Mustacchi 31*7fd79137SRobert Mustacchi For further information regarding this notice, see: 32*7fd79137SRobert Mustacchi 33*7fd79137SRobert Mustacchi http://oss.sgi.com/projects/GenInfo/NoticeExplan 34*7fd79137SRobert Mustacchi 35*7fd79137SRobert Mustacchi */ 36*7fd79137SRobert Mustacchi 37*7fd79137SRobert Mustacchi 38*7fd79137SRobert Mustacchi 39*7fd79137SRobert Mustacchi #include "config.h" 40*7fd79137SRobert Mustacchi #include "libdwarfdefs.h" 41*7fd79137SRobert Mustacchi #include <stdio.h> 42*7fd79137SRobert Mustacchi #include <string.h> 43*7fd79137SRobert Mustacchi /*#include <elfaccess.h> */ 44*7fd79137SRobert Mustacchi #include "pro_incl.h" 45*7fd79137SRobert Mustacchi 46*7fd79137SRobert Mustacchi 47*7fd79137SRobert Mustacchi /*Do initial alloc of newslots slots. 48*7fd79137SRobert Mustacchi Fails only if malloc fails. 49*7fd79137SRobert Mustacchi 50*7fd79137SRobert Mustacchi Supposed to be called before any relocs allocated. 51*7fd79137SRobert Mustacchi Ignored if after any allocated. 52*7fd79137SRobert Mustacchi 53*7fd79137SRobert Mustacchi Part of an optimization, so that for a known 'newslots' 54*7fd79137SRobert Mustacchi relocations count we can preallocate the right size block. 55*7fd79137SRobert Mustacchi Called from just 2 places. 56*7fd79137SRobert Mustacchi 57*7fd79137SRobert Mustacchi returns DW_DLV_OK or DW_DLV_ERROR 58*7fd79137SRobert Mustacchi */ 59*7fd79137SRobert Mustacchi int 60*7fd79137SRobert Mustacchi _dwarf_pro_pre_alloc_n_reloc_slots(Dwarf_P_Debug dbg, 61*7fd79137SRobert Mustacchi int rel_sec_index, 62*7fd79137SRobert Mustacchi Dwarf_Unsigned newslots) 63*7fd79137SRobert Mustacchi { 64*7fd79137SRobert Mustacchi unsigned long len = 0; 65*7fd79137SRobert Mustacchi struct Dwarf_P_Relocation_Block_s *data = 0; 66*7fd79137SRobert Mustacchi Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[rel_sec_index]; 67*7fd79137SRobert Mustacchi unsigned long slots_in_blk = (unsigned long) newslots; 68*7fd79137SRobert Mustacchi unsigned long rel_rec_size = dbg->de_relocation_record_size; 69*7fd79137SRobert Mustacchi 70*7fd79137SRobert Mustacchi if (prel->pr_first_block) 71*7fd79137SRobert Mustacchi return DW_DLV_OK; /* do nothing */ 72*7fd79137SRobert Mustacchi 73*7fd79137SRobert Mustacchi len = sizeof(struct Dwarf_P_Relocation_Block_s) + 74*7fd79137SRobert Mustacchi slots_in_blk * rel_rec_size; 75*7fd79137SRobert Mustacchi 76*7fd79137SRobert Mustacchi 77*7fd79137SRobert Mustacchi data = (struct Dwarf_P_Relocation_Block_s *) 78*7fd79137SRobert Mustacchi _dwarf_p_get_alloc(dbg, len); 79*7fd79137SRobert Mustacchi if (!data) { 80*7fd79137SRobert Mustacchi return DW_DLV_ERROR; 81*7fd79137SRobert Mustacchi } 82*7fd79137SRobert Mustacchi data->rb_slots_in_block = slots_in_blk; /* could use default 83*7fd79137SRobert Mustacchi here, as fallback in 84*7fd79137SRobert Mustacchi case our origininal 85*7fd79137SRobert Mustacchi estimate wrong. When 86*7fd79137SRobert Mustacchi we call this we 87*7fd79137SRobert Mustacchi presumably know what 88*7fd79137SRobert Mustacchi we are doing, so 89*7fd79137SRobert Mustacchi keep this count for 90*7fd79137SRobert Mustacchi now */ 91*7fd79137SRobert Mustacchi data->rb_next_slot_to_use = 0; 92*7fd79137SRobert Mustacchi data->rb_where_to_add_next = 93*7fd79137SRobert Mustacchi ((char *) data) + sizeof(struct Dwarf_P_Relocation_Block_s); 94*7fd79137SRobert Mustacchi data->rb_data = data->rb_where_to_add_next; 95*7fd79137SRobert Mustacchi 96*7fd79137SRobert Mustacchi prel->pr_first_block = data; 97*7fd79137SRobert Mustacchi prel->pr_last_block = data; 98*7fd79137SRobert Mustacchi prel->pr_block_count = 1; 99*7fd79137SRobert Mustacchi 100*7fd79137SRobert Mustacchi 101*7fd79137SRobert Mustacchi return DW_DLV_OK; 102*7fd79137SRobert Mustacchi } 103*7fd79137SRobert Mustacchi 104*7fd79137SRobert Mustacchi 105*7fd79137SRobert Mustacchi /*Do alloc of slots. 106*7fd79137SRobert Mustacchi Fails only if malloc fails. 107*7fd79137SRobert Mustacchi 108*7fd79137SRobert Mustacchi Only allocator used. 109*7fd79137SRobert Mustacchi 110*7fd79137SRobert Mustacchi returns DW_DLV_OK or DW_DLV_ERROR 111*7fd79137SRobert Mustacchi */ 112*7fd79137SRobert Mustacchi int 113*7fd79137SRobert Mustacchi _dwarf_pro_alloc_reloc_slots(Dwarf_P_Debug dbg, int rel_sec_index) 114*7fd79137SRobert Mustacchi { 115*7fd79137SRobert Mustacchi unsigned long len = 0; 116*7fd79137SRobert Mustacchi struct Dwarf_P_Relocation_Block_s *data = 0; 117*7fd79137SRobert Mustacchi Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[rel_sec_index]; 118*7fd79137SRobert Mustacchi unsigned long slots_in_blk = prel->pr_slots_per_block_to_alloc; 119*7fd79137SRobert Mustacchi unsigned long rel_rec_size = dbg->de_relocation_record_size; 120*7fd79137SRobert Mustacchi 121*7fd79137SRobert Mustacchi len = sizeof(struct Dwarf_P_Relocation_Block_s) + 122*7fd79137SRobert Mustacchi slots_in_blk * rel_rec_size; 123*7fd79137SRobert Mustacchi 124*7fd79137SRobert Mustacchi data = (struct Dwarf_P_Relocation_Block_s *) 125*7fd79137SRobert Mustacchi _dwarf_p_get_alloc(dbg, len); 126*7fd79137SRobert Mustacchi if (!data) { 127*7fd79137SRobert Mustacchi return DW_DLV_ERROR; 128*7fd79137SRobert Mustacchi } 129*7fd79137SRobert Mustacchi 130*7fd79137SRobert Mustacchi if (prel->pr_first_block) { 131*7fd79137SRobert Mustacchi prel->pr_last_block->rb_next = data; 132*7fd79137SRobert Mustacchi prel->pr_last_block = data; 133*7fd79137SRobert Mustacchi prel->pr_block_count += 1; 134*7fd79137SRobert Mustacchi 135*7fd79137SRobert Mustacchi } else { 136*7fd79137SRobert Mustacchi 137*7fd79137SRobert Mustacchi prel->pr_first_block = data; 138*7fd79137SRobert Mustacchi prel->pr_last_block = data; 139*7fd79137SRobert Mustacchi prel->pr_block_count = 1; 140*7fd79137SRobert Mustacchi } 141*7fd79137SRobert Mustacchi 142*7fd79137SRobert Mustacchi data->rb_slots_in_block = slots_in_blk; 143*7fd79137SRobert Mustacchi data->rb_next_slot_to_use = 0; 144*7fd79137SRobert Mustacchi data->rb_where_to_add_next = 145*7fd79137SRobert Mustacchi ((char *) data) + sizeof(struct Dwarf_P_Relocation_Block_s); 146*7fd79137SRobert Mustacchi data->rb_data = data->rb_where_to_add_next; 147*7fd79137SRobert Mustacchi 148*7fd79137SRobert Mustacchi return DW_DLV_OK; 149*7fd79137SRobert Mustacchi 150*7fd79137SRobert Mustacchi } 151*7fd79137SRobert Mustacchi 152*7fd79137SRobert Mustacchi /* 153*7fd79137SRobert Mustacchi Reserve a slot. return DW_DLV_OK if succeeds. 154*7fd79137SRobert Mustacchi 155*7fd79137SRobert Mustacchi Return DW_DLV_ERROR if fails (malloc error). 156*7fd79137SRobert Mustacchi 157*7fd79137SRobert Mustacchi Use the relrec_to_fill to pass back a pointer to 158*7fd79137SRobert Mustacchi a slot space to use. 159*7fd79137SRobert Mustacchi */ 160*7fd79137SRobert Mustacchi int 161*7fd79137SRobert Mustacchi _dwarf_pro_reloc_get_a_slot(Dwarf_P_Debug dbg, 162*7fd79137SRobert Mustacchi int base_sec_index, void **relrec_to_fill) 163*7fd79137SRobert Mustacchi { 164*7fd79137SRobert Mustacchi struct Dwarf_P_Relocation_Block_s *data = 0; 165*7fd79137SRobert Mustacchi Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[base_sec_index]; 166*7fd79137SRobert Mustacchi unsigned long rel_rec_size = dbg->de_relocation_record_size; 167*7fd79137SRobert Mustacchi 168*7fd79137SRobert Mustacchi char *ret_addr = 0; 169*7fd79137SRobert Mustacchi 170*7fd79137SRobert Mustacchi data = prel->pr_last_block; 171*7fd79137SRobert Mustacchi if ((data == 0) || 172*7fd79137SRobert Mustacchi (data->rb_next_slot_to_use >= data->rb_slots_in_block)) { 173*7fd79137SRobert Mustacchi int res; 174*7fd79137SRobert Mustacchi 175*7fd79137SRobert Mustacchi res = _dwarf_pro_alloc_reloc_slots(dbg, base_sec_index); 176*7fd79137SRobert Mustacchi if (res != DW_DLV_OK) { 177*7fd79137SRobert Mustacchi return res; 178*7fd79137SRobert Mustacchi } 179*7fd79137SRobert Mustacchi } 180*7fd79137SRobert Mustacchi 181*7fd79137SRobert Mustacchi data = prel->pr_last_block; 182*7fd79137SRobert Mustacchi /* now we have an empty slot */ 183*7fd79137SRobert Mustacchi ret_addr = data->rb_where_to_add_next; 184*7fd79137SRobert Mustacchi 185*7fd79137SRobert Mustacchi data->rb_where_to_add_next += rel_rec_size; 186*7fd79137SRobert Mustacchi data->rb_next_slot_to_use += 1; 187*7fd79137SRobert Mustacchi 188*7fd79137SRobert Mustacchi prel->pr_reloc_total_count += 1; 189*7fd79137SRobert Mustacchi 190*7fd79137SRobert Mustacchi *relrec_to_fill = (void *) ret_addr; 191*7fd79137SRobert Mustacchi 192*7fd79137SRobert Mustacchi return DW_DLV_OK; 193*7fd79137SRobert Mustacchi 194*7fd79137SRobert Mustacchi } 195*7fd79137SRobert Mustacchi 196*7fd79137SRobert Mustacchi /* 197*7fd79137SRobert Mustacchi On success returns count of 198*7fd79137SRobert Mustacchi .rel.* sections that are symbolic 199*7fd79137SRobert Mustacchi thru count_of_relocation_sections. 200*7fd79137SRobert Mustacchi 201*7fd79137SRobert Mustacchi On success, returns DW_DLV_OK. 202*7fd79137SRobert Mustacchi 203*7fd79137SRobert Mustacchi If this is not a 'symbolic' run, returns 204*7fd79137SRobert Mustacchi DW_DLV_NO_ENTRY. 205*7fd79137SRobert Mustacchi 206*7fd79137SRobert Mustacchi No errors are possible. 207*7fd79137SRobert Mustacchi 208*7fd79137SRobert Mustacchi 209*7fd79137SRobert Mustacchi 210*7fd79137SRobert Mustacchi 211*7fd79137SRobert Mustacchi */ 212*7fd79137SRobert Mustacchi 213*7fd79137SRobert Mustacchi /*ARGSUSED*/ int 214*7fd79137SRobert Mustacchi dwarf_get_relocation_info_count(Dwarf_P_Debug dbg, 215*7fd79137SRobert Mustacchi Dwarf_Unsigned * 216*7fd79137SRobert Mustacchi count_of_relocation_sections, 217*7fd79137SRobert Mustacchi int *drd_buffer_version, 218*7fd79137SRobert Mustacchi Dwarf_Error * error) 219*7fd79137SRobert Mustacchi { 220*7fd79137SRobert Mustacchi if (dbg->de_flags & DW_DLC_SYMBOLIC_RELOCATIONS) { 221*7fd79137SRobert Mustacchi int i; 222*7fd79137SRobert Mustacchi unsigned int count = 0; 223*7fd79137SRobert Mustacchi 224*7fd79137SRobert Mustacchi for (i = 0; i < NUM_DEBUG_SECTIONS; ++i) { 225*7fd79137SRobert Mustacchi if (dbg->de_reloc_sect[i].pr_reloc_total_count > 0) { 226*7fd79137SRobert Mustacchi ++count; 227*7fd79137SRobert Mustacchi } 228*7fd79137SRobert Mustacchi } 229*7fd79137SRobert Mustacchi *count_of_relocation_sections = (Dwarf_Unsigned) count; 230*7fd79137SRobert Mustacchi *drd_buffer_version = DWARF_DRD_BUFFER_VERSION; 231*7fd79137SRobert Mustacchi return DW_DLV_OK; 232*7fd79137SRobert Mustacchi } 233*7fd79137SRobert Mustacchi return DW_DLV_NO_ENTRY; 234*7fd79137SRobert Mustacchi } 235*7fd79137SRobert Mustacchi 236*7fd79137SRobert Mustacchi int 237*7fd79137SRobert Mustacchi dwarf_get_relocation_info(Dwarf_P_Debug dbg, 238*7fd79137SRobert Mustacchi Dwarf_Signed * elf_section_index, 239*7fd79137SRobert Mustacchi Dwarf_Signed * elf_section_index_link, 240*7fd79137SRobert Mustacchi Dwarf_Unsigned * relocation_buffer_count, 241*7fd79137SRobert Mustacchi Dwarf_Relocation_Data * reldata_buffer, 242*7fd79137SRobert Mustacchi Dwarf_Error * error) 243*7fd79137SRobert Mustacchi { 244*7fd79137SRobert Mustacchi int next = dbg->de_reloc_next_to_return; 245*7fd79137SRobert Mustacchi 246*7fd79137SRobert Mustacchi if (dbg->de_flags & DW_DLC_SYMBOLIC_RELOCATIONS) { 247*7fd79137SRobert Mustacchi int i; 248*7fd79137SRobert Mustacchi 249*7fd79137SRobert Mustacchi for (i = next; i < NUM_DEBUG_SECTIONS; ++i) { 250*7fd79137SRobert Mustacchi Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[i]; 251*7fd79137SRobert Mustacchi 252*7fd79137SRobert Mustacchi if (prel->pr_reloc_total_count > 0) { 253*7fd79137SRobert Mustacchi dbg->de_reloc_next_to_return = i + 1; 254*7fd79137SRobert Mustacchi 255*7fd79137SRobert Mustacchi 256*7fd79137SRobert Mustacchi /* ASSERT: prel->.pr_block_count == 1 */ 257*7fd79137SRobert Mustacchi 258*7fd79137SRobert Mustacchi *elf_section_index = prel->pr_sect_num_of_reloc_sect; 259*7fd79137SRobert Mustacchi *elf_section_index_link = dbg->de_elf_sects[i]; 260*7fd79137SRobert Mustacchi *relocation_buffer_count = prel->pr_reloc_total_count; 261*7fd79137SRobert Mustacchi *reldata_buffer = (Dwarf_Relocation_Data) 262*7fd79137SRobert Mustacchi (prel->pr_first_block->rb_data); 263*7fd79137SRobert Mustacchi return DW_DLV_OK; 264*7fd79137SRobert Mustacchi } 265*7fd79137SRobert Mustacchi } 266*7fd79137SRobert Mustacchi DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, DW_DLV_ERROR); 267*7fd79137SRobert Mustacchi } 268*7fd79137SRobert Mustacchi return DW_DLV_NO_ENTRY; 269*7fd79137SRobert Mustacchi } 270