xref: /titanic_44/usr/src/tools/ctf/dwarf/common/pro_reloc.c (revision 8b1606b5d15e5e037182f32e0306c43206772082)
1 /*
2 
3   Copyright (C) 2000 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., 1600 Amphitheatre Pky,
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 /*#include <elfaccess.h> */
43 #include "pro_incl.h"
44 
45 
46 /*Do initial alloc of newslots slots.
47   Fails only if malloc fails.
48 
49   Supposed to be called before any relocs allocated.
50   Ignored if after any allocated.
51 
52   Part of an optimization, so that for a known 'newslots'
53   relocations count we can preallocate the right size block.
54   Called from just 2 places.
55 
56   returns DW_DLV_OK or  DW_DLV_ERROR
57 */
58 int
59 _dwarf_pro_pre_alloc_n_reloc_slots(Dwarf_P_Debug dbg,
60 				   int rel_sec_index,
61 				   Dwarf_Unsigned newslots)
62 {
63     unsigned long len;
64     struct Dwarf_P_Relocation_Block_s *data;
65     Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[rel_sec_index];
66     unsigned long slots_in_blk = (unsigned long) newslots;
67     unsigned long rel_rec_size = dbg->de_relocation_record_size;
68 
69     if (prel->pr_first_block)
70 	return DW_DLV_OK;	/* do nothing */
71 
72     len = sizeof(struct Dwarf_P_Relocation_Block_s) +
73 	slots_in_blk * rel_rec_size;
74 
75 
76     data = (struct Dwarf_P_Relocation_Block_s *)
77 	_dwarf_p_get_alloc(dbg, len);
78     if (!data) {
79 	return DW_DLV_ERROR;
80     }
81     data->rb_slots_in_block = slots_in_blk;	/* could use default
82 						   here, as fallback in
83 						   case our origininal
84 						   estimate wrong.
85 						   When we call this we
86 						   presumably know what
87 						   we are doing, so
88 						   keep this count for
89 						   now */
90     data->rb_next_slot_to_use = 0;
91     data->rb_where_to_add_next =
92 	((char *) data) + sizeof(struct Dwarf_P_Relocation_Block_s);
93     data->rb_data = data->rb_where_to_add_next;
94 
95     prel->pr_first_block = data;
96     prel->pr_last_block = data;
97     prel->pr_block_count = 1;
98 
99 
100     return DW_DLV_OK;
101 }
102 
103 
104 /*Do alloc of slots.
105   Fails only if malloc fails.
106 
107   Only allocator used.
108 
109   returns DW_DLV_OK or  DW_DLV_ERROR
110 */
111 int
112 _dwarf_pro_alloc_reloc_slots(Dwarf_P_Debug dbg, int rel_sec_index)
113 {
114     unsigned long len;
115     struct Dwarf_P_Relocation_Block_s *data;
116     Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[rel_sec_index];
117     unsigned long slots_in_blk = prel->pr_slots_per_block_to_alloc;
118     unsigned long rel_rec_size = dbg->de_relocation_record_size;
119 
120     len = sizeof(struct Dwarf_P_Relocation_Block_s) +
121 	slots_in_blk * rel_rec_size;
122 
123     data = (struct Dwarf_P_Relocation_Block_s *)
124 	_dwarf_p_get_alloc(dbg, len);
125     if (!data) {
126 	return DW_DLV_ERROR;
127     }
128 
129     if (prel->pr_first_block) {
130 	prel->pr_last_block->rb_next = data;
131 	prel->pr_last_block = data;
132 	prel->pr_block_count += 1;
133 
134     } else {
135 
136 	prel->pr_first_block = data;
137 	prel->pr_last_block = data;
138 	prel->pr_block_count = 1;
139     }
140 
141     data->rb_slots_in_block = slots_in_blk;
142     data->rb_next_slot_to_use = 0;
143     data->rb_where_to_add_next =
144 	((char *) data) + sizeof(struct Dwarf_P_Relocation_Block_s);
145     data->rb_data = data->rb_where_to_add_next;
146 
147     return DW_DLV_OK;
148 
149 }
150 
151 /*
152 	Reserve a slot. return DW_DLV_OK if succeeds.
153 
154 	Return DW_DLV_ERROR if fails (malloc error).
155 
156 	Use the relrec_to_fill to pass back a pointer to
157 	a slot space to use.
158 */
159 int
160 _dwarf_pro_reloc_get_a_slot(Dwarf_P_Debug dbg,
161 			    int base_sec_index, void **relrec_to_fill)
162 {
163     struct Dwarf_P_Relocation_Block_s *data;
164     Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[base_sec_index];
165     unsigned long rel_rec_size = dbg->de_relocation_record_size;
166 
167     char *ret_addr;
168 
169     data = prel->pr_last_block;
170     if ((data == 0) ||
171 	(data->rb_next_slot_to_use >= data->rb_slots_in_block)) {
172 	int res;
173 
174 	res = _dwarf_pro_alloc_reloc_slots(dbg, base_sec_index);
175 	if (res != DW_DLV_OK) {
176 	    return res;
177 	}
178     }
179 
180     data = prel->pr_last_block;
181     /* now we have an empty slot */
182     ret_addr = data->rb_where_to_add_next;
183 
184     data->rb_where_to_add_next += rel_rec_size;
185     data->rb_next_slot_to_use += 1;
186 
187     prel->pr_reloc_total_count += 1;
188 
189     *relrec_to_fill = (void *) ret_addr;
190 
191     return DW_DLV_OK;
192 
193 }
194 
195 /*
196    On success  returns count of
197    .rel.* sections that are symbolic
198    thru count_of_relocation_sections.
199 
200    On success, returns DW_DLV_OK.
201 
202    If this is not a 'symbolic' run, returns
203     DW_DLV_NO_ENTRY.
204 
205    No errors are possible.
206 
207 
208 
209 
210 */
211 
212  /*ARGSUSED*/ int
213 dwarf_get_relocation_info_count(Dwarf_P_Debug dbg,
214 				Dwarf_Unsigned *
215 				count_of_relocation_sections,
216 				int *drd_buffer_version,
217 				Dwarf_Error * error)
218 {
219     if (dbg->de_flags & DW_DLC_SYMBOLIC_RELOCATIONS) {
220 	int i;
221 	unsigned int count = 0;
222 
223 	for (i = 0; i < NUM_DEBUG_SECTIONS; ++i) {
224 	    if (dbg->de_reloc_sect[i].pr_reloc_total_count > 0) {
225 		++count;
226 	    }
227 	}
228 	*count_of_relocation_sections = (Dwarf_Unsigned) count;
229 	*drd_buffer_version = DWARF_DRD_BUFFER_VERSION;
230 	return DW_DLV_OK;
231     }
232     return DW_DLV_NO_ENTRY;
233 }
234 
235 int
236 dwarf_get_relocation_info(Dwarf_P_Debug dbg,
237 			  Dwarf_Signed * elf_section_index,
238 			  Dwarf_Signed * elf_section_index_link,
239 			  Dwarf_Unsigned * relocation_buffer_count,
240 			  Dwarf_Relocation_Data * reldata_buffer,
241 			  Dwarf_Error * error)
242 {
243     int next = dbg->de_reloc_next_to_return;
244 
245     if (dbg->de_flags & DW_DLC_SYMBOLIC_RELOCATIONS) {
246 	int i;
247 
248 	for (i = next; i < NUM_DEBUG_SECTIONS; ++i) {
249 	    Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[i];
250 
251 	    if (prel->pr_reloc_total_count > 0) {
252 		dbg->de_reloc_next_to_return = i + 1;
253 
254 
255 		/* ASSERT: prel->.pr_block_count == 1 */
256 
257 		*elf_section_index = prel->pr_sect_num_of_reloc_sect;
258 		*elf_section_index_link = dbg->de_elf_sects[i];
259 		*relocation_buffer_count = prel->pr_reloc_total_count;
260 		*reldata_buffer = (Dwarf_Relocation_Data)
261 		    (prel->pr_first_block->rb_data);
262 		return DW_DLV_OK;
263 	    }
264 	}
265 	DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, DW_DLV_ERROR);
266     }
267     return DW_DLV_NO_ENTRY;
268 }
269